d4cd5a6a9dbe343de802f93d40c8b6ed340f78a5
[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 namespace PBD {
38         class StatefulDiffCommand;
39 }
40
41 namespace Gnome {
42         namespace Canvas {
43                 class CanvasNoteEvent;
44                 class CanvasPatchChange;
45         }
46 }
47
48 class Editor;
49 class EditorCursor;
50 class TimeAxisView;
51 class MidiTimeAxisView;
52 class Drag;
53
54 /** Class to manage current drags */
55 class DragManager
56 {
57 public:
58
59         DragManager (Editor* e);
60         ~DragManager ();
61
62         bool motion_handler (GdkEvent *, bool);
63
64         void abort ();
65         void add (Drag *);
66         void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
67         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
68         bool end_grab (GdkEvent *);
69         bool have_item (ArdourCanvas::Item *) const;
70
71         /** @return true if an end drag or abort is in progress */
72         bool ending () const {
73                 return _ending;
74         }
75
76         bool active () const {
77                 return !_drags.empty ();
78         }
79
80         /** @return current pointer x position in trackview coordinates */
81         double current_pointer_x () const {
82                 return _current_pointer_x;
83         }
84
85         /** @return current pointer y position in trackview coordinates */
86         double current_pointer_y () const {
87                 return _current_pointer_y;
88         }
89
90         /** @return current pointer frame */
91         ARDOUR::framepos_t current_pointer_frame () const {
92                 return _current_pointer_frame;
93         }
94
95 private:
96         Editor* _editor;
97         std::list<Drag*> _drags;
98         bool _ending; ///< true if end_grab or abort is in progress, otherwise false
99         double _current_pointer_x; ///< trackview x of the current pointer
100         double _current_pointer_y; ///< trackview y of the current pointer
101         ARDOUR::framepos_t _current_pointer_frame; ///< frame that the pointer is now at
102         bool _old_follow_playhead; ///< state of Editor::follow_playhead() before the drags started
103 };
104
105 /** Abstract base class for dragging of things within the editor */
106 class Drag
107 {
108 public:
109         Drag (Editor *, ArdourCanvas::Item *);
110         virtual ~Drag () {}
111
112         void set_manager (DragManager* m) {
113                 _drags = m;
114         }
115
116         /** @return the canvas item being dragged */
117         ArdourCanvas::Item* item () const {
118                 return _item;
119         }
120
121         void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
122         bool motion_handler (GdkEvent*, bool);
123         void abort ();
124
125         ARDOUR::framepos_t adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
126         ARDOUR::framepos_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
127
128         /** Called to start a grab of an item.
129          *  @param e Event that caused the grab to start.
130          *  @param c Cursor to use, or 0.
131          */
132         virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
133
134         virtual bool end_grab (GdkEvent *);
135
136         /** Called when a drag motion has occurred.
137          *  @param e Event describing the motion.
138          *  @param f true if this is the first movement, otherwise false.
139          */
140         virtual void motion (GdkEvent* e, bool f) = 0;
141
142         /** Called when a drag has finished.
143          *  @param e Event describing the finish.
144          *  @param m true if some movement occurred, otherwise false.
145          */
146         virtual void finished (GdkEvent* e, bool m) = 0;
147
148         /** Called to abort a drag and return things to how
149          *  they were before it started.
150          *  @param m true if some movement occurred, otherwise false.
151          */
152         virtual void aborted (bool m) = 0;
153
154         /** @param m Mouse mode.
155          *  @return true if this drag should happen in this mouse mode.
156          */
157         virtual bool active (Editing::MouseMode m) {
158                 return (m != Editing::MouseGain);
159         }
160
161         /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
162         virtual std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
163                 return std::make_pair (1, 1);
164         }
165
166         virtual bool allow_vertical_autoscroll () const {
167                 return true;
168         }
169
170         /** @return true if x movement matters to this drag */
171         virtual bool x_movement_matters () const {
172                 return true;
173         }
174
175         /** @return true if y movement matters to this drag */
176         virtual bool y_movement_matters () const {
177                 return true;
178         }
179
180         /** Set up the _pointer_frame_offset */
181         virtual void setup_pointer_frame_offset () {
182                 _pointer_frame_offset = 0;
183         }
184
185 protected:
186
187         double grab_x () const {
188                 return _grab_x;
189         }
190
191         double grab_y () const {
192                 return _grab_y;
193         }
194
195         ARDOUR::framepos_t raw_grab_frame () const {
196                 return _raw_grab_frame;
197         }
198
199         ARDOUR::framepos_t grab_frame () const {
200                 return _grab_frame;
201         }
202
203         double last_pointer_x () const {
204                 return _last_pointer_x;
205         }
206
207         double last_pointer_y () const {
208                 return _last_pointer_y;
209         }
210
211         double last_pointer_frame () const {
212                 return _last_pointer_frame;
213         }
214
215         void show_verbose_cursor_time (framepos_t);
216         void show_verbose_cursor_duration (framepos_t, framepos_t, double xoffset = 0);
217         void show_verbose_cursor_text (std::string const &);
218
219         Editor* _editor; ///< our editor
220         DragManager* _drags;
221         ArdourCanvas::Item* _item; ///< our item
222         /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
223         ARDOUR::framecnt_t _pointer_frame_offset;
224         bool _x_constrained; ///< true if x motion is constrained, otherwise false
225         bool _y_constrained; ///< true if y motion is constrained, otherwise false
226         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
227
228 private:
229
230         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
231         double _grab_x; ///< trackview x of the grab start position
232         double _grab_y; ///< trackview y of the grab start position
233         double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
234         double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
235         ARDOUR::framepos_t _raw_grab_frame; ///< unsnapped frame that the mouse was at when start_grab was called, or 0
236         ARDOUR::framepos_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
237         ARDOUR::framepos_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
238 };
239
240 class RegionDrag;
241
242 /** Container for details about a region being dragged */
243 struct DraggingView
244 {
245         DraggingView (RegionView *, RegionDrag *);
246
247         RegionView* view; ///< the view
248         /** index into RegionDrag::_time_axis_views of the view that this region is currently beind displayed on */
249         int time_axis_view;
250         /** layer that this region is currently being displayed on */
251         ARDOUR::layer_t layer;
252         double initial_y; ///< the initial y position of the view before any reparenting
253         framepos_t initial_position; ///< initial position of the region
254         framepos_t initial_end; ///< initial end position of the region
255         boost::shared_ptr<ARDOUR::Playlist> initial_playlist;
256 };
257
258 /** Abstract base class for drags that involve region(s) */
259 class RegionDrag : public Drag, public sigc::trackable
260 {
261 public:
262         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
263         virtual ~RegionDrag () {}
264
265 protected:
266
267         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
268         std::list<DraggingView> _views; ///< information about all views that are being dragged
269
270         /** a list of the non-hidden TimeAxisViews sorted by editor order key */
271         std::vector<TimeAxisView*> _time_axis_views;
272         int find_time_axis_view (TimeAxisView *) const;
273
274         int _visible_y_low;
275         int _visible_y_high;
276
277         friend class DraggingView;
278
279 private:
280
281         void region_going_away (RegionView *);
282         PBD::ScopedConnection death_connection;
283 };
284
285
286 /** Drags involving region motion from somewhere */
287 class RegionMotionDrag : public RegionDrag
288 {
289 public:
290
291         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
292         virtual ~RegionMotionDrag () {}
293
294         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
295         virtual void motion (GdkEvent *, bool);
296         virtual void finished (GdkEvent *, bool) = 0;
297         virtual void aborted (bool);
298
299         /** @return true if the regions being `moved' came from somewhere on the canvas;
300          *  false if they came from outside (e.g. from the region list).
301          */
302         virtual bool regions_came_from_canvas () const = 0;
303
304 protected:
305
306         double compute_x_delta (GdkEvent const *, ARDOUR::framecnt_t *);
307         bool y_movement_allowed (int, ARDOUR::layer_t) const;
308
309         bool _brushing;
310         ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
311         double _total_x_delta;
312         int _last_pointer_time_axis_view;
313         ARDOUR::layer_t _last_pointer_layer;
314 };
315
316
317 /** Drags to move (or copy) regions that are already shown in the GUI to
318  *  somewhere different.
319  */
320 class RegionMoveDrag : public RegionMotionDrag
321 {
322 public:
323         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
324         virtual ~RegionMoveDrag () {}
325
326         void motion (GdkEvent *, bool);
327         void finished (GdkEvent *, bool);
328         void aborted (bool);
329
330         bool regions_came_from_canvas () const {
331                 return true;
332         }
333
334         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
335                 return std::make_pair (4, 4);
336         }
337
338         void setup_pointer_frame_offset ();
339
340 private:
341         typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
342
343         void finished_no_copy (
344                 bool const,
345                 bool const,
346                 ARDOUR::framecnt_t const
347                 );
348
349         void finished_copy (
350                 bool const,
351                 bool const,
352                 ARDOUR::framecnt_t const
353                 );
354
355         RegionView* insert_region_into_playlist (
356                 boost::shared_ptr<ARDOUR::Region>,
357                 RouteTimeAxisView*,
358                 ARDOUR::layer_t,
359                 ARDOUR::framecnt_t,
360                 PlaylistSet&
361                 );
362
363         void remove_region_from_playlist (
364                 boost::shared_ptr<ARDOUR::Region>,
365                 boost::shared_ptr<ARDOUR::Playlist>,
366                 PlaylistSet& modified_playlists
367                 );
368
369         void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
370
371         void collect_new_region_view (RegionView *);
372
373         bool _copy;
374         RegionView* _new_region_view;
375 };
376
377 /** Drag to insert a region from somewhere */
378 class RegionInsertDrag : public RegionMotionDrag
379 {
380 public:
381         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, ARDOUR::framepos_t);
382
383         void finished (GdkEvent *, bool);
384         void aborted (bool);
385
386         bool regions_came_from_canvas () const {
387                 return false;
388         }
389 };
390
391 /** Region drag in splice mode */
392 class RegionSpliceDrag : public RegionMoveDrag
393 {
394 public:
395         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
396
397         void motion (GdkEvent *, bool);
398         void finished (GdkEvent *, bool);
399         void aborted (bool);
400 };
401
402 /** Drags to create regions */
403 class RegionCreateDrag : public Drag
404 {
405 public:
406         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
407
408         void motion (GdkEvent *, bool);
409         void finished (GdkEvent *, bool);
410         void aborted (bool);
411
412 private:
413         MidiTimeAxisView* _view;
414         boost::shared_ptr<ARDOUR::Region> _region;
415         void add_region ();
416 };
417
418 /** Drags to resize MIDI notes */
419 class NoteResizeDrag : public Drag
420 {
421 public:
422         NoteResizeDrag (Editor *, ArdourCanvas::Item *);
423
424         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
425         void motion (GdkEvent *, bool);
426         void finished (GdkEvent *, bool);
427         void aborted (bool);
428
429 private:
430         MidiRegionView*     region;
431         bool                relative;
432         bool                at_front;
433 };
434
435 /** Drags to move MIDI notes */
436 class NoteDrag : public Drag
437 {
438   public:
439         NoteDrag (Editor*, ArdourCanvas::Item*);
440
441         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
442         void motion (GdkEvent *, bool);
443         void finished (GdkEvent *, bool);
444         void aborted (bool);
445
446   private:
447
448         ARDOUR::frameoffset_t total_dx () const;
449         int8_t total_dy () const;
450
451         MidiRegionView* _region;
452         Gnome::Canvas::CanvasNoteEvent* _primary;
453         double _cumulative_dx;
454         double _cumulative_dy;
455         bool _was_selected;
456         double _note_height;
457 };
458
459 /** Drag to move MIDI patch changes */
460 class PatchChangeDrag : public Drag
461 {
462 public:
463         PatchChangeDrag (Editor *, ArdourCanvas::CanvasPatchChange *, MidiRegionView *);
464
465         void motion (GdkEvent *, bool);
466         void finished (GdkEvent *, bool);
467         void aborted (bool);
468
469         bool y_movement_matters () const {
470                 return false;
471         }
472
473         void setup_pointer_frame_offset ();
474
475 private:
476         MidiRegionView* _region_view;
477         ArdourCanvas::CanvasPatchChange* _patch_change;
478         double _cumulative_dx;
479 };
480
481 /** Drag of region gain */
482 class RegionGainDrag : public Drag
483 {
484 public:
485         RegionGainDrag (Editor *, ArdourCanvas::Item *);
486
487         void motion (GdkEvent *, bool);
488         void finished (GdkEvent *, bool);
489         bool active (Editing::MouseMode m) {
490                 return (m == Editing::MouseGain);
491         }
492
493         void aborted (bool);
494 };
495
496 /** Drag to trim region(s) */
497 class TrimDrag : public RegionDrag
498 {
499 public:
500         enum Operation {
501                 StartTrim,
502                 EndTrim,
503                 ContentsTrim,
504         };
505
506         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
507
508         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
509         void motion (GdkEvent *, bool);
510         void finished (GdkEvent *, bool);
511         void aborted (bool);
512
513         bool y_movement_matters () const {
514                 return false;
515         }
516
517         void setup_pointer_frame_offset ();
518
519 private:
520
521         Operation _operation;
522 };
523
524 /** Meter marker drag */
525 class MeterMarkerDrag : public Drag
526 {
527 public:
528         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
529
530         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
531         void motion (GdkEvent *, bool);
532         void finished (GdkEvent *, bool);
533         void aborted (bool);
534
535         bool allow_vertical_autoscroll () const {
536                 return false;
537         }
538
539         bool y_movement_matters () const {
540                 return false;
541         }
542
543         void setup_pointer_frame_offset ();
544
545 private:
546         MeterMarker* _marker;
547         bool _copy;
548 };
549
550 /** Tempo marker drag */
551 class TempoMarkerDrag : public Drag
552 {
553 public:
554         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
555
556         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
557         void motion (GdkEvent *, bool);
558         void finished (GdkEvent *, bool);
559         void aborted (bool);
560
561         bool allow_vertical_autoscroll () const {
562                 return false;
563         }
564
565         bool y_movement_matters () const {
566                 return false;
567         }
568
569         void setup_pointer_frame_offset ();
570
571 private:
572         TempoMarker* _marker;
573         bool _copy;
574 };
575
576
577 /** Drag of the playhead cursor */
578 class CursorDrag : public Drag
579 {
580 public:
581         CursorDrag (Editor *, ArdourCanvas::Item *, bool);
582
583         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
584         void motion (GdkEvent *, bool);
585         void finished (GdkEvent *, bool);
586         void aborted (bool);
587
588         bool active (Editing::MouseMode) {
589                 return true;
590         }
591
592         bool allow_vertical_autoscroll () const {
593                 return false;
594         }
595
596         bool y_movement_matters () const {
597                 return true;
598         }
599
600 private:
601         void fake_locate (framepos_t);
602
603         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
604         double _grab_zoom; ///< editor frames per unit when our grab started
605 };
606
607 /** Region fade-in drag */
608 class FadeInDrag : public RegionDrag
609 {
610 public:
611         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
612
613         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
614         void motion (GdkEvent *, bool);
615         void finished (GdkEvent *, bool);
616         void aborted (bool);
617
618         bool y_movement_matters () const {
619                 return false;
620         }
621
622         void setup_pointer_frame_offset ();
623 };
624
625 /** Region fade-out drag */
626 class FadeOutDrag : public RegionDrag
627 {
628 public:
629         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
630
631         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
632         void motion (GdkEvent *, bool);
633         void finished (GdkEvent *, bool);
634         void aborted (bool);
635
636         bool y_movement_matters () const {
637                 return false;
638         }
639
640         void setup_pointer_frame_offset ();
641 };
642
643 /** Marker drag */
644 class MarkerDrag : public Drag
645 {
646 public:
647         MarkerDrag (Editor *, ArdourCanvas::Item *);
648         ~MarkerDrag ();
649
650         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
651         void motion (GdkEvent *, bool);
652         void finished (GdkEvent *, bool);
653         void aborted (bool);
654
655         bool allow_vertical_autoscroll () const {
656                 return false;
657         }
658
659         bool y_movement_matters () const {
660                 return false;
661         }
662
663         void setup_pointer_frame_offset ();
664
665 private:
666         void update_item (ARDOUR::Location *);
667
668         Marker* _marker; ///< marker being dragged
669         std::list<ARDOUR::Location*> _copied_locations;
670         ArdourCanvas::Points _points;
671 };
672
673 /** Control point drag */
674 class ControlPointDrag : public Drag
675 {
676 public:
677         ControlPointDrag (Editor *, ArdourCanvas::Item *);
678
679         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
680         void motion (GdkEvent *, bool);
681         void finished (GdkEvent *, bool);
682         void aborted (bool);
683
684         bool active (Editing::MouseMode m);
685
686 private:
687
688         ControlPoint* _point;
689         double _fixed_grab_x;
690         double _fixed_grab_y;
691         double _cumulative_x_drag;
692         double _cumulative_y_drag;
693         static double _zero_gain_fraction;
694 };
695
696 /** Gain or automation line drag */
697 class LineDrag : public Drag
698 {
699 public:
700         LineDrag (Editor *e, ArdourCanvas::Item *i);
701
702         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
703         void motion (GdkEvent *, bool);
704         void finished (GdkEvent *, bool);
705         void aborted (bool);
706
707         bool active (Editing::MouseMode) {
708                 return true;
709         }
710
711 private:
712
713         AutomationLine* _line;
714         double _fixed_grab_x;
715         double _fixed_grab_y;
716         uint32_t _before;
717         uint32_t _after;
718         double _cumulative_y_drag;
719 };
720
721 /** Transient feature line drags*/
722 class FeatureLineDrag : public Drag
723 {
724 public:
725         FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
726
727         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
728         void motion (GdkEvent *, bool);
729         void finished (GdkEvent *, bool);
730         void aborted (bool);
731
732         bool active (Editing::MouseMode) {
733                 return true;
734         }
735
736 private:
737
738         ArdourCanvas::Line* _line;
739         AudioRegionView* _arv;
740
741         double _region_view_grab_x;
742         double _cumulative_x_drag;
743
744         float _before;
745         uint32_t _max_x;
746 };
747
748 /** Dragging of a rubberband rectangle for selecting things */
749 class RubberbandSelectDrag : public Drag
750 {
751 public:
752         RubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
753
754         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
755         void motion (GdkEvent *, bool);
756         void finished (GdkEvent *, bool);
757         void aborted (bool);
758
759         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
760                 return std::make_pair (8, 1);
761         }
762 };
763
764 /** Region drag in time-FX mode */
765 class TimeFXDrag : public RegionDrag
766 {
767 public:
768         TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
769
770         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
771         void motion (GdkEvent *, bool);
772         void finished (GdkEvent *, bool);
773         void aborted (bool);
774 };
775
776 /** Scrub drag in audition mode */
777 class ScrubDrag : public Drag
778 {
779 public:
780         ScrubDrag (Editor *, ArdourCanvas::Item *);
781
782         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
783         void motion (GdkEvent *, bool);
784         void finished (GdkEvent *, bool);
785         void aborted (bool);
786 };
787
788 /** Drag in range select mode */
789 class SelectionDrag : public Drag
790 {
791 public:
792         enum Operation {
793                 CreateSelection,
794                 SelectionStartTrim,
795                 SelectionEndTrim,
796                 SelectionMove
797         };
798
799         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
800
801         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
802         void motion (GdkEvent *, bool);
803         void finished (GdkEvent *, bool);
804         void aborted (bool);
805
806         void setup_pointer_frame_offset ();
807
808 private:
809         Operation _operation;
810         bool _copy;
811         int _original_pointer_time_axis;
812         int _last_pointer_time_axis;
813         std::list<TimeAxisView*> _added_time_axes;
814 };
815
816 /** Range marker drag */
817 class RangeMarkerBarDrag : public Drag
818 {
819 public:
820         enum Operation {
821                 CreateRangeMarker,
822                 CreateTransportMarker,
823                 CreateCDMarker
824         };
825
826         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
827
828         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
829         void motion (GdkEvent *, bool);
830         void finished (GdkEvent *, bool);
831         void aborted (bool);
832
833         bool allow_vertical_autoscroll () const {
834                 return false;
835         }
836
837         bool y_movement_matters () const {
838                 return false;
839         }
840
841 private:
842         void update_item (ARDOUR::Location *);
843
844         Operation _operation;
845         ArdourCanvas::SimpleRect* _drag_rect;
846         bool _copy;
847 };
848
849 /** Drag of rectangle to set zoom */
850 class MouseZoomDrag : public Drag
851 {
852 public:
853         MouseZoomDrag (Editor *, ArdourCanvas::Item *);
854
855         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
856         void motion (GdkEvent *, bool);
857         void finished (GdkEvent *, bool);
858         void aborted (bool);
859
860         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
861                 return std::make_pair (4, 4);
862         }
863
864 private:
865         bool _zoom_out;
866 };
867
868 /** Drag of a range of automation data, changing value but not position */
869 class AutomationRangeDrag : public Drag
870 {
871 public:
872         AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
873
874         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
875         void motion (GdkEvent *, bool);
876         void finished (GdkEvent *, bool);
877         void aborted (bool);
878
879         bool x_movement_matters () const {
880                 return false;
881         }
882
883 private:
884         std::list<ARDOUR::AudioRange> _ranges;
885         AutomationTimeAxisView* _atav;
886
887         /** A line that is part of the drag */
888         struct Line {
889                 boost::shared_ptr<AutomationLine> line; ///< the line
890                 std::list<ControlPoint*> points; ///< points to drag on the line
891                 std::pair<ARDOUR::framepos_t, ARDOUR::framepos_t> range; ///< the range of all points on the line, in session frames
892                 XMLNode* state; ///< the XML state node before the drag
893         };
894
895         std::list<Line> _lines;
896
897         bool _nothing_to_drag;
898 };
899
900 #endif /* __gtk2_ardour_editor_drag_h_ */
901