2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "pbd/stacktrace.h"
25 #include "ardour/session.h"
26 #include "ardour/playlist.h"
27 #include "ardour/route_group.h"
28 #include "ardour/profile.h"
32 #include "audio_time_axis.h"
33 #include "audio_region_view.h"
34 #include "audio_streamview.h"
35 #include "automation_line.h"
36 #include "control_point.h"
37 #include "editor_regions.h"
42 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace Editing;
49 struct TrackViewByPositionSorter
51 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
52 return a->y_position() < b->y_position();
57 Editor::extend_selection_to_track (TimeAxisView& view)
59 if (selection->selected (&view)) {
60 /* already selected, do nothing */
64 if (selection->tracks.empty()) {
66 if (!selection->selected (&view)) {
67 selection->set (&view);
74 /* something is already selected, so figure out which range of things to add */
76 TrackViewList to_be_added;
77 TrackViewList sorted = track_views;
78 TrackViewByPositionSorter cmp;
79 bool passed_clicked = false;
84 if (!selection->selected (&view)) {
85 to_be_added.push_back (&view);
88 /* figure out if we should go forward or backwards */
90 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
93 passed_clicked = true;
96 if (selection->selected (*i)) {
106 passed_clicked = false;
110 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
113 passed_clicked = true;
117 if (passed_clicked) {
118 if ((*i)->hidden()) {
121 if (selection->selected (*i)) {
123 } else if (!(*i)->hidden()) {
124 to_be_added.push_back (*i);
131 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
134 passed_clicked = true;
138 if (passed_clicked) {
140 if ((*r)->hidden()) {
144 if (selection->selected (*r)) {
146 } else if (!(*r)->hidden()) {
147 to_be_added.push_back (*r);
153 if (!to_be_added.empty()) {
154 selection->add (to_be_added);
162 Editor::select_all_tracks ()
164 TrackViewList visible_views;
165 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
166 if ((*i)->marked_for_display()) {
167 visible_views.push_back (*i);
170 selection->set (visible_views);
173 /** Select clicked_axisview, unless there are no currently selected
174 * tracks, in which case nothing will happen unless `force' is true.
177 Editor::set_selected_track_as_side_effect (bool force)
179 if (!clicked_axisview) {
183 if (!selection->tracks.empty()) {
184 if (!selection->selected (clicked_axisview)) {
185 selection->add (clicked_axisview);
189 selection->set (clicked_axisview);
194 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
197 case Selection::Toggle:
198 if (selection->selected (&view)) {
200 selection->remove (&view);
203 selection->add (&view);
208 if (!selection->selected (&view)) {
209 selection->add (&view);
214 selection->set (&view);
217 case Selection::Extend:
218 extend_selection_to_track (view);
224 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
226 if (!clicked_routeview) {
234 set_selected_track (*clicked_routeview, op, no_remove);
238 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
240 if (!clicked_control_point) {
246 selection->set (clicked_control_point);
249 selection->add (clicked_control_point);
251 case Selection::Toggle:
252 selection->toggle (clicked_control_point);
254 case Selection::Extend:
263 Editor::get_onscreen_tracks (TrackViewList& tvl)
265 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
266 if ((*i)->y_position() < _canvas_height) {
272 /** Call a slot for a given `basis' track and also for any track that is in the same
273 * active route group with a particular set of properties.
275 * @param sl Slot to call.
276 * @param basis Basis track.
277 * @param prop Properties that active edit groups must share to be included in the map.
281 Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, PBD::PropertyID prop) const
283 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
285 if (route_basis == 0) {
289 set<RouteTimeAxisView*> tracks;
290 tracks.insert (route_basis);
292 RouteGroup* group = route_basis->route()->route_group();
294 if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id) ) {
296 /* the basis is a member of an active route group, with the appropriate
297 properties; find other members */
299 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
300 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
301 if (v && v->route()->route_group() == group) {
308 uint32_t const sz = tracks.size ();
310 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
316 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
318 boost::shared_ptr<Playlist> pl;
319 vector<boost::shared_ptr<Region> > results;
321 boost::shared_ptr<Track> tr;
323 if ((tr = tv.track()) == 0) {
328 if (&tv == &basis->get_time_axis_view()) {
329 /* looking in same track as the original */
333 if ((pl = tr->playlist()) != 0) {
334 pl->get_equivalent_regions (basis->region(), results);
337 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
338 if ((marv = tv.view()->find_view (*ir)) != 0) {
339 all_equivs->push_back (marv);
345 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const
347 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), property);
349 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
351 equivalent_regions.push_back (basis);
355 Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) const
357 RegionSelection equivalent;
359 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
361 vector<RegionView*> eq;
364 sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
365 &(*i)->get_trackview(), prop
368 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
380 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
382 int region_count = 0;
384 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
386 RouteTimeAxisView* tatv;
388 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
390 boost::shared_ptr<Playlist> pl;
391 vector<boost::shared_ptr<Region> > results;
393 boost::shared_ptr<Track> tr;
395 if ((tr = tatv->track()) == 0) {
400 if ((pl = (tr->playlist())) != 0) {
401 pl->get_region_list_equivalent_regions (region, results);
404 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
405 if ((marv = tatv->view()->find_view (*ir)) != 0) {
418 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
420 vector<RegionView*> all_equivalent_regions;
423 if (!clicked_regionview || !clicked_routeview) {
428 button_release_can_deselect = false;
431 if (op == Selection::Toggle || op == Selection::Set) {
435 case Selection::Toggle:
437 if (selection->selected (clicked_regionview)) {
440 /* whatever was clicked was selected already; do nothing here but allow
441 the button release to deselect it
444 button_release_can_deselect = true;
448 if (button_release_can_deselect) {
450 /* just remove this one region, but only on a permitted button release */
452 selection->remove (clicked_regionview);
455 /* no more deselect action on button release till a new press
456 finds an already selected object.
459 button_release_can_deselect = false;
467 if (selection->selected (clicked_routeview)) {
468 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
470 all_equivalent_regions.push_back (clicked_regionview);
473 /* add all the equivalent regions, but only on button press */
475 if (!all_equivalent_regions.empty()) {
479 selection->add (all_equivalent_regions);
485 if (!selection->selected (clicked_regionview)) {
486 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
487 selection->set (all_equivalent_regions);
490 /* no commit necessary: clicked on an already selected region */
500 } else if (op == Selection::Extend) {
502 list<Selectable*> results;
503 nframes64_t last_frame;
504 nframes64_t first_frame;
505 bool same_track = false;
507 /* 1. find the last selected regionview in the track that was clicked in */
510 first_frame = max_frames;
512 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
513 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
515 if ((*x)->region()->last_frame() > last_frame) {
516 last_frame = (*x)->region()->last_frame();
519 if ((*x)->region()->first_frame() < first_frame) {
520 first_frame = (*x)->region()->first_frame();
529 /* 2. figure out the boundaries for our search for new objects */
531 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
533 if (last_frame < clicked_regionview->region()->first_frame()) {
534 first_frame = last_frame;
535 last_frame = clicked_regionview->region()->last_frame();
537 last_frame = first_frame;
538 first_frame = clicked_regionview->region()->first_frame();
542 case OverlapExternal:
543 if (last_frame < clicked_regionview->region()->first_frame()) {
544 first_frame = last_frame;
545 last_frame = clicked_regionview->region()->last_frame();
547 last_frame = first_frame;
548 first_frame = clicked_regionview->region()->first_frame();
552 case OverlapInternal:
553 if (last_frame < clicked_regionview->region()->first_frame()) {
554 first_frame = last_frame;
555 last_frame = clicked_regionview->region()->last_frame();
557 last_frame = first_frame;
558 first_frame = clicked_regionview->region()->first_frame();
564 /* nothing to do except add clicked region to selection, since it
565 overlaps with the existing selection in this track.
572 /* click in a track that has no regions selected, so extend vertically
573 to pick out all regions that are defined by the existing selection
578 first_frame = entered_regionview->region()->position();
579 last_frame = entered_regionview->region()->last_frame();
581 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
582 if ((*i)->region()->position() < first_frame) {
583 first_frame = (*i)->region()->position();
585 if ((*i)->region()->last_frame() + 1 > last_frame) {
586 last_frame = (*i)->region()->last_frame();
591 /* 2. find all the tracks we should select in */
593 set<RouteTimeAxisView*> relevant_tracks;
595 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
596 RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
598 relevant_tracks.insert (r);
602 set<RouteTimeAxisView*> already_in_selection;
604 if (relevant_tracks.empty()) {
606 /* no tracks selected .. thus .. if the
607 regionview we're in isn't selected
608 (i.e. we're about to extend to it), then
609 find all tracks between the this one and
613 if (!selection->selected (entered_regionview)) {
615 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
619 /* add this track to the ones we will search */
621 relevant_tracks.insert (rtv);
623 /* find the track closest to this one that
624 already a selected region.
627 RouteTimeAxisView* closest = 0;
628 int distance = INT_MAX;
629 int key = rtv->route()->order_key ("editor");
631 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
633 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
635 if (artv && artv != rtv) {
637 pair<set<RouteTimeAxisView*>::iterator,bool> result;
639 result = already_in_selection.insert (artv);
642 /* newly added to already_in_selection */
644 int d = artv->route()->order_key ("editor");
648 if (abs (d) < distance) {
658 /* now add all tracks between that one and this one */
660 int okey = closest->route()->order_key ("editor");
666 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
667 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
668 if (artv && artv != rtv) {
670 int k = artv->route()->order_key ("editor");
672 if (k >= okey && k <= key) {
674 /* in range but don't add it if
675 it already has tracks selected.
676 this avoids odd selection
677 behaviour that feels wrong.
680 if (find (already_in_selection.begin(),
681 already_in_selection.end(),
682 artv) == already_in_selection.end()) {
684 relevant_tracks.insert (artv);
694 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
695 one that was clicked.
698 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
699 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
702 /* 4. convert to a vector of regions */
704 vector<RegionView*> regions;
706 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
709 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
710 regions.push_back (arv);
714 if (!regions.empty()) {
715 selection->add (regions);
726 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
728 vector<RegionView*> all_equivalent_regions;
730 get_regions_corresponding_to (region, all_equivalent_regions);
732 if (all_equivalent_regions.empty()) {
736 begin_reversible_command (_("set selected regions"));
739 case Selection::Toggle:
740 /* XXX this is not correct */
741 selection->toggle (all_equivalent_regions);
744 selection->set (all_equivalent_regions);
746 case Selection::Extend:
747 selection->add (all_equivalent_regions);
750 selection->add (all_equivalent_regions);
754 commit_reversible_command () ;
758 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
761 boost::shared_ptr<Region> r (weak_r.lock());
767 if ((rv = sv->find_view (r)) == 0) {
771 /* don't reset the selection if its something other than
772 a single other region.
775 if (selection->regions.size() > 1) {
779 begin_reversible_command (_("set selected regions"));
783 commit_reversible_command () ;
789 Editor::track_selection_changed ()
791 switch (selection->tracks.size()) {
795 set_selected_mixer_strip (*(selection->tracks.front()));
799 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
800 (*i)->set_selected (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end());
802 TimeAxisView::Children c = (*i)->get_child_list ();
803 for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) {
804 (*j)->set_selected (find (selection->tracks.begin(), selection->tracks.end(), j->get()) != selection->tracks.end());
808 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
812 Editor::time_selection_changed ()
814 if (Profile->get_sae()) {
818 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
819 (*i)->hide_selection ();
822 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
823 (*i)->show_selection (selection->time);
826 if (selection->time.empty()) {
827 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
829 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
834 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
836 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
837 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
839 string accel_path = (*x)->get_accel_path ();
842 /* if there is an accelerator, it should always be sensitive
843 to allow for keyboard ops on entered regions.
846 bool known = ActionManager::lookup_entry (accel_path, key);
848 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
849 (*x)->set_sensitive (true);
851 (*x)->set_sensitive (have_selected_regions);
858 Editor::region_selection_changed ()
860 _regions->block_change_connection (true);
861 editor_regions_selection_changed_connection.block(true);
863 _regions->unselect_all ();
865 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
866 (*i)->set_selected_regionviews (selection->regions);
869 _regions->set_selected (selection->regions);
871 sensitize_the_right_region_actions (!selection->regions.empty());
873 _regions->block_change_connection (false);
874 editor_regions_selection_changed_connection.block(false);
878 Editor::point_selection_changed ()
880 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
881 (*i)->set_selected_points (selection->points);
886 Editor::select_all_in_track (Selection::Operation op)
888 list<Selectable *> touched;
890 if (!clicked_routeview) {
894 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
897 case Selection::Toggle:
898 selection->add (touched);
901 selection->set (touched);
903 case Selection::Extend:
904 /* meaningless, because we're selecting everything */
907 selection->add (touched);
913 Editor::select_all (Selection::Operation op)
915 list<Selectable *> touched;
917 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
918 if ((*iter)->hidden()) {
921 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
923 begin_reversible_command (_("select all"));
926 selection->add (touched);
928 case Selection::Toggle:
929 selection->add (touched);
932 selection->set (touched);
934 case Selection::Extend:
935 /* meaningless, because we're selecting everything */
938 commit_reversible_command ();
941 Editor::invert_selection_in_track ()
943 list<Selectable *> touched;
945 if (!clicked_routeview) {
949 clicked_routeview->get_inverted_selectables (*selection, touched);
950 selection->set (touched);
954 Editor::invert_selection ()
956 list<Selectable *> touched;
958 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
959 if ((*iter)->hidden()) {
962 (*iter)->get_inverted_selectables (*selection, touched);
965 selection->set (touched);
968 /** @param start Start time in session frames.
969 * @param end End time in session frames.
970 * @param top Top (lower) y limit in trackview coordinates (ie 0 at the top of the track view)
971 * @param bottom Bottom (higher) y limit in trackview coordinates (ie 0 at the top of the track view)
972 * @param preserve_if_selected true to leave the current selection alone if we're adding to the selection and all of the selectables
973 * within the region are already selected.
976 Editor::select_all_within (
977 framepos_t start, framepos_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op, bool preserve_if_selected
980 list<Selectable*> found;
982 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
984 if ((*iter)->hidden()) {
988 (*iter)->get_selectables (start, end, top, bot, found);
995 if (preserve_if_selected && op != Selection::Toggle) {
996 list<Selectable*>::iterator i = found.begin();
997 while (i != found.end() && (*i)->get_selected()) {
1001 if (i == found.end()) {
1006 begin_reversible_command (_("select all within"));
1008 case Selection::Add:
1009 selection->add (found);
1011 case Selection::Toggle:
1012 selection->toggle (found);
1014 case Selection::Set:
1015 selection->set (found);
1017 case Selection::Extend:
1018 /* not defined yet */
1022 commit_reversible_command ();
1024 return !found.empty();
1028 Editor::set_selection_from_region ()
1030 if (selection->regions.empty()) {
1034 selection->set (selection->regions.start(), selection->regions.end_frame());
1035 if (!Profile->get_sae()) {
1036 set_mouse_mode (Editing::MouseRange, false);
1041 Editor::set_selection_from_punch()
1045 if ((location = _session->locations()->auto_punch_location()) == 0) {
1049 set_selection_from_range (*location);
1053 Editor::set_selection_from_loop()
1057 if ((location = _session->locations()->auto_loop_location()) == 0) {
1060 set_selection_from_range (*location);
1064 Editor::set_selection_from_range (Location& loc)
1066 begin_reversible_command (_("set selection from range"));
1067 selection->set (loc.start(), loc.end());
1068 commit_reversible_command ();
1070 if (!Profile->get_sae()) {
1071 set_mouse_mode (Editing::MouseRange, false);
1076 Editor::select_all_selectables_using_time_selection ()
1078 list<Selectable *> touched;
1080 if (selection->time.empty()) {
1084 nframes64_t start = selection->time[clicked_selection].start;
1085 nframes64_t end = selection->time[clicked_selection].end;
1087 if (end - start < 1) {
1093 if (selection->tracks.empty()) {
1096 ts = &selection->tracks;
1099 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1100 if ((*iter)->hidden()) {
1103 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1106 begin_reversible_command (_("select all from range"));
1107 selection->set (touched);
1108 commit_reversible_command ();
1113 Editor::select_all_selectables_using_punch()
1115 Location* location = _session->locations()->auto_punch_location();
1116 list<Selectable *> touched;
1118 if (location == 0 || (location->end() - location->start() <= 1)) {
1125 if (selection->tracks.empty()) {
1128 ts = &selection->tracks;
1131 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1132 if ((*iter)->hidden()) {
1135 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1137 begin_reversible_command (_("select all from punch"));
1138 selection->set (touched);
1139 commit_reversible_command ();
1144 Editor::select_all_selectables_using_loop()
1146 Location* location = _session->locations()->auto_loop_location();
1147 list<Selectable *> touched;
1149 if (location == 0 || (location->end() - location->start() <= 1)) {
1156 if (selection->tracks.empty()) {
1159 ts = &selection->tracks;
1162 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1163 if ((*iter)->hidden()) {
1166 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1168 begin_reversible_command (_("select all from loop"));
1169 selection->set (touched);
1170 commit_reversible_command ();
1175 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1179 list<Selectable *> touched;
1182 begin_reversible_command (_("select all after cursor"));
1183 start = cursor->current_frame ;
1184 end = _session->current_end_frame();
1186 if (cursor->current_frame > 0) {
1187 begin_reversible_command (_("select all before cursor"));
1189 end = cursor->current_frame - 1;
1198 if (selection->tracks.empty()) {
1201 ts = &selection->tracks;
1204 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1205 if ((*iter)->hidden()) {
1208 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1210 selection->set (touched);
1211 commit_reversible_command ();
1215 Editor::select_all_selectables_using_edit (bool after)
1219 list<Selectable *> touched;
1222 begin_reversible_command (_("select all after edit"));
1223 start = get_preferred_edit_position();
1224 end = _session->current_end_frame();
1226 if ((end = get_preferred_edit_position()) > 1) {
1227 begin_reversible_command (_("select all before edit"));
1238 if (selection->tracks.empty()) {
1241 ts = &selection->tracks;
1244 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1245 if ((*iter)->hidden()) {
1248 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1250 selection->set (touched);
1251 commit_reversible_command ();
1255 Editor::select_all_selectables_between (bool /*within*/)
1259 list<Selectable *> touched;
1261 if (!get_edit_op_range (start, end)) {
1267 if (selection->tracks.empty()) {
1270 ts = &selection->tracks;
1273 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1274 if ((*iter)->hidden()) {
1277 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1280 selection->set (touched);
1284 Editor::select_range_between ()
1289 if (mouse_mode == MouseRange && !selection->time.empty()) {
1290 selection->clear_time ();
1293 if (!get_edit_op_range (start, end)) {
1297 set_mouse_mode (MouseRange);
1298 selection->set (start, end);
1302 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1307 /* in range mode, use any existing selection */
1309 if (mouse_mode == MouseRange && !selection->time.empty()) {
1310 /* we know that these are ordered */
1311 start = selection->time.start();
1312 end = selection->time.end_frame();
1316 if (!mouse_frame (m, ignored)) {
1317 /* mouse is not in a canvas, try playhead+selected marker.
1318 this is probably most true when using menus.
1321 if (selection->markers.empty()) {
1325 start = selection->markers.front()->position();
1326 end = _session->audible_frame();
1330 switch (_edit_point) {
1331 case EditAtPlayhead:
1332 if (selection->markers.empty()) {
1333 /* use mouse + playhead */
1335 end = _session->audible_frame();
1337 /* use playhead + selected marker */
1338 start = _session->audible_frame();
1339 end = selection->markers.front()->position();
1344 /* use mouse + selected marker */
1345 if (selection->markers.empty()) {
1347 end = _session->audible_frame();
1349 start = selection->markers.front()->position();
1354 case EditAtSelectedMarker:
1355 /* use mouse + selected marker */
1356 if (selection->markers.empty()) {
1358 MessageDialog win (_("No edit range defined"),
1363 win.set_secondary_text (
1364 _("the edit point is Selected Marker\nbut there is no selected marker."));
1367 win.set_default_response (RESPONSE_CLOSE);
1368 win.set_position (Gtk::WIN_POS_MOUSE);
1373 return false; // NO RANGE
1375 start = selection->markers.front()->position();
1389 /* turn range into one delimited by start...end,
1399 Editor::deselect_all ()
1401 selection->clear ();
1405 Editor::select_range_around_region (RegionView* rv)
1409 selection->set (&rv->get_time_axis_view());
1411 selection->time.clear ();
1412 boost::shared_ptr<Region> r = rv->region ();
1413 return selection->set (r->position(), r->position() + r->length());