summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-01-12 16:14:49 +0000
committerCarl Hetherington <carl@carlh.net>2010-01-12 16:14:49 +0000
commit11bd4eed89f79927f2f7d8cab50a60380cf9e49e (patch)
tree7b44c72e1e6c1d29b5a1639fce9103b07064196b /gtk2_ardour
parent642f41b82fc710246ee85dbc09eaa19ee6c3e633 (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.cc10
-rw-r--r--gtk2_ardour/editor.h17
-rw-r--r--gtk2_ardour/editor_canvas.cc23
-rw-r--r--gtk2_ardour/editor_canvas_events.cc13
-rw-r--r--gtk2_ardour/editor_drag.cc215
-rw-r--r--gtk2_ardour/editor_drag.h70
-rw-r--r--gtk2_ardour/editor_keyboard.cc6
-rw-r--r--gtk2_ardour/editor_markers.cc3
-rw-r--r--gtk2_ardour/editor_mixer.cc3
-rw-r--r--gtk2_ardour/editor_mouse.cc369
-rw-r--r--gtk2_ardour/editor_ops.cc15
-rw-r--r--gtk2_ardour/editor_rulers.cc14
-rw-r--r--gtk2_ardour/editor_selection.cc4
-rw-r--r--gtk2_ardour/time_axis_view.h4
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;