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