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_
28 #include "ardour/types.h"
31 #include "editor_items.h"
41 /** Abstract base class for dragging of things within the editor */
46 Drag (Editor *, ArdourCanvas::Item *);
49 /** @return the canvas item being dragged */
50 ArdourCanvas::Item* item () const {
54 void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
57 bool motion_handler (GdkEvent*, bool);
59 /** @return true if an end drag is in progress */
60 bool ending () const {
64 /** @return current pointer x position in trackview coordinates */
65 double current_pointer_x () const {
66 return _current_pointer_x;
69 /** @return current pointer y position in trackview coordinates */
70 double current_pointer_y () const {
71 return _current_pointer_y;
74 nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
75 nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
77 /** Called to start a grab of an item.
78 * @param e Event that caused the grab to start.
79 * @param c Cursor to use, or 0.
81 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
83 virtual bool end_grab (GdkEvent *);
85 /** Called when a drag motion has occurred.
86 * @param e Event describing the motion.
87 * @param f true if this is the first movement, otherwise false.
89 virtual void motion (GdkEvent* e, bool f) = 0;
91 /** Called when a drag has finished.
92 * @param e Event describing the finish.
93 * @param m true if some movement occurred, otherwise false.
95 virtual void finished (GdkEvent* e, bool m) = 0;
97 /** @param m Mouse mode.
98 * @return true if this drag should happen in this mouse mode.
100 virtual bool active (Editing::MouseMode m) {
101 return (m != Editing::MouseGain);
104 /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
105 virtual std::pair<nframes64_t, int> move_threshold () const {
106 return std::make_pair (1, 1);
109 virtual bool allow_vertical_autoscroll () const {
113 /** @return true if x movement matters to this drag */
114 virtual bool x_movement_matters () const {
118 /** @return true if y movement matters to this drag */
119 virtual bool y_movement_matters () const {
125 double grab_x () const {
129 double grab_y () const {
133 double grab_frame () const {
137 double last_pointer_x () const {
138 return _last_pointer_x;
141 double last_pointer_y () const {
142 return _last_pointer_y;
145 double last_pointer_frame () const {
146 return _last_pointer_frame;
149 Editor* _editor; ///< our editor
150 ArdourCanvas::Item* _item; ///< our item
151 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
152 nframes64_t _pointer_frame_offset;
153 bool _x_constrained; ///< true if x motion is constrained, otherwise false
154 bool _y_constrained; ///< true if y motion is constrained, otherwise false
155 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
156 bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
160 bool _ending; ///< true if end_grab is in progress, otherwise false
161 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
162 double _original_x; ///< original world x of the thing being dragged
163 double _original_y; ///< original world y of the thing being dragged
164 double _grab_x; ///< trackview x of the grab start position
165 double _grab_y; ///< trackview y of the grab start position
166 double _current_pointer_x; ///< trackview x of the current pointer
167 double _current_pointer_y; ///< trackview y of the current pointer
168 double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
169 double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
170 nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
171 nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
172 nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
176 /** Abstract base class for drags that involve region(s) */
177 class RegionDrag : public Drag, public sigc::trackable
180 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
181 virtual ~RegionDrag () {}
185 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
186 std::list<RegionView*> _views; ///< all views that are being dragged
189 void region_going_away (RegionView *);
190 PBD::ScopedConnection death_connection;
194 /** Drags involving region motion from somewhere */
195 class RegionMotionDrag : public RegionDrag
199 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
200 virtual ~RegionMotionDrag () {}
202 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
203 virtual void motion (GdkEvent *, bool);
204 virtual void finished (GdkEvent *, bool) = 0;
207 struct TimeAxisViewSummary {
208 TimeAxisViewSummary () : height_list(512) {}
210 std::bitset<512> tracks;
211 std::vector<int32_t> height_list;
216 void copy_regions (GdkEvent *);
217 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
218 std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
219 double compute_x_delta (GdkEvent const *, nframes64_t *);
220 bool compute_y_delta (
221 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
222 int32_t *, int32_t *, int32_t *
225 TimeAxisViewSummary get_time_axis_view_summary ();
226 bool x_move_allowed () const;
228 TimeAxisView* _dest_trackview;
229 ARDOUR::layer_t _dest_layer;
230 bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
232 nframes64_t _last_frame_position; ///< last position of the thing being dragged
236 /** Drags to move (or copy) regions that are already shown in the GUI to
237 * somewhere different.
239 class RegionMoveDrag : public RegionMotionDrag
242 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
243 virtual ~RegionMoveDrag () {}
245 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
246 void motion (GdkEvent *, bool);
247 void finished (GdkEvent *, bool);
249 std::pair<nframes64_t, int> move_threshold () const {
250 return std::make_pair (4, 4);
257 /** Drag to insert a region from somewhere */
258 class RegionInsertDrag : public RegionMotionDrag
261 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
263 void finished (GdkEvent *, bool);
266 /** Region drag in splice mode */
267 class RegionSpliceDrag : public RegionMoveDrag
270 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
272 void motion (GdkEvent *, bool);
273 void finished (GdkEvent *, bool);
276 /** Drags to create regions */
277 class RegionCreateDrag : public Drag
280 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
282 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
283 void motion (GdkEvent *, bool);
284 void finished (GdkEvent *, bool);
288 TimeAxisView* _dest_trackview;
291 /** Drags to resize MIDI notes */
292 class NoteResizeDrag : public Drag
295 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
297 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
298 void motion (GdkEvent *, bool);
299 void finished (GdkEvent *, bool);
302 MidiRegionView* region;
307 class NoteDrag : public Drag
310 NoteDrag (Editor*, ArdourCanvas::Item*);
312 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
313 void motion (GdkEvent *, bool);
314 void finished (GdkEvent *, bool);
317 MidiRegionView* region;
321 double drag_delta_note;
325 /** Drag of region gain */
326 class RegionGainDrag : public Drag
329 RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
331 void motion (GdkEvent *, bool);
332 void finished (GdkEvent *, bool);
333 bool active (Editing::MouseMode m) {
334 return (m == Editing::MouseGain);
338 /** Drag to trim region(s) */
339 class TrimDrag : public RegionDrag
348 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
350 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
351 void motion (GdkEvent *, bool);
352 void finished (GdkEvent *, bool);
354 bool y_movement_matters () const {
360 Operation _operation;
363 /** Meter marker drag */
364 class MeterMarkerDrag : public Drag
367 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
369 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
370 void motion (GdkEvent *, bool);
371 void finished (GdkEvent *, bool);
373 bool allow_vertical_autoscroll () const {
377 bool y_movement_matters () const {
382 MeterMarker* _marker;
386 /** Tempo marker drag */
387 class TempoMarkerDrag : public Drag
390 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
392 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
393 void motion (GdkEvent *, bool);
394 void finished (GdkEvent *, bool);
396 bool allow_vertical_autoscroll () const {
400 bool y_movement_matters () const {
405 TempoMarker* _marker;
410 /** Drag of a cursor */
411 class CursorDrag : public Drag
414 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
416 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
417 void motion (GdkEvent *, bool);
418 void finished (GdkEvent *, bool);
420 bool active (Editing::MouseMode) {
424 bool allow_vertical_autoscroll () const {
428 bool y_movement_matters () const {
433 EditorCursor* _cursor; ///< cursor being dragged
434 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
438 /** Region fade-in drag */
439 class FadeInDrag : public RegionDrag
442 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
444 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
445 void motion (GdkEvent *, bool);
446 void finished (GdkEvent *, bool);
448 bool y_movement_matters () const {
453 /** Region fade-out drag */
454 class FadeOutDrag : public RegionDrag
457 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
459 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
460 void motion (GdkEvent *, bool);
461 void finished (GdkEvent *, bool);
463 bool y_movement_matters () const {
469 class MarkerDrag : public Drag
472 MarkerDrag (Editor *, ArdourCanvas::Item *);
475 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
476 void motion (GdkEvent *, bool);
477 void finished (GdkEvent *, bool);
479 bool allow_vertical_autoscroll () const {
483 bool y_movement_matters () const {
488 void update_item (ARDOUR::Location *);
490 Marker* _marker; ///< marker being dragged
491 std::list<ARDOUR::Location*> _copied_locations;
492 ArdourCanvas::Line* _line;
493 ArdourCanvas::Points _points;
496 /** Control point drag */
497 class ControlPointDrag : public Drag
500 ControlPointDrag (Editor *, ArdourCanvas::Item *);
502 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
503 void motion (GdkEvent *, bool);
504 void finished (GdkEvent *, bool);
506 bool active (Editing::MouseMode m);
510 ControlPoint* _point;
511 double _time_axis_view_grab_x;
512 double _time_axis_view_grab_y;
513 double _cumulative_x_drag;
514 double _cumulative_y_drag;
515 static double const _zero_gain_fraction;
518 /** Gain or automation line drag */
519 class LineDrag : public Drag
522 LineDrag (Editor *e, ArdourCanvas::Item *i);
524 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
525 void motion (GdkEvent *, bool);
526 void finished (GdkEvent *, bool);
528 bool active (Editing::MouseMode) {
534 AutomationLine* _line;
535 double _time_axis_view_grab_x;
536 double _time_axis_view_grab_y;
539 double _cumulative_y_drag;
542 /** Dragging of a rubberband rectangle for selecting things */
543 class RubberbandSelectDrag : public Drag
546 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
548 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
549 void motion (GdkEvent *, bool);
550 void finished (GdkEvent *, bool);
553 /** Region drag in time-FX mode */
554 class TimeFXDrag : public RegionDrag
557 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
559 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
560 void motion (GdkEvent *, bool);
561 void finished (GdkEvent *, bool);
564 /** Scrub drag in audition mode */
565 class ScrubDrag : public Drag
568 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
570 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
571 void motion (GdkEvent *, bool);
572 void finished (GdkEvent *, bool);
575 /** Drag in range select mode */
576 class SelectionDrag : public Drag
586 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
588 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
589 void motion (GdkEvent *, bool);
590 void finished (GdkEvent *, bool);
593 Operation _operation;
595 int _original_pointer_time_axis;
596 int _last_pointer_time_axis;
597 std::list<TimeAxisView*> _added_time_axes;
600 /** Range marker drag */
601 class RangeMarkerBarDrag : public Drag
606 CreateTransportMarker,
610 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
612 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
613 void motion (GdkEvent *, bool);
614 void finished (GdkEvent *, bool);
616 bool allow_vertical_autoscroll () const {
620 bool y_movement_matters () const {
625 void update_item (ARDOUR::Location *);
627 Operation _operation;
628 ArdourCanvas::SimpleRect* _drag_rect;
632 /** Drag of rectangle to set zoom */
633 class MouseZoomDrag : public Drag
636 MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {}
638 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
639 void motion (GdkEvent *, bool);
640 void finished (GdkEvent *, bool);
643 /** Drag of a range of automation data, changing value but not position */
644 class AutomationRangeDrag : public Drag
647 AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
649 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
650 void motion (GdkEvent *, bool);
651 void finished (GdkEvent *, bool);
653 bool x_movement_matters () const {
658 std::list<ARDOUR::AudioRange> _ranges;
659 AutomationTimeAxisView* _atav;
660 boost::shared_ptr<AutomationLine> _line;
661 bool _nothing_to_drag;
664 #endif /* __gtk2_ardour_editor_drag_h_ */