Some small cleanups to dragging.
[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 true if the first move (past any move threshold) has occurred */
65         bool first_move () const {
66                 return _first_move;
67         }
68
69         /** @return current pointer x position in item coordinates */
70         double current_pointer_x () const {
71                 return _current_pointer_x;
72         }
73
74         /** @return current pointer y position in item coordinates */
75         double current_pointer_y () const {
76                 return _current_pointer_y;
77         }
78
79         /** @return current pointer frame */
80         nframes64_t current_pointer_frame () const {
81                 return _current_pointer_frame;
82         }
83
84         /** Called to start a grab of an item.
85          *  @param e Event that caused the grab to start.
86          *  @param c Cursor to use, or 0.
87          */
88         virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
89
90         virtual bool end_grab (GdkEvent *);
91
92         /** Called when a drag motion has occurred.
93          *  @param e Event describing the motion.
94          */
95         virtual void motion (GdkEvent* e) = 0;
96
97         /** Called when a drag has finished.
98          *  @param e Event describing the finish.
99          */
100         virtual void finished (GdkEvent *) = 0;
101
102         /** @param m Mouse mode.
103          *  @return true if this drag should happen in this mouse mode.
104          */
105         virtual bool active (Editing::MouseMode m) {
106                 return (m != Editing::MouseGain);
107         }
108
109         /** Called when a subclass should update the editor's selection following a drag */
110         virtual void update_selection () {}
111
112 protected:
113         nframes64_t adjusted_current_frame () const;
114         
115         Editor* _editor; ///< our editor
116         ArdourCanvas::Item* _item; ///< our item
117         nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag
118                                            ///< to the start of the thing that is being dragged
119         nframes64_t _last_frame_position; ///< last position of the thing being dragged
120         nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0
121         nframes64_t _last_pointer_frame; ///< frame that the pointer was at last time a motion occurred
122         nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
123         double _original_x; ///< original world x of the thing being dragged
124         double _original_y; ///< original world y of the thing being dragged
125         double _grab_x; ///< item x of the grab start position
126         double _grab_y; ///< item y of the grab start position
127         double _current_pointer_x; ///< item x of the current pointer
128         double _current_pointer_y; ///< item y of the current pointer
129         double _last_pointer_x; ///< item x of the pointer last time a motion occurred
130         double _last_pointer_y; ///< item y of the pointer last time a motion occurred
131         bool _x_constrained; ///< true if x motion is constrained, otherwise false
132         bool _y_constrained; ///< true if y motion is constrained, otherwise false
133         bool _copy; ///< true if we're copying the things that we're dragging
134         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
135         bool _first_move; ///< true if some movement has occurred, otherwise false
136         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
137         bool _want_move_threshold; ///< true if a move threshold should be applied, otherwise false
138
139 private:
140         
141         bool _ending; ///< true if end_grab is in progress, otherwise false
142 };
143
144
145 /** Abstract base class for drags that involve region(s) */
146 class RegionDrag : public Drag, public sigc::trackable
147 {
148 public:
149         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
150         virtual ~RegionDrag () {}
151
152         void update_selection ();
153
154 protected:
155         
156         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
157         std::list<RegionView*> _views; ///< all views that are being dragged
158
159 private:
160         void region_going_away (RegionView *);
161 };
162
163
164 /** Drags to move regions */
165 class RegionMoveDrag : public RegionDrag
166 {
167 public:
168         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
169         virtual ~RegionMoveDrag () {}
170
171         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
172         virtual void motion (GdkEvent *);
173         virtual void finished (GdkEvent *);
174
175 protected:
176
177         bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
178
179         TimeAxisView* _dest_trackview;
180         ARDOUR::layer_t _dest_layer;
181
182 private:
183
184         void copy_regions (GdkEvent *);
185         bool y_movement_disallowed (int, int, int, int, int, std::bitset<512> const &, std::vector<int32_t> const &) const;
186
187         bool _brushing;
188 };
189
190 /** Region drag in splice mode */
191 class RegionSpliceDrag : public RegionMoveDrag
192 {
193 public:
194         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
195
196         void motion (GdkEvent *);
197         void finished (GdkEvent *);
198 };
199
200 /** Drags to create regions */
201 class RegionCreateDrag : public Drag
202 {
203 public:
204         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
205
206         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
207         void motion (GdkEvent *);
208         void finished (GdkEvent *);
209
210 private:
211         TimeAxisView* _view;
212         TimeAxisView* _dest_trackview;
213 };
214
215 /** Drag of region gain */
216 class RegionGainDrag : public Drag
217 {
218 public:
219         RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
220
221         void motion (GdkEvent *);
222         void finished (GdkEvent *);
223         bool active (Editing::MouseMode m) {
224                 return (m == Editing::MouseGain);
225         }
226 };
227
228 /** Drag to trim region(s) */
229 class TrimDrag : public RegionDrag
230 {
231 public:
232         enum Operation {
233                 StartTrim,
234                 EndTrim,
235                 ContentsTrim,
236         };
237
238         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
239
240         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
241         void motion (GdkEvent *);
242         void finished (GdkEvent *);
243
244 private:
245
246         Operation _operation;
247 };
248
249 /** Meter marker drag */
250 class MeterMarkerDrag : public Drag
251 {
252 public:
253         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
254
255         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
256         void motion (GdkEvent *);
257         void finished (GdkEvent *);
258
259 private:
260         MeterMarker* _marker;
261 };
262
263 /** Tempo marker drag */
264 class TempoMarkerDrag : public Drag
265 {
266 public:
267         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
268
269         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
270         void motion (GdkEvent *);
271         void finished (GdkEvent *);
272
273 private:
274         TempoMarker* _marker;
275 };
276
277
278 /** Drag of a cursor */
279 class CursorDrag : public Drag
280 {
281 public:
282         CursorDrag (Editor *, ArdourCanvas::Item *, bool);
283
284         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
285         void motion (GdkEvent *);
286         void finished (GdkEvent *);
287
288 private:
289         EditorCursor* _cursor; ///< cursor being dragged
290         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
291         
292 };
293
294 /** Region fade-in drag */
295 class FadeInDrag : public RegionDrag
296 {
297 public:
298         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
299
300         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
301         void motion (GdkEvent *);
302         void finished (GdkEvent *);
303 };
304
305 /** Region fade-out drag */
306 class FadeOutDrag : public RegionDrag
307 {
308 public:
309         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
310
311         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
312         void motion (GdkEvent *);
313         void finished (GdkEvent *);
314 };
315
316 /** Marker drag */
317 class MarkerDrag : public Drag
318 {
319 public:
320         MarkerDrag (Editor *, ArdourCanvas::Item *);
321         ~MarkerDrag ();
322
323         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
324         void motion (GdkEvent *);
325         void finished (GdkEvent *);
326
327 private:
328         void update_item (ARDOUR::Location *);
329         
330         Marker* _marker; ///< marker being dragged
331         std::list<ARDOUR::Location*> _copied_locations;
332         ArdourCanvas::Line* _line;
333         ArdourCanvas::Points _points;
334 };
335
336 /** Control point drag */
337 class ControlPointDrag : public Drag
338 {
339 public:
340         ControlPointDrag (Editor *, ArdourCanvas::Item *);
341
342         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
343         void motion (GdkEvent *);
344         void finished (GdkEvent *);
345
346 private:
347         
348         ControlPoint* _point;
349         double _cumulative_x_drag;
350         double _cumulative_y_drag;
351         static double const _zero_gain_fraction;
352 };
353
354 /** Gain or automation line drag */
355 class LineDrag : public Drag
356 {
357 public:
358         LineDrag (Editor *e, ArdourCanvas::Item *i);
359
360         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
361         void motion (GdkEvent *);
362         void finished (GdkEvent *);
363
364 private:
365
366         AutomationLine* _line;
367         uint32_t _before;
368         uint32_t _after;
369         double _cumulative_y_drag;
370 };
371
372 /** Dragging of a rubberband rectangle for selecting things */
373 class RubberbandSelectDrag : public Drag
374 {
375 public:
376         RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
377
378         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
379         void motion (GdkEvent *);
380         void finished (GdkEvent *);
381 };
382
383 /** Region drag in time-FX mode */
384 class TimeFXDrag : public RegionDrag
385 {
386 public:
387         TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
388
389         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
390         void motion (GdkEvent *);
391         void finished (GdkEvent *);
392 };
393
394 /** Drag in range selection mode */
395 class SelectionDrag : public Drag
396 {
397 public:
398         enum Operation {
399                 CreateSelection,
400                 SelectionStartTrim,
401                 SelectionEndTrim,
402                 SelectionMove
403         };
404
405         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
406
407         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
408         void motion (GdkEvent *);
409         void finished (GdkEvent *);
410
411 private:
412         Operation _operation;
413 };
414
415 /** Range marker drag */
416 class RangeMarkerBarDrag : public Drag
417 {
418 public:
419         enum Operation {
420                 CreateRangeMarker,
421                 CreateTransportMarker,
422                 CreateCDMarker
423         };
424
425         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
426
427         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
428         void motion (GdkEvent *);
429         void finished (GdkEvent *);
430
431 private:
432         void update_item (ARDOUR::Location *);
433
434         Operation _operation;
435         ArdourCanvas::SimpleRect* _drag_rect;
436 };
437
438 /* Drag of rectangle to set zoom */
439 class MouseZoomDrag : public Drag
440 {
441 public:
442         MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
443
444         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
445         void motion (GdkEvent *);
446         void finished (GdkEvent *);
447 };
448
449 #endif /* __gtk2_ardour_editor_drag_h_ */
450