add move-selected-tracks-{up,down} commands

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3879 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2008-10-07 21:46:42 +00:00
parent c021a56672
commit 0d173fdccd
7 changed files with 258 additions and 1 deletions

View file

@ -140,8 +140,10 @@
(gtk_accel_path "<Actions>/Editor/select-prev-route" "uparrow")
(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<%PRIMARY%>uparrow")
(gtk_accel_path "<Actions>/Editor/move-selected-tracks-up" "<%TERTIARY%>uparrow")
(gtk_accel_path "<Actions>/Editor/select-next-route" "downarrow")
(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<%PRIMARY%>downarrow")
(gtk_accel_path "<Actions>/Editor/move-selected-tracks-down" "<%TERTIARY%>downarrow")
;; keypad

View file

@ -251,6 +251,8 @@
<menuitem action='zoom-to-region'/>
<menuitem action='toggle-zoom'/>
</menu>
<menu action="move-selected-tracks-up"/>
<menu action="move-selected-tracks-down"/>
<menu action="ScrollMenu">
<menuitem action='scroll-tracks-down'/>
<menuitem action='scroll-tracks-up'/>

View file

@ -336,6 +336,8 @@
<menuitem action="toggle-cd-marker-ruler"/>
<menuitem action="toggle-marker-ruler"/>
</menu>
<menu action="move-selected-tracks-up"/>
<menu action="move-selected-tracks-down"/>
<menu action="ScrollMenu">
<menuitem action='scroll-tracks-down'/>
<menuitem action='scroll-tracks-up'/>

View file

@ -354,6 +354,8 @@ class Editor : public PublicEditor
void scroll_tracks_down_line ();
void scroll_tracks_up_line ();
void move_selected_tracks (bool up);
bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; }
void prepare_for_cleanup ();
void finish_cleanup ();
@ -525,7 +527,7 @@ class Editor : public PublicEditor
void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
void select_all_tracks ();
bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false);
void set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false);
void set_selected_track_as_side_effect (bool force = false);

View file

@ -301,6 +301,11 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, "toggle-zoom", _("Toggle Zoom State"), mem_fun(*this, &Editor::swap_visual_state));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "move-selected-tracks-up", _("Move Selected Tracks Up"), bind (mem_fun(*this, &Editor::move_selected_tracks), true));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "move-selected-tracks-down", _("Move Selected Tracks Down"), bind (mem_fun(*this, &Editor::move_selected_tracks), false));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "scroll-tracks-up", _("Scroll Tracks Up"), mem_fun(*this, &Editor::scroll_tracks_up));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "scroll-tracks-down", _("Scroll Tracks Down"), mem_fun(*this, &Editor::scroll_tracks_down));

View file

