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