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);
361 bool allow_vertical_autoscroll () const {
366 MeterMarker* _marker;
370 /** Tempo marker drag */
371 class TempoMarkerDrag : public Drag
374 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
376 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
377 void motion (GdkEvent *, bool);
378 void finished (GdkEvent *, bool);
380 bool allow_vertical_autoscroll () const {
385 TempoMarker* _marker;
390 /** Drag of a cursor */
391 class CursorDrag : public Drag
394 CursorDrag (Editor *, ArdourCanvas::Item *, bool);
396 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
397 void motion (GdkEvent *, bool);
398 void finished (GdkEvent *, bool);
400 bool active (Editing::MouseMode) {
404 bool allow_vertical_autoscroll () const {
409 EditorCursor* _cursor; ///< cursor being dragged
410 bool _stop; ///< true to stop the transport on starting the drag, otherwise false
414 /** Region fade-in drag */
415 class FadeInDrag : public RegionDrag
418 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
420 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
421 void motion (GdkEvent *, bool);
422 void finished (GdkEvent *, bool);
425 /** Region fade-out drag */
426 class FadeOutDrag : public RegionDrag
429 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
431 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
432 void motion (GdkEvent *, bool);
433 void finished (GdkEvent *, bool);
437 class MarkerDrag : public Drag
440 MarkerDrag (Editor *, ArdourCanvas::Item *);
443 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
444 void motion (GdkEvent *, bool);
445 void finished (GdkEvent *, bool);
447 bool allow_vertical_autoscroll () const {
452 void update_item (ARDOUR::Location *);
454 Marker* _marker; ///< marker being dragged
455 std::list<ARDOUR::Location*> _copied_locations;
456 ArdourCanvas::Line* _line;
457 ArdourCanvas::Points _points;
460 /** Control point drag */
461 class ControlPointDrag : public Drag
464 ControlPointDrag (Editor *, ArdourCanvas::Item *);
466 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
467 void motion (GdkEvent *, bool);
468 void finished (GdkEvent *, bool);
470 bool active (Editing::MouseMode m);
474 ControlPoint* _point;
475 double _time_axis_view_grab_x;
476 double _time_axis_view_grab_y;
477 double _cumulative_x_drag;
478 double _cumulative_y_drag;
479 static double const _zero_gain_fraction;
482 /** Gain or automation line drag */
483 class LineDrag : public Drag
486 LineDrag (Editor *e, ArdourCanvas::Item *i);
488 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
489 void motion (GdkEvent *, bool);
490 void finished (GdkEvent *, bool);
492 bool active (Editing::MouseMode) {
498 AutomationLine* _line;
499 double _time_axis_view_grab_x;
500 double _time_axis_view_grab_y;
503 double _cumulative_y_drag;
506 /** Dragging of a rubberband rectangle for selecting things */
507 class RubberbandSelectDrag : public Drag
510 RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
512 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
513 void motion (GdkEvent *, bool);
514 void finished (GdkEvent *, bool);
517 /** Region drag in time-FX mode */
518 class TimeFXDrag : public RegionDrag
521 TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
523 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
524 void motion (GdkEvent *, bool);
525 void finished (GdkEvent *, bool);
528 /** Scrub drag in audition mode */
529 class ScrubDrag : public Drag
532 ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
534 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
535 void motion (GdkEvent *, bool);
536 void finished (GdkEvent *, bool);
539 /** Drag in range select mode */
540 class SelectionDrag : public Drag
550 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
552 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
553 void motion (GdkEvent *, bool);
554 void finished (GdkEvent *, bool);
557 Operation _operation;
559 int _original_pointer_time_axis;
560 int _last_pointer_time_axis;
561 std::list<TimeAxisView*> _added_time_axes;
564 /** Range marker drag */
565 class RangeMarkerBarDrag : public Drag
570 CreateTransportMarker,
574 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
576 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
577 void motion (GdkEvent *, bool);
578 void finished (GdkEvent *, bool);
581 void update_item (ARDOUR::Location *);
583 Operation _operation;
584 ArdourCanvas::SimpleRect* _drag_rect;
588 /** Drag of rectangle to set zoom */
589 class MouseZoomDrag : public Drag
592 MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {}
594 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
595 void motion (GdkEvent *, bool);
596 void finished (GdkEvent *, bool);
599 /** Drag of a range of automation data, changing value but not position */
600 class AutomationRangeDrag : public Drag
603 AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
605 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
606 void motion (GdkEvent *, bool);
607 void finished (GdkEvent *, bool);
610 std::list<ARDOUR::AudioRange> _ranges;
611 AutomationTimeAxisView* _atav;
612 boost::shared_ptr<AutomationLine> _line;
613 bool _nothing_to_drag;
616 #endif /* __gtk2_ardour_editor_drag_h_ */