@ -614,3 +614,245 @@ Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
theslot (**i);
}
}
static uint32_t
compute_new_key (uint32_t old_key, bool up, uint32_t distance, uint32_t limit)
{
uint32_t new_key;
if (up) {
if (old_key >= distance) {
new_key = old_key - distance; // towards top
} else {
new_key = old_key; // already at top
}
} else {
if (old_key >= limit - distance) {
new_key = old_key; // already at bottom
} else {
new_key = old_key + distance; // towards bottom
}
}
return new_key;
}
void
Editor::move_selected_tracks (bool up)
{
if (selection->tracks.empty()) {
return;
}
typedef pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
list<ViewRoute> view_routes;
vector<int> neworder;
TreeModel::Children rows = route_display_model->children();
TreeModel::Children::iterator ri;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
TimeAxisView* tv = (*ri)[route_display_columns.tv];
boost::shared_ptr<Route> route = (*ri)[route_display_columns.route];
view_routes.push_back (ViewRoute (tv, route));
}
list<ViewRoute>::iterator trailing;
list<ViewRoute>::iterator leading;
if (up) {
trailing = view_routes.begin();
leading = view_routes.begin();
++leading;
while (leading != view_routes.end()) {
if (selection->selected (leading->first)) {
view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
leading = view_routes.erase (leading);
} else {
++leading;
++trailing;
}
}
} else {
/* if we could use reverse_iterator in list::insert, this code
would be a beautiful reflection of the code above. but we can't
and so it looks like a bit of a mess.
*/
trailing = view_routes.end();
leading = view_routes.end();
--leading; if (leading == view_routes.begin()) { return; }
--leading;
--trailing;
while (1) {
if (selection->selected (leading->first)) {
list<ViewRoute>::iterator tmp;
/* need to insert *after* trailing, not *before* it,
which is what insert (iter, val) normally does.
*/
tmp = trailing;
tmp++;
view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
/* can't use iter = cont.erase (iter); form here, because
we need iter to move backwards.
*/
tmp = leading;
--tmp;
bool done = false;
if (leading == view_routes.begin()) {
/* the one we've just inserted somewhere else
was the first in the list. erase this copy,
and then break, because we're done.
*/
done = true;
}
view_routes.erase (leading);
if (done) {
break;
}
leading = tmp;
} else {
if (leading == view_routes.begin()) {
break;
}
--leading;
--trailing;
}
};
}
for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
neworder.push_back (leading->second->order_key (_order_key));
}
route_display_model->reorder (neworder);
}
#if 0
vector<boost::shared_ptr<Route> > selected_block;
boost::shared_ptr<Route> target_unselected_route;
bool last_track_was_selected = false;
vector<int> neworder;
TreeModel::Children rows = route_display_model->children();
TreeModel::Children::iterator ri;
uint32_t old_key;
uint32_t new_key;
int n;
/* preload "neworder" with the current order */
for (n = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++n) {
neworder.push_back (n);
}
for (ri = rows.begin(); ri != rows.end(); ++ri) {
TimeAxisView* tv = (*ri)[route_display_columns.tv];
boost::shared_ptr<Route> route = (*ri)[route_display_columns.route];
if (selection->selected (tv)) {
selected_block.push_back (route);
cerr << "--SAVE as SELECTED " << route->name() << endl;
last_track_was_selected = true;
continue;
} else {
if (!last_track_was_selected) {
/* keep moving through unselected tracks, but save this
one in case we need it later as the one that will
move *down* as the selected block moves up.
*/
target_unselected_route = route;
cerr << "--pre-SAVE as UNSELECTED " << route->name() << endl;
continue;
}
last_track_was_selected = false;
if (!up) {
/* this is the track immediately after a selected block,
and this is the one that will move *up* as
the selected block moves down.
*/
target_unselected_route = route;
cerr << "--post-SAVE as UNSELECTED " << route->name() << endl;
} else {
cerr << "--(up) plan to use existing unselected target\n";
}
}
cerr << "TRANSITION: sel = " << selected_block.size() << " unsel = " << target_unselected_route << endl;
/* transitioned between selected/not-selected */
uint32_t distance;
for (vector<boost::shared_ptr<Route> >::iterator x = selected_block.begin(); x != selected_block.end(); ++x) {
old_key = (*x)->order_key (_order_key);
new_key = compute_new_key (old_key, up, 1, rows.size());
neworder[new_key] = old_key;
cerr << "--SELECTED, reorder from " << old_key << " => " << new_key << endl;
}
/* now move the unselected tracks in the opposite direction */
if (!selected_block.empty() && target_unselected_route) {
distance = selected_block.size();
old_key = target_unselected_route->order_key (_order_key);
new_key = compute_new_key (old_key, !up, distance, rows.size());
neworder[new_key] = old_key;
cerr << "--UNSELECTED, reorder from " << old_key << " => " << new_key << endl;
}
selected_block.clear ();
target_unselected_route.reset ();
}
cerr << "when done ... sel = " << selected_block.size() << " unsel = " << target_unselected_route << endl;
if (!selected_block.empty() || target_unselected_route) {
/* left over blocks */
uint32_t distance;
for (vector<boost::shared_ptr<Route> >::iterator x = selected_block.begin(); x != selected_block.end(); ++x) {
old_key = (*x)->order_key (_order_key);
new_key = compute_new_key (old_key, up, 1, rows.size());
neworder[new_key] = old_key;
cerr << "--SELECTED, reorder from " << old_key << " => " << new_key << endl;
}
if (!selected_block.empty() && target_unselected_route) {
distance = selected_block.size();
old_key = target_unselected_route->order_key (_order_key);
new_key = compute_new_key (old_key, !up, distance, rows.size());
neworder[new_key] = old_key;
cerr << "--UNSELECTED, reorder from " << old_key << " => " << new_key << endl;
}
}
route_display_model->reorder (neworder);
#endif

View file

@ -114,10 +114,12 @@
(gtk_accel_path "<Actions>/Editor/step-tracks-up" "uparrow")
(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<%PRIMARY%>uparrow")
(gtk_accel_path "<Actions>/Editor/select-prev-route" "<%SECONDARY%>uparrow")
(gtk_accel_path "<Actions>/Editor/move-selected-tracks-up" "<%TERTIARY%>uparrow")
(gtk_accel_path "<Actions>/Editor/step-tracks-down" "downarrow")
(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<%PRIMARY%>downarrow")
(gtk_accel_path "<Actions>/Editor/select-next-route" "<%SECONDARY%>downarrow")
(gtk_accel_path "<Actions>/Editor/move-selected-tracks-down" "<%TERTIARY%>downarrow")
(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary" "leftarrow")
(gtk_accel_path "<Actions>/Editor/tab-to-transient-backwards" "<%PRIMARY%>leftarrow")