Merge branch 'pathscanner-refactor' of https://github.com/mojofunk/ardour into cairoc...
[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 "editor_items.h"
31
32 namespace ARDOUR {
33         class Location;
34 }
35
36 namespace PBD {
37         class StatefulDiffCommand;
38 }
39
40 class PatchChange;
41 class Editor;
42 class EditorCursor;
43 class TimeAxisView;
44 class MidiTimeAxisView;
45 class Drag;
46 class NoteBase;
47
48 /** Class to manage current drags */
49 class DragManager
50 {
51 public:
52
53         DragManager (Editor* e);
54         ~DragManager ();
55
56         bool motion_handler (GdkEvent *, bool);
57
58         void abort ();
59         void add (Drag *);
60         void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
61         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
62         bool end_grab (GdkEvent *);
63         bool have_item (ArdourCanvas::Item *) const;
64
65         void mark_double_click ();
66
67         /** @return true if an end drag or abort is in progress */
68         bool ending () const {
69                 return _ending;
70         }
71
72         bool active () const {
73                 return !_drags.empty ();
74         }
75
76         /** @return current pointer x position in canvas coordinates */
77         double current_pointer_x () const {
78                 return _current_pointer_x;
79         }
80
81         /** @return current pointer y position in canvas coordinates */
82         double current_pointer_y () const {
83                 return _current_pointer_y;
84         }
85
86         /** @return current pointer frame */
87         ARDOUR::framepos_t current_pointer_frame () const {
88                 return _current_pointer_frame;
89         }
90
91 private:
92         Editor* _editor;
93         std::list<Drag*> _drags;
94         bool _ending; ///< true if end_grab or abort is in progress, otherwise false
95         double _current_pointer_x; ///< canvas-coordinate space x of the current pointer
96         double _current_pointer_y; ///< canvas-coordinate space y of the current pointer
97         ARDOUR::framepos_t _current_pointer_frame; ///< frame that the pointer is now at
98         bool _old_follow_playhead; ///< state of Editor::follow_playhead() before the drags started
99 };
100
101 /** Abstract base class for dragging of things within the editor */
102 class Drag
103 {
104 public:
105         Drag (Editor *, ArdourCanvas::Item *, bool trackview_only = true);
106         virtual ~Drag () {}
107
108         void set_manager (DragManager* m) {
109                 _drags = m;
110         }
111
112         /** @return the canvas item being dragged */
113         ArdourCanvas::Item* item () const {
114                 return _item;
115         }
116
117         void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
118         bool motion_handler (GdkEvent*, bool);
119         void abort ();
120
121         ARDOUR::framepos_t adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
122         ARDOUR::framepos_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
123
124         bool was_double_click() const { return _was_double_click; }
125         void set_double_click (bool yn) { _was_double_click = yn; }
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          *  @param m true if some movement occurred, otherwise false.
150          */
151         virtual void aborted (bool m) = 0;
152
153         /** @param m Mouse mode.
154          *  @return true if this drag should happen in this mouse mode.
155          */
156         virtual bool active (Editing::MouseMode m) {
157                 return (m != Editing::MouseGain);
158         }
159
160         /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
161         virtual std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
162                 return std::make_pair (1, 1);
163         }
164
165         virtual bool allow_vertical_autoscroll () const {
166                 return true;
167         }
168
169         /** @return true if x movement matters to this drag */
170         virtual bool x_movement_matters () const {
171                 return true;
172         }
173
174         /** @return true if y movement matters to this drag */
175         virtual bool y_movement_matters () const {
176                 return true;
177         }
178
179         /** Set up the _pointer_frame_offset */
180         virtual void setup_pointer_frame_offset () {
181                 _pointer_frame_offset = 0;
182         }
183
184 protected:
185
186         double grab_x () const {
187                 return _grab_x;
188         }
189
190         double grab_y () const {
191                 return _grab_y;
192         }
193
194         ARDOUR::framepos_t raw_grab_frame () const {
195                 return _raw_grab_frame;
196         }
197
198         ARDOUR::framepos_t grab_frame () const {
199                 return _grab_frame;
200         }
201
202         double last_pointer_x () const {
203                 return _last_pointer_x;
204         }
205
206         double last_pointer_y () const {
207                 return _last_pointer_y;
208         }
209
210         double last_pointer_frame () const {
211                 return _last_pointer_frame;
212         }
213
214         double current_pointer_y () const;
215
216         boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*);
217
218         void show_verbose_cursor_time (framepos_t);
219         void show_verbose_cursor_duration (framepos_t, framepos_t, double xoffset = 0);
220         void show_verbose_cursor_text (std::string const &);
221
222         Editor* _editor; ///< our editor
223         DragManager* _drags;
224         ArdourCanvas::Item* _item; ///< our item
225         /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
226         ARDOUR::framecnt_t _pointer_frame_offset;
227         bool _x_constrained; ///< true if x motion is constrained, otherwise false
228         bool _y_constrained; ///< true if y motion is constrained, otherwise false
229         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
230
231 private:
232         bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group
233         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
234         bool _was_double_click; ///< true if drag initiated by a double click event
235         double _grab_x; ///< trackview x of the grab start position
236         double _grab_y; ///< y of the grab start position, possibly adjusted if _trackview_only is true
237         double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
238         double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
239         ARDOUR::framepos_t _raw_grab_frame; ///< unsnapped frame that the mouse was at when start_grab was called, or 0
240         ARDOUR::framepos_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
241         ARDOUR::framepos_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
242 };
243
244 class RegionDrag;
245
246 /** Container for details about a region being dragged */
247 class DraggingView
248 {
249 public:
250         DraggingView (RegionView *, RegionDrag *);
251
252         RegionView* view; ///< the view
253         /** index into RegionDrag::_time_axis_views of the view that this region is currently being displayed on,
254          *  or -1 if it is not visible.
255          */
256         int time_axis_view;
257         /** layer that this region is currently being displayed on.  This is a double
258             rather than a layer_t as we use fractional layers during drags to allow the user
259             to indicate a new layer to put a region on.
260         */
261         double layer;
262         double initial_y; ///< the initial y position of the view before any reparenting
263         framepos_t initial_position; ///< initial position of the region
264         framepos_t initial_end; ///< initial end position of the region
265         framepos_t anchored_fade_length; ///< fade_length when anchored during drag
266         boost::shared_ptr<ARDOUR::Playlist> initial_playlist;
267 };
268
269 /** Abstract base class for drags that involve region(s) */
270 class RegionDrag : public Drag, public sigc::trackable
271 {
272 public:
273         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
274         virtual ~RegionDrag () {}
275
276 protected:
277
278         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
279         std::list<DraggingView> _views; ///< information about all views that are being dragged
280
281         /** a list of the non-hidden TimeAxisViews sorted by editor order key */
282         std::vector<TimeAxisView*> _time_axis_views;
283         int find_time_axis_view (TimeAxisView *) const;
284
285         int _visible_y_low;
286         int _visible_y_high;
287
288         friend class DraggingView;
289
290 private:
291
292         void region_going_away (RegionView *);
293         PBD::ScopedConnection death_connection;
294 };
295
296
297 /** Drags involving region motion from somewhere */
298 class RegionMotionDrag : public RegionDrag
299 {
300 public:
301
302         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
303         virtual ~RegionMotionDrag () {}
304
305         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
306         virtual void motion (GdkEvent *, bool);
307         virtual void finished (GdkEvent *, bool);
308         virtual void aborted (bool);
309
310         /** @return true if the regions being `moved' came from somewhere on the canvas;
311          *  false if they came from outside (e.g. from the region list).
312          */
313         virtual bool regions_came_from_canvas () const = 0;
314
315 protected:
316
317         double compute_x_delta (GdkEvent const *, ARDOUR::framepos_t *);
318         bool y_movement_allowed (int, double) const;
319
320         bool _brushing;
321         ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
322         double _total_x_delta;
323         int _last_pointer_time_axis_view;
324         double _last_pointer_layer;
325 };
326
327
328 /** Drags to move (or copy) regions that are already shown in the GUI to
329  *  somewhere different.
330  */
331 class RegionMoveDrag : public RegionMotionDrag
332 {
333 public:
334         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
335         virtual ~RegionMoveDrag () {}
336
337         void motion (GdkEvent *, bool);
338         void finished (GdkEvent *, bool);
339         void aborted (bool);
340
341         bool regions_came_from_canvas () const {
342                 return true;
343         }
344
345         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
346                 return std::make_pair (4, 4);
347         }
348
349         void setup_pointer_frame_offset ();
350
351 private:
352         typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
353
354         void finished_no_copy (
355                 bool const,
356                 bool const,
357                 ARDOUR::framecnt_t const
358                 );
359
360         void finished_copy (
361                 bool const,
362                 bool const,
363                 ARDOUR::framecnt_t const
364                 );
365
366         RegionView* insert_region_into_playlist (
367                 boost::shared_ptr<ARDOUR::Region>,
368                 RouteTimeAxisView*,
369                 ARDOUR::layer_t,
370                 ARDOUR::framecnt_t,
371                 PlaylistSet&
372                 );
373
374         void remove_region_from_playlist (
375                 boost::shared_ptr<ARDOUR::Region>,
376                 boost::shared_ptr<ARDOUR::Playlist>,
377                 PlaylistSet& modified_playlists
378                 );
379
380         void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
381
382         void collect_new_region_view (RegionView *);
383         RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>);
384
385         bool _copy;
386         RegionView* _new_region_view;
387 };
388
389 /** Drag to insert a region from somewhere */
390 class RegionInsertDrag : public RegionMotionDrag
391 {
392 public:
393         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, ARDOUR::framepos_t);
394
395         void finished (GdkEvent *, bool);
396         void aborted (bool);
397
398         bool regions_came_from_canvas () const {
399                 return false;
400         }
401 };
402
403 /** Region drag in splice mode */
404 class RegionSpliceDrag : public RegionMoveDrag
405 {
406 public:
407         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
408
409         void motion (GdkEvent *, bool);
410         void finished (GdkEvent *, bool);
411         void aborted (bool);
412 };
413
414 /** Drags to create regions */
415 class RegionCreateDrag : public Drag
416 {
417 public:
418         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
419
420         void motion (GdkEvent *, bool);
421         void finished (GdkEvent *, bool);
422         void aborted (bool);
423
424 private:
425         MidiTimeAxisView* _view;
426         boost::shared_ptr<ARDOUR::Region> _region;
427 };
428
429 /** Drags to resize MIDI notes */
430 class NoteResizeDrag : public Drag
431 {
432 public:
433         NoteResizeDrag (Editor *, ArdourCanvas::Item *);
434
435         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
436         void motion (GdkEvent *, bool);
437         void finished (GdkEvent *, bool);
438         void aborted (bool);
439
440 private:
441         MidiRegionView*     region;
442         bool                relative;
443         bool                at_front;
444 };
445
446 /** Drags to move MIDI notes */
447 class NoteDrag : public Drag
448 {
449   public:
450         NoteDrag (Editor*, ArdourCanvas::Item*);
451
452         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
453         void motion (GdkEvent *, bool);
454         void finished (GdkEvent *, bool);
455         void aborted (bool);
456
457   private:
458
459         ARDOUR::frameoffset_t total_dx () const;
460         int8_t total_dy () const;
461
462         MidiRegionView* _region;
463         NoteBase* _primary;
464         double _cumulative_dx;
465         double _cumulative_dy;
466         bool _was_selected;
467         double _note_height;
468 };
469
470 class NoteCreateDrag : public Drag
471 {
472 public:
473         NoteCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
474         ~NoteCreateDrag ();
475
476         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
477         void motion (GdkEvent *, bool);
478         void finished (GdkEvent *, bool);
479         void aborted (bool);
480
481 private:
482         double y_to_region (double) const;
483         framecnt_t grid_frames (framepos_t) const;
484         
485         MidiRegionView* _region_view;
486         ArdourCanvas::Rectangle* _drag_rect;
487         framepos_t _note[2];
488 };
489
490 /** Drag to move MIDI patch changes */
491 class PatchChangeDrag : public Drag
492 {
493 public:
494         PatchChangeDrag (Editor *, PatchChange *, MidiRegionView *);
495
496         void motion (GdkEvent *, bool);
497         void finished (GdkEvent *, bool);
498         void aborted (bool);
499
500         bool y_movement_matters () const {
501                 return false;
502         }
503
504         void setup_pointer_frame_offset ();
505
506 private:
507         MidiRegionView* _region_view;
508         PatchChange* _patch_change;
509         double _cumulative_dx;
510 };
511
512 /** Container for details about audio regions being dragged along with video */
513 class AVDraggingView
514 {
515 public:
516         AVDraggingView (RegionView *);
517
518         RegionView* view; ///< the view
519         framepos_t initial_position; ///< initial position of the region
520 };
521
522 /** Drag of video offset */
523 class VideoTimeLineDrag : public Drag
524 {
525 public:
526         VideoTimeLineDrag (Editor *e, ArdourCanvas::Item *i);
527
528         void motion (GdkEvent *, bool);
529         void finished (GdkEvent *, bool);
530         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
531
532         bool y_movement_matters () const {
533                 return false;
534         }
535
536         bool allow_vertical_autoscroll () const {
537                 return false;
538         }
539
540         void aborted (bool);
541
542 protected:
543         std::list<AVDraggingView> _views; ///< information about all audio that are being dragged along
544
545 private:
546         ARDOUR::frameoffset_t _startdrag_video_offset;
547         ARDOUR::frameoffset_t _max_backwards_drag;
548 };
549
550 /** Drag to trim region(s) */
551 class TrimDrag : public RegionDrag
552 {
553 public:
554         enum Operation {
555                 StartTrim,
556                 EndTrim,
557                 ContentsTrim,
558         };
559
560         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, bool preserve_fade_anchor = false);
561
562         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
563         void motion (GdkEvent *, bool);
564         void finished (GdkEvent *, bool);
565         void aborted (bool);
566
567         bool y_movement_matters () const {
568                 return false;
569         }
570
571         void setup_pointer_frame_offset ();
572
573 private:
574
575         Operation _operation;
576         
577         bool _preserve_fade_anchor;
578         bool _jump_position_when_done;
579 };
580
581 /** Meter marker drag */
582 class MeterMarkerDrag : public Drag
583 {
584 public:
585         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
586
587         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
588         void motion (GdkEvent *, bool);
589         void finished (GdkEvent *, bool);
590         void aborted (bool);
591
592         bool allow_vertical_autoscroll () const {
593                 return false;
594         }
595
596         bool y_movement_matters () const {
597                 return false;
598         }
599
600         void setup_pointer_frame_offset ();
601
602 private:
603         MeterMarker* _marker;
604         bool _copy;
605         XMLNode* before_state;
606 };
607
608 /** Tempo marker drag */
609 class TempoMarkerDrag : public Drag
610 {
611 public:
612         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
613
614         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
615         void motion (GdkEvent *, bool);
616         void finished (GdkEvent *, bool);
617         void aborted (bool);
618
619         bool allow_vertical_autoscroll () const {
620                 return false;
621         }
622
623         bool y_movement_matters () const {
624                 return false;
625         }
626
627         void setup_pointer_frame_offset ();
628
629 private:
630         TempoMarker* _marker;
631         bool _copy;
632         XMLNode* before_state;
633 };
634
635
636 /** Drag of the playhead cursor */
637 class CursorDrag : public Drag
638 {
639 public:
640         CursorDrag (Editor *, EditorCursor&, bool);
641
642         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
643         void motion (GdkEvent *, bool);
644         void finished (GdkEvent *, bool);
645         void aborted (bool);
646
647         bool active (Editing::MouseMode) {
648                 return true;
649         }
650
651         bool allow_vertical_autoscroll () const {
652                 return false;
653         }
654
655         bool y_movement_matters () const {
656                 return true;
657         }
658
659 private:
660         void fake_locate (framepos_t);
661
662         EditorCursor& _cursor;
663         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
664         double _grab_zoom; ///< editor frames per unit when our grab started
665 };
666
667 /** Region fade-in drag */
668 class FadeInDrag : public RegionDrag
669 {
670 public:
671         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
672
673         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
674         void motion (GdkEvent *, bool);
675         void finished (GdkEvent *, bool);
676         void aborted (bool);
677
678         bool y_movement_matters () const {
679                 return false;
680         }
681
682         void setup_pointer_frame_offset ();
683 };
684
685 /** Region fade-out drag */
686 class FadeOutDrag : public RegionDrag
687 {
688 public:
689         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
690
691         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
692         void motion (GdkEvent *, bool);
693         void finished (GdkEvent *, bool);
694         void aborted (bool);
695
696         bool y_movement_matters () const {
697                 return false;
698         }
699
700         void setup_pointer_frame_offset ();
701 };
702
703 /** Marker drag */
704 class MarkerDrag : public Drag
705 {
706 public:
707         MarkerDrag (Editor *, ArdourCanvas::Item *);
708         ~MarkerDrag ();
709
710         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
711         void motion (GdkEvent *, bool);
712         void finished (GdkEvent *, bool);
713         void aborted (bool);
714
715         bool allow_vertical_autoscroll () const {
716                 return false;
717         }
718
719         bool y_movement_matters () const {
720                 return false;
721         }
722
723         void setup_pointer_frame_offset ();
724
725 private:
726         void update_item (ARDOUR::Location *);
727
728         Marker* _marker; ///< marker being dragged
729
730         struct CopiedLocationMarkerInfo {
731             ARDOUR::Location* location;
732             std::vector<Marker*> markers;
733             bool    move_both;
734             CopiedLocationMarkerInfo (ARDOUR::Location* l, Marker* m);
735         };
736
737         typedef std::list<CopiedLocationMarkerInfo> CopiedLocationInfo;
738         CopiedLocationInfo _copied_locations;
739         ArdourCanvas::Points _points;
740 };
741
742 /** Control point drag */
743 class ControlPointDrag : public Drag
744 {
745 public:
746         ControlPointDrag (Editor *, ArdourCanvas::Item *);
747
748         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
749         void motion (GdkEvent *, bool);
750         void finished (GdkEvent *, bool);
751         void aborted (bool);
752
753         bool active (Editing::MouseMode m);
754
755 private:
756
757         ControlPoint* _point;
758         double _fixed_grab_x;
759         double _fixed_grab_y;
760         double _cumulative_x_drag;
761         double _cumulative_y_drag;
762         bool     _pushing;
763         uint32_t _final_index;
764         static double _zero_gain_fraction;
765 };
766
767 /** Gain or automation line drag */
768 class LineDrag : public Drag
769 {
770 public:
771         LineDrag (Editor *e, ArdourCanvas::Item *i);
772
773         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
774         void motion (GdkEvent *, bool);
775         void finished (GdkEvent *, bool);
776         void aborted (bool);
777
778         bool active (Editing::MouseMode) {
779                 return true;
780         }
781
782 private:
783
784         AutomationLine* _line;
785         double _fixed_grab_x;
786         double _fixed_grab_y;
787         uint32_t _before;
788         uint32_t _after;
789         double _cumulative_y_drag;
790 };
791
792 /** Transient feature line drags*/
793 class FeatureLineDrag : public Drag
794 {
795 public:
796         FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
797
798         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
799         void motion (GdkEvent *, bool);
800         void finished (GdkEvent *, bool);
801         void aborted (bool);
802
803         bool active (Editing::MouseMode) {
804                 return true;
805         }
806
807 private:
808
809         ArdourCanvas::Line* _line;
810         AudioRegionView* _arv;
811
812         double _region_view_grab_x;
813         double _cumulative_x_drag;
814
815         float _before;
816         uint32_t _max_x;
817 };
818
819 /** Dragging of a rubberband rectangle for selecting things */
820 class RubberbandSelectDrag : public Drag
821 {
822 public:
823         RubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
824
825         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
826         void motion (GdkEvent *, bool);
827         void finished (GdkEvent *, bool);
828         void aborted (bool);
829
830         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
831                 return std::make_pair (8, 1);
832         }
833
834         void do_select_things (GdkEvent *, bool);
835
836         /** Select some things within a rectangle.
837          *  @param button_state The button state from the GdkEvent.
838          *  @param x1 The left-hand side of the rectangle in session frames.
839          *  @param x2 The right-hand side of the rectangle in session frames.
840          *  @param y1 The top of the rectangle in trackview coordinates.
841          *  @param y2 The bottom of the rectangle in trackview coordinates.
842          *  @param drag_in_progress true if the drag is currently happening.
843          */
844         virtual void select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress) = 0;
845         
846         virtual void deselect_things () = 0;
847
848   protected:
849         bool _vertical_only;
850 };
851
852 /** A general editor RubberbandSelectDrag (for regions, automation points etc.) */
853 class EditorRubberbandSelectDrag : public RubberbandSelectDrag
854 {
855 public:
856         EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
857
858         void select_things (int, framepos_t, framepos_t, double, double, bool);
859         void deselect_things ();
860 };
861
862 /** A RubberbandSelectDrag for selecting MIDI notes */
863 class MidiRubberbandSelectDrag : public RubberbandSelectDrag
864 {
865 public:
866         MidiRubberbandSelectDrag (Editor *, MidiRegionView *);
867
868         void select_things (int, framepos_t, framepos_t, double, double, bool);
869         void deselect_things ();
870
871 private:
872         MidiRegionView* _region_view;
873 };
874
875 /** A RubberbandSelectDrag for selecting MIDI notes but with no horizonal component */
876 class MidiVerticalSelectDrag : public RubberbandSelectDrag
877 {
878 public:
879         MidiVerticalSelectDrag (Editor *, MidiRegionView *);
880
881         void select_things (int, framepos_t, framepos_t, double, double, bool);
882         void deselect_things ();
883
884 private:
885         MidiRegionView* _region_view;
886 };
887
888 /** Region drag in time-FX mode */
889 class TimeFXDrag : public RegionDrag
890 {
891 public:
892         TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
893
894         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
895         void motion (GdkEvent *, bool);
896         void finished (GdkEvent *, bool);
897         void aborted (bool);
898 };
899
900 /** Scrub drag in audition mode */
901 class ScrubDrag : public Drag
902 {
903 public:
904         ScrubDrag (Editor *, ArdourCanvas::Item *);
905
906         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
907         void motion (GdkEvent *, bool);
908         void finished (GdkEvent *, bool);
909         void aborted (bool);
910 };
911
912 /** Drag in range select mode */
913 class SelectionDrag : public Drag
914 {
915 public:
916         enum Operation {
917                 CreateSelection,
918                 SelectionStartTrim,
919                 SelectionEndTrim,
920                 SelectionMove,
921                 SelectionExtend
922         };
923
924         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
925
926         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
927         void motion (GdkEvent *, bool);
928         void finished (GdkEvent *, bool);
929         void aborted (bool);
930
931         void setup_pointer_frame_offset ();
932
933 private:
934         Operation _operation;
935         bool _add;
936         bool _extend;
937         int _original_pointer_time_axis;
938         int _last_pointer_time_axis;
939         std::list<TimeAxisView*> _added_time_axes;
940         bool _time_selection_at_start;
941         framepos_t start_at_start;
942         framepos_t end_at_start;
943 };
944
945 /** Range marker drag */
946 class RangeMarkerBarDrag : public Drag
947 {
948 public:
949         enum Operation {
950                 CreateRangeMarker,
951                 CreateTransportMarker,
952                 CreateCDMarker
953         };
954
955         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
956
957         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
958         void motion (GdkEvent *, bool);
959         void finished (GdkEvent *, bool);
960         void aborted (bool);
961
962         bool allow_vertical_autoscroll () const {
963                 return false;
964         }
965
966         bool y_movement_matters () const {
967                 return false;
968         }
969
970 private:
971         void update_item (ARDOUR::Location *);
972
973         Operation _operation;
974         ArdourCanvas::Rectangle* _drag_rect;
975         bool _copy;
976 };
977
978 /** Drag of rectangle to set zoom */
979 class MouseZoomDrag : public Drag
980 {
981 public:
982         MouseZoomDrag (Editor *, ArdourCanvas::Item *);
983
984         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
985         void motion (GdkEvent *, bool);
986         void finished (GdkEvent *, bool);
987         void aborted (bool);
988
989         std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
990                 return std::make_pair (4, 4);
991         }
992
993 private:
994         bool _zoom_out;
995 };
996
997 /** Drag of a range of automation data (either on an automation track or region gain),
998  *  changing value but not position.
999  */
1000 class AutomationRangeDrag : public Drag
1001 {
1002 public:
1003         AutomationRangeDrag (Editor *, AutomationTimeAxisView *, std::list<ARDOUR::AudioRange> const &);
1004         AutomationRangeDrag (Editor *, AudioRegionView *, std::list<ARDOUR::AudioRange> const &);
1005
1006         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1007         void motion (GdkEvent *, bool);
1008         void finished (GdkEvent *, bool);
1009         void aborted (bool);
1010
1011         bool x_movement_matters () const {
1012                 return false;
1013         }
1014
1015         bool active (Editing::MouseMode) {
1016                 return true;
1017         }
1018
1019 private:
1020         void setup (std::list<boost::shared_ptr<AutomationLine> > const &);
1021         double y_fraction (boost::shared_ptr<AutomationLine>, double global_y_position) const;
1022
1023         std::list<ARDOUR::AudioRange> _ranges;
1024
1025         /** A line that is part of the drag */
1026         struct Line {
1027                 boost::shared_ptr<AutomationLine> line; ///< the line
1028                 std::list<ControlPoint*> points; ///< points to drag on the line
1029                 std::pair<ARDOUR::framepos_t, ARDOUR::framepos_t> range; ///< the range of all points on the line, in session frames
1030                 XMLNode* state; ///< the XML state node before the drag
1031                 double original_fraction; ///< initial y-fraction before the drag
1032         };
1033
1034         std::list<Line> _lines;
1035         double y_origin;
1036         bool _nothing_to_drag;
1037 };
1038
1039 /** Drag of one edge of an xfade
1040  */
1041 class CrossfadeEdgeDrag : public Drag
1042 {
1043   public:
1044         CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
1045
1046         void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
1047         void motion (GdkEvent*, bool);
1048         void finished (GdkEvent*, bool);
1049         void aborted (bool);
1050         
1051         bool y_movement_matters () const {
1052                 return false;
1053         }
1054
1055         virtual std::pair<ARDOUR::framecnt_t, int> move_threshold () const {
1056                 return std::make_pair (4, 4);
1057         }
1058
1059   private:
1060         AudioRegionView* arv;
1061         bool start;
1062 };
1063
1064 #endif /* __gtk2_ardour_editor_drag_h_ */
1065