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