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"
43 /** Class to manage current drags */
48 DragManager (Editor
* e
);
51 bool motion_handler (GdkEvent
*, bool);
55 void set (Drag
*, GdkEvent
*, Gdk::Cursor
* c
= 0);
56 void start_grab (GdkEvent
*);
57 bool end_grab (GdkEvent
*);
58 bool have_item (ArdourCanvas::Item
*) const;
60 /** @return true if an end drag or abort is in progress */
61 bool ending () const {
65 bool active () const {
66 return !_drags
.empty ();
69 /** @return current pointer x position in trackview coordinates */
70 double current_pointer_x () const {
71 return _current_pointer_x
;
74 /** @return current pointer y position in trackview coordinates */
75 double current_pointer_y () const {
76 return _current_pointer_y
;
79 /** @return current pointer frame */
80 nframes64_t
current_pointer_frame () const {
81 return _current_pointer_frame
;
86 std::list
<Drag
*> _drags
;
87 bool _ending
; ///< true if end_grab or abort is in progress, otherwise false
88 double _current_pointer_x
; ///< trackview x of the current pointer
89 double _current_pointer_y
; ///< trackview y of the current pointer
90 nframes64_t _current_pointer_frame
; ///< frame that the pointer is now at
93 /** Abstract base class for dragging of things within the editor */
97 Drag (Editor
*, ArdourCanvas::Item
*);
100 void set_manager (DragManager
* m
) {
104 /** @return the canvas item being dragged */
105 ArdourCanvas::Item
* item () const {
109 void swap_grab (ArdourCanvas::Item
*, Gdk::Cursor
*, uint32_t);
110 bool motion_handler (GdkEvent
*, bool);
113 nframes64_t
adjusted_frame (nframes64_t
, GdkEvent
const *, bool snap
= true) const;
114 nframes64_t
adjusted_current_frame (GdkEvent
const *, bool snap
= true) const;
116 /** Called to start a grab of an item.
117 * @param e Event that caused the grab to start.
118 * @param c Cursor to use, or 0.
120 virtual void start_grab (GdkEvent
* e
, Gdk::Cursor
* c
= 0);
122 virtual bool end_grab (GdkEvent
*);
124 /** Called when a drag motion has occurred.
125 * @param e Event describing the motion.
126 * @param f true if this is the first movement, otherwise false.
128 virtual void motion (GdkEvent
* e
, bool f
) = 0;
130 /** Called when a drag has finished.
131 * @param e Event describing the finish.
132 * @param m true if some movement occurred, otherwise false.
134 virtual void finished (GdkEvent
* e
, bool m
) = 0;
136 /** Called to abort a drag and return things to how
137 * they were before it started.
139 virtual void aborted () = 0;
141 /** @param m Mouse mode.
142 * @return true if this drag should happen in this mouse mode.
144 virtual bool active (Editing::MouseMode m
) {
145 return (m
!= Editing::MouseGain
);
148 /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
149 virtual std::pair
<nframes64_t
, int> move_threshold () const {
150 return std::make_pair (1, 1);
153 virtual bool allow_vertical_autoscroll () const {
157 /** @return true if x movement matters to this drag */
158 virtual bool x_movement_matters () const {
162 /** @return true if y movement matters to this drag */
163 virtual bool y_movement_matters () const {
169 double grab_x () const {
173 double grab_y () const {
177 double grab_frame () const {
181 double last_pointer_x () const {
182 return _last_pointer_x
;
185 double last_pointer_y () const {
186 return _last_pointer_y
;
189 double last_pointer_frame () const {
190 return _last_pointer_frame
;
193 Editor
* _editor
; ///< our editor
195 ArdourCanvas::Item
* _item
; ///< our item
196 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
197 nframes64_t _pointer_frame_offset
;
198 bool _x_constrained
; ///< true if x motion is constrained, otherwise false
199 bool _y_constrained
; ///< true if y motion is constrained, otherwise false
200 bool _was_rolling
; ///< true if the session was rolling before the drag started, otherwise false
204 bool _move_threshold_passed
; ///< true if the move threshold has been passed, otherwise false
205 double _grab_x
; ///< trackview x of the grab start position
206 double _grab_y
; ///< trackview y of the grab start position
207 double _last_pointer_x
; ///< trackview x of the pointer last time a motion occurred
208 double _last_pointer_y
; ///< trackview y of the pointer last time a motion occurred
209 nframes64_t _grab_frame
; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
210 nframes64_t _last_pointer_frame
; ///< adjusted_frame the last time a motion occurred
215 DraggingView (RegionView
* v
);
217 RegionView
* view
; ///< the view
218 double initial_y
; ///< the initial y position of the view before any reparenting
221 /** Abstract base class for drags that involve region(s) */
222 class RegionDrag
: public Drag
, public sigc::trackable
225 RegionDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &);
226 virtual ~RegionDrag () {}
230 RegionView
* _primary
; ///< the view that was clicked on (or whatever) to start the drag
231 std::list
<DraggingView
> _views
; ///< information about all views that are being dragged
234 void region_going_away (RegionView
*);
235 PBD::ScopedConnection death_connection
;
239 /** Drags involving region motion from somewhere */
240 class RegionMotionDrag
: public RegionDrag
244 RegionMotionDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &, bool);
245 virtual ~RegionMotionDrag () {}
247 virtual void start_grab (GdkEvent
*, Gdk::Cursor
*);
248 virtual void motion (GdkEvent
*, bool);
249 virtual void finished (GdkEvent
*, bool) = 0;
250 virtual void aborted ();
253 struct TimeAxisViewSummary
{
254 TimeAxisViewSummary () : height_list(512) {}
256 std::bitset
<512> tracks
;
257 std::vector
<int32_t> height_list
;
262 void copy_regions (GdkEvent
*);
263 bool y_movement_disallowed (int, int, int, TimeAxisViewSummary
const &) const;
264 std::map
<RegionView
*, std::pair
<RouteTimeAxisView
*, int> > find_time_axis_views_and_layers ();
265 double compute_x_delta (GdkEvent
const *, nframes64_t
*);
266 bool compute_y_delta (
267 TimeAxisView
const *, TimeAxisView
*, int32_t, int32_t, TimeAxisViewSummary
const &,
268 int32_t *, int32_t *, int32_t *
271 TimeAxisViewSummary
get_time_axis_view_summary ();
272 bool x_move_allowed () const;
274 TimeAxisView
* _dest_trackview
;
275 ARDOUR::layer_t _dest_layer
;
276 bool check_possible (RouteTimeAxisView
**, ARDOUR::layer_t
*);
278 nframes64_t _last_frame_position
; ///< last position of the thing being dragged
279 double _total_x_delta
;
283 /** Drags to move (or copy) regions that are already shown in the GUI to
284 * somewhere different.
286 class RegionMoveDrag
: public RegionMotionDrag
289 RegionMoveDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &, bool, bool);
290 virtual ~RegionMoveDrag () {}
292 virtual void start_grab (GdkEvent
*, Gdk::Cursor
*);
293 void motion (GdkEvent
*, bool);
294 void finished (GdkEvent
*, bool);
297 std::pair
<nframes64_t
, int> move_threshold () const {
298 return std::make_pair (4, 4);
305 /** Drag to insert a region from somewhere */
306 class RegionInsertDrag
: public RegionMotionDrag
309 RegionInsertDrag (Editor
*, boost::shared_ptr
<ARDOUR::Region
>, RouteTimeAxisView
*, nframes64_t
);
311 void finished (GdkEvent
*, bool);
315 /** Region drag in splice mode */
316 class RegionSpliceDrag
: public RegionMoveDrag
319 RegionSpliceDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &);
321 void motion (GdkEvent
*, bool);
322 void finished (GdkEvent
*, bool);
326 /** Drags to create regions */
327 class RegionCreateDrag
: public Drag
330 RegionCreateDrag (Editor
*, ArdourCanvas::Item
*, TimeAxisView
*);
332 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
333 void motion (GdkEvent
*, bool);
334 void finished (GdkEvent
*, bool);
339 TimeAxisView
* _dest_trackview
;
342 /** Drags to resize MIDI notes */
343 class NoteResizeDrag
: public Drag
346 NoteResizeDrag (Editor
*, ArdourCanvas::Item
*);
348 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
349 void motion (GdkEvent
*, bool);
350 void finished (GdkEvent
*, bool);
354 MidiRegionView
* region
;
359 class NoteDrag
: public Drag
362 NoteDrag (Editor
*, ArdourCanvas::Item
*);
364 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
365 void motion (GdkEvent
*, bool);
366 void finished (GdkEvent
*, bool);
370 MidiRegionView
* region
;
374 double drag_delta_note
;
378 /** Drag of region gain */
379 class RegionGainDrag
: public Drag
382 RegionGainDrag (Editor
*e
, ArdourCanvas::Item
*i
) : Drag (e
, i
) {}
384 void motion (GdkEvent
*, bool);
385 void finished (GdkEvent
*, bool);
386 bool active (Editing::MouseMode m
) {
387 return (m
== Editing::MouseGain
);
393 /** Drag to trim region(s) */
394 class TrimDrag
: public RegionDrag
403 TrimDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &);
405 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
406 void motion (GdkEvent
*, bool);
407 void finished (GdkEvent
*, bool);
410 bool y_movement_matters () const {
416 Operation _operation
;
417 bool _have_transaction
; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
420 /** Meter marker drag */
421 class MeterMarkerDrag
: public Drag
424 MeterMarkerDrag (Editor
*, ArdourCanvas::Item
*, bool);
426 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
427 void motion (GdkEvent
*, bool);
428 void finished (GdkEvent
*, bool);
431 bool allow_vertical_autoscroll () const {
435 bool y_movement_matters () const {
440 MeterMarker
* _marker
;
444 /** Tempo marker drag */
445 class TempoMarkerDrag
: public Drag
448 TempoMarkerDrag (Editor
*, ArdourCanvas::Item
*, bool);
450 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
451 void motion (GdkEvent
*, bool);
452 void finished (GdkEvent
*, bool);
455 bool allow_vertical_autoscroll () const {
459 bool y_movement_matters () const {
464 TempoMarker
* _marker
;
469 /** Drag of a cursor */
470 class CursorDrag
: public Drag
473 CursorDrag (Editor
*, ArdourCanvas::Item
*, bool);
475 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
476 void motion (GdkEvent
*, bool);
477 void finished (GdkEvent
*, bool);
480 bool active (Editing::MouseMode
) {
484 bool allow_vertical_autoscroll () const {
488 bool y_movement_matters () const {
493 EditorCursor
* _cursor
; ///< cursor being dragged
494 bool _stop
; ///< true to stop the transport on starting the drag, otherwise false
498 /** Region fade-in drag */
499 class FadeInDrag
: public RegionDrag
502 FadeInDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &);
504 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
505 void motion (GdkEvent
*, bool);
506 void finished (GdkEvent
*, bool);
509 bool y_movement_matters () const {
514 /** Region fade-out drag */
515 class FadeOutDrag
: public RegionDrag
518 FadeOutDrag (Editor
*, ArdourCanvas::Item
*, RegionView
*, std::list
<RegionView
*> const &);
520 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
521 void motion (GdkEvent
*, bool);
522 void finished (GdkEvent
*, bool);
525 bool y_movement_matters () const {
531 class MarkerDrag
: public Drag
534 MarkerDrag (Editor
*, ArdourCanvas::Item
*);
537 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
538 void motion (GdkEvent
*, bool);
539 void finished (GdkEvent
*, bool);
542 bool allow_vertical_autoscroll () const {
546 bool y_movement_matters () const {
551 void update_item (ARDOUR::Location
*);
553 Marker
* _marker
; ///< marker being dragged
554 std::list
<ARDOUR::Location
*> _copied_locations
;
555 ArdourCanvas::Line
* _line
;
556 ArdourCanvas::Points _points
;
559 /** Control point drag */
560 class ControlPointDrag
: public Drag
563 ControlPointDrag (Editor
*, ArdourCanvas::Item
*);
565 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
566 void motion (GdkEvent
*, bool);
567 void finished (GdkEvent
*, bool);
570 bool active (Editing::MouseMode m
);
574 ControlPoint
* _point
;
575 double _time_axis_view_grab_x
;
576 double _time_axis_view_grab_y
;
577 double _cumulative_x_drag
;
578 double _cumulative_y_drag
;
579 static double const _zero_gain_fraction
;
582 /** Gain or automation line drag */
583 class LineDrag
: public Drag
586 LineDrag (Editor
*e
, ArdourCanvas::Item
*i
);
588 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
589 void motion (GdkEvent
*, bool);
590 void finished (GdkEvent
*, bool);
593 bool active (Editing::MouseMode
) {
599 AutomationLine
* _line
;
600 double _time_axis_view_grab_x
;
601 double _time_axis_view_grab_y
;
604 double _cumulative_y_drag
;
607 /** Transient feature line drags*/
608 class FeatureLineDrag
: public Drag
611 FeatureLineDrag (Editor
*e
, ArdourCanvas::Item
*i
);
613 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
614 void motion (GdkEvent
*, bool);
615 void finished (GdkEvent
*, bool);
618 bool active (Editing::MouseMode
) {
624 ArdourCanvas::SimpleLine
* _line
;
625 AudioRegionView
* _arv
;
627 double _region_view_grab_x
;
628 double _cumulative_x_drag
;
634 /** Dragging of a rubberband rectangle for selecting things */
635 class RubberbandSelectDrag
: public Drag
638 RubberbandSelectDrag (Editor
*e
, ArdourCanvas::Item
*i
) : Drag (e
, i
) {}
640 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
641 void motion (GdkEvent
*, bool);
642 void finished (GdkEvent
*, bool);
645 std::pair
<nframes64_t
, int> move_threshold () const {
646 return std::make_pair (8, 1);
650 /** Region drag in time-FX mode */
651 class TimeFXDrag
: public RegionDrag
654 TimeFXDrag (Editor
*e
, ArdourCanvas::Item
*i
, RegionView
* p
, std::list
<RegionView
*> const & v
) : RegionDrag (e
, i
, p
, v
) {}
656 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
657 void motion (GdkEvent
*, bool);
658 void finished (GdkEvent
*, bool);
662 /** Scrub drag in audition mode */
663 class ScrubDrag
: public Drag
666 ScrubDrag (Editor
*e
, ArdourCanvas::Item
*i
) : Drag (e
, i
) {}
668 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
669 void motion (GdkEvent
*, bool);
670 void finished (GdkEvent
*, bool);
674 /** Drag in range select mode */
675 class SelectionDrag
: public Drag
685 SelectionDrag (Editor
*, ArdourCanvas::Item
*, Operation
);
687 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
688 void motion (GdkEvent
*, bool);
689 void finished (GdkEvent
*, bool);
693 Operation _operation
;
695 int _original_pointer_time_axis
;
696 int _last_pointer_time_axis
;
697 std::list
<TimeAxisView
*> _added_time_axes
;
700 /** Range marker drag */
701 class RangeMarkerBarDrag
: public Drag
706 CreateTransportMarker
,
710 RangeMarkerBarDrag (Editor
*, ArdourCanvas::Item
*, Operation
);
712 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
713 void motion (GdkEvent
*, bool);
714 void finished (GdkEvent
*, bool);
717 bool allow_vertical_autoscroll () const {
721 bool y_movement_matters () const {
726 void update_item (ARDOUR::Location
*);
728 Operation _operation
;
729 ArdourCanvas::SimpleRect
* _drag_rect
;
733 /** Drag of rectangle to set zoom */
734 class MouseZoomDrag
: public Drag
737 MouseZoomDrag (Editor
* e
, ArdourCanvas::Item
*i
) : Drag (e
, i
) {}
739 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
740 void motion (GdkEvent
*, bool);
741 void finished (GdkEvent
*, bool);
745 /** Drag of a range of automation data, changing value but not position */
746 class AutomationRangeDrag
: public Drag
749 AutomationRangeDrag (Editor
*, ArdourCanvas::Item
*, std::list
<ARDOUR::AudioRange
> const &);
751 void start_grab (GdkEvent
*, Gdk::Cursor
* c
= 0);
752 void motion (GdkEvent
*, bool);
753 void finished (GdkEvent
*, bool);
756 bool x_movement_matters () const {
761 std::list
<ARDOUR::AudioRange
> _ranges
;
762 AutomationTimeAxisView
* _atav
;
763 boost::shared_ptr
<AutomationLine
> _line
;
764 bool _nothing_to_drag
;
767 #endif /* __gtk2_ardour_editor_drag_h_ */