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_current_frame (GdkEvent const *, bool snap = true) const;
76 /** Called to start a grab of an item.
77 * @param e Event that caused the grab to start.
78 * @param c Cursor to use, or 0.
80 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
82 virtual bool end_grab (GdkEvent *);
84 /** Called when a drag motion has occurred.
85 * @param e Event describing the motion.
86 * @param f true if this is the first movement, otherwise false.
88 virtual void motion (GdkEvent* e, bool f) = 0;
90 /** Called when a drag has finished.
91 * @param e Event describing the finish.
92 * @param m true if some movement occurred, otherwise false.
94 virtual void finished (GdkEvent* e, bool m) = 0;
96 /** @param m Mouse mode.
97 * @return true if this drag should happen in this mouse mode.
99 virtual bool active (Editing::MouseMode m) {
100 return (m != Editing::MouseGain);
103 /** @return true if a small threshold should be applied before a mouse movement
104 * is considered a drag, otherwise false.
106 virtual bool apply_move_threshold () const {
110 virtual bool allow_vertical_autoscroll () const {
116 double grab_x () const {
120 double grab_y () const {
124 double grab_frame () const {
128 double last_pointer_x () const {
129 return _last_pointer_x;
132 double last_pointer_y () const {
133 return _last_pointer_y;
136 double last_pointer_frame () const {
137 return _last_pointer_frame;
140 Editor* _editor; ///< our editor
141 ArdourCanvas::Item* _item; ///< our item
142 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
143 nframes64_t _pointer_frame_offset;
144 bool _x_constrained; ///< true if x motion is constrained, otherwise false
145 bool _y_constrained; ///< true if y motion is constrained, otherwise false
146 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
147 bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
151 bool _ending; ///< true if end_grab is in progress, otherwise false
152 bool _had_movement; ///< true if movement has occurred, otherwise false
153 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
154 double _original_x; ///< original world x of the thing being dragged
155 double _original_y; ///< original world y of the thing being dragged
156 double _grab_x; ///< trackview x of the grab start position
157 double _grab_y; ///< trackview y of the grab start position
158 double _current_pointer_x; ///< trackview x of the current pointer
159 double _current_pointer_y; ///< trackview y of the current pointer
160 double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
161 double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
162 nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0
163 nframes64_t _last_pointer_frame; ///< adjusted_current_frame the last time a motion occurred
164 nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
168 /** Abstract base class for drags that involve region(s) */
169 class RegionDrag : public Drag, public sigc::trackable
172 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
173 virtual ~RegionDrag () {}
177 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
178 std::list<RegionView*> _views; ///< all views that are being dragged
181 void region_going_away (RegionView *);
182 PBD::ScopedConnection death_connection;
186 /** Drags involving region motion from somewhere */
187 class RegionMotionDrag : public RegionDrag
191 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
192 virtual ~RegionMotionDrag () {}
194 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
195 virtual void motion (GdkEvent *, bool);
196 virtual void finished (GdkEvent *, bool) = 0;
199 struct TimeAxisViewSummary {
200 TimeAxisViewSummary () : height_list(512) {}
202 std::bitset<512> tracks;
203 std::vector<int32_t> height_list;
208 void copy_regions (GdkEvent *);
209 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
210 std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
211 double compute_x_delta (GdkEvent const *, nframes64_t *);
212 bool compute_y_delta (
213 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
214 int32_t *, int32_t *, int32_t *
217 TimeAxisViewSummary get_time_axis_view_summary ();
218 bool x_move_allowed () const;
220 TimeAxisView* _dest_trackview;
221 ARDOUR::layer_t _dest_layer;
222 bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
224 nframes64_t _last_frame_position; ///< last position of the thing being dragged
228 /** Drags to move (or copy) regions that are already shown in the GUI to
229 * somewhere different.
231 class RegionMoveDrag : public RegionMotionDrag
234 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
235 virtual ~RegionMoveDrag () {}
237 virtual void start_grab (GdkEvent *, Gdk::Cursor *);
238 void motion (GdkEvent *, bool);
239 void finished (GdkEvent *, bool);
241 bool apply_move_threshold () const {
249 /** Drag to insert a region from somewhere */
250 class RegionInsertDrag : public RegionMotionDrag
253 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
255 void finished (GdkEvent *, bool);
258 /** Region drag in splice mode */
259 class RegionSpliceDrag : public RegionMoveDrag
262 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
264 void motion (GdkEvent *, bool);
265 void finished (GdkEvent *, bool);
268 /** Drags to create regions */
269 class RegionCreateDrag : public Drag
272 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
274 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
275 void motion (GdkEvent *, bool);
276 void finished (GdkEvent *, bool);
280 TimeAxisView* _dest_trackview;
283 /** Drags to resize MIDI notes */
284 class NoteResizeDrag : public Drag
287 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
289 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
290 void motion (GdkEvent *, bool);
291 void finished (GdkEvent *, bool);
294 MidiRegionView* region;
299 class NoteDrag : public Drag
302 NoteDrag (Editor*, ArdourCanvas::Item*);
304 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
305 void motion (GdkEvent *, bool);
306 void finished (GdkEvent *, bool);
309 MidiRegionView* region;
313 double drag_delta_note;
317 /** Drag of region gain */
318 class RegionGainDrag : public Drag
321 RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
323 void motion (GdkEvent *, bool);
324 void finished (GdkEvent *, bool);
325 bool active (Editing::MouseMode m) {
326 return (m == Editing::MouseGain);
330 /** Drag to trim region(s) */
331 class TrimDrag : public RegionDrag
340 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
342 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
343 void motion (GdkEvent *, bool);
344 void finished (GdkEvent *, bool);
348 Operation _operation;
351 /** Meter marker drag */
352 class MeterMarkerDrag : public Drag
355 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
357 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
358 void motion (GdkEvent *, bool);
359 void finished (GdkEvent *, bool);
362 MeterMarker* _marker;
366 /** Tempo marker drag */
367 class TempoMarkerDrag : public Drag
370 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
372 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
373 void motion (GdkEvent *, bool);
374 void finished (GdkEvent *, bool);
377 TempoMarker* _marker;
382 /** Drag of a cursor */
383 class CursorDrag : public Drag
386 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
388 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
389 void motion (GdkEvent *, bool);
390 void finished (GdkEvent *, bool);
392 bool active (Editing::MouseMode) {
396 bool allow_vertical_autoscroll () const {
401 EditorCursor* _cursor; ///< cursor being dragged
402 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
406 /** Region fade-in drag */
407 class FadeInDrag : public RegionDrag
410 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
412 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
413 void motion (GdkEvent *, bool);
414 void finished (GdkEvent *, bool);
417 /** Region fade-out drag */
418 class FadeOutDrag : public RegionDrag
421 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
423 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
424 void motion (GdkEvent *, bool);
425 void finished (GdkEvent *, bool);
429 class MarkerDrag : public Drag
432 MarkerDrag (Editor *, ArdourCanvas::Item *);
435 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
436 void motion (GdkEvent *, bool);
437 void finished (GdkEvent *, bool);
440 void update_item (ARDOUR::Location *);
442 Marker* _marker; ///< marker being dragged
443 std::list<ARDOUR::Location*> _copied_locations;
444 ArdourCanvas::Line* _line;
445 ArdourCanvas::Points _points;
448 /** Control point drag */
449 class ControlPointDrag : public Drag
452 ControlPointDrag (Editor *, ArdourCanvas::Item *);
454 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
455 void motion (GdkEvent *, bool);
456 void finished (GdkEvent *, bool);
458 bool active (Editing::MouseMode m);
462 ControlPoint* _point;
463 double _time_axis_view_grab_x;
464 double _time_axis_view_grab_y;
465 nframes64_t _time_axis_view_grab_frame;
466 double _cumulative_x_drag;
467 double _cumulative_y_drag;
468 static double const _zero_gain_fraction;
471 /** Gain or automation line drag */
472 class LineDrag : public Drag
475 LineDrag (Editor *e, ArdourCanvas::Item *i);
477 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
478 void motion (GdkEvent *, bool);
479 void finished (GdkEvent *, bool);
481 bool active (Editing::MouseMode) {
487 AutomationLine* _line;
488 double _time_axis_view_grab_x;
489 double _time_axis_view_grab_y;
492 double _cumulative_y_drag;
495 /** Dragging of a rubberband rectangle for selecting things */
496 class RubberbandSelectDrag : public Drag
499 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
501 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
502 void motion (GdkEvent *, bool);
503 void finished (GdkEvent *, bool);
506 /** Region drag in time-FX mode */
507 class TimeFXDrag : public RegionDrag
510 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
512 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
513 void motion (GdkEvent *, bool);
514 void finished (GdkEvent *, bool);
517 /** Scrub drag in audition mode */
518 class ScrubDrag : public Drag
521 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
523 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
524 void motion (GdkEvent *, bool);
525 void finished (GdkEvent *, bool);
528 /** Drag in range select(gc_owner.get()) moAutomatable */
529 class SelectionDrag : public Drag
539 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
541 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
542 void motion (GdkEvent *, bool);
543 void finished (GdkEvent *, bool);
546 Operation _operation;
550 /** Range marker drag */
551 class RangeMarkerBarDrag : public Drag
556 CreateTransportMarker,
560 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
562 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
563 void motion (GdkEvent *, bool);
564 void finished (GdkEvent *, bool);
567 void update_item (ARDOUR::Location *);
569 Operation _operation;
570 ArdourCanvas::SimpleRect* _drag_rect;
574 /* Drag of rectangle to set zoom */
575 class MouseZoomDrag : public Drag
578 MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
580 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
581 void motion (GdkEvent *, bool);
582 void finished (GdkEvent *, bool);
585 #endif /* __gtk2_ardour_editor_drag_h_ */