first pass (ok, third really) at internal send+return - audio routing inside ardour...
[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         /** Called when a subclass should update the editor's selection following a drag */
118         virtual void update_selection () {}
119
120 protected:
121         nframes64_t adjusted_current_frame (GdkEvent *) const;
122         
123         Editor* _editor; ///< our editor
124         ArdourCanvas::Item* _item; ///< our item
125         nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag
126                                            ///< to the start of the thing that is being dragged
127         nframes64_t _last_frame_position; ///< last position of the thing being dragged
128         nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0
129         nframes64_t _last_pointer_frame; ///< frame that the pointer was at last time a motion occurred
130         nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
131         double _original_x; ///< original world x of the thing being dragged
132         double _original_y; ///< original world y of the thing being dragged
133         double _grab_x; ///< item x of the grab start position
134         double _grab_y; ///< item y of the grab start position
135         double _current_pointer_x; ///< item x of the current pointer
136         double _current_pointer_y; ///< item y of the current pointer
137         double _last_pointer_x; ///< item x of the pointer last time a motion occurred
138         double _last_pointer_y; ///< item y of the pointer last time a motion occurred
139         bool _x_constrained; ///< true if x motion is constrained, otherwise false
140         bool _y_constrained; ///< true if y motion is constrained, otherwise false
141         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
142
143 private:
144         
145         bool _ending; ///< true if end_grab is in progress, otherwise false
146         bool _had_movement; ///< true if movement has occurred, otherwise false
147         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
148 };
149
150
151 /** Abstract base class for drags that involve region(s) */
152 class RegionDrag : public Drag, public sigc::trackable
153 {
154 public:
155         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
156         virtual ~RegionDrag () {}
157
158         void update_selection ();
159
160 protected:
161         
162         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
163         std::list<RegionView*> _views; ///< all views that are being dragged
164
165 private:
166         void region_going_away (RegionView *);
167 };
168
169
170 /** Drags involving region motion from somewhere */
171 class RegionMotionDrag : public RegionDrag
172 {
173 public:
174         
175         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
176         virtual ~RegionMotionDrag () {}
177
178         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
179         virtual void motion (GdkEvent *, bool);
180         virtual void finished (GdkEvent *, bool) = 0;
181
182 protected:
183         struct TimeAxisViewSummary {
184                 TimeAxisViewSummary () : height_list(512) {}
185                 
186                 std::bitset<512> tracks;
187                 std::vector<int32_t> height_list;
188                 int visible_y_low;
189                 int visible_y_high;
190         };
191         
192         void copy_regions (GdkEvent *);
193         bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
194         std::map<RegionView*, RouteTimeAxisView*> find_time_axis_views ();
195         double compute_x_delta (GdkEvent const *, nframes64_t *);
196         bool compute_y_delta (
197                 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
198                 int32_t *, int32_t *, int32_t *
199                 );
200
201         TimeAxisViewSummary get_time_axis_view_summary ();
202         virtual bool x_move_allowed () const = 0;
203         
204         TimeAxisView* _dest_trackview;
205         ARDOUR::layer_t _dest_layer;
206         bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
207         bool _brushing;
208 };
209
210
211 /** Drags to move (or copy) regions that are already shown in the GUI to
212  *  somewhere different.
213  */
214 class RegionMoveDrag : public RegionMotionDrag
215 {
216 public:
217         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
218         virtual ~RegionMoveDrag () {}
219
220         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
221         void motion (GdkEvent *, bool);
222         void finished (GdkEvent *, bool);
223         
224         bool apply_move_threshold () const {
225                 return true;
226         }
227
228 private:
229         bool x_move_allowed () const;
230
231         bool _copy;
232 };
233
234 /** Drag to insert a region from somewhere */
235 class RegionInsertDrag : public RegionMotionDrag
236 {
237 public:
238         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
239
240         void finished (GdkEvent *, bool);
241         
242 private:
243         bool x_move_allowed () const;
244 };
245
246 /** Region drag in splice mode */
247 class RegionSpliceDrag : public RegionMoveDrag
248 {
249 public:
250         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
251
252         void motion (GdkEvent *, bool);
253         void finished (GdkEvent *, bool);
254 };
255
256 /** Drags to create regions */
257 class RegionCreateDrag : public Drag
258 {
259 public:
260         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
261
262         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
263         void motion (GdkEvent *, bool);
264         void finished (GdkEvent *, bool);
265
266 private:
267         TimeAxisView* _view;
268         TimeAxisView* _dest_trackview;
269 };
270
271 /** Drag of region gain */
272 class RegionGainDrag : public Drag
273 {
274 public:
275         RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
276
277         void motion (GdkEvent *, bool);
278         void finished (GdkEvent *, bool);
279         bool active (Editing::MouseMode m) {
280                 return (m == Editing::MouseGain);
281         }
282 };
283
284 /** Drag to trim region(s) */
285 class TrimDrag : public RegionDrag
286 {
287 public:
288         enum Operation {
289                 StartTrim,
290                 EndTrim,
291                 ContentsTrim,
292         };
293
294         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
295
296         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
297         void motion (GdkEvent *, bool);
298         void finished (GdkEvent *, bool);
299
300 private:
301
302         Operation _operation;
303 };
304
305 /** Meter marker drag */
306 class MeterMarkerDrag : public Drag
307 {
308 public:
309         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
310
311         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
312         void motion (GdkEvent *, bool);
313         void finished (GdkEvent *, bool);
314
315 private:
316         MeterMarker* _marker;
317         bool _copy;
318 };
319
320 /** Tempo marker drag */
321 class TempoMarkerDrag : public Drag
322 {
323 public:
324         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
325
326         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
327         void motion (GdkEvent *, bool);
328         void finished (GdkEvent *, bool);
329
330 private:
331         TempoMarker* _marker;
332         bool _copy;
333 };
334
335
336 /** Drag of a cursor */
337 class CursorDrag : public Drag
338 {
339 public:
340         CursorDrag (Editor *, ArdourCanvas::Item *, bool);
341
342         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
343         void motion (GdkEvent *, bool);
344         void finished (GdkEvent *, bool);
345
346         bool active (Editing::MouseMode) {
347                 return true;
348         }
349
350         bool allow_vertical_autoscroll () const {
351                 return false;
352         }
353
354 private:
355         EditorCursor* _cursor; ///< cursor being dragged
356         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
357         
358 };
359
360 /** Region fade-in drag */
361 class FadeInDrag : public RegionDrag
362 {
363 public:
364         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
365
366         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
367         void motion (GdkEvent *, bool);
368         void finished (GdkEvent *, bool);
369 };
370
371 /** Region fade-out drag */
372 class FadeOutDrag : public RegionDrag
373 {
374 public:
375         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
376
377         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
378         void motion (GdkEvent *, bool);
379         void finished (GdkEvent *, bool);
380 };
381
382 /** Marker drag */
383 class MarkerDrag : public Drag
384 {
385 public:
386         MarkerDrag (Editor *, ArdourCanvas::Item *);
387         ~MarkerDrag ();
388
389         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
390         void motion (GdkEvent *, bool);
391         void finished (GdkEvent *, bool);
392
393 private:
394         void update_item (ARDOUR::Location *);
395         
396         Marker* _marker; ///< marker being dragged
397         std::list<ARDOUR::Location*> _copied_locations;
398         ArdourCanvas::Line* _line;
399         ArdourCanvas::Points _points;
400 };
401
402 /** Control point drag */
403 class ControlPointDrag : public Drag
404 {
405 public:
406         ControlPointDrag (Editor *, ArdourCanvas::Item *);
407
408         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
409         void motion (GdkEvent *, bool);
410         void finished (GdkEvent *, bool);
411
412         bool active (Editing::MouseMode m) {
413                 return (m == Editing::MouseGain);
414         }
415
416 private:
417         
418         ControlPoint* _point;
419         double _cumulative_x_drag;
420         double _cumulative_y_drag;
421         static double const _zero_gain_fraction;
422 };
423
424 /** Gain or automation line drag */
425 class LineDrag : public Drag
426 {
427 public:
428         LineDrag (Editor *e, ArdourCanvas::Item *i);
429
430         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
431         void motion (GdkEvent *, bool);
432         void finished (GdkEvent *, bool);
433         
434         bool active (Editing::MouseMode) {
435                 return true;
436         }
437
438 private:
439
440         AutomationLine* _line;
441         uint32_t _before;
442         uint32_t _after;
443         double _cumulative_y_drag;
444 };
445
446 /** Dragging of a rubberband rectangle for selecting things */
447 class RubberbandSelectDrag : public Drag
448 {
449 public:
450         RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
451
452         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
453         void motion (GdkEvent *, bool);
454         void finished (GdkEvent *, bool);
455 };
456
457 /** Region drag in time-FX mode */
458 class TimeFXDrag : public RegionDrag
459 {
460 public:
461         TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
462
463         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
464         void motion (GdkEvent *, bool);
465         void finished (GdkEvent *, bool);
466 };
467
468 /** Scrub drag in audition mode */
469 class ScrubDrag : public Drag
470 {
471 public:
472         ScrubDrag (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 /** Drag in range select(gc_owner.get()) moAutomatable */
480 class SelectionDrag : public Drag
481 {
482 public:
483         enum Operation {
484                 CreateSelection,
485                 SelectionStartTrim,
486                 SelectionEndTrim,
487                 SelectionMove
488         };
489
490         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
491
492         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
493         void motion (GdkEvent *, bool);
494         void finished (GdkEvent *, bool);
495
496 private:
497         Operation _operation;
498         bool _copy;
499 };
500
501 /** Range marker drag */
502 class RangeMarkerBarDrag : public Drag
503 {
504 public:
505         enum Operation {
506                 CreateRangeMarker,
507                 CreateTransportMarker,
508                 CreateCDMarker
509         };
510
511         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
512
513         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
514         void motion (GdkEvent *, bool);
515         void finished (GdkEvent *, bool);
516
517 private:
518         void update_item (ARDOUR::Location *);
519
520         Operation _operation;
521         ArdourCanvas::SimpleRect* _drag_rect;
522         bool _copy;
523 };
524
525 /* Drag of rectangle to set zoom */
526 class MouseZoomDrag : public Drag
527 {
528 public:
529         MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
530
531         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
532         void motion (GdkEvent *, bool);
533         void finished (GdkEvent *, bool);
534 };
535
536 #endif /* __gtk2_ardour_editor_drag_h_ */
537