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