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