2 Copyright (C) 2009 Paul Davis
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.
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.
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.
20 #ifndef __gtk2_ardour_editor_drag_h_
21 #define __gtk2_ardour_editor_drag_h_
29 #include "ardour/types.h"
32 #include "editor_items.h"
43 /** Class to manage current drags */
48 DragManager (Editor* e);
51 bool motion_handler (GdkEvent *, bool);
55 void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
56 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
57 bool end_grab (GdkEvent *);
58 bool have_item (ArdourCanvas::Item *) const;
60 /** @return true if an end drag or abort is in progress */
61 bool ending () const {
65 bool active () const {
66 return !_drags.empty ();
69 /** @return current pointer x position in trackview coordinates */
70 double current_pointer_x () const {
71 return _current_pointer_x;
74 /** @return current pointer y position in trackview coordinates */
75 double current_pointer_y () const {
76 return _current_pointer_y;
79 /** @return current pointer frame */
80 nframes64_t current_pointer_frame () const {
81 return _current_pointer_frame;
86 std::list<Drag*> _drags;
87 bool _ending; ///< true if end_grab or abort is in progress, otherwise false
88 double _current_pointer_x; ///< trackview x of the current pointer
89 double _current_pointer_y; ///< trackview y of the current pointer
90 nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
93 /** Abstract base class for dragging of things within the editor */
97 Drag (Editor *, ArdourCanvas::Item *);
100 void set_manager (DragManager* m) {
104 /** @return the canvas item being dragged */
105 ArdourCanvas::Item* item () const {
109 void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
110 bool motion_handler (GdkEvent*, bool);
113 nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
114 nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
116 /** Called to start a grab of an item.
117 * @param e Event that caused the grab to start.
118 * @param c Cursor to use, or 0.
120 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
122 virtual bool end_grab (GdkEvent *);
124 /** Called when a drag motion has occurred.
125 * @param e Event describing the motion.
126 * @param f true if this is the first movement, otherwise false.
128 virtual void motion (GdkEvent* e, bool f) = 0;
130 /** Called when a drag has finished.
131 * @param e Event describing the finish.
132 * @param m true if some movement occurred, otherwise false.
134 virtual void finished (GdkEvent* e, bool m) = 0;
136 /** Called to abort a drag and return things to how
137 * they were before it started.
139 virtual void aborted () = 0;
141 /** @param m Mouse mode.
142 * @return true if this drag should happen in this mouse mode.
144 virtual bool active (Editing::MouseMode m) {
145 return (m != Editing::MouseGain);
148 /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
149 virtual std::pair<nframes64_t, int> move_threshold () const {
150 return std::make_pair (1, 1);
153 virtual bool allow_vertical_autoscroll () const {
157 /** @return true if x movement matters to this drag */
158 virtual bool x_movement_matters () const {
162 /** @return true if y movement matters to this drag */
163 virtual bool y_movement_matters () const {
169 double grab_x () const {
173 double grab_y () const {
177 double grab_frame () const {
181 double last_pointer_x () const {
182 return _last_pointer_x;
185 double last_pointer_y () const {
186 return _last_pointer_y;
189 double last_pointer_frame () const {
190 return _last_pointer_frame;
193 Editor* _editor; ///< our editor
195 ArdourCanvas::Item* _item; ///< our item
196 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
197 nframes64_t _pointer_frame_offset;
198 bool _x_constrained; ///< true if x motion is constrained, otherwise false
199 bool _y_constrained; ///< true if y motion is constrained, otherwise false
200 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
204 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
205 double _grab_x; ///< trackview x of the grab start position
206 double _grab_y; ///< trackview y of the grab start position
207 double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
208 double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
209 nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
210 nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
215 DraggingView (RegionView* v);
217 RegionView* view; ///< the view
218 double initial_y; ///< the initial y position of the view before any reparenting
221 /** Abstract base class for drags that involve region(s) */
222 class RegionDrag : public Drag, public sigc::trackable
225 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
226 virtual ~RegionDrag () {}
230 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
231 std::list<DraggingView> _views; ///< information about all views that are being dragged
234 void region_going_away (RegionView *);
235 PBD::ScopedConnection death_connection;
239 /** Drags involving region motion from somewhere */
240 class RegionMotionDrag : public RegionDrag
244 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
245 virtual ~RegionMotionDrag () {}
247 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
248 virtual void motion (GdkEvent *, bool);
249 virtual void finished (GdkEvent *, bool) = 0;
250 virtual void aborted ();
253 struct TimeAxisViewSummary {
254 TimeAxisViewSummary () : height_list(512) {}
256 std::bitset<512> tracks;
257 std::vector<int32_t> height_list;
262 void copy_regions (GdkEvent *);
263 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
264 std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
265 double compute_x_delta (GdkEvent const *, nframes64_t *);
266 bool compute_y_delta (
267 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
268 int32_t *, int32_t *, int32_t *
271 TimeAxisViewSummary get_time_axis_view_summary ();
272 bool x_move_allowed () const;
274 TimeAxisView* _dest_trackview;
275 ARDOUR::layer_t _dest_layer;
276 bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
278 nframes64_t _last_frame_position; ///< last position of the thing being dragged
279 double _total_x_delta;
283 /** Drags to move (or copy) regions that are already shown in the GUI to
284 * somewhere different.
286 class RegionMoveDrag : public RegionMotionDrag
289 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
290 virtual ~RegionMoveDrag () {}
292 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
293 void motion (GdkEvent *, bool);
294 void finished (GdkEvent *, bool);
297 std::pair<nframes64_t, int> move_threshold () const {
298 return std::make_pair (4, 4);
305 /** Drag to insert a region from somewhere */
306 class RegionInsertDrag : public RegionMotionDrag
309 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
311 void finished (GdkEvent *, bool);
315 /** Region drag in splice mode */
316 class RegionSpliceDrag : public RegionMoveDrag
319 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
321 void motion (GdkEvent *, bool);
322 void finished (GdkEvent *, bool);
326 /** Drags to create regions */
327 class RegionCreateDrag : public Drag
330 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
332 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
333 void motion (GdkEvent *, bool);
334 void finished (GdkEvent *, bool);
339 TimeAxisView* _dest_trackview;
342 /** Drags to resize MIDI notes */
343 class NoteResizeDrag : public Drag
346 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
348 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
349 void motion (GdkEvent *, bool);
350 void finished (GdkEvent *, bool);
354 MidiRegionView* region;
359 class NoteDrag : public Drag
362 NoteDrag (Editor*, ArdourCanvas::Item*);
364 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
365 void motion (GdkEvent *, bool);
366 void finished (GdkEvent *, bool);
370 MidiRegionView* region;
374 double drag_delta_note;
378 /** Drag of region gain */
379 class RegionGainDrag : public Drag
382 RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
384 void motion (GdkEvent *, bool);
385 void finished (GdkEvent *, bool);
386 bool active (Editing::MouseMode m) {
387 return (m == Editing::MouseGain);
393 /** Drag to trim region(s) */
394 class TrimDrag : public RegionDrag
403 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
405 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
406 void motion (GdkEvent *, bool);
407 void finished (GdkEvent *, bool);
410 bool y_movement_matters () const {
416 Operation _operation;
417 bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
420 /** Meter marker drag */
421 class MeterMarkerDrag : public Drag
424 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
426 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
427 void motion (GdkEvent *, bool);
428 void finished (GdkEvent *, bool);
431 bool allow_vertical_autoscroll () const {
435 bool y_movement_matters () const {
440 MeterMarker* _marker;
444 /** Tempo marker drag */
445 class TempoMarkerDrag : public Drag
448 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
450 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
451 void motion (GdkEvent *, bool);
452 void finished (GdkEvent *, bool);
455 bool allow_vertical_autoscroll () const {
459 bool y_movement_matters () const {
464 TempoMarker* _marker;
469 /** Drag of a cursor */
470 class CursorDrag : public Drag
473 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
475 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
476 void motion (GdkEvent *, bool);
477 void finished (GdkEvent *, bool);
480 bool active (Editing::MouseMode) {
484 bool allow_vertical_autoscroll () const {
488 bool y_movement_matters () const {
493 EditorCursor* _cursor; ///< cursor being dragged
494 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
498 /** Region fade-in drag */
499 class FadeInDrag : public RegionDrag
502 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
504 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
505 void motion (GdkEvent *, bool);
506 void finished (GdkEvent *, bool);
509 bool y_movement_matters () const {
514 /** Region fade-out drag */
515 class FadeOutDrag : public RegionDrag
518 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
520 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
521 void motion (GdkEvent *, bool);
522 void finished (GdkEvent *, bool);
525 bool y_movement_matters () const {
531 class MarkerDrag : public Drag
534 MarkerDrag (Editor *, ArdourCanvas::Item *);
537 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
538 void motion (GdkEvent *, bool);
539 void finished (GdkEvent *, bool);
542 bool allow_vertical_autoscroll () const {
546 bool y_movement_matters () const {
551 void update_item (ARDOUR::Location *);
553 Marker* _marker; ///< marker being dragged
554 std::list<ARDOUR::Location*> _copied_locations;
555 ArdourCanvas::Line* _line;
556 ArdourCanvas::Points _points;
559 /** Control point drag */
560 class ControlPointDrag : public Drag
563 ControlPointDrag (Editor *, ArdourCanvas::Item *);
565 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
566 void motion (GdkEvent *, bool);
567 void finished (GdkEvent *, bool);
570 bool active (Editing::MouseMode m);
574 ControlPoint* _point;
575 double _time_axis_view_grab_x;
576 double _time_axis_view_grab_y;
577 double _cumulative_x_drag;
578 double _cumulative_y_drag;
579 static double const _zero_gain_fraction;
582 /** Gain or automation line drag */
583 class LineDrag : public Drag
586 LineDrag (Editor *e, ArdourCanvas::Item *i);
588 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
589 void motion (GdkEvent *, bool);
590 void finished (GdkEvent *, bool);
593 bool active (Editing::MouseMode) {
599 AutomationLine* _line;
600 double _time_axis_view_grab_x;
601 double _time_axis_view_grab_y;
604 double _cumulative_y_drag;
607 /** Transient feature line drags*/
608 class FeatureLineDrag : public Drag
611 FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
613 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
614 void motion (GdkEvent *, bool);
615 void finished (GdkEvent *, bool);
618 bool active (Editing::MouseMode) {
624 ArdourCanvas::SimpleLine* _line;
625 AudioRegionView* _arv;
627 double _region_view_grab_x;
628 double _cumulative_x_drag;
634 /** Dragging of a rubberband rectangle for selecting things */
635 class RubberbandSelectDrag : public Drag
638 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
640 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
641 void motion (GdkEvent *, bool);
642 void finished (GdkEvent *, bool);
645 std::pair<nframes64_t, int> move_threshold () const {
646 return std::make_pair (8, 1);
650 /** Region drag in time-FX mode */
651 class TimeFXDrag : public RegionDrag
654 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
656 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
657 void motion (GdkEvent *, bool);
658 void finished (GdkEvent *, bool);
662 /** Scrub drag in audition mode */
663 class ScrubDrag : public Drag
666 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
668 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
669 void motion (GdkEvent *, bool);
670 void finished (GdkEvent *, bool);
674 /** Drag in range select mode */
675 class SelectionDrag : public Drag
685 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
687 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
688 void motion (GdkEvent *, bool);
689 void finished (GdkEvent *, bool);
693 Operation _operation;
695 int _original_pointer_time_axis;
696 int _last_pointer_time_axis;
697 std::list<TimeAxisView*> _added_time_axes;
700 /** Range marker drag */
701 class RangeMarkerBarDrag : public Drag
706 CreateTransportMarker,
710 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
712 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
713 void motion (GdkEvent *, bool);
714 void finished (GdkEvent *, bool);
717 bool allow_vertical_autoscroll () const {
721 bool y_movement_matters () const {
726 void update_item (ARDOUR::Location *);
728 Operation _operation;
729 ArdourCanvas::SimpleRect* _drag_rect;
733 /** Drag of rectangle to set zoom */
734 class MouseZoomDrag : public Drag
737 MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {}
739 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
740 void motion (GdkEvent *, bool);
741 void finished (GdkEvent *, bool);
745 /** Drag of a range of automation data, changing value but not position */
746 class AutomationRangeDrag : public Drag
749 AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
751 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
752 void motion (GdkEvent *, bool);
753 void finished (GdkEvent *, bool);
756 bool x_movement_matters () const {
761 std::list<ARDOUR::AudioRange> _ranges;
762 AutomationTimeAxisView* _atav;
763 boost::shared_ptr<AutomationLine> _line;
764 bool _nothing_to_drag;
767 #endif /* __gtk2_ardour_editor_drag_h_ */