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 item coordinates */
65 double current_pointer_x () const {
66 return _current_pointer_x;
69 /** @return current pointer y position in item coordinates */
70 double current_pointer_y () const {
71 return _current_pointer_y;
74 /** @return current pointer frame */
75 nframes64_t current_pointer_frame () const {
76 return _current_pointer_frame;
79 /** Called to start a grab of an item.
80 * @param e Event that caused the grab to start.
81 * @param c Cursor to use, or 0.
83 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
85 virtual bool end_grab (GdkEvent *);
87 /** Called when a drag motion has occurred.
88 * @param e Event describing the motion.
89 * @param f true if this is the first movement, otherwise false.
91 virtual void motion (GdkEvent* e, bool f) = 0;
93 /** Called when a drag has finished.
94 * @param e Event describing the finish.
95 * @param m true if some movement occurred, otherwise false.
97 virtual void finished (GdkEvent* e, bool m) = 0;
99 /** @param m Mouse mode.
100 * @return true if this drag should happen in this mouse mode.
102 virtual bool active (Editing::MouseMode m) {
103 return (m != Editing::MouseGain);
106 /** @return true if a small threshold should be applied before a mouse movement
107 * is considered a drag, otherwise false.
109 virtual bool apply_move_threshold () const {
113 virtual bool allow_vertical_autoscroll () const {
118 nframes64_t adjusted_current_frame (GdkEvent *) const;
120 Editor* _editor; ///< our editor
121 ArdourCanvas::Item* _item; ///< our item
122 nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag
123 ///< to the start of the thing that is being dragged
124 nframes64_t _last_frame_position; ///< last position of the thing being dragged
125 nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0
126 nframes64_t _last_pointer_frame; ///< frame that the pointer was at last time a motion occurred
127 nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
128 double _original_x; ///< original world x of the thing being dragged
129 double _original_y; ///< original world y of the thing being dragged
130 double _grab_x; ///< item x of the grab start position
131 double _grab_y; ///< item y of the grab start position
132 double _current_pointer_x; ///< item x of the current pointer
133 double _current_pointer_y; ///< item y of the current pointer
134 double _last_pointer_x; ///< item x of the pointer last time a motion occurred
135 double _last_pointer_y; ///< item y of the pointer last time a motion occurred
136 bool _x_constrained; ///< true if x motion is constrained, otherwise false
137 bool _y_constrained; ///< true if y motion is constrained, otherwise false
138 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
139 bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
143 bool _ending; ///< true if end_grab is in progress, otherwise false
144 bool _had_movement; ///< true if movement has occurred, otherwise false
145 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
149 /** Abstract base class for drags that involve region(s) */
150 class RegionDrag : public Drag, public sigc::trackable
153 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
154 virtual ~RegionDrag () {}
158 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
159 std::list<RegionView*> _views; ///< all views that are being dragged
162 void region_going_away (RegionView *);
163 PBD::ScopedConnection death_connection;
167 /** Drags involving region motion from somewhere */
168 class RegionMotionDrag : public RegionDrag
172 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
173 virtual ~RegionMotionDrag () {}
175 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
176 virtual void motion (GdkEvent *, bool);
177 virtual void finished (GdkEvent *, bool) = 0;
180 struct TimeAxisViewSummary {
181 TimeAxisViewSummary () : height_list(512) {}
183 std::bitset<512> tracks;
184 std::vector<int32_t> height_list;
189 void copy_regions (GdkEvent *);
190 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
191 std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
192 double compute_x_delta (GdkEvent const *, nframes64_t *);
193 bool compute_y_delta (
194 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
195 int32_t *, int32_t *, int32_t *
198 TimeAxisViewSummary get_time_axis_view_summary ();
199 bool x_move_allowed () const;
201 TimeAxisView* _dest_trackview;
202 ARDOUR::layer_t _dest_layer;
203 bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
208 /** Drags to move (or copy) regions that are already shown in the GUI to
209 * somewhere different.
211 class RegionMoveDrag : public RegionMotionDrag
214 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
215 virtual ~RegionMoveDrag () {}
217 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
218 void motion (GdkEvent *, bool);
219 void finished (GdkEvent *, bool);
221 bool apply_move_threshold () const {
229 /** Drag to insert a region from somewhere */
230 class RegionInsertDrag : public RegionMotionDrag
233 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
235 void finished (GdkEvent *, bool);
238 /** Region drag in splice mode */
239 class RegionSpliceDrag : public RegionMoveDrag
242 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
244 void motion (GdkEvent *, bool);
245 void finished (GdkEvent *, bool);
248 /** Drags to create regions */
249 class RegionCreateDrag : public Drag
252 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
254 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
255 void motion (GdkEvent *, bool);
256 void finished (GdkEvent *, bool);
260 TimeAxisView* _dest_trackview;
263 /** Drags to resize MIDI notes */
264 class NoteResizeDrag : public Drag
267 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
269 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
270 void motion (GdkEvent *, bool);
271 void finished (GdkEvent *, bool);
274 MidiRegionView* region;
279 class NoteDrag : public Drag
282 NoteDrag (Editor*, ArdourCanvas::Item*);
284 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
285 void motion (GdkEvent *, bool);
286 void finished (GdkEvent *, bool);
289 MidiRegionView* region;
293 double drag_delta_note;
297 /** Drag of region gain */
298 class RegionGainDrag : public Drag
301 RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
303 void motion (GdkEvent *, bool);
304 void finished (GdkEvent *, bool);
305 bool active (Editing::MouseMode m) {
306 return (m == Editing::MouseGain);
310 /** Drag to trim region(s) */
311 class TrimDrag : public RegionDrag
320 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
322 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
323 void motion (GdkEvent *, bool);
324 void finished (GdkEvent *, bool);
328 Operation _operation;
331 /** Meter marker drag */
332 class MeterMarkerDrag : public Drag
335 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
337 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
338 void motion (GdkEvent *, bool);
339 void finished (GdkEvent *, bool);
342 MeterMarker* _marker;
346 /** Tempo marker drag */
347 class TempoMarkerDrag : public Drag
350 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
352 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
353 void motion (GdkEvent *, bool);
354 void finished (GdkEvent *, bool);
357 TempoMarker* _marker;
362 /** Drag of a cursor */
363 class CursorDrag : public Drag
366 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
368 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
369 void motion (GdkEvent *, bool);
370 void finished (GdkEvent *, bool);
372 bool active (Editing::MouseMode) {
376 bool allow_vertical_autoscroll () const {
381 EditorCursor* _cursor; ///< cursor being dragged
382 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
386 /** Region fade-in drag */
387 class FadeInDrag : public RegionDrag
390 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
392 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
393 void motion (GdkEvent *, bool);
394 void finished (GdkEvent *, bool);
397 /** Region fade-out drag */
398 class FadeOutDrag : public RegionDrag
401 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
403 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
404 void motion (GdkEvent *, bool);
405 void finished (GdkEvent *, bool);
409 class MarkerDrag : public Drag
412 MarkerDrag (Editor *, ArdourCanvas::Item *);
415 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
416 void motion (GdkEvent *, bool);
417 void finished (GdkEvent *, bool);
420 void update_item (ARDOUR::Location *);
422 Marker* _marker; ///< marker being dragged
423 std::list<ARDOUR::Location*> _copied_locations;
424 ArdourCanvas::Line* _line;
425 ArdourCanvas::Points _points;
428 /** Control point drag */
429 class ControlPointDrag : public Drag
432 ControlPointDrag (Editor *, ArdourCanvas::Item *);
434 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
435 void motion (GdkEvent *, bool);
436 void finished (GdkEvent *, bool);
438 bool active (Editing::MouseMode m);
442 ControlPoint* _point;
443 double _cumulative_x_drag;
444 double _cumulative_y_drag;
445 static double const _zero_gain_fraction;
448 /** Gain or automation line drag */
449 class LineDrag : public Drag
452 LineDrag (Editor *e, ArdourCanvas::Item *i);
454 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
455 void motion (GdkEvent *, bool);
456 void finished (GdkEvent *, bool);
458 bool active (Editing::MouseMode) {
464 AutomationLine* _line;
467 double _cumulative_y_drag;
470 /** Dragging of a rubberband rectangle for selecting things */
471 class RubberbandSelectDrag : public Drag
474 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
476 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
477 void motion (GdkEvent *, bool);
478 void finished (GdkEvent *, bool);
481 /** Region drag in time-FX mode */
482 class TimeFXDrag : public RegionDrag
485 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
487 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
488 void motion (GdkEvent *, bool);
489 void finished (GdkEvent *, bool);
492 /** Scrub drag in audition mode */
493 class ScrubDrag : public Drag
496 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
498 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
499 void motion (GdkEvent *, bool);
500 void finished (GdkEvent *, bool);
503 /** Drag in range select(gc_owner.get()) moAutomatable */
504 class SelectionDrag : public Drag
514 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
516 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
517 void motion (GdkEvent *, bool);
518 void finished (GdkEvent *, bool);
521 Operation _operation;
525 /** Range marker drag */
526 class RangeMarkerBarDrag : public Drag
531 CreateTransportMarker,
535 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
537 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
538 void motion (GdkEvent *, bool);
539 void finished (GdkEvent *, bool);
542 void update_item (ARDOUR::Location *);
544 Operation _operation;
545 ArdourCanvas::SimpleRect* _drag_rect;
549 /* Drag of rectangle to set zoom */
550 class MouseZoomDrag : public Drag
553 MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
555 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
556 void motion (GdkEvent *, bool);
557 void finished (GdkEvent *, bool);
560 #endif /* __gtk2_ardour_editor_drag_h_ */