beat slicing patch #1 from lincoln spiteri
[ardour2.git] / gtk2_ardour / editor_drag.h
blob9e206cfebf712ad24bbb422e1fcada9b1b6befaa
1 /*
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_
23 #include <list>
25 #include <gdk/gdk.h>
26 #include <stdint.h>
27 #include <bitset>
29 #include "ardour/types.h"
31 #include "canvas.h"
32 #include "editor_items.h"
34 namespace ARDOUR {
35 class Location;
38 class Editor;
39 class EditorCursor;
40 class TimeAxisView;
41 class Drag;
43 /** Class to manage current drags */
44 class DragManager
46 public:
48 DragManager (Editor* e);
49 ~DragManager ();
51 bool motion_handler (GdkEvent *, bool);
53 void abort ();
54 void add (Drag *);
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 {
62 return _ending;
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;
84 private:
85 Editor* _editor;
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 */
94 class Drag
96 public:
97 Drag (Editor *, ArdourCanvas::Item *);
98 virtual ~Drag () {}
100 void set_manager (DragManager* m) {
101 _drags = m;
104 /** @return the canvas item being dragged */
105 ArdourCanvas::Item* item () const {
106 return _item;
109 void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
110 bool motion_handler (GdkEvent*, bool);
111 void abort ();
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 {
154 return true;
157 /** @return true if x movement matters to this drag */
158 virtual bool x_movement_matters () const {
159 return true;
162 /** @return true if y movement matters to this drag */
163 virtual bool y_movement_matters () const {
164 return true;
167 protected:
169 double grab_x () const {
170 return _grab_x;
173 double grab_y () const {
174 return _grab_y;
177 double grab_frame () const {
178 return _grab_frame;
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
194 DragManager* _drags;
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
202 private:
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
213 struct DraggingView
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
224 public:
225 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
226 virtual ~RegionDrag () {}
228 protected:
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
233 private:
234 void region_going_away (RegionView *);
235 PBD::ScopedConnection death_connection;
239 /** Drags involving region motion from somewhere */
240 class RegionMotionDrag : public RegionDrag
242 public:
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 ();
252 protected:
253 struct TimeAxisViewSummary {
254 TimeAxisViewSummary () : height_list(512) {}
256 std::bitset<512> tracks;
257 std::vector<int32_t> height_list;
258 int visible_y_low;
259 int visible_y_high;
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 *);
277 bool _brushing;
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
288 public:
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);
295 void aborted ();
297 std::pair<nframes64_t, int> move_threshold () const {
298 return std::make_pair (4, 4);
301 private:
302 bool _copy;
305 /** Drag to insert a region from somewhere */
306 class RegionInsertDrag : public RegionMotionDrag
308 public:
309 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
311 void finished (GdkEvent *, bool);
312 void aborted ();
315 /** Region drag in splice mode */
316 class RegionSpliceDrag : public RegionMoveDrag
318 public:
319 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
321 void motion (GdkEvent *, bool);
322 void finished (GdkEvent *, bool);
323 void aborted ();
326 /** Drags to create regions */
327 class RegionCreateDrag : public Drag
329 public:
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);
335 void aborted ();
337 private:
338 TimeAxisView* _view;
339 TimeAxisView* _dest_trackview;
342 /** Drags to resize MIDI notes */
343 class NoteResizeDrag : public Drag
345 public:
346 NoteResizeDrag (Editor *, ArdourCanvas::Item *);
348 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
349 void motion (GdkEvent *, bool);
350 void finished (GdkEvent *, bool);
351 void aborted ();
353 private:
354 MidiRegionView* region;
355 bool relative;
356 bool at_front;
359 class NoteDrag : public Drag
361 public:
362 NoteDrag (Editor*, ArdourCanvas::Item*);
364 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
365 void motion (GdkEvent *, bool);
366 void finished (GdkEvent *, bool);
367 void aborted ();
369 private:
370 MidiRegionView* region;
371 double last_x;
372 double last_y;
373 double drag_delta_x;
374 double drag_delta_note;
375 bool was_selected;
378 /** Drag of region gain */
379 class RegionGainDrag : public Drag
381 public:
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);
390 void aborted ();
393 /** Drag to trim region(s) */
394 class TrimDrag : public RegionDrag
396 public:
397 enum Operation {
398 StartTrim,
399 EndTrim,
400 ContentsTrim,
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);
408 void aborted ();
410 bool y_movement_matters () const {
411 return false;
414 private:
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
423 public:
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);
429 void aborted ();
431 bool allow_vertical_autoscroll () const {
432 return false;
435 bool y_movement_matters () const {
436 return false;
439 private:
440 MeterMarker* _marker;
441 bool _copy;
444 /** Tempo marker drag */
445 class TempoMarkerDrag : public Drag
447 public:
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);
453 void aborted ();
455 bool allow_vertical_autoscroll () const {
456 return false;
459 bool y_movement_matters () const {
460 return false;
463 private:
464 TempoMarker* _marker;
465 bool _copy;
469 /** Drag of a cursor */
470 class CursorDrag : public Drag
472 public:
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);
478 void aborted ();
480 bool active (Editing::MouseMode) {
481 return true;
484 bool allow_vertical_autoscroll () const {
485 return false;
488 bool y_movement_matters () const {
489 return false;
492 private:
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
501 public:
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);
507 void aborted ();
509 bool y_movement_matters () const {
510 return false;
514 /** Region fade-out drag */
515 class FadeOutDrag : public RegionDrag
517 public:
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);
523 void aborted ();
525 bool y_movement_matters () const {
526 return false;
530 /** Marker drag */
531 class MarkerDrag : public Drag
533 public:
534 MarkerDrag (Editor *, ArdourCanvas::Item *);
535 ~MarkerDrag ();
537 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
538 void motion (GdkEvent *, bool);
539 void finished (GdkEvent *, bool);
540 void aborted ();
542 bool allow_vertical_autoscroll () const {
543 return false;
546 bool y_movement_matters () const {
547 return false;
550 private:
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
562 public:
563 ControlPointDrag (Editor *, ArdourCanvas::Item *);
565 void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
566 void motion (GdkEvent *, bool);
567 void finished (GdkEvent *, bool);
568 void aborted ();
570 bool active (Editing::MouseMode m);
572 private:
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
585 public:
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);
591 void aborted ();
593 bool active (Editing::MouseMode) {
594 return true;
597 private:
599 AutomationLine* _line;
600 double _time_axis_view_grab_x;
601 double _time_axis_view_grab_y;
602 uint32_t _before;
603 uint32_t _after;
604 double _cumulative_y_drag;
607 /** Transient feature line drags*/
608 class FeatureLineDrag : public Drag
610 public:
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);
616 void aborted ();
618 bool active (Editing::MouseMode) {
619 return true;
622 private:
624 ArdourCanvas::SimpleLine* _line;
625 AudioRegionView* _arv;
627 double _region_view_grab_x;
628 double _cumulative_x_drag;
630 uint32_t _before;
631 uint32_t _max_x;
634 /** Dragging of a rubberband rectangle for selecting things */
635 class RubberbandSelectDrag : public Drag
637 public:
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);
643 void aborted ();
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
653 public:
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);
659 void aborted ();
662 /** Scrub drag in audition mode */
663 class ScrubDrag : public Drag
665 public:
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);
671 void aborted ();
674 /** Drag in range select mode */
675 class SelectionDrag : public Drag
677 public:
678 enum Operation {
679 CreateSelection,
680 SelectionStartTrim,
681 SelectionEndTrim,
682 SelectionMove
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);
690 void aborted ();
692 private:
693 Operation _operation;
694 bool _copy;
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
703 public:
704 enum Operation {
705 CreateRangeMarker,
706 CreateTransportMarker,
707 CreateCDMarker
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);
715 void aborted ();
717 bool allow_vertical_autoscroll () const {
718 return false;
721 bool y_movement_matters () const {
722 return false;
725 private:
726 void update_item (ARDOUR::Location *);
728 Operation _operation;
729 ArdourCanvas::SimpleRect* _drag_rect;
730 bool _copy;
733 /** Drag of rectangle to set zoom */
734 class MouseZoomDrag : public Drag
736 public:
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);
742 void aborted ();
745 /** Drag of a range of automation data, changing value but not position */
746 class AutomationRangeDrag : public Drag
748 public:
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);
754 void aborted ();
756 bool x_movement_matters () const {
757 return false;
760 private:
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_ */