From 40e9dae606c034ce078e929421f8ae122dda4efc Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 13 Dec 2012 19:39:36 +0000 Subject: [PATCH] various fixes for "advanced" operations on range selections. ctrl-drags now add a new range selection, allowing discontiguous selections as in ardour2, shift-click extends an existing range selection to the clicked position, alt-drag on a range selection moves it, and to do a so-called "separation drag" now use ctrl-alt-drag (or ctrl-alt-click) git-svn-id: svn://localhost/ardour2/branches/3.0@13660 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor_drag.cc | 67 ++++++++++++++++++++++++++++++------- gtk2_ardour/editor_drag.h | 8 +++-- gtk2_ardour/editor_mouse.cc | 46 ++++++++++++++----------- gtk2_ardour/selection.cc | 15 +++++++++ gtk2_ardour/selection.h | 2 ++ 5 files changed, 105 insertions(+), 33 deletions(-) diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index d13b81e916..578f149167 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3421,12 +3421,18 @@ ScrubDrag::aborted (bool) SelectionDrag::SelectionDrag (Editor* e, ArdourCanvas::Item* i, Operation o) : Drag (e, i) , _operation (o) - , _copy (false) + , _add (false) + , _extend (false) , _original_pointer_time_axis (-1) , _last_pointer_time_axis (-1) , _time_selection_at_start (!_editor->get_selection().time.empty()) { DEBUG_TRACE (DEBUG::Drags, "New SelectionDrag\n"); + + if (_time_selection_at_start) { + start_at_start = _editor->get_selection().time.start(); + end_at_start = _editor->get_selection().time.end_frame(); + } } void @@ -3440,10 +3446,10 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) switch (_operation) { case CreateSelection: - if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) { - _copy = true; + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)) { + _add = true; } else { - _copy = false; + _add = false; } cursor = _editor->cursors()->selector; Drag::start_grab (event, cursor); @@ -3466,6 +3472,10 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*) case SelectionMove: Drag::start_grab (event, cursor); break; + + case SelectionExtend: + Drag::start_grab (event, cursor); + break; } if (_operation == SelectionMove) { @@ -3493,6 +3503,9 @@ SelectionDrag::setup_pointer_frame_offset () case SelectionEndTrim: _pointer_frame_offset = raw_grab_frame() - _editor->selection->time[_editor->clicked_selection].end; break; + + case SelectionExtend: + break; } } @@ -3501,7 +3514,8 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) { framepos_t start = 0; framepos_t end = 0; - framecnt_t length; + framecnt_t length = 0; + framecnt_t distance = 0; pair const pending_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()); if (pending_time_axis.first == 0) { @@ -3544,12 +3558,12 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) if (first_move) { - if (_copy) { + if (_add) { /* adding to the selection */ _editor->set_selected_track_as_side_effect (Selection::Add); //_editor->selection->add (_editor->clicked_axisview); _editor->clicked_selection = _editor->selection->add (start, end); - _copy = false; + _add = false; } else { /* new selection */ @@ -3617,20 +3631,23 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) } break; - + case SelectionMove: start = _editor->selection->time[_editor->clicked_selection].start; end = _editor->selection->time[_editor->clicked_selection].end; length = end - start; - + distance = pending_position - start; start = pending_position; _editor->snap_to (start); end = start + length; break; + + case SelectionExtend: + break; } if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) { @@ -3638,7 +3655,15 @@ SelectionDrag::motion (GdkEvent* event, bool first_move) } if (start != end) { - _editor->selection->replace (_editor->clicked_selection, start, end); + switch (_operation) { + case SelectionMove: + if (_time_selection_at_start) { + _editor->selection->move_time (distance); + } + break; + default: + _editor->selection->replace (_editor->clicked_selection, start, end); + } } if (_operation == SelectionMove) { @@ -3674,12 +3699,30 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred) } else { /* just a click, no pointer movement. */ - _editor->selection->clear_time(); + + if (_operation == SelectionExtend) { + if (_time_selection_at_start) { + framepos_t pos = adjusted_current_frame (event, false); + framepos_t start = min (pos, start_at_start); + framepos_t end = max (pos, end_at_start); + _editor->selection->set (start, end); + } + } else { + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)) { + if (_editor->clicked_selection) { + _editor->selection->remove (_editor->clicked_selection); + } + } else { + if (!_editor->clicked_selection) { + _editor->selection->clear_time(); + } + } + } if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) { _editor->selection->set (_editor->clicked_axisview); } - + if (s && s->get_play_range () && s->transport_rolling()) { s->request_stop (false, false); } diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index f18a40a9e2..e78a9fa96a 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -862,7 +862,8 @@ public: CreateSelection, SelectionStartTrim, SelectionEndTrim, - SelectionMove + SelectionMove, + SelectionExtend }; SelectionDrag (Editor *, ArdourCanvas::Item *, Operation); @@ -876,11 +877,14 @@ public: private: Operation _operation; - bool _copy; + bool _add; + bool _extend; int _original_pointer_time_axis; int _last_pointer_time_axis; std::list _added_time_axes; bool _time_selection_at_start; + framepos_t start_at_start; + framepos_t end_at_start; }; /** Range marker drag */ diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index cce09f8baf..9452b5e2a4 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -598,23 +598,25 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp switch (item_type) { case RegionItem: - if (press) { - if (mouse_mode != MouseRange) { - set_selected_regionview_from_click (press, op); + if (!get_smart_mode() || (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT)) { + if (press) { + if (mouse_mode != MouseRange) { + set_selected_regionview_from_click (press, op); + } else { + /* don't change the selection unless the + clicked track is not currently selected. if + so, "collapse" the selection to just this + track + */ + if (!selection->selected (clicked_axisview)) { + set_selected_track_as_side_effect (Selection::Set); + } + } } else { - /* don't change the selection unless the - clicked track is not currently selected. if - so, "collapse" the selection to just this - track - */ - if (!selection->selected (clicked_axisview)) { - set_selected_track_as_side_effect (Selection::Set); + if (mouse_mode != MouseRange) { + set_selected_regionview_from_click (press, op); } } - } else { - if (mouse_mode != MouseRange) { - set_selected_regionview_from_click (press, op); - } } break; @@ -800,9 +802,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case SelectionItem: - if (Keyboard::modifier_state_contains - (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier))) { - // contains and not equals because I can't use alt as a modifier alone. + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { start_selection_grab (item, event); } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) { /* grab selection for moving */ @@ -831,7 +831,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT return true; } } else { - _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::RangeSelectModifier)) { + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionExtend), event); + } else { + _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); + } return true; } break; @@ -855,7 +859,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT default: if (!internal_editing()) { - _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::RangeSelectModifier)) { + _drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionExtend), event); + } else { + _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event); + } } } return true; diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 395ceda169..cf25826676 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -531,6 +531,21 @@ Selection::add (framepos_t start, framepos_t end) return next_time_id - 1; } +void +Selection::move_time (framecnt_t distance) +{ + if (distance == 0) { + return; + } + + for (list::iterator i = time.begin(); i != time.end(); ++i) { + (*i).start += distance; + (*i).end += distance; + } + + TimeChanged (); +} + void Selection::replace (uint32_t sid, framepos_t start, framepos_t end) { diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index 73acaaa7c0..3c14eb9a09 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -184,6 +184,8 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList void remove_regions (TimeAxisView *); + void move_time (framecnt_t); + void replace (uint32_t time_index, framepos_t start, framepos_t end); /* -- 2.30.2