Update GPL boilerplate and (C)
[ardour.git] / gtk2_ardour / editor_drag.h
1 /*
2  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2009-2015 David Robillard <d@drobilla.net>
4  * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
6  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
8  * Copyright (C) 2015-2018 Ben Loftis <ben@harrisonconsoles.com>
9  * Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #ifndef __gtk2_ardour_editor_drag_h_
27 #define __gtk2_ardour_editor_drag_h_
28
29 #include <list>
30
31 #include <gdk/gdk.h>
32 #include <stdint.h>
33
34 #include "ardour/tempo.h"
35 #include "ardour/types.h"
36
37 #include "canvas/types.h"
38
39 #include "cursor_context.h"
40 #include "editor_items.h"
41 #include "mouse_cursors.h"
42 #include "editing.h"
43 #include "track_selection.h"
44
45 namespace ARDOUR {
46         class Location;
47         class TempoSection;
48 }
49
50 namespace ArdourCanvas {
51         class Item;
52         class Line;
53         class Rectangle;
54 }
55
56 namespace PBD {
57         class StatefulDiffCommand;
58 }
59
60 class PatchChange;
61 class Editor;
62 class EditorCursor;
63 class TimeAxisView;
64 class MidiTimeAxisView;
65 class Drag;
66 class NoteBase;
67 class RegionView;
68 class TimeAxisView;
69 class RouteTimeAxisView;
70 class RegionSelection;
71 class MidiRegionView;
72 class MeterMarker;
73 class ArdourMarker;
74 class TempoMarker;
75 class ControlPoint;
76 class AudioRegionView;
77 class AutomationLine;
78 class AutomationTimeAxisView;
79
80 /** Class to manage current drags */
81 class DragManager
82 {
83 public:
84
85         DragManager (Editor* e);
86         ~DragManager ();
87
88         bool motion_handler (GdkEvent *, bool);
89
90         void abort ();
91         void add (Drag *);
92         void set (Drag *, GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor());
93         void start_grab (GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor());
94         bool end_grab (GdkEvent *);
95         bool have_item (ArdourCanvas::Item *) const;
96
97         void mark_double_click ();
98
99         /** @return true if an end drag or abort is in progress */
100         bool ending () const {
101                 return _ending;
102         }
103
104         bool active () const {
105                 return !_drags.empty ();
106         }
107
108         /** @return current pointer x position in canvas coordinates */
109         double current_pointer_x () const {
110                 return _current_pointer_x;
111         }
112
113         /** @return current pointer y position in canvas coordinates */
114         double current_pointer_y () const {
115                 return _current_pointer_y;
116         }
117
118         /** @return current pointer sample */
119         ARDOUR::samplepos_t current_pointer_sample () const {
120                 return _current_pointer_sample;
121         }
122
123 private:
124         Editor* _editor;
125         std::list<Drag*> _drags;
126         bool _ending; ///< true if end_grab or abort is in progress, otherwise false
127         double _current_pointer_x; ///< canvas-coordinate space x of the current pointer
128         double _current_pointer_y; ///< canvas-coordinate space y of the current pointer
129         ARDOUR::samplepos_t _current_pointer_sample; ///< sample that the pointer is now at
130         bool _old_follow_playhead; ///< state of Editor::follow_playhead() before the drags started
131 };
132
133 /** Abstract base class for dragging of things within the editor */
134 class Drag
135 {
136 public:
137         Drag (Editor *, ArdourCanvas::Item *, bool trackview_only = true);
138         virtual ~Drag () {}
139
140         void set_manager (DragManager* m) {
141                 _drags = m;
142         }
143
144         /** @return the canvas item being dragged */
145         ArdourCanvas::Item* item () const {
146                 return _item;
147         }
148
149         void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
150         bool motion_handler (GdkEvent*, bool);
151         void abort ();
152
153         ARDOUR::MusicSample adjusted_sample (ARDOUR::samplepos_t, GdkEvent const *, bool snap = true) const;
154         ARDOUR::samplepos_t adjusted_current_sample (GdkEvent const *, bool snap = true) const;
155
156         bool was_double_click() const { return _was_double_click; }
157         void set_double_click (bool yn) { _was_double_click = yn; }
158
159         /** Called to start a grab of an item.
160          *  @param e Event that caused the grab to start.
161          *  @param c Cursor to use, or 0.
162          */
163         virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
164
165         virtual bool end_grab (GdkEvent *);
166
167         /** Called when a drag motion has occurred.
168          *  @param e Event describing the motion.
169          *  @param f true if this is the first movement, otherwise false.
170          */
171         virtual void motion (GdkEvent* e, bool f) = 0;
172
173         /** Called when a drag has finished.
174          *  @param e Event describing the finish.
175          *  @param m true if some movement occurred, otherwise false.
176          */
177         virtual void finished (GdkEvent* e, bool m) = 0;
178
179         /** Called to abort a drag and return things to how
180          *  they were before it started.
181          *  @param m true if some movement occurred, otherwise false.
182          */
183         virtual void aborted (bool m) = 0;
184
185         /** @param m Mouse mode.
186          *  @return true if this drag should happen in this mouse mode.
187          */
188         virtual bool active (Editing::MouseMode m) {
189                 return true;
190         }
191
192         /** @return minimum number of samples (in x) and pixels (in y) that should be considered a movement */
193         virtual std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
194                 return std::make_pair (1, 1);
195         }
196
197         virtual bool allow_vertical_autoscroll () const {
198                 return true;
199         }
200
201         /** @return true if x movement matters to this drag */
202         virtual bool x_movement_matters () const {
203                 return true;
204         }
205
206         /** @return true if y movement matters to this drag */
207         virtual bool y_movement_matters () const {
208                 return true;
209         }
210
211         bool initially_vertical() const {
212                 return _initially_vertical;
213         }
214
215         /** Set up the _pointer_sample_offset */
216         virtual void setup_pointer_sample_offset () {
217                 _pointer_sample_offset = 0;
218         }
219
220 protected:
221
222         double grab_x () const {
223                 return _grab_x;
224         }
225
226         double grab_y () const {
227                 return _grab_y;
228         }
229
230         ARDOUR::samplepos_t raw_grab_sample () const {
231                 return _raw_grab_sample;
232         }
233
234         ARDOUR::samplepos_t grab_sample () const {
235                 return _grab_sample;
236         }
237
238         double last_pointer_x () const {
239                 return _last_pointer_x;
240         }
241
242         double last_pointer_y () const {
243                 return _last_pointer_y;
244         }
245
246         ARDOUR::samplepos_t last_pointer_sample () const {
247                 return _last_pointer_sample;
248         }
249
250         ARDOUR::sampleoffset_t snap_delta (guint const) const;
251         double  snap_delta_music (guint const) const;
252
253         double current_pointer_x () const;
254         double current_pointer_y () const;
255
256         /* sets snap delta from unsnapped pos */
257         void setup_snap_delta (ARDOUR::MusicSample pos);
258
259         boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit);
260
261         void show_verbose_cursor_time (samplepos_t);
262         void show_verbose_cursor_duration (samplepos_t, samplepos_t, double xoffset = 0);
263         void show_verbose_cursor_text (std::string const &);
264
265         Editor* _editor; ///< our editor
266         DragManager* _drags;
267         ArdourCanvas::Item* _item; ///< our item
268         /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
269         ARDOUR::samplecnt_t _pointer_sample_offset;
270         bool _x_constrained; ///< true if x motion is constrained, otherwise false
271         bool _y_constrained; ///< true if y motion is constrained, otherwise false
272         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
273
274 private:
275         bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group
276         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
277         bool _starting_point_passed; ///< true if we called move () with first_move flag, otherwise false
278         bool _initially_vertical; ///< true if after move threshold is passed we appear to be moving vertically; undefined before that
279         bool _was_double_click; ///< true if drag initiated by a double click event
280         double _grab_x; ///< trackview x of the grab start position
281         double _grab_y; ///< y of the grab start position, possibly adjusted if _trackview_only is true
282         double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
283         double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
284         ARDOUR::samplepos_t _raw_grab_sample; ///< unsnapped sample that the mouse was at when start_grab was called, or 0
285         ARDOUR::samplepos_t _grab_sample; ///< adjusted_sample that the mouse was at when start_grab was called, or 0
286         ARDOUR::samplepos_t _last_pointer_sample; ///< adjusted_sample the last time a motion occurred
287
288         /* difference between some key position's snapped and unsnapped
289          *  samplepos. used for relative snap.
290          */
291         samplepos_t _snap_delta;
292         double      _snap_delta_music;
293         CursorContext::Handle _cursor_ctx; ///< cursor change context
294         bool _constraint_pressed; ///< if the keyboard indicated constraint modifier was pressed on start_grab()
295 };
296
297 class RegionDrag;
298
299 /** Container for details about a region being dragged */
300 class DraggingView
301 {
302 public:
303         DraggingView (RegionView *, RegionDrag *, TimeAxisView* original_tav);
304
305         RegionView* view; ///< the view
306         /** index into RegionDrag::_time_axis_views of the view that this region is currently being displayed on,
307          *  or -1 if it is not visible.
308          */
309         int time_axis_view;
310         /** layer that this region is currently being displayed on.  This is a double
311             rather than a layer_t as we use fractional layers during drags to allow the user
312             to indicate a new layer to put a region on.
313         */
314         double layer;
315         double initial_y; ///< the initial y position of the view before any reparenting
316         samplepos_t initial_position; ///< initial position of the region
317         samplepos_t initial_end; ///< initial end position of the region
318         samplepos_t anchored_fade_length; ///< fade_length when anchored during drag
319         boost::shared_ptr<ARDOUR::Playlist> initial_playlist;
320         TimeAxisView* initial_time_axis_view;
321 };
322
323 /** Abstract base class for drags that involve region(s) */
324 class RegionDrag : public Drag, public sigc::trackable
325 {
326 public:
327         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
328         virtual ~RegionDrag () {}
329
330 protected:
331
332         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
333         std::list<DraggingView> _views; ///< information about all views that are being dragged
334
335         /** a list of the non-hidden TimeAxisViews sorted by editor order key */
336         std::vector<TimeAxisView*> _time_axis_views;
337         int find_time_axis_view (TimeAxisView *) const;
338         int apply_track_delta (const int start, const int delta, const int skip, const bool distance_only = false) const;
339
340         int _visible_y_low;
341         int _visible_y_high;
342         uint32_t _ntracks;
343
344         friend class DraggingView;
345
346 private:
347
348         void region_going_away (RegionView *);
349         PBD::ScopedConnection death_connection;
350 };
351
352
353 /** Drags involving region motion from somewhere */
354 class RegionMotionDrag : public RegionDrag
355 {
356 public:
357
358         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
359         virtual ~RegionMotionDrag () {}
360
361         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
362         virtual void motion (GdkEvent *, bool);
363         virtual void finished (GdkEvent *, bool);
364         virtual void aborted (bool);
365
366         /** @return true if the regions being `moved' came from somewhere on the canvas;
367          *  false if they came from outside (e.g. from the region list).
368          */
369         virtual bool regions_came_from_canvas () const = 0;
370
371 protected:
372
373         double compute_x_delta (GdkEvent const *, ARDOUR::MusicSample *);
374         virtual bool y_movement_allowed (int, double, int skip_invisible = 0) const;
375
376         bool _brushing;
377         bool _ignore_video_lock;
378         ARDOUR::MusicSample _last_position; ///< last position of the thing being dragged
379         double _total_x_delta;
380         int _last_pointer_time_axis_view;
381         double _last_pointer_layer;
382 private:
383         uint32_t _ndropzone;
384         uint32_t _pdropzone;
385         uint32_t _ddropzone;
386 };
387
388
389 /** Drags to move (or copy) regions that are already shown in the GUI to
390  *  somewhere different.
391  */
392 class RegionMoveDrag : public RegionMotionDrag
393 {
394 public:
395         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
396         virtual ~RegionMoveDrag () {}
397
398         void motion (GdkEvent *, bool);
399         void finished (GdkEvent *, bool);
400         void aborted (bool);
401
402         bool regions_came_from_canvas () const {
403                 return true;
404         }
405
406         std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
407                 return std::make_pair (4, 4);
408         }
409
410         void setup_pointer_sample_offset ();
411
412 protected:
413         typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
414         void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
415
416 private:
417         void finished_no_copy (
418                 bool const,
419                 bool const,
420                 ARDOUR::MusicSample,
421                 int32_t const ev_state
422                 );
423
424         void finished_copy (
425                 bool const,
426                 bool const,
427                 ARDOUR::MusicSample,
428                 int32_t const ev_state
429                 );
430
431         RegionView* insert_region_into_playlist (
432                 boost::shared_ptr<ARDOUR::Region>,
433                 RouteTimeAxisView*,
434                 ARDOUR::layer_t,
435                 ARDOUR::MusicSample,
436                 double quarter_note,
437                 PlaylistSet&,
438                 bool for_music = false
439                 );
440
441         void remove_region_from_playlist (
442                 boost::shared_ptr<ARDOUR::Region>,
443                 boost::shared_ptr<ARDOUR::Playlist>,
444                 PlaylistSet& modified_playlists
445                 );
446
447
448         void collect_new_region_view (RegionView *);
449         RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>, TimeAxisView* original);
450
451         bool _copy;
452         RegionView* _new_region_view;
453 };
454
455 /** Drag to insert a region from somewhere */
456 class RegionInsertDrag : public RegionMotionDrag
457 {
458 public:
459         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, ARDOUR::samplepos_t);
460
461         void finished (GdkEvent *, bool);
462         void aborted (bool);
463
464         bool regions_came_from_canvas () const {
465                 return false;
466         }
467 };
468
469 /** Region drag in splice mode */
470 class RegionSpliceDrag : public RegionMoveDrag
471 {
472 public:
473         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
474
475         void motion (GdkEvent *, bool);
476         void finished (GdkEvent *, bool);
477         void aborted (bool);
478 };
479
480 /** Region drag in ripple mode */
481
482 class RegionRippleDrag : public RegionMoveDrag
483 {
484 public:
485         RegionRippleDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
486         ~RegionRippleDrag () { delete exclude; }
487
488         void motion (GdkEvent *, bool);
489         void finished (GdkEvent *, bool);
490         void aborted (bool);
491 protected:
492         bool y_movement_allowed (int delta_track, double delta_layer, int skip_invisible = 0) const;
493
494 private:
495         TimeAxisView *prev_tav; // where regions were most recently dragged from
496         TimeAxisView *orig_tav; // where drag started
497         ARDOUR::samplecnt_t prev_amount;
498         ARDOUR::samplepos_t prev_position;
499         ARDOUR::samplecnt_t selection_length;
500         bool allow_moves_across_tracks; // only if all selected regions are on one track
501         ARDOUR::RegionList *exclude;
502         void add_all_after_to_views (TimeAxisView *tav, ARDOUR::samplepos_t where, const RegionSelection &exclude, bool drag_in_progress);
503         void remove_unselected_from_views (ARDOUR::samplecnt_t amount, bool move_regions);
504
505 };
506
507 /** "Drag" to cut a region (action only on button release) */
508 class RegionCutDrag : public Drag
509 {
510 public:
511         RegionCutDrag (Editor*, ArdourCanvas::Item*, samplepos_t);
512         ~RegionCutDrag ();
513
514         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
515         void motion (GdkEvent*, bool);
516         void finished (GdkEvent*, bool);
517         void aborted (bool);
518
519 private:
520 };
521
522 /** Drags to create regions */
523 class RegionCreateDrag : public Drag
524 {
525 public:
526         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
527
528         void motion (GdkEvent *, bool);
529         void finished (GdkEvent *, bool);
530         void aborted (bool);
531
532 private:
533         MidiTimeAxisView* _view;
534         boost::shared_ptr<ARDOUR::Region> _region;
535 };
536
537 /** Drags to resize MIDI notes */
538 class NoteResizeDrag : public Drag
539 {
540 public:
541         NoteResizeDrag (Editor *, ArdourCanvas::Item *);
542
543         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
544         void motion (GdkEvent *, bool);
545         void finished (GdkEvent *, bool);
546         void aborted (bool);
547
548 private:
549         MidiRegionView*     region;
550         bool                relative;
551         bool                at_front;
552         bool                _was_selected;
553         double              _snap_delta;
554 };
555
556 /** Drags to move MIDI notes */
557 class NoteDrag : public Drag
558 {
559 public:
560         NoteDrag (Editor*, ArdourCanvas::Item*);
561
562         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
563         void motion (GdkEvent *, bool);
564         void finished (GdkEvent *, bool);
565         void aborted (bool);
566
567         void setup_pointer_sample_offset ();
568 private:
569
570         double total_dx (GdkEvent * event) const; // total movement in quarter notes
571         int8_t total_dy () const;
572
573         MidiRegionView* _region;
574         NoteBase* _primary;
575         double _cumulative_dx;
576         double _cumulative_dy;
577         double _earliest; // earliest quarter note in note selection
578         bool   _was_selected;
579         double _note_height;
580         bool   _copy;
581 };
582
583 class NoteCreateDrag : public Drag
584 {
585 public:
586         NoteCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
587         ~NoteCreateDrag ();
588
589         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
590         void motion (GdkEvent *, bool);
591         void finished (GdkEvent *, bool);
592         void aborted (bool);
593
594         bool active (Editing::MouseMode mode) {
595                 return mode == Editing::MouseDraw || mode == Editing::MouseContent;
596         }
597
598         bool y_movement_matters () const {
599                 return false;
600         }
601
602 private:
603         double y_to_region (double) const;
604         ARDOUR::samplecnt_t grid_samples (samplepos_t) const;
605
606         /** @return minimum number of samples (in x) and pixels (in y) that should be considered a movement */
607         virtual std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
608                 return std::make_pair (0, 0);
609         }
610
611         MidiRegionView* _region_view;
612         ArdourCanvas::Rectangle* _drag_rect;
613         samplepos_t _note[2];
614 };
615
616 class HitCreateDrag : public Drag
617 {
618 public:
619         HitCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
620         ~HitCreateDrag ();
621
622         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
623         void motion (GdkEvent *, bool);
624         void finished (GdkEvent *, bool);
625         void aborted (bool);
626
627         bool active (Editing::MouseMode mode) {
628                 return mode == Editing::MouseDraw || mode == Editing::MouseContent;
629         }
630
631         bool y_movement_matters () const {
632                 return false;
633         }
634
635 private:
636         double y_to_region (double) const;
637         ARDOUR::samplecnt_t grid_samples (samplepos_t) const;
638
639         /** @return minimum number of samples (in x) and pixels (in y) that should be considered a movement */
640         virtual std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
641                 return std::make_pair (0, 0);
642         }
643
644         MidiRegionView* _region_view;
645         samplepos_t     _last_pos;
646         double          _y;
647
648 };
649
650 /** Drag to move MIDI patch changes */
651 class PatchChangeDrag : public Drag
652 {
653 public:
654         PatchChangeDrag (Editor *, PatchChange *, MidiRegionView *);
655
656         void motion (GdkEvent *, bool);
657         void finished (GdkEvent *, bool);
658         void aborted (bool);
659
660         bool y_movement_matters () const {
661                 return false;
662         }
663
664         void setup_pointer_sample_offset ();
665
666 private:
667         MidiRegionView* _region_view;
668         PatchChange* _patch_change;
669         double _cumulative_dx;
670 };
671
672 /** Container for details about audio regions being dragged along with video */
673 class AVDraggingView
674 {
675 public:
676         AVDraggingView (RegionView *);
677
678         RegionView* view; ///< the view
679         samplepos_t initial_position; ///< initial position of the region
680 };
681
682 /** Drag of video offset */
683 class VideoTimeLineDrag : public Drag
684 {
685 public:
686         VideoTimeLineDrag (Editor *e, ArdourCanvas::Item *i);
687
688         void motion (GdkEvent *, bool);
689         void finished (GdkEvent *, bool);
690         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
691
692         bool y_movement_matters () const {
693                 return false;
694         }
695
696         bool allow_vertical_autoscroll () const {
697                 return false;
698         }
699
700         void aborted (bool);
701
702 protected:
703         std::list<AVDraggingView> _views; ///< information about all audio that are being dragged along
704
705 private:
706         ARDOUR::sampleoffset_t _startdrag_video_offset;
707         ARDOUR::sampleoffset_t _max_backwards_drag;
708         bool _stuck;
709 };
710
711 /** Drag to trim region(s) */
712 class TrimDrag : public RegionDrag
713 {
714 public:
715         enum Operation {
716                 StartTrim,
717                 EndTrim,
718                 ContentsTrim,
719         };
720
721         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, bool preserve_fade_anchor = false);
722
723         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
724         void motion (GdkEvent *, bool);
725         void finished (GdkEvent *, bool);
726         void aborted (bool);
727
728         bool y_movement_matters () const {
729                 return false;
730         }
731
732         void setup_pointer_sample_offset ();
733
734 private:
735
736         Operation _operation;
737
738         bool _preserve_fade_anchor;
739         bool _jump_position_when_done;
740 };
741
742 /** Meter marker drag */
743 class MeterMarkerDrag : public Drag
744 {
745 public:
746         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
747
748         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
749         void motion (GdkEvent *, bool);
750         void finished (GdkEvent *, bool);
751         void aborted (bool);
752
753         bool allow_vertical_autoscroll () const {
754                 return false;
755         }
756
757         bool y_movement_matters () const {
758                 return false;
759         }
760
761         void setup_pointer_sample_offset ();
762
763 private:
764         MeterMarker* _marker;
765         ARDOUR::MeterSection* _real_section;
766
767         bool _copy;
768         Editing::GridType _old_grid_type;
769         Editing::SnapMode _old_snap_mode;
770         XMLNode* before_state;
771 };
772
773 /** Tempo marker drag */
774 class TempoMarkerDrag : public Drag
775 {
776 public:
777         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
778
779         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
780         void motion (GdkEvent *, bool);
781         void finished (GdkEvent *, bool);
782         void aborted (bool);
783
784         bool allow_vertical_autoscroll () const {
785                 return false;
786         }
787
788         bool y_movement_matters () const {
789                 return true;
790         }
791
792         void setup_pointer_sample_offset ();
793
794 private:
795         TempoMarker* _marker;
796         ARDOUR::TempoSection* _real_section;
797
798         bool _copy;
799         bool _movable;
800         ARDOUR::Tempo _grab_bpm;
801         double _grab_qn;
802         XMLNode* _before_state;
803 };
804
805 /** BBT Ruler drag */
806 class BBTRulerDrag : public Drag
807 {
808 public:
809         BBTRulerDrag (Editor *, ArdourCanvas::Item *);
810
811         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
812         void motion (GdkEvent *, bool);
813         void finished (GdkEvent *, bool);
814         void aborted (bool);
815
816         bool allow_vertical_autoscroll () const {
817                 return false;
818         }
819
820         bool y_movement_matters () const {
821                 return false;
822         }
823
824         void setup_pointer_sample_offset ();
825
826 private:
827         double _grab_qn;
828         ARDOUR::TempoSection* _tempo;
829         XMLNode* _before_state;
830         bool     _drag_valid;
831 };
832
833 /** tempo curve twist drag */
834 class TempoTwistDrag : public Drag
835 {
836 public:
837         TempoTwistDrag (Editor *, ArdourCanvas::Item *);
838
839         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
840         void motion (GdkEvent *, bool);
841         void finished (GdkEvent *, bool);
842         void aborted (bool);
843
844         bool allow_vertical_autoscroll () const {
845                 return false;
846         }
847
848         bool y_movement_matters () const {
849                 return true;
850         }
851
852         void setup_pointer_sample_offset ();
853
854 private:
855         double _grab_qn;
856         ARDOUR::Tempo  _grab_tempo;
857         ARDOUR::TempoSection* _tempo;
858         ARDOUR::TempoSection* _next_tempo;
859         bool _drag_valid;
860         XMLNode* _before_state;
861 };
862
863
864 /** tempo curve twist drag */
865 class TempoEndDrag : public Drag
866 {
867 public:
868         TempoEndDrag (Editor *, ArdourCanvas::Item *);
869
870         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
871         void motion (GdkEvent *, bool);
872         void finished (GdkEvent *, bool);
873         void aborted (bool);
874
875         bool allow_vertical_autoscroll () const {
876                 return false;
877         }
878
879         bool y_movement_matters () const {
880                 return true;
881         }
882
883         void setup_pointer_sample_offset ();
884
885 private:
886         double _grab_qn;
887         ARDOUR::TempoSection* _tempo;
888         XMLNode* _before_state;
889         bool _drag_valid;
890 };
891
892 /** Drag of the playhead cursor */
893 class CursorDrag : public Drag
894 {
895 public:
896         CursorDrag (Editor *, EditorCursor&, bool);
897
898         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
899         void motion (GdkEvent *, bool);
900         void finished (GdkEvent *, bool);
901         void aborted (bool);
902
903         bool allow_vertical_autoscroll () const {
904                 return false;
905         }
906
907         bool y_movement_matters () const {
908                 return true;
909         }
910
911 private:
912         void fake_locate (samplepos_t);
913
914         EditorCursor& _cursor;
915         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
916         double _grab_zoom; ///< editor samples per unit when our grab started
917
918         //used for zooming
919         int _last_mx;
920         int _last_my;
921         int _last_dx;
922         int _last_y_delta;
923 };
924
925 /** Region fade-in drag */
926 class FadeInDrag : public RegionDrag
927 {
928 public:
929         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
930
931         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
932         void motion (GdkEvent *, bool);
933         void finished (GdkEvent *, bool);
934         void aborted (bool);
935
936         bool y_movement_matters () const {
937                 return false;
938         }
939
940         void setup_pointer_sample_offset ();
941 };
942
943 /** Region fade-out drag */
944 class FadeOutDrag : public RegionDrag
945 {
946 public:
947         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
948
949         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
950         void motion (GdkEvent *, bool);
951         void finished (GdkEvent *, bool);
952         void aborted (bool);
953
954         bool y_movement_matters () const {
955                 return false;
956         }
957
958         void setup_pointer_sample_offset ();
959 };
960
961 /** Marker drag */
962 class MarkerDrag : public Drag
963 {
964 public:
965         MarkerDrag (Editor *, ArdourCanvas::Item *);
966         ~MarkerDrag ();
967
968         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
969         void motion (GdkEvent *, bool);
970         void finished (GdkEvent *, bool);
971         void aborted (bool);
972
973         bool allow_vertical_autoscroll () const {
974                 return false;
975         }
976
977         bool y_movement_matters () const {
978                 return false;
979         }
980
981         void setup_pointer_sample_offset ();
982
983 private:
984         void update_item (ARDOUR::Location *);
985
986         ArdourMarker* _marker; ///< marker being dragged
987         bool _selection_changed;
988         struct CopiedLocationMarkerInfo {
989                 ARDOUR::Location* location;
990                 std::vector<ArdourMarker*> markers;
991                 bool    move_both;
992                 CopiedLocationMarkerInfo (ARDOUR::Location* l, ArdourMarker* m);
993         };
994
995         typedef std::list<CopiedLocationMarkerInfo> CopiedLocationInfo;
996         CopiedLocationInfo _copied_locations;
997         ArdourCanvas::Points _points;
998 };
999
1000 /** Control point drag */
1001 class ControlPointDrag : public Drag
1002 {
1003 public:
1004         ControlPointDrag (Editor *, ArdourCanvas::Item *);
1005
1006         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1007         void motion (GdkEvent *, bool);
1008         void finished (GdkEvent *, bool);
1009         void aborted (bool);
1010
1011         bool active (Editing::MouseMode m);
1012
1013 private:
1014
1015         ControlPoint* _point;
1016         double _fixed_grab_x;
1017         double _fixed_grab_y;
1018         double _cumulative_x_drag;
1019         double _cumulative_y_drag;
1020         bool     _pushing;
1021         uint32_t _final_index;
1022         static double _zero_gain_fraction;
1023 };
1024
1025 /** Gain or automation line drag */
1026 class LineDrag : public Drag
1027 {
1028 public:
1029         LineDrag (Editor *e, ArdourCanvas::Item *i);
1030
1031         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1032         void motion (GdkEvent *, bool);
1033         void finished (GdkEvent *, bool);
1034         void aborted (bool);
1035
1036 private:
1037
1038         AutomationLine* _line;
1039         double _fixed_grab_x;
1040         double _fixed_grab_y;
1041         double _cumulative_y_drag;
1042         uint32_t _before;
1043         uint32_t _after;
1044 };
1045
1046 /** Transient feature line drags*/
1047 class FeatureLineDrag : public Drag
1048 {
1049 public:
1050         FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
1051
1052         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1053         void motion (GdkEvent *, bool);
1054         void finished (GdkEvent *, bool);
1055         void aborted (bool);
1056
1057 private:
1058
1059         ArdourCanvas::Line* _line;
1060         AudioRegionView* _arv;
1061
1062         double _region_view_grab_x;
1063         double _cumulative_x_drag;
1064
1065         float _before;
1066         uint32_t _max_x;
1067 };
1068
1069 /** Dragging of a rubberband rectangle for selecting things */
1070 class RubberbandSelectDrag : public Drag
1071 {
1072 public:
1073         RubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
1074
1075         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1076         void motion (GdkEvent *, bool);
1077         void finished (GdkEvent *, bool);
1078         void aborted (bool);
1079
1080         std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
1081                 return std::make_pair (8, 1);
1082         }
1083
1084         void do_select_things (GdkEvent *, bool);
1085
1086         /** Select some things within a rectangle.
1087          *  @param button_state The button state from the GdkEvent.
1088          *  @param x1 The left-hand side of the rectangle in session samples.
1089          *  @param x2 The right-hand side of the rectangle in session samples.
1090          *  @param y1 The top of the rectangle in trackview coordinates.
1091          *  @param y2 The bottom of the rectangle in trackview coordinates.
1092          *  @param drag_in_progress true if the drag is currently happening.
1093          */
1094         virtual void select_things (int button_state, samplepos_t x1, samplepos_t x2, double y1, double y2, bool drag_in_progress) = 0;
1095
1096         virtual void deselect_things () = 0;
1097
1098   protected:
1099         bool _vertical_only;
1100 };
1101
1102 /** A general editor RubberbandSelectDrag (for regions, automation points etc.) */
1103 class EditorRubberbandSelectDrag : public RubberbandSelectDrag
1104 {
1105 public:
1106         EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
1107
1108         void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1109         void deselect_things ();
1110 };
1111
1112 /** A RubberbandSelectDrag for selecting MIDI notes */
1113 class MidiRubberbandSelectDrag : public RubberbandSelectDrag
1114 {
1115 public:
1116         MidiRubberbandSelectDrag (Editor *, MidiRegionView *);
1117
1118         void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1119         void deselect_things ();
1120
1121 private:
1122         MidiRegionView* _region_view;
1123 };
1124
1125 /** A RubberbandSelectDrag for selecting MIDI notes but with no horizonal component */
1126 class MidiVerticalSelectDrag : public RubberbandSelectDrag
1127 {
1128 public:
1129         MidiVerticalSelectDrag (Editor *, MidiRegionView *);
1130
1131         void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1132         void deselect_things ();
1133
1134 private:
1135         MidiRegionView* _region_view;
1136 };
1137
1138 /** Region drag in time-FX mode */
1139 class TimeFXDrag : public RegionDrag
1140 {
1141 public:
1142         TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
1143
1144         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1145         void motion (GdkEvent *, bool);
1146         void finished (GdkEvent *, bool);
1147         void aborted (bool);
1148 };
1149
1150 /** Scrub drag in audition mode */
1151 class ScrubDrag : public Drag
1152 {
1153 public:
1154         ScrubDrag (Editor *, ArdourCanvas::Item *);
1155
1156         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1157         void motion (GdkEvent *, bool);
1158         void finished (GdkEvent *, bool);
1159         void aborted (bool);
1160 };
1161
1162 /** Drag in range select mode */
1163 class SelectionDrag : public Drag
1164 {
1165 public:
1166         enum Operation {
1167                 CreateSelection,
1168                 SelectionStartTrim,
1169                 SelectionEndTrim,
1170                 SelectionMove,
1171                 SelectionExtend
1172         };
1173
1174         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
1175
1176         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1177         void motion (GdkEvent *, bool);
1178         void finished (GdkEvent *, bool);
1179         void aborted (bool);
1180
1181         void setup_pointer_sample_offset ();
1182
1183 private:
1184         Operation _operation;
1185         bool _add;
1186         TrackSelection _track_selection_at_start;
1187         bool _time_selection_at_start;
1188         samplepos_t start_at_start;
1189         samplepos_t end_at_start;
1190 };
1191
1192 /** Range marker drag */
1193 class RangeMarkerBarDrag : public Drag
1194 {
1195 public:
1196         enum Operation {
1197                 CreateSkipMarker,
1198                 CreateRangeMarker,
1199                 CreateTransportMarker,
1200                 CreateCDMarker
1201         };
1202
1203         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
1204         ~RangeMarkerBarDrag ();
1205
1206         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1207         void motion (GdkEvent *, bool);
1208         void finished (GdkEvent *, bool);
1209         void aborted (bool);
1210
1211         bool allow_vertical_autoscroll () const {
1212                 return false;
1213         }
1214
1215         bool y_movement_matters () const {
1216                 return false;
1217         }
1218
1219 private:
1220         void update_item (ARDOUR::Location *);
1221
1222         Operation _operation;
1223         ArdourCanvas::Rectangle* _drag_rect;
1224         bool _copy;
1225 };
1226
1227 /** Drag of rectangle to set zoom */
1228 class MouseZoomDrag : public Drag
1229 {
1230 public:
1231         MouseZoomDrag (Editor *, ArdourCanvas::Item *);
1232
1233         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1234         void motion (GdkEvent *, bool);
1235         void finished (GdkEvent *, bool);
1236         void aborted (bool);
1237
1238         std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
1239                 return std::make_pair (4, 4);
1240         }
1241
1242 private:
1243         bool _zoom_out;
1244 };
1245
1246 /** Drag of a range of automation data (either on an automation track or region gain),
1247  *  changing value but not position.
1248  */
1249 class AutomationRangeDrag : public Drag
1250 {
1251 public:
1252         AutomationRangeDrag (Editor *, AutomationTimeAxisView *, std::list<ARDOUR::AudioRange> const &);
1253         AutomationRangeDrag (Editor *, std::list<RegionView*> const &, std::list<ARDOUR::AudioRange> const &, double y_origin, double y_height);
1254
1255         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1256         void motion (GdkEvent *, bool);
1257         void finished (GdkEvent *, bool);
1258         void aborted (bool);
1259
1260         bool x_movement_matters () const {
1261                 return false;
1262         }
1263
1264 private:
1265         void setup (std::list<boost::shared_ptr<AutomationLine> > const &);
1266         double y_fraction (double global_y_position) const;
1267         double value (boost::shared_ptr<ARDOUR::AutomationList> list, double x) const;
1268
1269         std::list<ARDOUR::AudioRange> _ranges;
1270
1271         /** A line that is part of the drag */
1272         struct Line {
1273                 boost::shared_ptr<AutomationLine> line; ///< the line
1274                 std::list<ControlPoint*> points; ///< points to drag on the line
1275                 std::pair<ARDOUR::samplepos_t, ARDOUR::samplepos_t> range; ///< the range of all points on the line, in session samples
1276                 XMLNode* state; ///< the XML state node before the drag
1277         };
1278
1279         std::list<Line> _lines;
1280         double          _y_origin;
1281         double          _y_height;
1282         bool            _nothing_to_drag;
1283         bool            _integral;
1284 };
1285
1286 /** Drag of one edge of an xfade
1287  */
1288 class CrossfadeEdgeDrag : public Drag
1289 {
1290 public:
1291         CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
1292
1293         void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
1294         void motion (GdkEvent*, bool);
1295         void finished (GdkEvent*, bool);
1296         void aborted (bool);
1297
1298         bool y_movement_matters () const {
1299                 return false;
1300         }
1301
1302         virtual std::pair<ARDOUR::samplecnt_t, int> move_threshold () const {
1303                 return std::make_pair (4, 4);
1304         }
1305
1306 private:
1307         AudioRegionView* arv;
1308         bool start;
1309 };
1310
1311 #endif /* __gtk2_ardour_editor_drag_h_ */
1312