colinf's vertical double arrow track resize cursor patch
[ardour.git] / gtk2_ardour / editor_drag.h
index 5d8cf390903c85eef6bdcb5f2564ce49ca358de7..fb66a2c74665a86baa060312665c670d504310eb 100644 (file)
@@ -37,30 +37,35 @@ 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 break_drag ();
+       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 break_drag is in progress */
        bool ending () const {
                return _ending;
        }
 
+       bool active () const {
+               return !_drags.empty ();
+       }
+
        /** @return current pointer x position in trackview coordinates */
        double current_pointer_x () const {
                return _current_pointer_x;
@@ -71,6 +76,40 @@ public:
                return _current_pointer_y;
        }
 
+       /** @return current pointer frame */
+       nframes64_t current_pointer_frame () const {
+               return _current_pointer_frame;
+       }
+
+private:
+       Editor* _editor;
+       std::list<Drag*> _drags;
+       bool _ending; ///< true if end_grab or break_drag 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 break_drag ();
+
        nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
        nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
        
@@ -94,6 +133,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.
         */
@@ -147,29 +191,23 @@ protected:
        }
 
        Editor* _editor; ///< our editor
+       DragManager* _drags;
        ArdourCanvas::Item* _item; ///< our item
        /** 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
-       bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
 
 private:
 
-       bool _ending; ///< true if end_grab is in progress, otherwise false
        bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
-       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; ///< trackview x of the grab start position
        double _grab_y; ///< trackview y of the grab start position
-       double _current_pointer_x; ///< trackview x of the current pointer
-       double _current_pointer_y; ///< trackview y of the current pointer
        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
-       nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
 };
 
 
@@ -202,6 +240,7 @@ public:
        virtual void start_grab (GdkEvent *, Gdk::Cursor *);
        virtual void motion (GdkEvent *, bool);
        virtual void finished (GdkEvent *, bool) = 0;
+       virtual void aborted ();
 
 protected:
        struct TimeAxisViewSummary {
@@ -230,6 +269,7 @@ protected:
        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;
 };
 
 
@@ -245,6 +285,7 @@ public:
        virtual void start_grab (GdkEvent *, Gdk::Cursor *);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
        std::pair<nframes64_t, int> move_threshold () const {
                return std::make_pair (4, 4);
@@ -261,6 +302,7 @@ public:
        RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
 
        void finished (GdkEvent *, bool);
+       void aborted ();
 };
 
 /** Region drag in splice mode */
@@ -271,6 +313,7 @@ public:
 
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 };
 
 /** Drags to create regions */
@@ -282,6 +325,7 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
 private:
        TimeAxisView* _view;
@@ -297,6 +341,7 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
 private:
        MidiRegionView*     region;
@@ -312,6 +357,7 @@ class NoteDrag : public Drag
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
   private:
        MidiRegionView* region;
@@ -333,6 +379,8 @@ public:
        bool active (Editing::MouseMode m) {
                return (m == Editing::MouseGain);
        }
+
+       void aborted ();
 };
 
 /** Drag to trim region(s) */
@@ -350,6 +398,7 @@ 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;
@@ -358,6 +407,7 @@ public:
 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 */
@@ -369,6 +419,7 @@ 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;
@@ -392,6 +443,7 @@ 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;
@@ -416,6 +468,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;
@@ -444,6 +497,7 @@ 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;
@@ -459,6 +513,7 @@ 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;
@@ -475,6 +530,7 @@ 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;
@@ -502,6 +558,7 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
        bool active (Editing::MouseMode m);
 
@@ -524,6 +581,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;
@@ -548,6 +606,11 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
+
+       std::pair<nframes64_t, int> move_threshold () const {
+               return std::make_pair (8, 1);
+       }
 };
 
 /** Region drag in time-FX mode */
@@ -559,6 +622,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 */
@@ -570,6 +634,7 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 };
 
 /** Drag in range select mode */
@@ -588,6 +653,7 @@ public:
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
        void motion (GdkEvent *, bool);
        void finished (GdkEvent *, bool);
+       void aborted ();
 
 private:
        Operation _operation;
@@ -612,6 +678,11 @@ 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;
@@ -634,6 +705,7 @@ public:
        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 */
@@ -645,6 +717,7 @@ public:
        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;