diff options
author | Carl Hetherington <carl@carlh.net> | 2010-01-12 16:14:49 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-01-12 16:14:49 +0000 |
commit | 11bd4eed89f79927f2f7d8cab50a60380cf9e49e (patch) | |
tree | 7b44c72e1e6c1d29b5a1639fce9103b07064196b /gtk2_ardour | |
parent | 642f41b82fc710246ee85dbc09eaa19ee6c3e633 (diff) |
Allow multiple simulataneous Drags to be active, and hence set up and drag time ranges when moving regions in PT-edit mode.
git-svn-id: svn://localhost/ardour2/branches/3.0@6478 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/editor.cc | 10 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 17 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 23 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas_events.cc | 13 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 215 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.h | 70 | ||||
-rw-r--r-- | gtk2_ardour/editor_keyboard.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/editor_markers.cc | 3 | ||||
-rw-r--r-- | gtk2_ardour/editor_mixer.cc | 3 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 369 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 15 | ||||
-rw-r--r-- | gtk2_ardour/editor_rulers.cc | 14 | ||||
-rw-r--r-- | gtk2_ardour/editor_selection.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/time_axis_view.h | 4 |
14 files changed, 415 insertions, 351 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 16153908e2..fad8738149 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -281,7 +281,7 @@ Editor::Editor () clicked_crossfadeview = 0; clicked_control_point = 0; last_update_frame = 0; - _drag = 0; + _drags = new DragManager (this); current_mixer_strip = 0; current_bbt_points = 0; tempo_lines = 0; @@ -714,7 +714,7 @@ Editor::~Editor() delete _routes; delete _route_groups; delete track_canvas; - delete _drag; + delete _drags; } void @@ -731,10 +731,8 @@ Editor::catch_vanishing_regionview (RegionView *rv) audioregionview by itself. */ - if (_drag && rv->get_canvas_group() == _drag->item() && !_drag->ending()) { - _drag->end_grab (0); - delete _drag; - _drag = 0; + if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) { + _drags->abort (); } if (clicked_regionview == rv) { diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 74f3ab0448..4568a80630 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -107,7 +107,7 @@ class AutomationTimeAxisView; class BundleManager; class ControlPoint; class CrossfadeView; -class Drag; +class DragManager; class GlobalPortMatrixWindow; class GroupedButtons; class Marker; @@ -607,7 +607,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void collect_new_region_view (RegionView *); void collect_and_select_new_region_view (RegionView *); - void select_range_around_region (RegionView *); + long select_range_around_region (RegionView *); Gtk::Menu track_context_menu; Gtk::Menu track_region_context_menu; @@ -1260,7 +1260,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD int scrubbing_direction; int scrub_reversals; int scrub_reverse_distance; - void scrub (); + void scrub (nframes64_t, double); void keyboard_selection_begin (); void keyboard_selection_finish (bool add); @@ -1279,9 +1279,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD bool ignore_gui_changes; - Drag* _drag; + DragManager* _drags; - void break_drag (); void escape (); Gtk::Menu fade_context_menu; @@ -1305,10 +1304,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD gint mouse_rename_region (ArdourCanvas::Item*, GdkEvent*); - void start_region_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*); + void add_region_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*); void start_create_region_grab (ArdourCanvas::Item*, GdkEvent*); - void start_region_copy_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*); - void start_region_brush_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*); + void add_region_copy_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*); + void add_region_brush_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*); void start_selection_grab (ArdourCanvas::Item*, GdkEvent*); void region_view_item_click (AudioRegionView&, GdkEventButton*); @@ -1676,7 +1675,7 @@ public: bool allow_vertical_scroll; /* trimming */ - void point_trim (GdkEvent*); + void point_trim (GdkEvent *, nframes64_t); void single_contents_trim (RegionView&, nframes64_t, bool, bool, bool); void single_start_trim (RegionView&, nframes64_t, bool, bool, bool); void single_end_trim (RegionView&, nframes64_t, bool, bool, bool); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 7df20c610b..031e58bf61 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -541,17 +541,14 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/, const SelectionData& /*data*/, guint /*info*/, guint /*time*/) { - assert (_drag); - _drag->end_grab (0); - delete _drag; - _drag = 0; + _drags->end_grab (0); } void Editor::maybe_autoscroll (GdkEventMotion* event, bool allow_vert) { nframes64_t rightmost_frame = leftmost_frame + current_page_frames(); - pair<nframes64_t, nframes64_t> frames = _drag->extent (); + pair<nframes64_t, nframes64_t> frames = _drags->extent (); bool startit = false; autoscroll_y = 0; @@ -610,11 +607,9 @@ Editor::autoscroll_canvas () double new_pixel; double target_pixel; - assert (_drag); - if (autoscroll_x_distance != 0) { - pair<nframes64_t, nframes64_t> const e = _drag->extent (); + pair<nframes64_t, nframes64_t> const e = _drags->extent (); if (autoscroll_x > 0) { autoscroll_x_distance = (e.second - (leftmost_frame + current_page_frames())) / 3; @@ -626,10 +621,10 @@ Editor::autoscroll_canvas () if (autoscroll_y_distance != 0) { if (autoscroll_y > 0) { - autoscroll_y_distance = (_drag->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3; + autoscroll_y_distance = (_drags->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3; } else if (autoscroll_y < 0) { - autoscroll_y_distance = (vertical_adjustment.get_value () - _drag->current_pointer_y()) / 3; + autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3; } } @@ -659,7 +654,7 @@ Editor::autoscroll_canvas () new_pixel = vertical_pos - autoscroll_y_distance; } - target_pixel = _drag->current_pointer_y() - autoscroll_y_distance; + target_pixel = _drags->current_pointer_y() - autoscroll_y_distance; target_pixel = max (target_pixel, 0.0); } else if (autoscroll_y > 0) { @@ -674,7 +669,7 @@ Editor::autoscroll_canvas () new_pixel = min (top_of_bottom_of_canvas, new_pixel); - target_pixel = _drag->current_pointer_y() + autoscroll_y_distance; + target_pixel = _drags->current_pointer_y() + autoscroll_y_distance; /* don't move to the full canvas height because the item will be invisible (its top edge will line up with the bottom of the visible canvas. @@ -683,7 +678,7 @@ Editor::autoscroll_canvas () target_pixel = min (target_pixel, full_canvas_height - 10); } else { - target_pixel = _drag->current_pointer_y(); + target_pixel = _drags->current_pointer_y(); new_pixel = vertical_pos; } @@ -709,7 +704,7 @@ Editor::autoscroll_canvas () ev.x = x; ev.y = y; - motion_handler (_drag->item(), (GdkEvent*) &ev, true); + motion_handler (0, (GdkEvent*) &ev, true); autoscroll_cnt++; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index f3131487cd..93402c7854 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -196,10 +196,8 @@ Editor::track_canvas_button_press_event (GdkEventButton */*event*/) bool Editor::track_canvas_button_release_event (GdkEventButton *event) { - if (_drag) { - _drag->end_grab ((GdkEvent*) event); - delete _drag; - _drag = 0; + if (_drags->active ()) { + _drags->end_grab ((GdkEvent*) event); } return false; } @@ -1008,7 +1006,7 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, /* assume we're dragging with button 1 */ event.motion.state = Gdk::BUTTON1_MASK; - if (_drag == 0) { + if (!_drags->active ()) { double px; double py; @@ -1042,11 +1040,10 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, return true; } - _drag = new RegionInsertDrag (this, region_copy, rtav, pos); - _drag->start_grab (&event); + _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event); } - _drag->motion_handler (&event, false); + _drags->motion_handler (&event, false); return true; } diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 5203e1d489..fb68e74e26 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -53,15 +53,149 @@ using Gtkmm2ext::Keyboard; double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0)); +DragManager::DragManager (Editor* e) + : _editor (e) + , _ending (false) + , _current_pointer_frame (0) +{ + +} + +DragManager::~DragManager () +{ + abort (); +} + +void +DragManager::abort () +{ + for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) { + (*i)->end_grab (0); + delete *i; + } + + _drags.clear (); +} + +void +DragManager::break_drag () +{ + _ending = true; + + for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) { + (*i)->break_drag (); + delete *i; + } + + _drags.clear (); + + _ending = false; +} + +void +DragManager::add (Drag* d) +{ + d->set_manager (this); + _drags.push_back (d); +} + +void +DragManager::set (Drag* d, GdkEvent* e, Gdk::Cursor* c) +{ + assert (_drags.empty ()); + d->set_manager (this); + _drags.push_back (d); + start_grab (e); +} + +void +DragManager::start_grab (GdkEvent* e) +{ + _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y); + + for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) { + (*i)->start_grab (e); + } +} + +bool +DragManager::end_grab (GdkEvent* e) +{ + _ending = true; + + bool r = false; + for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) { + bool const t = (*i)->end_grab (e); + if (t) { + r = true; + } + delete *i; + } + + _drags.clear (); + + _ending = false; + + return r; +} + +bool +DragManager::motion_handler (GdkEvent* e, bool from_autoscroll) +{ + bool r = false; + + _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y); + + for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) { + bool const t = (*i)->motion_handler (e, from_autoscroll); + if (t) { + r = true; + } + + } + + return r; +} + +bool +DragManager::have_item (ArdourCanvas::Item* i) const +{ + list<Drag*>::const_iterator j = _drags.begin (); + while (j != _drags.end() && (*j)->item () != i) { + ++j; + } + + return j != _drags.end (); +} + +pair<nframes64_t, nframes64_t> +DragManager::extent () const +{ + if (_drags.empty()) { + return make_pair (0, 0); + } + + list<Drag*>::const_iterator i = _drags.begin (); + pair<nframes64_t, nframes64_t> e = (*i)->extent (); + ++i; + + while (i != _drags.end()) { + pair<nframes64_t, nframes64_t> const t = (*i)->extent (); + e.first = min (e.first, t.first); + e.second = max (e.second, t.second); + ++i; + } + + return e; +} + Drag::Drag (Editor* e, ArdourCanvas::Item* i) : _editor (e) , _item (i) , _pointer_frame_offset (0) - , _ending (false) , _move_threshold_passed (false) , _grab_frame (0) , _last_pointer_frame (0) - , _current_pointer_frame (0) { } @@ -104,11 +238,8 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor) _grab_frame = _editor->event_frame (event, &_grab_x, &_grab_y); _grab_frame = adjusted_frame (_grab_frame, event); _last_pointer_frame = _grab_frame; - _current_pointer_frame = _grab_frame; - _current_pointer_x = _grab_x; - _current_pointer_y = _grab_y; - _last_pointer_x = _current_pointer_x; - _last_pointer_y = _current_pointer_y; + _last_pointer_x = _grab_x; + _last_pointer_y = _grab_y; _item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, @@ -138,20 +269,14 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor) bool Drag::end_grab (GdkEvent* event) { - _ending = true; - _editor->stop_canvas_autoscroll (); _item->ungrab (event ? event->button.time : 0); - _last_pointer_x = _current_pointer_x; - _last_pointer_y = _current_pointer_y; finished (event, _move_threshold_passed); _editor->hide_verbose_canvas_cursor(); - _ending = false; - return _move_threshold_passed; } @@ -174,17 +299,15 @@ Drag::adjusted_frame (nframes64_t f, GdkEvent const * event, bool snap) const nframes64_t Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const { - return adjusted_frame (_current_pointer_frame, event, snap); + return adjusted_frame (_drags->current_pointer_frame (), event, snap); } bool Drag::motion_handler (GdkEvent* event, bool from_autoscroll) { - _current_pointer_frame = _editor->event_frame (event, &_current_pointer_x, &_current_pointer_y); - /* check to see if we have moved in any way that matters since the last motion event */ if ( (!x_movement_matters() || _last_pointer_frame == adjusted_current_frame (event)) && - (!y_movement_matters() || _last_pointer_y == _current_pointer_y) ) { + (!y_movement_matters() || _last_pointer_y == _drags->current_pointer_y ()) ) { return false; } @@ -195,7 +318,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll) if (!from_autoscroll && !_move_threshold_passed) { bool const xp = (::llabs (adjusted_current_frame (event) - _grab_frame) >= threshold.first); - bool const yp = (::fabs ((_current_pointer_y - _grab_y)) >= threshold.second); + bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second); _move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters())); } @@ -209,8 +332,8 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll) motion (event, _move_threshold_passed != old_move_threshold_passed); - _last_pointer_x = _current_pointer_x; - _last_pointer_y = _current_pointer_y; + _last_pointer_x = _drags->current_pointer_x (); + _last_pointer_y = _drags->current_pointer_y (); _last_pointer_frame = adjusted_current_frame (event); return true; @@ -223,8 +346,6 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll) void Drag::break_drag () { - _ending = true; - if (_item) { _item->ungrab (0); } @@ -233,8 +354,6 @@ Drag::break_drag () _editor->stop_canvas_autoscroll (); _editor->hide_verbose_canvas_cursor (); - - _ending = false; } pair<nframes64_t, nframes64_t> @@ -255,7 +374,7 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Re void RegionDrag::region_going_away (RegionView* v) { - if (!ending ()) { + if (!_drags->ending ()) { _views.remove (v); } } @@ -1102,7 +1221,7 @@ RegionMotionDrag::check_possible (RouteTimeAxisView** tv, layer_t* layer) { /* Which trackview is this ? */ - pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (current_pointer_y ()); + pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ()); (*tv) = dynamic_cast<RouteTimeAxisView*> (tvp.first); (*layer) = tvp.second; @@ -1335,7 +1454,7 @@ RegionSpliceDrag::motion (GdkEvent* event, bool) int dir; - if ((current_pointer_x() - last_pointer_x()) > 0) { + if ((_drags->current_pointer_x() - last_pointer_x()) > 0) { dir = 1; } else { dir = -1; @@ -1501,7 +1620,7 @@ NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/) { MidiRegionSelection& ms (_editor->get_selection().midi_regions); for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) { - (*r)->update_resizing (at_front, current_pointer_x() - grab_x(), relative); + (*r)->update_resizing (at_front, _drags->current_pointer_x() - grab_x(), relative); } } @@ -1510,7 +1629,7 @@ NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/) { MidiRegionSelection& ms (_editor->get_selection().midi_regions); for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) { - (*r)->commit_resizing (at_front, current_pointer_x() - grab_x(), relative); + (*r)->commit_resizing (at_front, _drags->current_pointer_x() - grab_x(), relative); } } @@ -1754,7 +1873,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred) } else { /* no mouse movement */ - _editor->point_trim (event); + _editor->point_trim (event, adjusted_current_frame (event)); } } @@ -2614,8 +2733,8 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) void ControlPointDrag::motion (GdkEvent* event, bool) { - double dx = current_pointer_x() - last_pointer_x(); - double dy = current_pointer_y() - last_pointer_y(); + double dx = _drags->current_pointer_x() - last_pointer_x(); + double dy = _drags->current_pointer_y() - last_pointer_y(); if (event->button.state & Keyboard::SecondaryModifier) { dx *= 0.1; @@ -2753,7 +2872,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) void LineDrag::motion (GdkEvent* event, bool) { - double dy = current_pointer_y() - last_pointer_y(); + double dy = _drags->current_pointer_y() - last_pointer_y(); if (event->button.state & Keyboard::SecondaryModifier) { dy *= 0.1; @@ -2827,11 +2946,11 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool) start = grab; } - if (current_pointer_y() < grab_y()) { - y1 = current_pointer_y(); + if (_drags->current_pointer_y() < grab_y()) { + y1 = _drags->current_pointer_y(); y2 = grab_y(); } else { - y2 = current_pointer_y(); + y2 = _drags->current_pointer_y(); y1 = grab_y(); } @@ -2861,11 +2980,11 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred) motion (event, false); double y1,y2; - if (current_pointer_y() < grab_y()) { - y1 = current_pointer_y(); + if (_drags->current_pointer_y() < grab_y()) { + y1 = _drags->current_pointer_y(); y2 = grab_y(); } else { - y2 = current_pointer_y(); + y2 = _drags->current_pointer_y(); y1 = grab_y(); } @@ -2978,7 +3097,7 @@ ScrubDrag::start_grab (GdkEvent* event, Gdk::Cursor *) void ScrubDrag::motion (GdkEvent* /*event*/, bool) { - _editor->scrub (); + _editor->scrub (adjusted_current_frame (0, false), _drags->current_pointer_x ()); } void @@ -3060,7 +3179,7 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); } - _original_pointer_time_axis = _editor->trackview_by_y_position (current_pointer_y ()).first->order (); + _original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order (); } void @@ -3070,7 +3189,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) nframes64_t end = 0; nframes64_t length; - pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (current_pointer_y ()); + pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()); if (pending_time_axis.first == 0) { return; } @@ -3547,8 +3666,8 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *) double event_x; double event_y; - event_x = current_pointer_x(); - event_y = current_pointer_y(); + event_x = _drags->current_pointer_x(); + event_y = _drags->current_pointer_y(); _item->property_parent().get_value()->w2i(event_x, event_y); @@ -3585,8 +3704,8 @@ NoteDrag::motion (GdkEvent*, bool) double event_x; double event_y; - event_x = current_pointer_x(); - event_y = current_pointer_y(); + event_x = _drags->current_pointer_x(); + event_y = _drags->current_pointer_y(); _item->property_parent().get_value()->w2i(event_x, event_y); @@ -3738,7 +3857,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) return; } - _line->start_drag_multiple (points, 1 - (current_pointer_y() / _line->height ()), state); + _line->start_drag_multiple (points, 1 - (_drags->current_pointer_y() / _line->height ()), state); } void @@ -3748,7 +3867,7 @@ AutomationRangeDrag::motion (GdkEvent* event, bool first_move) return; } - float const f = 1 - (current_pointer_y() / _line->height()); + float const f = 1 - (_drags->current_pointer_y() / _line->height()); /* we are ignoring x position for this drag, so we can just pass in anything */ _line->drag_motion (0, f, true, false); diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 6b6a9ee1b5..7347780019 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -37,29 +37,36 @@ 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); - 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; + std::pair<nframes64_t, nframes64_t> extent () 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; @@ -70,6 +77,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; @@ -156,6 +197,7 @@ 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; @@ -165,17 +207,13 @@ protected: private: - bool _ending; ///< true if end_grab or break_drag is in progress, 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 _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 }; diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc index 4b16a4b8a2..ea40b43f50 100644 --- a/gtk2_ardour/editor_keyboard.cc +++ b/gtk2_ardour/editor_keyboard.cc @@ -53,10 +53,8 @@ Editor::kbd_driver (sigc::slot<void,GdkEvent*> theslot, bool use_track_canvas, b /* any use of "keyboard mouse buttons" invalidates an existing grab */ - if (_drag) { - _drag->item()->ungrab (GDK_CURRENT_TIME); - delete _drag; - _drag = 0; + if (_drags->active ()) { + _drags->abort (); } if (doit) { diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index c976507cfe..d23afbf14c 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -37,6 +37,7 @@ #include "simplerect.h" #include "actions.h" #include "prompter.h" +#include "editor_drag.h" #include "i18n.h" @@ -1088,7 +1089,7 @@ Editor::new_transport_marker_menu_popdown () // hide rects transport_bar_drag_rect->hide(); - break_drag (); + _drags->break_drag (); } void diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 21a35f6da3..d3c40418fa 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -36,6 +36,7 @@ #include "editor_route_groups.h" #include "editor_regions.h" #include "gui_thread.h" +#include "editor_drag.h" #include "i18n.h" @@ -342,7 +343,7 @@ Editor::session_going_away () entered_regionview = 0; entered_track = 0; last_update_frame = 0; - _drag = 0; + _drags->abort (); playhead_cursor->canvas_item.hide (); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index c0beab03aa..c39d562165 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -271,7 +271,7 @@ Editor::set_canvas_cursor () void Editor::set_mouse_mode (MouseMode m, bool force) { - if (_drag) { + if (_drags->active ()) { return; } @@ -462,7 +462,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp set_selected_track_as_side_effect (true); } if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) { - select_range_around_region (selection->regions.front()); + clicked_selection = select_range_around_region (selection->regions.front()); } break; @@ -514,10 +514,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp bool Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - if (_drag) { - _drag->item()->ungrab (event->button.time); - delete _drag; - _drag = 0; + if (_drags->active ()) { + _drags->abort (); } /* single mouse clicks on any of these item types operate @@ -528,83 +526,73 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT switch (item_type) { case PlayheadCursorItem: - assert (_drag == 0); - _drag = new CursorDrag (this, item, true); - _drag->start_grab (event); + _drags->set (new CursorDrag (this, item, true), event); return true; case MarkerItem: if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { hide_marker (item, event); } else { - assert (_drag == 0); - _drag = new MarkerDrag (this, item); - _drag->start_grab (event); + _drags->set (new MarkerDrag (this, item), event); } return true; case TempoMarkerItem: - assert (_drag == 0); - _drag = new TempoMarkerDrag ( - this, - item, - Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + _drags->set ( + new TempoMarkerDrag ( + this, + item, + Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + ), + event ); - _drag->start_grab (event); return true; case MeterMarkerItem: - assert (_drag == 0); - _drag = new MeterMarkerDrag ( - this, - item, - Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + _drags->set ( + new MeterMarkerDrag ( + this, + item, + Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + ), + event ); - _drag->start_grab (event); return true; case MarkerBarItem: case TempoBarItem: case MeterBarItem: if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - assert (_drag == 0); - _drag = new CursorDrag (this, &playhead_cursor->canvas_item, false); - _drag->start_grab (event); + _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event); } return true; break; case RangeMarkerBarItem: - assert (_drag == 0); if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - _drag = new CursorDrag (this, &playhead_cursor->canvas_item, false); + _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event); } else { - _drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker); + _drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker), event); } - _drag->start_grab (event); return true; break; case CdMarkerBarItem: - assert (_drag == 0); if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - _drag = new CursorDrag (this, &playhead_cursor->canvas_item, false); + _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event); } else { - _drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker); + _drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker), event); } - _drag->start_grab (event); return true; break; case TransportMarkerBarItem: - assert (_drag == 0); if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - _drag = new CursorDrag (this, &playhead_cursor->canvas_item, false); + _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event); } else { - _drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker); + _drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker), event); } - _drag->start_grab (event); return true; break; @@ -620,13 +608,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT over a region. */ if (item_type == StartSelectionTrimItem) { - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event); } else if (item_type == EndSelectionTrimItem) { - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event); } } @@ -636,15 +620,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseRange: switch (item_type) { case StartSelectionTrimItem: - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event); break; case EndSelectionTrimItem: - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event); break; case SelectionItem: @@ -654,32 +634,26 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT start_selection_grab (item, event); } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { /* grab selection for moving */ - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::SelectionMove); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionMove), event); } else { double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize; pair<TimeAxisView*, int> tvp = trackview_by_y_position (y); if (tvp.first) { AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first); - assert (_drag == 0); if (join_object_range_button.get_active() && atv) { /* smart "join" mode: drag automation */ - _drag = new AutomationRangeDrag (this, atv->base_item(), selection->time); + _drags->set (new AutomationRangeDrag (this, atv->base_item(), selection->time), event); } else { /* this was debated, but decided the more common action was to make a new selection */ - _drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection); + _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); } - _drag->start_grab (event); } } break; default: - assert (_drag == 0); - _drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection); - _drag->start_grab (event); + _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); } return true; break; @@ -689,9 +663,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case NoteItem: if (internal_editing()) { /* Note: we don't get here if not in internal_editing() mode */ - assert (_drag == 0); - _drag = new NoteDrag (this, item); - _drag->start_grab (event); + _drags->set (new NoteDrag (this, item), event); return true; } break; @@ -703,47 +675,45 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) && event->type == GDK_BUTTON_PRESS) { - assert (_drag == 0); - _drag = new RubberbandSelectDrag (this, item); - _drag->start_grab (event); + _drags->set (new RubberbandSelectDrag (this, item), event); } else if (event->type == GDK_BUTTON_PRESS) { switch (item_type) { case FadeInHandleItem: { - assert (_drag == 0); RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new FadeInDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s); - _drag->start_grab (event); + _drags->set (new FadeInDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s), event); return true; } case FadeOutHandleItem: { - assert (_drag == 0); RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new FadeOutDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s); - _drag->start_grab (event); + _drags->set (new FadeOutDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s), event); return true; } case RegionItem: if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) { - start_region_copy_grab (item, event, clicked_regionview); + add_region_copy_drag (item, event, clicked_regionview); } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) { - start_region_brush_grab (item, event, clicked_regionview); + add_region_brush_drag (item, event, clicked_regionview); } else { - start_region_grab (item, event, clicked_regionview); + add_region_drag (item, event, clicked_regionview); } + + if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) { + _drags->add (new SelectionDrag (this, clicked_axisview->get_selection_rect (clicked_selection)->rect, SelectionDrag::SelectionMove)); + } + + _drags->start_grab (event); break; case RegionViewNameHighlight: { - assert (_drag == 0); RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new TrimDrag (this, item, clicked_regionview, s.by_layer()); - _drag->start_grab (event); + _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event); return true; break; } @@ -751,61 +721,68 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case RegionViewName: { /* rename happens on edit clicks */ - assert (_drag == 0); RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, s.by_layer()); - _drag->start_grab (event); + _drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, s.by_layer()), event); return true; break; } case ControlPointItem: - assert (_drag == 0); - _drag = new ControlPointDrag (this, item); - _drag->start_grab (event); + _drags->set (new ControlPointDrag (this, item), event); return true; break; case AutomationLineItem: - assert (_drag == 0); - _drag = new LineDrag (this, item); - _drag->start_grab (event); + _drags->set (new LineDrag (this, item), event); return true; break; case StreamItem: if (internal_editing()) { - assert (_drag == 0); - _drag = new RegionCreateDrag (this, item, clicked_axisview); - _drag->start_grab (event); + _drags->set (new RegionCreateDrag (this, item, clicked_axisview), event); return true; } else { - assert (_drag == 0); - _drag = new RubberbandSelectDrag (this, item); - _drag->start_grab (event); + _drags->set (new RubberbandSelectDrag (this, item), event); } break; case AutomationTrackItem: - assert (_drag == 0); /* rubberband drag to select automation points */ - _drag = new RubberbandSelectDrag (this, item); - _drag->start_grab (event); + _drags->set (new RubberbandSelectDrag (this, item), event); break; case SelectionItem: { if (join_object_range_button.get_active()) { - /* we're in "smart" joined mode, and we've clicked on a Selection; if we're - * over an automation track, start a drag of its data */ + /* we're in "smart" joined mode, and we've clicked on a Selection */ double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize; pair<TimeAxisView*, int> tvp = trackview_by_y_position (y); if (tvp.first) { + /* if we're over an automation track, start a drag of its data */ AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first); if (atv) { - assert (_drag == 0); - _drag = new AutomationRangeDrag (this, atv->base_item(), selection->time); - _drag->start_grab (event); + _drags->set (new AutomationRangeDrag (this, atv->base_item(), selection->time), event); + } + + /* if we're over a track and a region, and in the `object' part of a region, + put a selection around the region and drag both + */ + RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first); + if (rtv && _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) { + boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (rtv->route ()); + if (t) { + boost::shared_ptr<Playlist> pl = t->diskstream()->playlist (); + if (pl) { + boost::shared_ptr<Region> r = pl->top_region_at (unit_to_frame (event->button.x)); + RegionView* rv = rtv->view()->find_view (r); + clicked_selection = select_range_around_region (rv); + _drags->add (new SelectionDrag (this, item, SelectionDrag::SelectionMove)); + list<RegionView*> rvs; + rvs.push_back (rv); + _drags->add (new RegionMoveDrag (this, item, rv, rvs, false, false)); + _drags->start_grab (event); + } + } } } } @@ -854,21 +831,15 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT /* start a grab so that if we finish after moving we can tell what happened. */ - assert (_drag == 0); - _drag = new RegionGainDrag (this, item); - _drag->start_grab (event, current_canvas_cursor); + _drags->set (new RegionGainDrag (this, item), event, current_canvas_cursor); break; case GainLineItem: - assert (_drag == 0); - _drag = new LineDrag (this, item); - _drag->start_grab (event); + _drags->set (new LineDrag (this, item), event); return true; case ControlPointItem: - assert (_drag == 0); - _drag = new ControlPointDrag (this, item); - _drag->start_grab (event); + _drags->set (new ControlPointDrag (this, item), event); return true; break; @@ -880,15 +851,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT switch (item_type) { case ControlPointItem: - assert (_drag == 0); - _drag = new ControlPointDrag (this, item); - _drag->start_grab (event); + _drags->set (new ControlPointDrag (this, item), event); break; case AutomationLineItem: - assert (_drag == 0); - _drag = new LineDrag (this, item); - _drag->start_grab (event); + _drags->set (new LineDrag (this, item), event); break; case RegionItem: @@ -905,9 +872,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseZoom: if (event->type == GDK_BUTTON_PRESS) { - assert (_drag == 0); - _drag = new MouseZoomDrag (this, item); - _drag->start_grab (event); + _drags->set (new MouseZoomDrag (this, item), event); } return true; @@ -915,21 +880,16 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseTimeFX: if (internal_editing() && item_type == NoteItem) { - assert (_drag == 0); - _drag = new NoteResizeDrag (this, item); - _drag->start_grab (event); + _drags->set (new NoteResizeDrag (this, item), event); return true; } else if (!internal_editing() && item_type == RegionItem) { - assert (_drag == 0); - _drag = new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer()); - _drag->start_grab (event); + _drags->set (new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer()), event); return true; } break; case MouseAudition: - _drag = new ScrubDrag (this, item); - _drag->start_grab (event); + _drags->set (new ScrubDrag (this, item), event); scrub_reversals = 0; scrub_reverse_distance = 0; last_scrub_x = event->button.x; @@ -954,16 +914,15 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT switch (item_type) { case RegionItem: if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) { - start_region_copy_grab (item, event, clicked_regionview); + add_region_copy_drag (item, event, clicked_regionview); } else { - start_region_grab (item, event, clicked_regionview); + add_region_drag (item, event, clicked_regionview); } + _drags->start_grab (event); return true; break; case ControlPointItem: - assert (_drag == 0); - _drag = new ControlPointDrag (this, item); - _drag->start_grab (event); + _drags->set (new ControlPointDrag (this, item), event); return true; break; @@ -973,16 +932,12 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT switch (item_type) { case RegionViewNameHighlight: - assert (_drag == 0); - _drag = new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer()); - _drag->start_grab (event); + _drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer()), event); return true; break; case RegionViewName: - assert (_drag == 0); - _drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer()); - _drag->start_grab (event); + _drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer()), event); return true; break; @@ -1047,7 +1002,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp button_selection (item, event, item_type); - if (_drag == 0 && + if (!_drags->active () && (Keyboard::is_delete_event (&event->button) || Keyboard::is_context_menu_event (&event->button) || Keyboard::is_edit_event (&event->button))) { @@ -1091,10 +1046,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT /* first, see if we're finishing a drag ... */ bool were_dragging = false; - if (_drag) { - bool const r = _drag->end_grab (event); - delete _drag; - _drag = 0; + if (_drags->active ()) { + bool const r = _drags->end_grab (event); if (r) { /* grab dragged, so do nothing else */ return true; @@ -1107,7 +1060,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT /* edit events get handled here */ - if (_drag == 0 && Keyboard::is_edit_event (&event->button)) { + if (!_drags->active () && Keyboard::is_edit_event (&event->button)) { switch (item_type) { case RegionItem: edit_region (); @@ -1141,7 +1094,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT if (Keyboard::is_context_menu_event (&event->button)) { - if (_drag == 0) { + if (!_drags->active ()) { /* no matter which button pops up the context menu, tell the menu widget to use button 1 to drive menu selection. @@ -1225,7 +1178,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT Editing::MouseMode const eff = effective_mouse_mode (); - if (_drag == 0 && Keyboard::is_delete_event (&event->button)) { + if (!_drags->active () && Keyboard::is_delete_event (&event->button)) { switch (item_type) { case TempoMarkerItem: @@ -1447,7 +1400,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ fraction = 1.0 - (cp->get_y() / cp->line().height()); - if (is_drawable() && dynamic_cast<ScrubDrag*> (_drag) == 0) { + if (is_drawable() && !_drags->active ()) { track_canvas->get_window()->set_cursor (*fader_cursor); } @@ -1734,10 +1687,6 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ break; } - if (item_type == RegionItem) { - update_join_object_range_location (event->crossing.x, event->crossing.y); - } - return false; } @@ -1752,19 +1701,19 @@ Editor::left_automation_track () } void -Editor::scrub () +Editor::scrub (nframes64_t frame, double current_x) { double delta; if (scrubbing_direction == 0) { /* first move */ - _session->request_locate (_drag->adjusted_current_frame (0), false); + _session->request_locate (frame, false); _session->request_transport_speed (0.1); scrubbing_direction = 1; } else { - if (last_scrub_x > _drag->current_pointer_x()) { + if (last_scrub_x > current_x) { /* pointer moved to the left */ @@ -1773,7 +1722,7 @@ Editor::scrub () /* we reversed direction to go backwards */ scrub_reversals++; - scrub_reverse_distance += (int) (last_scrub_x - _drag->current_pointer_x()); + scrub_reverse_distance += (int) (last_scrub_x - current_x); } else { @@ -1782,7 +1731,7 @@ Editor::scrub () scrub_reversals = 0; scrub_reverse_distance = 0; - delta = 0.01 * (last_scrub_x - _drag->current_pointer_x()); + delta = 0.01 * (last_scrub_x - current_x); _session->request_transport_speed (_session->transport_speed() - delta); } @@ -1793,7 +1742,7 @@ Editor::scrub () /* we reversed direction to go forward */ scrub_reversals++; - scrub_reverse_distance += (int) (_drag->current_pointer_x() - last_scrub_x); + scrub_reverse_distance += (int) (current_x - last_scrub_x); } else { /* still moving to the right */ @@ -1801,7 +1750,7 @@ Editor::scrub () scrub_reversals = 0; scrub_reverse_distance = 0; - delta = 0.01 * (_drag->current_pointer_x() - last_scrub_x); + delta = 0.01 * (current_x - last_scrub_x); _session->request_transport_speed (_session->transport_speed() + delta); } } @@ -1827,7 +1776,7 @@ Editor::scrub () } } - last_scrub_x = _drag->current_pointer_x(); + last_scrub_x = current_x; } bool @@ -1866,8 +1815,8 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from } bool handled = false; - if (_drag) { - handled = _drag->motion_handler (event, from_autoscroll); + if (_drags->active ()) { + handled = _drags->motion_handler (event, from_autoscroll); } if (!handled) { @@ -2042,7 +1991,7 @@ Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos, if (xpos >= 0 && ypos >=0) { set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset); } else { - set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset - horizontal_adjustment.get_value(), _drag->current_pointer_y() + offset - vertical_adjustment.get_value() + canvas_timebars_vsize); + set_verbose_canvas_cursor (buf, _drags->current_pointer_x() + offset - horizontal_adjustment.get_value(), _drags->current_pointer_y() + offset - vertical_adjustment.get_value() + canvas_timebars_vsize); } show_verbose_canvas_cursor (); } @@ -2124,7 +2073,7 @@ Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset); } else { - set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset, _drag->current_pointer_y() + offset); + set_verbose_canvas_cursor (buf, _drags->current_pointer_x() + offset, _drags->current_pointer_y() + offset); } show_verbose_canvas_cursor (); @@ -2310,14 +2259,10 @@ Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_dire void -Editor::point_trim (GdkEvent* event) +Editor::point_trim (GdkEvent* event, nframes64_t new_bound) { RegionView* rv = clicked_regionview; - nframes64_t new_bound = _drag->adjusted_current_frame (event); - - snap_to_with_modifier (new_bound, event); - /* Choose action dependant on which button was pressed */ switch (event->button.button) { case 1: @@ -2519,23 +2464,19 @@ Editor::track_height_step_timeout () } void -Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) +Editor::add_region_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) { assert (region_view); _region_motion_group->raise_to_top (); - assert (_drag == 0); - if (Config->get_edit_mode() == Splice) { - _drag = new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer()); + _drags->add (new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer())); } else { RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), false, false); + _drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), false, false)); } - _drag->start_grab (event); - begin_reversible_command (_("move region(s)")); /* sync the canvas to what we think is its current state */ @@ -2543,31 +2484,27 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView } void -Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) +Editor::add_region_copy_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) { assert (region_view); - assert (_drag == 0); _region_motion_group->raise_to_top (); RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), false, true); - _drag->start_grab(event); + _drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), false, true)); } void -Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) +Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view) { assert (region_view); - assert (_drag == 0); if (Config->get_edit_mode() == Splice) { return; } RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit); - _drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), true, false); - _drag->start_grab (event); + _drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), true, false)); begin_reversible_command (_("Drag region brush")); } @@ -2633,32 +2570,20 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event) */ selection->set (latest_regionviews); - assert (_drag == 0); - _drag = new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false); - _drag->start_grab (event); + _drags->set (new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false), event); } void Editor::escape () { - if (_drag) { - break_drag (); + if (_drags->active ()) { + _drags->break_drag (); } else { selection->clear (); } } void -Editor::break_drag () -{ - if (_drag) { - _drag->break_drag (); - delete _drag; - _drag = 0; - } -} - -void Editor::set_internal_edit (bool yn) { _internal_editing = yn; @@ -2700,33 +2625,37 @@ Editor::set_internal_edit (bool yn) void Editor::update_join_object_range_location (double x, double y) { + /* XXX: actually, this decides based on whether the mouse is in the top or bottom half of a RouteTimeAxisView; + entered_{track,regionview} is not always setup (e.g. if the mouse is over a TimeSelection), and to get a Region + that we're over requires searching the playlist. + */ + if (join_object_range_button.get_active() == false || (mouse_mode != MouseRange && mouse_mode != MouseObject)) { _join_object_range_state = JOIN_OBJECT_RANGE_NONE; return; } + + if (mouse_mode == MouseObject) { + _join_object_range_state = JOIN_OBJECT_RANGE_OBJECT; + } else if (mouse_mode == MouseRange) { + _join_object_range_state = JOIN_OBJECT_RANGE_RANGE; + } - if (entered_regionview) { - - double cx = x; - double cy = y; - entered_regionview->get_canvas_group()->w2i (cx, cy); - - double x1; - double y1; - double x2; - double y2; - entered_regionview->get_canvas_group()->get_bounds (x1, y1, x2, y2); - - bool const top_half = cy < (y2 - y1) / 2; - - _join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT; - - } else { + /* XXX: maybe we should make entered_track work in all cases, rather than resorting to this */ + pair<TimeAxisView*, int> tvp = trackview_by_y_position (y + vertical_adjustment.get_value() - canvas_timebars_vsize); + + if (tvp.first) { - if (mouse_mode == MouseObject) { - _join_object_range_state = JOIN_OBJECT_RANGE_OBJECT; - } else if (mouse_mode == MouseRange) { - _join_object_range_state = JOIN_OBJECT_RANGE_RANGE; + RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first); + if (rtv) { + + double cx = 0; + double cy = y; + rtv->canvas_display()->w2i (cx, cy); + + bool const top_half = cy < rtv->current_height () / 2; + + _join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT; } } } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index f4e40f4120..278aaf9cd6 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3826,10 +3826,8 @@ Editor::cut_copy (CutCopyOp op) */ if (op == Cut || op == Clear) { - if (_drag) { - _drag->item()->ungrab (0); - delete _drag; - _drag = 0; + if (_drags->active ()) { + _drags->abort (); } } @@ -3846,10 +3844,7 @@ Editor::cut_copy (CutCopyOp op) Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc)); } - break_drag (); - delete _drag; - _drag = 0; - + _drags->break_drag (); return; } @@ -3930,9 +3925,7 @@ Editor::cut_copy (CutCopyOp op) } if (op == Cut || op == Clear) { - break_drag (); - delete _drag; - _drag = 0; + _drags->break_drag (); } } diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index 880b6812b5..73ffcb4467 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -246,9 +246,7 @@ Editor::ruler_button_press (GdkEventButton* ev) } /* playhead cursor */ - assert (_drag == 0); - _drag = new CursorDrag (this, &playhead_cursor->canvas_item, false); - _drag->start_grab (reinterpret_cast<GdkEvent *> (ev)); + _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), reinterpret_cast<GdkEvent *> (ev)); _dragging_playhead = true; } @@ -265,10 +263,8 @@ Editor::ruler_button_release (GdkEventButton* ev) gint x,y; Gdk::ModifierType state; - if (_drag) { - _drag->end_grab (reinterpret_cast<GdkEvent*> (ev)); - delete _drag; - _drag = 0; + if (_drags->active ()) { + _drags->end_grab (reinterpret_cast<GdkEvent*> (ev)); _dragging_playhead = false; } @@ -312,8 +308,8 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev) return FALSE; } - if (_drag) { - _drag->motion_handler (reinterpret_cast<GdkEvent*> (ev), false); + if (_drags->active ()) { + _drags->motion_handler (reinterpret_cast<GdkEvent*> (ev), false); } return TRUE; diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 3423878190..e73de2bc51 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -1418,12 +1418,12 @@ Editor::deselect_all () selection->clear (); } -void +long Editor::select_range_around_region (RegionView* rv) { selection->set (&rv->get_time_axis_view()); selection->time.clear (); boost::shared_ptr<Region> r = rv->region (); - selection->set (r->position(), r->position() + r->length()); + return selection->set (r->position(), r->position() + r->length()); } diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h index 1d1d8e044b..e98579a683 100644 --- a/gtk2_ardour/time_axis_view.h +++ b/gtk2_ardour/time_axis_view.h @@ -221,6 +221,8 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful typedef std::vector<boost::shared_ptr<TimeAxisView> > Children; + SelectionRect* get_selection_rect(uint32_t id); + protected: /* The Standard LHS Controls */ Gtk::HBox controls_hbox; @@ -317,8 +319,6 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful std::list<SelectionRect*> free_selection_rects; std::list<SelectionRect*> used_selection_rects; - SelectionRect* get_selection_rect(uint32_t id); - virtual void selection_click (GdkEventButton*); bool _hidden; |