fix deadlock in protocol manager startup; fix some other ::set_session() SNAFUs;...
[ardour.git] / gtk2_ardour / editor_drag.h
index 1d0a366f151946ce9aec1cff559892aa7b8992f3..170c9a80802c84043e8641f790a1780fb2401c3a 100644 (file)
@@ -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
@@ -41,7 +41,7 @@ class TimeAxisView;
 /** Abstract base class for dragging of things within the editor */
 class Drag
 {
-       
+
 public:
        Drag (Editor *, ArdourCanvas::Item *);
        virtual ~Drag () {}
@@ -61,11 +61,6 @@ public:
                return _ending;
        }
 
-       /** @return true if the first move (past any move threshold) has occurred */
-       bool first_move () const {
-               return _first_move;
-       }
-
        /** @return current pointer x position in item coordinates */
        double current_pointer_x () const {
                return _current_pointer_x;
@@ -91,13 +86,15 @@ public:
 
        /** Called when a drag motion has occurred.
         *  @param e Event describing the motion.
+        *  @param f true if this is the first movement, otherwise false.
         */
-       virtual void motion (GdkEvent* e) = 0;
+       virtual void motion (GdkEvent* e, bool f) = 0;
 
        /** Called when a drag has finished.
         *  @param e Event describing the finish.
+        *  @param m true if some movement occurred, otherwise false.
         */
-       virtual void finished (GdkEvent *) = 0;
+       virtual void finished (GdkEvent* e, bool m) = 0;
 
        /** @param m Mouse mode.
         *  @return true if this drag should happen in this mouse mode.
@@ -106,12 +103,20 @@ public:
                return (m != Editing::MouseGain);
        }
 
-       /** Called when a subclass should update the editor's selection following a drag */
-       virtual void update_selection () {}
+       /** @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;
+       }
+
+       virtual bool allow_vertical_autoscroll () const {
+               return true;
+       }
 
 protected:
-       nframes64_t adjusted_current_frame () const;
-       
+       nframes64_t adjusted_current_frame (GdkEvent *) const;
+
        Editor* _editor; ///< our editor
        ArdourCanvas::Item* _item; ///< our item
        nframes64_t _pointer_frame_offset; ///< offset from the mouse's position for the drag
@@ -130,15 +135,14 @@ protected:
        double _last_pointer_y; ///< item y of the pointer last time a motion occurred
        bool _x_constrained; ///< true if x motion is constrained, otherwise false
        bool _y_constrained; ///< true if y motion is constrained, otherwise false
-       bool _copy; ///< true if we're copying the things that we're dragging
        bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
-       bool _first_move; ///< true if some movement has occurred, otherwise false
-       bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
-       bool _want_move_threshold; ///< true if a move threshold should be applied, 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 _had_movement; ///< true if movement has occurred, otherwise false
+       bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
 };
 
 
@@ -149,42 +153,86 @@ public:
        RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
        virtual ~RegionDrag () {}
 
-       void update_selection ();
-
 protected:
-       
+
        RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
        std::list<RegionView*> _views; ///< all views that are being dragged
 
 private:
        void region_going_away (RegionView *);
+       boost::signals2::scoped_connection death_connection;
 };
 
 
-/** Drags to move regions */
-class RegionMoveDrag : public RegionDrag
+/** Drags involving region motion from somewhere */
+class RegionMotionDrag : public RegionDrag
 {
 public:
-       RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
-       virtual ~RegionMoveDrag () {}
+
+       RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
+       virtual ~RegionMotionDrag () {}
 
        virtual void start_grab (GdkEvent *, Gdk::Cursor *);
-       virtual void motion (GdkEvent *);
-       virtual void finished (GdkEvent *);
+       virtual void motion (GdkEvent *, bool);
+       virtual void finished (GdkEvent *, bool) = 0;
 
 protected:
+       struct TimeAxisViewSummary {
+               TimeAxisViewSummary () : height_list(512) {}
 
-       bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
+               std::bitset<512> tracks;
+               std::vector<int32_t> 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<RegionView*, std::pair<RouteTimeAxisView*, int> > 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 &,
+               int32_t *, int32_t *, int32_t *
+               );
+
+       TimeAxisViewSummary get_time_axis_view_summary ();
+       bool x_move_allowed () const;
 
        TimeAxisView* _dest_trackview;
        ARDOUR::layer_t _dest_layer;
+       bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
+       bool _brushing;
+};
+
+
+/** Drags to move (or copy) regions that are already shown in the GUI to
+ *  somewhere different.
+ */
+class RegionMoveDrag : public RegionMotionDrag
+{
+public:
+       RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
+       virtual ~RegionMoveDrag () {}
+
+       virtual void start_grab (GdkEvent *, Gdk::Cursor *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
+
+       bool apply_move_threshold () const {
+               return true;
+       }
 
 private:
+       bool _copy;
+};
 
-       void copy_regions (GdkEvent *);
-       bool y_movement_disallowed (int, int, int, int, int, std::bitset<512> const &, std::vector<int32_t> const &) const;
+/** Drag to insert a region from somewhere */
+class RegionInsertDrag : public RegionMotionDrag
+{
+public:
+       RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
 
-       bool _brushing;
+       void finished (GdkEvent *, bool);
 };
 
 /** Region drag in splice mode */
@@ -193,8 +241,8 @@ class RegionSpliceDrag : public RegionMoveDrag
 public:
        RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
 
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 };
 
 /** Drags to create regions */
@@ -204,22 +252,56 @@ public:
        RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 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);
