X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_selection.cc;h=23fa4d1d8f7c98cb8c006d033de1f01f39efce3c;hb=e935890fc54af99e05dffcb0e07718e6895df47d;hp=59425b289c362f71cf423eb747b9059427186860;hpb=fa22520fd257f166c00615e7e40ec10c9e29b948;p=ardour.git diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 59425b289c..23fa4d1d8f 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -30,6 +30,7 @@ #include "control_protocol/control_protocol.h" +#include "editor_drag.h" #include "editor.h" #include "actions.h" #include "audio_time_axis.h" @@ -40,6 +41,7 @@ #include "editor_regions.h" #include "editor_cursors.h" #include "midi_region_view.h" +#include "sfdb_ui.h" #include "i18n.h" @@ -185,12 +187,12 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) return; } - if (!clicked_routeview) { - return; + RouteGroup* group = NULL; + if (clicked_routeview) { + group = clicked_routeview->route()->route_group(); } bool had_tracks = !selection->tracks.empty(); - RouteGroup* group = clicked_routeview->route()->route_group(); RouteGroup& arg (_session->all_route_group()); switch (op) { @@ -202,8 +204,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) } } else if (group && group->is_active()) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) { - if ((*i)->route_group() == group) + if ((*i)->route_group() == group) { selection->remove(*i); + } } } else { selection->remove (clicked_axisview); @@ -215,8 +218,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) } } else if (group && group->is_active()) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) { - if ( (*i)->route_group() == group) + if ((*i)->route_group() == group) { selection->add(*i); + } } } else { selection->add (clicked_axisview); @@ -234,8 +238,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) } } else if (group && group->is_active()) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) { - if ((*i)->route_group() == group) + if ((*i)->route_group() == group) { selection->add(*i); + } } } else { selection->add (clicked_axisview); @@ -253,8 +258,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) } } else if (group && group->is_active()) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) { - if ((*i)->route_group() == group) + if ((*i)->route_group() == group) { selection->add(*i); + } } } else { selection->set (clicked_axisview); @@ -270,6 +276,8 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op) void Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove) { + begin_reversible_selection_op (X_("Set Selected Track")); + switch (op) { case Selection::Toggle: if (selection->selected (&view)) { @@ -295,6 +303,8 @@ Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no extend_selection_to_track (view); break; } + + commit_reversible_selection_op (); } void @@ -317,19 +327,23 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation if (!clicked_control_point) { return false; } + bool ret = false; switch (op) { case Selection::Set: if (press) { selection->set (clicked_control_point); + ret = true; } break; case Selection::Add: if (press) { selection->add (clicked_control_point); + ret = true; } break; case Selection::Toggle: + /* This is a bit of a hack; if we Primary-Click-Drag a control point (for push drag) we want the point we clicked on to be selected, otherwise we end up confusingly dragging an @@ -344,9 +358,11 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation */ selection->toggle (clicked_control_point); _control_point_toggled_on_press = true; + ret = true; } else if (!press && !_control_point_toggled_on_press) { /* This is the release, and the point wasn't toggled on the press, so do it now */ selection->toggle (clicked_control_point); + ret = true; } else { /* Reset our flag */ _control_point_toggled_on_press = false; @@ -357,7 +373,7 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation break; } - return true; + return ret; } void @@ -640,8 +656,17 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op) selection->set (all_equivalent_regions); commit = true; } else { - /* no commit necessary: clicked on an already selected region */ - goto out; + /* clicked on an already selected region */ + if (press) + goto out; + else { + if (selection->regions.size() > 1) { + /* collapse region selection down to just this one region (and its equivalents) */ + get_equivalent_regions(clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id); + selection->set(all_equivalent_regions); + commit = true; + } + } } break; @@ -886,7 +911,7 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr regi return; } - begin_reversible_command (_("set selected regions")); + begin_reversible_selection_op (X_("set selected regions")); switch (op) { case Selection::Toggle: @@ -904,7 +929,7 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr regi break; } - commit_reversible_command () ; + commit_reversible_selection_op () ; } bool @@ -929,11 +954,11 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* return true; } - begin_reversible_command (_("set selected regions")); + begin_reversible_selection_op (X_("set selected regions")); selection->set (rv); - commit_reversible_command () ; + commit_reversible_selection_op () ; return true; } @@ -982,6 +1007,32 @@ Editor::track_selection_changed () /* notify control protocols */ ControlProtocol::TrackSelectionChanged (routes); + + if (sfbrowser && _session && !_session->deletion_in_progress()) { + uint32_t audio_track_cnt = 0; + uint32_t midi_track_cnt = 0; + + for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) { + AudioTimeAxisView* atv = dynamic_cast(*x); + + if (atv) { + if (atv->is_audio_track()) { + audio_track_cnt++; + } + + } else { + MidiTimeAxisView* mtv = dynamic_cast(*x); + + if (mtv) { + if (mtv->is_midi_track()) { + midi_track_cnt++; + } + } + } + } + + sfbrowser->reset (audio_track_cnt, midi_track_cnt); + } } void @@ -991,6 +1042,15 @@ Editor::time_selection_changed () return; } + /* XXX this is superficially inefficient. Hide the selection in all + * tracks, then show it in all selected tracks. + * + * However, if you investigate what this actually does, it isn't + * anywhere nearly as bad as it may appear. Remember: nothing is + * redrawn or even recomputed during these two loops - that only + * happens when we next render ... + */ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (*i)->hide_selection (); } @@ -1005,8 +1065,17 @@ Editor::time_selection_changed () ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true); } - if (_session && Config->get_always_play_range() && !_session->transport_rolling() && !selection->time.empty()) { - _session->request_locate (selection->time.start()); + /* propagate into backend, but only when there is no drag or we are at + * the end of a drag, otherwise this is too expensive (could case a + * locate per mouse motion event. + */ + + if (_session && !_drags->active()) { + if (selection->time.length() != 0) { + _session->set_range_selection (selection->time.start(), selection->time.end_frame()); + } else { + _session->clear_range_selection (); + } } } @@ -1170,6 +1239,8 @@ Editor::sensitize_the_right_region_actions () editor_menu_actions->get_action("RegionMenuMIDI")->set_sensitive (false); _region_actions->get_action("show-region-list-editor")->set_sensitive (false); _region_actions->get_action("quantize-region")->set_sensitive (false); + _region_actions->get_action("legatize-region")->set_sensitive (false); + _region_actions->get_action("remove-overlap")->set_sensitive (false); _region_actions->get_action("fork-region")->set_sensitive (false); _region_actions->get_action("insert-patch-change-context")->set_sensitive (false); _region_actions->get_action("insert-patch-change")->set_sensitive (false); @@ -1316,6 +1387,17 @@ Editor::region_selection_changed () if (_session && !_session->transport_rolling() && !selection->regions.empty()) { maybe_locate_with_edit_preroll (selection->regions.start()); } + + /* propagate into backend */ + + if (_session) { + if (!selection->regions.empty()) { + _session->set_object_selection (selection->regions.start(), selection->regions.end_frame()); + } else { + _session->clear_object_selection (); + } + } + } void @@ -1335,6 +1417,8 @@ Editor::select_all_in_track (Selection::Operation op) return; } + begin_reversible_selection_op (X_("Select All in Track")); + clicked_routeview->get_selectables (0, max_framepos, 0, DBL_MAX, touched); switch (op) { @@ -1351,57 +1435,41 @@ Editor::select_all_in_track (Selection::Operation op) selection->add (touched); break; } + + commit_reversible_selection_op (); } -void +bool Editor::select_all_internal_edit (Selection::Operation) { + bool selected = false; + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); if (mrv) { mrv->select_all_notes (); + selected = true; } } + + MidiRegionView* mrv = dynamic_cast(entered_regionview); + if (mrv) { + mrv->select_all_notes (); + selected = true; + } + + return selected; } void -Editor::select_all (Selection::Operation op) +Editor::select_all_objects (Selection::Operation op) { list touched; - TrackViewList ts; + TrackViewList ts = track_views; - if (selection->tracks.empty()) { - if (entered_track) { - ts.push_back (entered_track); - } else { - ts = track_views; - } - } else { - ts = selection->tracks; - } - - if (_internal_editing) { - - bool midi_selected = false; - - for (TrackViewList::iterator iter = ts.begin(); iter != ts.end(); ++iter) { - if ((*iter)->hidden()) { - continue; - } - - RouteTimeAxisView* rtav = dynamic_cast (*iter); - - if (rtav && rtav->is_midi_track()) { - midi_selected = true; - break; - } - } - - if (midi_selected) { - select_all_internal_edit (op); - return; - } + if (internal_editing() && select_all_internal_edit(op)) { + return; // Selected notes } for (TrackViewList::iterator iter = ts.begin(); iter != ts.end(); ++iter) { @@ -1409,9 +1477,11 @@ Editor::select_all (Selection::Operation op) continue; } (*iter)->get_selectables (0, max_framepos, 0, DBL_MAX, touched); + selection->add (*iter); } - begin_reversible_command (_("select all")); + + begin_reversible_selection_op (X_("select all")); switch (op) { case Selection::Add: selection->add (touched); @@ -1426,7 +1496,7 @@ Editor::select_all (Selection::Operation op) /* meaningless, because we're selecting everything */ break; } - commit_reversible_command (); + commit_reversible_selection_op (); } void @@ -1438,8 +1508,10 @@ Editor::invert_selection_in_track () return; } + begin_reversible_selection_op (X_("Invert Selection in Track")); clicked_routeview->get_inverted_selectables (*selection, touched); selection->set (touched); + commit_reversible_selection_op (); } void @@ -1447,7 +1519,7 @@ Editor::invert_selection () { list touched; - if (_internal_editing) { + if (internal_editing()) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); if (mrv) { @@ -1464,7 +1536,9 @@ Editor::invert_selection () (*iter)->get_inverted_selectables (*selection, touched); } + begin_reversible_selection_op (X_("Invert Selection")); selection->set (touched); + commit_reversible_selection_op (); } /** @param start Start time in session frames. @@ -1489,6 +1563,8 @@ Editor::select_all_within (framepos_t start, framepos_t end, double top, double } if (found.empty()) { + selection->clear_objects(); + selection->clear_time (); return; } @@ -1503,7 +1579,7 @@ Editor::select_all_within (framepos_t start, framepos_t end, double top, double } } - begin_reversible_command (_("select all within")); + begin_reversible_selection_op (X_("select all within")); switch (op) { case Selection::Add: selection->add (found); @@ -1519,7 +1595,7 @@ Editor::select_all_within (framepos_t start, framepos_t end, double top, double break; } - commit_reversible_command (); + commit_reversible_selection_op (); } void @@ -1529,7 +1605,25 @@ Editor::set_selection_from_region () return; } + /* find all the tracks that have selected regions */ + + set tracks; + + for (RegionSelection::const_iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) { + tracks.insert (&(*r)->get_time_axis_view()); + } + + TrackViewList tvl; + tvl.insert (tvl.end(), tracks.begin(), tracks.end()); + + /* select range (this will clear the region selection) */ + selection->set (selection->regions.start(), selection->regions.end_frame()); + + /* and select the tracks */ + + selection->set (tvl); + if (!Profile->get_sae()) { set_mouse_mode (Editing::MouseRange, false); } @@ -1561,9 +1655,9 @@ Editor::set_selection_from_loop() void Editor::set_selection_from_range (Location& loc) { - begin_reversible_command (_("set selection from range")); + begin_reversible_selection_op (X_("set selection from range")); selection->set (loc.start(), loc.end()); - commit_reversible_command (); + commit_reversible_selection_op (); if (!Profile->get_sae()) { set_mouse_mode (Editing::MouseRange, false); @@ -1601,9 +1695,9 @@ Editor::select_all_selectables_using_time_selection () (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched); } - begin_reversible_command (_("select all from range")); + begin_reversible_selection_op (X_("select all from range")); selection->set (touched); - commit_reversible_command (); + commit_reversible_selection_op (); } @@ -1632,9 +1726,9 @@ Editor::select_all_selectables_using_punch() } (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched); } - begin_reversible_command (_("select all from punch")); + begin_reversible_selection_op (X_("select all from punch")); selection->set (touched); - commit_reversible_command (); + commit_reversible_selection_op (); } @@ -1663,9 +1757,9 @@ Editor::select_all_selectables_using_loop() } (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched); } - begin_reversible_command (_("select all from loop")); + begin_reversible_selection_op (X_("select all from loop")); selection->set (touched); - commit_reversible_command (); + commit_reversible_selection_op (); } @@ -1688,7 +1782,7 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after) } } - if (_internal_editing) { + if (internal_editing()) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); if (mrv) { @@ -1699,9 +1793,9 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after) } if (after) { - begin_reversible_command (_("select all after cursor")); + begin_reversible_selection_op (X_("select all after cursor")); } else { - begin_reversible_command (_("select all before cursor")); + begin_reversible_selection_op (X_("select all before cursor")); } TrackViewList* ts; @@ -1719,7 +1813,7 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after) (*iter)->get_selectables (start, end, 0, DBL_MAX, touched); } selection->set (touched); - commit_reversible_command (); + commit_reversible_selection_op (); } void @@ -1730,10 +1824,10 @@ Editor::select_all_selectables_using_edit (bool after) list touched; if (after) { - start = get_preferred_edit_position(); + start = get_preferred_edit_position(EDIT_IGNORE_NONE, true); end = _session->current_end_frame(); } else { - if ((end = get_preferred_edit_position()) > 1) { + if ((end = get_preferred_edit_position(EDIT_IGNORE_NONE, true)) > 1) { start = 0; end -= 1; } else { @@ -1741,7 +1835,7 @@ Editor::select_all_selectables_using_edit (bool after) } } - if (_internal_editing) { + if (internal_editing()) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); mrv->select_range (start, end); @@ -1750,9 +1844,9 @@ Editor::select_all_selectables_using_edit (bool after) } if (after) { - begin_reversible_command (_("select all after edit")); + begin_reversible_selection_op (X_("select all after edit")); } else { - begin_reversible_command (_("select all before edit")); + begin_reversible_selection_op (X_("select all before edit")); } TrackViewList* ts; @@ -1770,11 +1864,11 @@ Editor::select_all_selectables_using_edit (bool after) (*iter)->get_selectables (start, end, 0, DBL_MAX, touched); } selection->set (touched); - commit_reversible_command (); + commit_reversible_selection_op (); } void -Editor::select_all_selectables_between (bool /*within*/) +Editor::select_all_selectables_between (bool within) { framepos_t start; framepos_t end; @@ -1784,7 +1878,7 @@ Editor::select_all_selectables_between (bool /*within*/) return; } - if (_internal_editing) { + if (internal_editing()) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); mrv->select_range (start, end); @@ -1804,10 +1898,12 @@ Editor::select_all_selectables_between (bool /*within*/) if ((*iter)->hidden()) { continue; } - (*iter)->get_selectables (start, end, 0, DBL_MAX, touched); + (*iter)->get_selectables (start, end, 0, DBL_MAX, touched, within); } + begin_reversible_selection_op (X_("Select all Selectables Between")); selection->set (touched); + commit_reversible_selection_op (); } void @@ -1824,117 +1920,128 @@ Editor::select_range_between () return; } + begin_reversible_selection_op (X_("Select Range Between")); set_mouse_mode (MouseRange); selection->set (start, end); + commit_reversible_selection_op (); } bool Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const { - framepos_t m; - bool ignored; +// framepos_t m; +// bool ignored; /* if an explicit range exists, use it */ - if (!selection->time.empty()) { + if ( (mouse_mode == MouseRange || get_smart_mode() ) && !selection->time.empty()) { /* we know that these are ordered */ start = selection->time.start(); end = selection->time.end_frame(); return true; - } - - if (!mouse_frame (m, ignored)) { - /* mouse is not in a canvas, try playhead+selected marker. - this is probably most true when using menus. - */ - - if (selection->markers.empty()) { - return false; - } - - start = selection->markers.front()->position(); - end = _session->audible_frame(); - } else { - - switch (_edit_point) { - case EditAtPlayhead: - if (selection->markers.empty()) { - /* use mouse + playhead */ - start = m; - end = _session->audible_frame(); - } else { - /* use playhead + selected marker */ - start = _session->audible_frame(); - end = selection->markers.front()->position(); - } - break; - - case EditAtMouse: - /* use mouse + selected marker */ - if (selection->markers.empty()) { - start = m; - end = _session->audible_frame(); - } else { - start = selection->markers.front()->position(); - end = m; - } - break; - - case EditAtSelectedMarker: - /* use mouse + selected marker */ - if (selection->markers.empty()) { - - MessageDialog win (_("No edit range defined"), - false, - MESSAGE_INFO, - BUTTONS_OK); - - win.set_secondary_text ( - _("the edit point is Selected Marker\nbut there is no selected marker.")); - - - win.set_default_response (RESPONSE_CLOSE); - win.set_position (Gtk::WIN_POS_MOUSE); - win.show_all(); - - win.run (); - - return false; // NO RANGE - } - start = selection->markers.front()->position(); - end = m; - break; - } - } - - if (start == end) { + start = 0; + end = 0; return false; } - - if (start > end) { - swap (start, end); - } + +// if (!mouse_frame (m, ignored)) { +// /* mouse is not in a canvas, try playhead+selected marker. +// this is probably most true when using menus. +// */ +// +// if (selection->markers.empty()) { +// return false; +// } + +// start = selection->markers.front()->position(); +// end = _session->audible_frame(); + +// } else { + +// switch (_edit_point) { +// case EditAtPlayhead: +// if (selection->markers.empty()) { +// /* use mouse + playhead */ +// start = m; +// end = _session->audible_frame(); +// } else { +// /* use playhead + selected marker */ +// start = _session->audible_frame(); +// end = selection->markers.front()->position(); +// } +// break; + +// case EditAtMouse: +// /* use mouse + selected marker */ +// if (selection->markers.empty()) { +// start = m; +// end = _session->audible_frame(); +// } else { +// start = selection->markers.front()->position(); +// end = m; +// } +// break; + +// case EditAtSelectedMarker: +// /* use mouse + selected marker */ +// if (selection->markers.empty()) { + +// MessageDialog win (_("No edit range defined"), +// false, +// MESSAGE_INFO, +// BUTTONS_OK); + +// win.set_secondary_text ( +// _("the edit point is Selected Marker\nbut there is no selected marker.")); + + +// win.set_default_response (RESPONSE_CLOSE); +// win.set_position (Gtk::WIN_POS_MOUSE); +// win.show_all(); + +// win.run (); + +// return false; // NO RANGE +// } +// start = selection->markers.front()->position(); +// end = m; +// break; +// } +// } + +// if (start == end) { +// return false; +// } + +// if (start > end) { +// swap (start, end); +// } /* turn range into one delimited by start...end, not start...end-1 */ - end++; +// end++; - return true; +// return true; } void Editor::deselect_all () { + begin_reversible_selection_op (X_("Deselect All")); selection->clear (); + commit_reversible_selection_op (); } long Editor::select_range (framepos_t s, framepos_t e) { + begin_reversible_selection_op (X_("Select Range")); selection->add (clicked_axisview); selection->time.clear (); - return selection->set (s, e); + long ret = selection->set (s, e); + commit_reversible_selection_op (); + return ret; }