X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_drag.h;h=fb5ef3da9e80c201da46b8b59543fae6d7375cff;hb=129ace60e24aa7b5297563d389edbae1d70a3a80;hp=97e503f0d680de2829eb4fb3609cfbaf85e6bea3;hpb=402cc384ced6cb152c8abe4294009fe0de0a6dea;p=ardour.git diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 97e503f0d6..fb5ef3da9e 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Paul Davis + Copyright (C) 2009 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,36 +37,40 @@ namespace ARDOUR { class Editor; class EditorCursor; class TimeAxisView; +class Drag; -/** Abstract base class for dragging of things within the editor */ -class Drag +/** Class to manage current drags */ +class DragManager { - public: - Drag (Editor *, ArdourCanvas::Item *); - virtual ~Drag () {} - /** @return the canvas item being dragged */ - ArdourCanvas::Item* item () const { - return _item; - } + DragManager (Editor* e); + ~DragManager (); - void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t); - void break_drag (); + bool motion_handler (GdkEvent *, bool); - bool motion_handler (GdkEvent*, bool); + void abort (); + void add (Drag *); + void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0); + void start_grab (GdkEvent *); + bool end_grab (GdkEvent *); + bool have_item (ArdourCanvas::Item *) const; - /** @return true if an end drag is in progress */ + /** @return true if an end drag or abort is in progress */ bool ending () const { return _ending; } - /** @return current pointer x position in item coordinates */ + bool active () const { + return !_drags.empty (); + } + + /** @return current pointer x position in trackview coordinates */ double current_pointer_x () const { return _current_pointer_x; } - /** @return current pointer y position in item coordinates */ + /** @return current pointer y position in trackview coordinates */ double current_pointer_y () const { return _current_pointer_y; } @@ -76,6 +80,38 @@ public: return _current_pointer_frame; } +private: + Editor* _editor; + std::list _drags; + bool _ending; ///< true if end_grab or abort is in progress, otherwise false + double _current_pointer_x; ///< trackview x of the current pointer + double _current_pointer_y; ///< trackview y of the current pointer + nframes64_t _current_pointer_frame; ///< frame that the pointer is now at +}; + +/** Abstract base class for dragging of things within the editor */ +class Drag +{ +public: + Drag (Editor *, ArdourCanvas::Item *); + virtual ~Drag () {} + + void set_manager (DragManager* m) { + _drags = m; + } + + /** @return the canvas item being dragged */ + ArdourCanvas::Item* item () const { + return _item; + } + + void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t); + bool motion_handler (GdkEvent*, bool); + void abort (); + + nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const; + nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const; + /** Called to start a grab of an item. * @param e Event that caused the grab to start. * @param c Cursor to use, or 0. @@ -96,6 +132,11 @@ public: */ virtual void finished (GdkEvent* e, bool m) = 0; + /** Called to abort a drag and return things to how + * they were before it started. + */ + virtual void aborted () = 0; + /** @param m Mouse mode. * @return true if this drag should happen in this mouse mode. */ @@ -103,47 +144,78 @@ public: return (m != Editing::MouseGain); } - /** @return true if a small threshold should be applied before a mouse movement - * is considered a drag, otherwise false. - */ - virtual bool apply_move_threshold () const { - return false; + /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */ + virtual std::pair move_threshold () const { + return std::make_pair (1, 1); } virtual bool allow_vertical_autoscroll () const { return true; } + /** @return true if x movement matters to this drag */ + virtual bool x_movement_matters () const { + return true; + } + + /** @return true if y movement matters to this drag */ + virtual bool y_movement_matters () const { + return true; + } + protected: - nframes64_t adjusted_current_frame (GdkEvent *) const; - + + double grab_x () const { + return _grab_x; + } + + double grab_y () const { + return _grab_y; + } + + double grab_frame () const { + return _grab_frame; + } + + double last_pointer_x () const { + return _last_pointer_x; + } + + double last_pointer_y () const { + return _last_pointer_y; + } + + double last_pointer_frame () const { + return _last_pointer_frame; + } + Editor* _editor; ///< our editor + DragManager* _drags; ArdourCanvas::Item* _item; ///< our item - nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag - ///< to the start of the thing that is being dragged - nframes64_t _last_frame_position; ///< last position of the thing being dragged - nframes64_t _grab_frame; ///< frame that the mouse was at when start_grab was called, or 0 - nframes64_t _last_pointer_frame; ///< frame that the pointer was at last time a motion occurred - nframes64_t _current_pointer_frame; ///< frame that the pointer is now at - double _original_x; ///< original world x of the thing being dragged - double _original_y; ///< original world y of the thing being dragged - double _grab_x; ///< item x of the grab start position - double _grab_y; ///< item y of the grab start position - double _current_pointer_x; ///< item x of the current pointer - double _current_pointer_y; ///< item y of the current pointer - double _last_pointer_x; ///< item x of the pointer last time a motion occurred - double _last_pointer_y; ///< item y of the pointer last time a motion occurred + /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */ + nframes64_t _pointer_frame_offset; bool _x_constrained; ///< true if x motion is constrained, otherwise false bool _y_constrained; ///< true if y motion is constrained, otherwise false bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false private: - - bool _ending; ///< true if end_grab is in progress, otherwise false - bool _had_movement; ///< true if movement has occurred, otherwise false + bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false + double _grab_x; ///< trackview x of the grab start position + double _grab_y; ///< trackview y of the grab start position + double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred + double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred + nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0 + nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred }; +struct DraggingView +{ + DraggingView (RegionView* v); + + RegionView* view; ///< the view + double initial_y; ///< the initial y position of the view before any reparenting +}; /** Abstract base class for drags that involve region(s) */ class RegionDrag : public Drag, public sigc::trackable @@ -153,12 +225,13 @@ public: virtual ~RegionDrag () {} protected: - + RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag - std::list _views; ///< all views that are being dragged + std::list _views; ///< information about all views that are being dragged private: void region_going_away (RegionView *); + PBD::ScopedConnection death_connection; }; @@ -166,27 +239,28 @@ private: class RegionMotionDrag : public RegionDrag { public: - + RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list const &, bool); virtual ~RegionMotionDrag () {} virtual void start_grab (GdkEvent *, Gdk::Cursor *); virtual void motion (GdkEvent *, bool); virtual void finished (GdkEvent *, bool) = 0; + virtual void aborted (); protected: struct TimeAxisViewSummary { TimeAxisViewSummary () : height_list(512) {} - + std::bitset<512> tracks; std::vector height_list; int visible_y_low; int visible_y_high; }; - + void copy_regions (GdkEvent *); bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const; - std::map find_time_axis_views (); + std::map > find_time_axis_views_and_layers (); double compute_x_delta (GdkEvent const *, nframes64_t *); bool compute_y_delta ( TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &, @@ -194,12 +268,14 @@ protected: ); TimeAxisViewSummary get_time_axis_view_summary (); - virtual bool x_move_allowed () const = 0; - + bool x_move_allowed () const; + TimeAxisView* _dest_trackview; ARDOUR::layer_t _dest_layer; bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *); bool _brushing; + nframes64_t _last_frame_position; ///< last position of the thing being dragged + double _total_x_delta; }; @@ -215,14 +291,13 @@ public: virtual void start_grab (GdkEvent *, Gdk::Cursor *); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); - - bool apply_move_threshold () const { - return true; + void aborted (); + + std::pair move_threshold () const { + return std::make_pair (4, 4); } private: - bool x_move_allowed () const; - bool _copy; }; @@ -233,9 +308,7 @@ public: RegionInsertDrag (Editor *, boost::shared_ptr, RouteTimeAxisView*, nframes64_t); void finished (GdkEvent *, bool); - -private: - bool x_move_allowed () const; + void aborted (); }; /** Region drag in splice mode */ @@ -246,6 +319,7 @@ public: void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); }; /** Drags to create regions */ @@ -257,12 +331,49 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); private: TimeAxisView* _view; TimeAxisView* _dest_trackview; }; +/** Drags to resize MIDI notes */ +class NoteResizeDrag : public Drag +{ +public: + NoteResizeDrag (Editor *, ArdourCanvas::Item *); + + void start_grab (GdkEvent *, Gdk::Cursor* c = 0); + void motion (GdkEvent *, bool); + void finished (GdkEvent *, bool); + void aborted (); + +private: + MidiRegionView* region; + bool relative; + bool at_front; +}; + +class NoteDrag : public Drag +{ + public: + NoteDrag (Editor*, ArdourCanvas::Item*); + + void start_grab (GdkEvent *, Gdk::Cursor* c = 0); + void motion (GdkEvent *, bool); + void finished (GdkEvent *, bool); + void aborted (); + + private: + MidiRegionView* region; + double last_x; + double last_y; + double drag_delta_x; + double drag_delta_note; + bool was_selected; +}; + /** Drag of region gain */ class RegionGainDrag : public Drag { @@ -274,6 +385,8 @@ public: bool active (Editing::MouseMode m) { return (m == Editing::MouseGain); } + + void aborted (); }; /** Drag to trim region(s) */ @@ -291,10 +404,16 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool y_movement_matters () const { + return false; + } private: Operation _operation; + bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class. }; /** Meter marker drag */ @@ -306,7 +425,16 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool allow_vertical_autoscroll () const { + return false; + } + bool y_movement_matters () const { + return false; + } + private: MeterMarker* _marker; bool _copy; @@ -321,6 +449,15 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool allow_vertical_autoscroll () const { + return false; + } + + bool y_movement_matters () const { + return false; + } private: TempoMarker* _marker; @@ -337,6 +474,7 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); bool active (Editing::MouseMode) { return true; @@ -346,10 +484,14 @@ public: return false; } + bool y_movement_matters () const { + return false; + } + private: EditorCursor* _cursor; ///< cursor being dragged bool _stop; ///< true to stop the transport on starting the drag, otherwise false - + }; /** Region fade-in drag */ @@ -361,6 +503,11 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool y_movement_matters () const { + return false; + } }; /** Region fade-out drag */ @@ -372,6 +519,11 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool y_movement_matters () const { + return false; + } }; /** Marker drag */ @@ -384,10 +536,19 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + bool allow_vertical_autoscroll () const { + return false; + } + + bool y_movement_matters () const { + return false; + } + private: void update_item (ARDOUR::Location *); - + Marker* _marker; ///< marker being dragged std::list _copied_locations; ArdourCanvas::Line* _line; @@ -403,12 +564,15 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); bool active (Editing::MouseMode m); private: - + ControlPoint* _point; + double _time_axis_view_grab_x; + double _time_axis_view_grab_y; double _cumulative_x_drag; double _cumulative_y_drag; static double const _zero_gain_fraction; @@ -423,7 +587,8 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); - + void aborted (); + bool active (Editing::MouseMode) { return true; } @@ -431,6 +596,8 @@ public: private: AutomationLine* _line; + double _time_axis_view_grab_x; + double _time_axis_view_grab_y; uint32_t _before; uint32_t _after; double _cumulative_y_drag; @@ -445,6 +612,11 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + std::pair move_threshold () const { + return std::make_pair (8, 1); + } }; /** Region drag in time-FX mode */ @@ -456,6 +628,7 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); }; /** Scrub drag in audition mode */ @@ -463,13 +636,14 @@ class ScrubDrag : public Drag { public: ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {} - + void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); }; -/** Drag in range select(gc_owner.get()) moAutomatable */ +/** Drag in range select mode */ class SelectionDrag : public Drag { public: @@ -485,10 +659,14 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); private: Operation _operation; bool _copy; + int _original_pointer_time_axis; + int _last_pointer_time_axis; + std::list _added_time_axes; }; /** Range marker drag */ @@ -506,6 +684,15 @@ public: void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); + + bool allow_vertical_autoscroll () const { + return false; + } + + bool y_movement_matters () const { + return false; + } private: void update_item (ARDOUR::Location *); @@ -515,15 +702,38 @@ private: bool _copy; }; -/* Drag of rectangle to set zoom */ +/** Drag of rectangle to set zoom */ class MouseZoomDrag : public Drag { public: - MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {} + MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {} void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void motion (GdkEvent *, bool); void finished (GdkEvent *, bool); + void aborted (); +}; + +/** Drag of a range of automation data, changing value but not position */ +class AutomationRangeDrag : public Drag +{ +public: + AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list const &); + + void start_grab (GdkEvent *, Gdk::Cursor* c = 0); + void motion (GdkEvent *, bool); + void finished (GdkEvent *, bool); + void aborted (); + + bool x_movement_matters () const { + return false; + } + +private: + std::list _ranges; + AutomationTimeAxisView* _atav; + boost::shared_ptr _line; + bool _nothing_to_drag; }; #endif /* __gtk2_ardour_editor_drag_h_ */