+
+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);
+
+  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
 {
 public:
        RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
 
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
        bool active (Editing::MouseMode m) {
                return (m == Editing::MouseGain);
        }
@@ -238,8 +320,8 @@ public:
        TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
 
@@ -253,11 +335,12 @@ public:
        MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
        MeterMarker* _marker;
+       bool _copy;
 };
 
 /** Tempo marker drag */
@@ -267,11 +350,12 @@ public:
        TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
        TempoMarker* _marker;
+       bool _copy;
 };
 
 
@@ -282,13 +366,21 @@ public:
        CursorDrag (Editor *, ArdourCanvas::Item *, bool);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
+
+       bool active (Editing::MouseMode) {
+               return true;
+       }
+
+       bool allow_vertical_autoscroll () 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 */
@@ -298,8 +390,8 @@ public:
        FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 };
 
 /** Region fade-out drag */
@@ -309,8 +401,8 @@ public:
        FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 };
 
 /** Marker drag */
@@ -321,12 +413,12 @@ public:
        ~MarkerDrag ();
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
        void update_item (ARDOUR::Location *);
-       
+
        Marker* _marker; ///< marker being dragged
        std::list<ARDOUR::Location*> _copied_locations;
        ArdourCanvas::Line* _line;
@@ -340,11 +432,13 @@ public:
        ControlPointDrag (Editor *, ArdourCanvas::Item *);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
+
+       bool active (Editing::MouseMode m);
 
 private:
-       
+
        ControlPoint* _point;
        double _cumulative_x_drag;
        double _cumulative_y_drag;
@@ -358,8 +452,12 @@ public:
        LineDrag (Editor *e, ArdourCanvas::Item *i);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
+
+       bool active (Editing::MouseMode) {
+               return true;
+       }
 
 private:
 
@@ -376,8 +474,8 @@ public:
        RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 };
 
 /** Region drag in time-FX mode */
@@ -387,11 +485,22 @@ public:
        TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
+};
+
+/** Scrub drag in audition mode */
+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);
 };
 
-/** Drag in range selection mode */
+/** Drag in range select(gc_owner.get()) moAutomatable */
 class SelectionDrag : public Drag
 {
 public:
@@ -405,11 +514,12 @@ public:
        SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
        Operation _operation;
+       bool _copy;
 };
 
 /** Range marker drag */
@@ -425,14 +535,15 @@ public:
        RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 
 private:
        void update_item (ARDOUR::Location *);
 
        Operation _operation;
        ArdourCanvas::SimpleRect* _drag_rect;
+       bool _copy;
 };
 
 /* Drag of rectangle to set zoom */
@@ -442,8 +553,8 @@ public:
        MouseZoomDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
 
        void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
-       void motion (GdkEvent *);
-       void finished (GdkEvent *);
+       void motion (GdkEvent *, bool);
+       void finished (GdkEvent *, bool);
 };
 
 #endif /* __gtk2_ardour_editor_drag_h_ */