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"
40 class CanvasNoteEvent;
49 /** Class to manage current drags */
54 DragManager (Editor* e);
57 bool motion_handler (GdkEvent *, bool);
61 void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
62 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
63 bool end_grab (GdkEvent *);
64 bool have_item (ArdourCanvas::Item *) const;
66 /** @return true if an end drag or abort is in progress */
67 bool ending () const {
71 bool active () const {
72 return !_drags.empty ();
75 /** @return current pointer x position in trackview coordinates */
76 double current_pointer_x () const {
77 return _current_pointer_x;
80 /** @return current pointer y position in trackview coordinates */
81 double current_pointer_y () const {
82 return _current_pointer_y;
85 /** @return current pointer frame */
86 nframes64_t current_pointer_frame () const {
87 return _current_pointer_frame;
92 std::list<Drag*> _drags;
93 bool _ending; ///< true if end_grab or abort is in progress, otherwise false
94 double _current_pointer_x; ///< trackview x of the current pointer
95 double _current_pointer_y; ///< trackview y of the current pointer
96 nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
99 /** Abstract base class for dragging of things within the editor */
103 Drag (Editor *, ArdourCanvas::Item *);
106 void set_manager (DragManager* m) {
110 /** @return the canvas item being dragged */
111 ArdourCanvas::Item* item () const {
115 void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
116 bool motion_handler (GdkEvent*, bool);
119 nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
120 nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
122 /** Called to start a grab of an item.
123 * @param e Event that caused the grab to start.
124 * @param c Cursor to use, or 0.
126 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
128 virtual bool end_grab (GdkEvent *);
130 /** Called when a drag motion has occurred.
131 * @param e Event describing the motion.
132 * @param f true if this is the first movement, otherwise false.
134 virtual void motion (GdkEvent* e, bool f) = 0;
136 /** Called when a drag has finished.
137 * @param e Event describing the finish.
138 * @param m true if some movement occurred, otherwise false.
140 virtual void finished (GdkEvent* e, bool m) = 0;
142 /** Called to abort a drag and return things to how
143 * they were before it started.
145 virtual void aborted () = 0;
147 /** @param m Mouse mode.
148 * @return true if this drag should happen in this mouse mode.
150 virtual bool active (Editing::MouseMode m) {
151 return (m != Editing::MouseGain);
154 /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
155 virtual std::pair<nframes64_t, int> move_threshold () const {
156 return std::make_pair (1, 1);
159 virtual bool allow_vertical_autoscroll () const {
163 /** @return true if x movement matters to this drag */
164 virtual bool x_movement_matters () const {
168 /** @return true if y movement matters to this drag */
169 virtual bool y_movement_matters () const {
175 double grab_x () const {
179 double grab_y () const {
183 double grab_frame () const {
187 double last_pointer_x () const {
188 return _last_pointer_x;
191 double last_pointer_y () const {
192 return _last_pointer_y;
195 double last_pointer_frame () const {
196 return _last_pointer_frame;
199 Editor* _editor; ///< our editor
201 ArdourCanvas::Item* _item; ///< our item
202 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
203 nframes64_t _pointer_frame_offset;
204 bool _x_constrained; ///< true if x motion is constrained, otherwise false
205 bool _y_constrained; ///< true if y motion is constrained, otherwise false
206 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
210 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
211 double _grab_x; ///< trackview x of the grab start position
212 double _grab_y; ///< trackview y of the grab start position
213 double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
214 double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
215 nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
216 nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
221 DraggingView (RegionView* v);
223 RegionView* view; ///< the view
224 double initial_y; ///< the initial y position of the view before any reparenting
227 /** Abstract base class for drags that involve region(s) */
228 class RegionDrag : public Drag, public sigc::trackable
231 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
232 virtual ~RegionDrag () {}
236 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
237 std::list<DraggingView> _views; ///< information about all views that are being dragged
240 void region_going_away (RegionView *);
241 PBD::ScopedConnection death_connection;
245 /** Drags involving region motion from somewhere */
246 class RegionMotionDrag : public RegionDrag
250 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
251 virtual ~RegionMotionDrag () {}
253 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
254 virtual void motion (GdkEvent *, bool);
255 virtual void finished (GdkEvent *, bool) = 0;
256 virtual void aborted ();
259 struct TimeAxisViewSummary {
260 TimeAxisViewSummary () : height_list(512) {}
262 std::bitset<512> tracks;
263 std::vector<int32_t> height_list;
268 void copy_regions (GdkEvent *);
269 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
270 std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
271 double compute_x_delta (GdkEvent const *, nframes64_t *);
272 bool compute_y_delta (
273 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
274 int32_t *, int32_t *, int32_t *
277 TimeAxisViewSummary get_time_axis_view_summary ();
278 bool x_move_allowed () const;
280 TimeAxisView* _dest_trackview;
281 ARDOUR::layer_t _dest_layer;
282 bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
284 nframes64_t _last_frame_position; ///< last position of the thing being dragged
285 double _total_x_delta;
289 /** Drags to move (or copy) regions that are already shown in the GUI to
290 * somewhere different.
292 class RegionMoveDrag : public RegionMotionDrag
295 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
296 virtual ~RegionMoveDrag () {}
298 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
299 void motion (GdkEvent *, bool);
300 void finished (GdkEvent *, bool);
303 std::pair<nframes64_t, int> move_threshold () const {
304 return std::make_pair (4, 4);
311 /** Drag to insert a region from somewhere */
312 class RegionInsertDrag : public RegionMotionDrag
315 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
317 void finished (GdkEvent *, bool);
321 /** Region drag in splice mode */
322 class RegionSpliceDrag : public RegionMoveDrag
325 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
327 void motion (GdkEvent *, bool);
328 void finished (GdkEvent *, bool);
332 /** Drags to create regions */
333 class RegionCreateDrag : public Drag
336 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
338 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
339 void motion (GdkEvent *, bool);
340 void finished (GdkEvent *, bool);
345 TimeAxisView* _dest_trackview;
348 /** Drags to resize MIDI notes */
349 class NoteResizeDrag : public Drag
352 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
354 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
355 void motion (GdkEvent *, bool);
356 void finished (GdkEvent *, bool);
360 MidiRegionView* region;
365 /** Drags to move MIDI notes */
366 class NoteDrag : public Drag
369 NoteDrag (Editor*, ArdourCanvas::Item*);
371 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
372 void motion (GdkEvent *, bool);
373 void finished (GdkEvent *, bool);
378 ARDOUR::frameoffset_t total_dx () const;
379 int8_t total_dy () const;
381 MidiRegionView* _region;
382 Gnome::Canvas::CanvasNoteEvent* _primary;
383 double _cumulative_dx;
384 double _cumulative_dy;
389 /** Drag of region gain */
390 class RegionGainDrag : public Drag
393 RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
395 void motion (GdkEvent *, bool);
396 void finished (GdkEvent *, bool);
397 bool active (Editing::MouseMode m) {
398 return (m == Editing::MouseGain);
404 /** Drag to trim region(s) */
405 class TrimDrag : public RegionDrag
414 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
416 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
417 void motion (GdkEvent *, bool);
418 void finished (GdkEvent *, bool);
421 bool y_movement_matters () const {
427 Operation _operation;
428 bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
431 /** Meter marker drag */
432 class MeterMarkerDrag : public Drag
435 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
437 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
438 void motion (GdkEvent *, bool);
439 void finished (GdkEvent *, bool);
442 bool allow_vertical_autoscroll () const {
446 bool y_movement_matters () const {
451 MeterMarker* _marker;
455 /** Tempo marker drag */
456 class TempoMarkerDrag : public Drag
459 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
461 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
462 void motion (GdkEvent *, bool);
463 void finished (GdkEvent *, bool);
466 bool allow_vertical_autoscroll () const {
470 bool y_movement_matters () const {
475 TempoMarker* _marker;
480 /** Drag of a cursor */
481 class CursorDrag : public Drag
484 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
486 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
487 void motion (GdkEvent *, bool);
488 void finished (GdkEvent *, bool);
491 bool active (Editing::MouseMode) {
495 bool allow_vertical_autoscroll () const {
499 bool y_movement_matters () const {
504 EditorCursor* _cursor; ///< cursor being dragged
505 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
509 /** Region fade-in drag */
510 class FadeInDrag : public RegionDrag
513 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
515 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
516 void motion (GdkEvent *, bool);
517 void finished (GdkEvent *, bool);
520 bool y_movement_matters () const {
525 /** Region fade-out drag */
526 class FadeOutDrag : public RegionDrag
529 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
531 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
532 void motion (GdkEvent *, bool);
533 void finished (GdkEvent *, bool);
536 bool y_movement_matters () const {
542 class MarkerDrag : public Drag
545 MarkerDrag (Editor *, ArdourCanvas::Item *);
548 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
549 void motion (GdkEvent *, bool);
550 void finished (GdkEvent *, bool);
553 bool allow_vertical_autoscroll () const {
557 bool y_movement_matters () const {
562 void update_item (ARDOUR::Location *);
564 Marker* _marker; ///< marker being dragged
565 std::list<ARDOUR::Location*> _copied_locations;
566 ArdourCanvas::Line* _line;
567 ArdourCanvas::Points _points;
570 /** Control point drag */
571 class ControlPointDrag : public Drag
574 ControlPointDrag (Editor *, ArdourCanvas::Item *);
576 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
577 void motion (GdkEvent *, bool);
578 void finished (GdkEvent *, bool);
581 bool active (Editing::MouseMode m);
585 ControlPoint* _point;
586 double _time_axis_view_grab_x;
587 double _time_axis_view_grab_y;
588 double _cumulative_x_drag;
589 double _cumulative_y_drag;
590 static double const _zero_gain_fraction;
593 /** Gain or automation line drag */
594 class LineDrag : public Drag
597 LineDrag (Editor *e, ArdourCanvas::Item *i);
599 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
600 void motion (GdkEvent *, bool);
601 void finished (GdkEvent *, bool);
604 bool active (Editing::MouseMode) {
610 AutomationLine* _line;
611 double _time_axis_view_grab_x;
612 double _time_axis_view_grab_y;
615 double _cumulative_y_drag;
618 /** Transient feature line drags*/
619 class FeatureLineDrag : public Drag
622 FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
624 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
625 void motion (GdkEvent *, bool);
626 void finished (GdkEvent *, bool);
629 bool active (Editing::MouseMode) {
635 ArdourCanvas::SimpleLine* _line;
636 AudioRegionView* _arv;
638 double _region_view_grab_x;
639 double _cumulative_x_drag;
645 /** Dragging of a rubberband rectangle for selecting things */
646 class RubberbandSelectDrag : public Drag
649 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
651 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
652 void motion (GdkEvent *, bool);
653 void finished (GdkEvent *, bool);
656 std::pair<nframes64_t, int> move_threshold () const {
657 return std::make_pair (8, 1);
661 /** Region drag in time-FX mode */
662 class TimeFXDrag : public RegionDrag
665 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
667 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
668 void motion (GdkEvent *, bool);
669 void finished (GdkEvent *, bool);
673 /** Scrub drag in audition mode */
674 class ScrubDrag : public Drag
677 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
679 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
680 void motion (GdkEvent *, bool);
681 void finished (GdkEvent *, bool);
685 /** Drag in range select mode */
686 class SelectionDrag : public Drag
696 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
698 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
699 void motion (GdkEvent *, bool);
700 void finished (GdkEvent *, bool);
704 Operation _operation;
706 int _original_pointer_time_axis;
707 int _last_pointer_time_axis;
708 std::list<TimeAxisView*> _added_time_axes;
711 /** Range marker drag */
712 class RangeMarkerBarDrag : public Drag
717 CreateTransportMarker,
721 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
723 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
724 void motion (GdkEvent *, bool);
725 void finished (GdkEvent *, bool);
728 bool allow_vertical_autoscroll () const {
732 bool y_movement_matters () const {
737 void update_item (ARDOUR::Location *);
739 Operation _operation;
740 ArdourCanvas::SimpleRect* _drag_rect;
744 /** Drag of rectangle to set zoom */
745 class MouseZoomDrag : public Drag
748 MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {}
750 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
751 void motion (GdkEvent *, bool);
752 void finished (GdkEvent *, bool);
756 /** Drag of a range of automation data, changing value but not position */
757 class AutomationRangeDrag : public Drag
760 AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
762 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
763 void motion (GdkEvent *, bool);
764 void finished (GdkEvent *, bool);
767 bool x_movement_matters () const {
772 std::list<ARDOUR::AudioRange> _ranges;
773 AutomationTimeAxisView* _atav;
774 boost::shared_ptr<AutomationLine> _line;
775 bool _nothing_to_drag;
778 #endif /* __gtk2_ardour_editor_drag_h_ */