Fixes to pointer constraints when copying in lock edit mode; make them behave the...
[ardour.git] / gtk2_ardour / editor_drag.h
1 /*
2     Copyright (C) 2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __gtk2_ardour_editor_drag_h_
21 #define __gtk2_ardour_editor_drag_h_
22
23 #include <list>
24
25 #include <gdk/gdk.h>
26 #include <stdint.h>
27
28 #include "ardour/types.h"
29
30 #include "canvas.h"
31 #include "editor_items.h"
32
33 namespace ARDOUR {
34         class Location;
35 }
36
37 class Editor;
38 class EditorCursor;
39 class TimeAxisView;
40
41 /** Abstract base class for dragging of things within the editor */
42 class Drag
43 {
44
45 public:
46         Drag (Editor *, ArdourCanvas::Item *);
47         virtual ~Drag () {}
48
49         /** @return the canvas item being dragged */
50         ArdourCanvas::Item* item () const {
51                 return _item;
52         }
53
54         void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
55         void break_drag ();
56
57         bool motion_handler (GdkEvent*, bool);
58
59         /** @return true if an end drag is in progress */
60         bool ending () const {
61                 return _ending;
62         }
63
64         /** @return current pointer x position in item coordinates */
65         double current_pointer_x () const {
66                 return _current_pointer_x;
67         }
68
69         /** @return current pointer y position in item coordinates */
70         double current_pointer_y () const {
71                 return _current_pointer_y;
72         }
73
74         /** @return current pointer frame */
75         nframes64_t current_pointer_frame () const {
76                 return _current_pointer_frame;
77         }
78
79         /** Called to start a grab of an item.
80          *  @param e Event that caused the grab to start.
81          *  @param c Cursor to use, or 0.
82          */
83         virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
84
85         virtual bool end_grab (GdkEvent *);
86
87         /** Called when a drag motion has occurred.
88          *  @param e Event describing the motion.
89          *  @param f true if this is the first movement, otherwise false.
90          */
91         virtual void motion (GdkEvent* e, bool f) = 0;
92
93         /** Called when a drag has finished.
94          *  @param e Event describing the finish.
95          *  @param m true if some movement occurred, otherwise false.
96          */
97         virtual void finished (GdkEvent* e, bool m) = 0;
98
99         /** @param m Mouse mode.
100          *  @return true if this drag should happen in this mouse mode.
101          */
102         virtual bool active (Editing::MouseMode m) {
103                 return (m != Editing::MouseGain);
104         }
105
106         /** @return true if a small threshold should be applied before a mouse movement
107          *  is considered a drag, otherwise false.
108          */
109         virtual bool apply_move_threshold () const {
110                 return false;
111         }
112
113         virtual bool allow_vertical_autoscroll () const {
114                 return true;
115         }
116
117 protected:
118         nframes64_t adjusted_current_frame (GdkEvent *) const;
119
120         Editor* _editor; ///< our editor
121         ArdourCanvas::Item* _item; ///< our item
122         nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag
123                                            ///< to the start of the thing that is being dragged
124         nframes64_t _last_frame_position; ///< last position of the thing being dragged
125         nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0
126         nframes64_t _last_pointer_frame; ///< frame that the pointer was at last time a motion occurred
127         nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
128         double _original_x; ///< original world x of the thing being dragged
129         double _original_y; ///< original world y of the thing being dragged
130         double _grab_x; ///< item x of the grab start position
131         double _grab_y; ///< item y of the grab start position
132         double _current_pointer_x; ///< item x of the current pointer
133         double _current_pointer_y; ///< item y of the current pointer
134         double _last_pointer_x; ///< item x of the pointer last time a motion occurred
135         double _last_pointer_y; ///< item y of the pointer last time a motion occurred
136         bool _x_constrained; ///< true if x motion is constrained, otherwise false
137         bool _y_constrained; ///< true if y motion is constrained, otherwise false
138         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
139
140 private:
141
142         bool _ending; ///< true if end_grab is in progress, otherwise false
143         bool _had_movement; ///< true if movement has occurred, otherwise false
144         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
145 };
146
147
148 /** Abstract base class for drags that involve region(s) */
149 class RegionDrag : public Drag, public sigc::trackable
150 {
151 public:
152         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
153         virtual ~RegionDrag () {}
154
155 protected:
156
157         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
158         std::list<RegionView*> _views; ///< all views that are being dragged
159
160 private:
161         void region_going_away (RegionView *);
162 };
163
164
165 /** Drags involving region motion from somewhere */
166 class RegionMotionDrag : public RegionDrag
167 {
168 public:
169
170         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
171         virtual ~RegionMotionDrag () {}
172
173         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
174         virtual void motion (GdkEvent *, bool);
175         virtual void finished (GdkEvent *, bool) = 0;
176
177 protected:
178         struct TimeAxisViewSummary {
179                 TimeAxisViewSummary () : height_list(512) {}
180
181                 std::bitset<512> tracks;
182                 std::vector<int32_t> height_list;
183                 int visible_y_low;
184                 int visible_y_high;
185         };
186
187         void copy_regions (GdkEvent *);
188         bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
189         std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
190         double compute_x_delta (GdkEvent const *, nframes64_t *);
191         bool compute_y_delta (
192                 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
193                 int32_t *, int32_t *, int32_t *
194                 );
195
196         TimeAxisViewSummary get_time_axis_view_summary ();
197         bool x_move_allowed () const;
198
199         TimeAxisView* _dest_trackview;
200         ARDOUR::layer_t _dest_layer;
201         bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
202         bool _brushing;
203 };
204
205
206 /** Drags to move (or copy) regions that are already shown in the GUI to
207  *  somewhere different.
208  */
209 class RegionMoveDrag : public RegionMotionDrag
210 {
211 public:
212         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
213         virtual ~RegionMoveDrag () {}
214
215         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
216         void motion (GdkEvent *, bool);
217         void finished (GdkEvent *, bool);
218
219         bool apply_move_threshold () const {
220                 return true;
221         }
222
223 private:
224         bool _copy;
225 };
226
227 /** Drag to insert a region from somewhere */
228 class RegionInsertDrag : public RegionMotionDrag
229 {
230 public:
231         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
232
233         void finished (GdkEvent *, bool);
234 };
235
236 /** Region drag in splice mode */
237 class RegionSpliceDrag : public RegionMoveDrag
238 {
239 public:
240         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
241
242         void motion (GdkEvent *, bool);
243         void finished (GdkEvent *, bool);
244 };
245
246 /** Drags to create regions */
247 class RegionCreateDrag : public Drag
248 {
249 public:
250         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
251
252         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
253         void motion (GdkEvent *, bool);
254         void finished (GdkEvent *, bool);
255
256 private:
257         TimeAxisView* _view;
258         TimeAxisView* _dest_trackview;
259 };
260
261 /** Drags to resize MIDI notes */
262 class NoteResizeDrag : public Drag
263 {
264 public:
265         NoteResizeDrag (Editor *, ArdourCanvas::Item *);
266
267         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
268         void motion (GdkEvent *, bool);
269         void finished (GdkEvent *, bool);
270
271 private:
272         MidiRegionView*     region;
273         bool                relative;
274         bool                at_front;
275 };
276
277 class NoteDrag : public Drag
278 {
279   public:
280         NoteDrag (Editor*, ArdourCanvas::Item*);
281
282         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
283         void motion (GdkEvent *, bool);
284         void finished (GdkEvent *, bool);
285
286   private:
287         MidiRegionView* region;
288         double last_x;
289         double last_y;
290         double drag_delta_x;
291         double drag_delta_note;
292         bool   was_selected;
293 };
294
295 /** Drag of region gain */
296 class RegionGainDrag : public Drag
297 {
298 public:
299         RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
300
301         void motion (GdkEvent *, bool);
302         void finished (GdkEvent *, bool);
303         bool active (Editing::MouseMode m) {
304                 return (m == Editing::MouseGain);
305         }
306 };
307
308 /** Drag to trim region(s) */
309 class TrimDrag : public RegionDrag
310 {
311 public:
312         enum Operation {
313                 StartTrim,
314                 EndTrim,
315                 ContentsTrim,
316         };
317
318         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
319
320         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
321         void motion (GdkEvent *, bool);
322         void finished (GdkEvent *, bool);
323
324 private:
325
326         Operation _operation;
327 };
328
329 /** Meter marker drag */
330 class MeterMarkerDrag : public Drag
331 {
332 public:
333         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
334
335         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
336         void motion (GdkEvent *, bool);
337         void finished (GdkEvent *, bool);
338
339 private:
340         MeterMarker* _marker;
341         bool _copy;
342 };
343
344 /** Tempo marker drag */
345 class TempoMarkerDrag : public Drag
346 {
347 public:
348         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
349
350         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
351         void motion (GdkEvent *, bool);
352         void finished (GdkEvent *, bool);
353
354 private:
355         TempoMarker* _marker;
356         bool _copy;
357 };
358
359
360 /** Drag of a cursor */
361 class CursorDrag : public Drag
362 {
363 public:
364         CursorDrag (Editor *, ArdourCanvas::Item *, bool);
365
366         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
367         void motion (GdkEvent *, bool);
368         void finished (GdkEvent *, bool);
369
370         bool active (Editing::MouseMode) {
371                 return true;
372         }
373
374         bool allow_vertical_autoscroll () const {
375                 return false;
376         }
377
378 private:
379         EditorCursor* _cursor; ///< cursor being dragged
380         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
381
382 };
383
384 /** Region fade-in drag */
385 class FadeInDrag : public RegionDrag
386 {
387 public:
388         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
389
390         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
391         void motion (GdkEvent *, bool);
392         void finished (GdkEvent *, bool);
393 };
394
395 /** Region fade-out drag */
396 class FadeOutDrag : public RegionDrag
397 {
398 public:
399         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
400
401         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
402         void motion (GdkEvent *, bool);
403         void finished (GdkEvent *, bool);
404 };
405
406 /** Marker drag */
407 class MarkerDrag : public Drag
408 {
409 public:
410         MarkerDrag (Editor *, ArdourCanvas::Item *);
411         ~MarkerDrag ();
412
413         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
414         void motion (GdkEvent *, bool);
415         void finished (GdkEvent *, bool);
416
417 private:
418         void update_item (ARDOUR::Location *);
419
420         Marker* _marker; ///< marker being dragged
421         std::list<ARDOUR::Location*> _copied_locations;
422         ArdourCanvas::Line* _line;
423         ArdourCanvas::Points _points;
424 };
425
426 /** Control point drag */
427 class ControlPointDrag : public Drag
428 {
429 public:
430         ControlPointDrag (Editor *, ArdourCanvas::Item *);
431
432         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
433         void motion (GdkEvent *, bool);
434         void finished (GdkEvent *, bool);
435
436         bool active (Editing::MouseMode m);
437
438 private:
439
440         ControlPoint* _point;
441         double _cumulative_x_drag;
442         double _cumulative_y_drag;
443         static double const _zero_gain_fraction;
444 };
445
446 /** Gain or automation line drag */
447 class LineDrag : public Drag
448 {
449 public:
450         LineDrag (Editor *e, ArdourCanvas::Item *i);
451
452         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
453         void motion (GdkEvent *, bool);
454         void finished (GdkEvent *, bool);
455
456         bool active (Editing::MouseMode) {
457                 return true;
458         }
459
460 private:
461
462         AutomationLine* _line;
463         uint32_t _before;
464         uint32_t _after;
465         double _cumulative_y_drag;
466 };
467
468 /** Dragging of a rubberband rectangle for selecting things */
469 class RubberbandSelectDrag : public Drag
470 {
471 public:
472         RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
473
474         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
475         void motion (GdkEvent *, bool);
476         void finished (GdkEvent *, bool);
477 };
478
479 /** Region drag in time-FX mode */
480 class TimeFXDrag : public RegionDrag
481 {
482 public:
483         TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
484
485         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
486         void motion (GdkEvent *, bool);
487         void finished (GdkEvent *, bool);
488 };
489
490 /** Scrub drag in audition mode */
491 class ScrubDrag : public Drag
492 {
493 public:
494         ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
495
496         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
497         void motion (GdkEvent *, bool);
498         void finished (GdkEvent *, bool);
499 };
500
501 /** Drag in range select(gc_owner.get()) moAutomatable */
502 class SelectionDrag : public Drag
503 {
504 public:
505         enum Operation {
506                 CreateSelection,
507                 SelectionStartTrim,
508                 SelectionEndTrim,
509                 SelectionMove
510         };
511
512         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
513
514         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
515         void motion (GdkEvent *, bool);
516         void finished (GdkEvent *, bool);
517
518 private:
519         Operation _operation;
520         bool _copy;
521 };
522
523 /** Range marker drag */
524 class RangeMarkerBarDrag : public Drag
525 {
526 public:
527         enum Operation {
528                 CreateRangeMarker,
529                 CreateTransportMarker,
530                 CreateCDMarker
531         };
532
533         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
534
535         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
536         void motion (GdkEvent *, bool);
537         void finished (GdkEvent *, bool);
538
539 private:
540         void update_item (ARDOUR::Location *);
541
542         Operation _operation;
543         ArdourCanvas::SimpleRect* _drag_rect;
544         bool _copy;
545 };
546
547 /* Drag of rectangle to set zoom */
548 class MouseZoomDrag : public Drag
549 {
550 public:
551         MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
552
553         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
554         void motion (GdkEvent *, bool);
555         void finished (GdkEvent *, bool);
556 };
557
558 #endif /* __gtk2_ardour_editor_drag_h_ */
559