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