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