#include "gui_thread.h"
#include "actions.h"
#include "utils.h"
+#include "route_sorter.h"
#include "editor_group_tabs.h"
#include "editor_routes.h"
: EditorComponent (e)
, _ignore_reorder (false)
, _no_redisplay (false)
+ , _adding_routes (false)
, _menu (0)
, old_focus (0)
, selection_countdown (0)
_display.get_selection()->set_mode (SELECTION_SINGLE);
_display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
_display.set_reorderable (true);
+ _display.set_name (X_("EditGroupList"));
_display.set_rules_hint (true);
_display.set_size_request (100, -1);
_display.add_object_drag (_columns.route.index(), "routes");
_display.set_enable_search (false);
- Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_model_from_order_keys, this, _1), gui_context());
+ Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context());
}
bool
/* show or hide the TimeAxisView */
if (visible) {
position += tv->show_at (position, n, &_editor->edit_controls_vbox);
- tv->clip_to_viewport ();
+ // SHOWTRACKS
} else {
tv->hide ();
}
_editor->reset_controls_layout_height (position);
_editor->reset_controls_layout_width ();
- _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
- _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
+ _editor->_full_canvas_height = position;
- if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
+ if ((_editor->vertical_adjustment.get_value() + _editor->_visible_canvas_height) > _editor->vertical_adjustment.get_upper()) {
/*
We're increasing the size of the canvas while the bottom is visible.
We scroll down to keep in step with the controls layout.
*/
- _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
+ _editor->vertical_adjustment.set_value (_editor->_full_canvas_height - _editor->_visible_canvas_height);
}
}
as when a row/route is actually deleted.
*/
DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
}
void
EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
{
DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
}
void
void
EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
{
- TreeModel::Row row;
+ PBD::Unwinder<bool> at (_adding_routes, true);
+
+ bool from_scratch = (_model->children().size() == 0);
+ Gtk::TreeModel::Children::iterator insert_iter = _model->children().end();
+
+ for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) {
+ boost::shared_ptr<Route> r = (*it)[_columns.route];
+
+ if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) {
+ insert_iter = it;
+ break;
+ }
+ }
+
+ if(!from_scratch) {
+ _editor->selection->tracks.clear();
+ }
suspend_redisplay ();
+ _display.set_model (Glib::RefPtr<ListStore>());
+
for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
boost::shared_ptr<MidiTrack> midi_trk = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
- row = *(_model->append ());
+ TreeModel::Row row = *(_model->insert (insert_iter));
row[_columns.text] = (*x)->route()->name();
row[_columns.visible] = (*x)->marked_for_display();
row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
row[_columns.name_editable] = true;
+ if (!from_scratch) {
+ _editor->selection->add(*x);
+ }
+
boost::weak_ptr<Route> wr ((*x)->route());
(*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
(*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
(*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
(*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ());
+
}
update_rec_display ();
update_solo_safe_display ();
update_input_active_display ();
update_active_display ();
+
resume_redisplay ();
+ _display.set_model (_model);
/* now update route order keys from the treeview/track display order */
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
}
void
EditorRoutes::handle_gui_changes (string const & what, void*)
{
- ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src)
+ if (_adding_routes) {
+ return;
+ }
if (what == "track_height") {
/* Optional :make tracks change height while it happens, instead
of on first-idle
*/
- //update_canvas_now ();
redisplay ();
}
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
resume_redisplay ();
}
}
void
-EditorRoutes::sync_order_keys_from_model ()
+EditorRoutes::reset_remote_control_ids ()
{
- if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
+ if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) {
return;
}
return;
}
- DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from model\n");
+
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n");
TreeModel::Children::iterator ri;
- bool changed = false;
- uint32_t order = 0;
+ bool rid_change = false;
+ uint32_t rid = 1;
+ uint32_t invisible_key = UINT32_MAX;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
+
boost::shared_ptr<Route> route = (*ri)[_columns.route];
bool visible = (*ri)[_columns.visible];
- uint32_t old_key = route->order_key (EditorSort);
- uint32_t new_key;
- if (!visible) {
- new_key = UINT_MAX;
- } else {
- new_key = order;
- }
+ if (!route->is_master() && !route->is_monitor()) {
- if (old_key != new_key) {
- route->set_order_key (EditorSort, new_key);
- changed = true;
- }
+ uint32_t new_rid = (visible ? rid : invisible_key--);
- order++;
+ if (new_rid != route->remote_control_id()) {
+ route->set_remote_control_id_explicit (new_rid);
+ rid_change = true;
+ }
+
+ if (visible) {
+ rid++;
+ }
+
+ }
}
-
- if (changed) {
- /* tell the world that we changed the editor sort keys */
- _session->sync_order_keys (EditorSort);
+
+ if (rid_change) {
+ /* tell the world that we changed the remote control IDs */
+ _session->notify_remote_id_change ();
}
}
+
void
-EditorRoutes::sync_model_from_order_keys (RouteSortOrderKey src)
+EditorRoutes::sync_order_keys_from_treeview ()
{
- if (!_session || _session->deletion_in_progress()) {
+ if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
+ return;
+ }
+
+ TreeModel::Children rows = _model->children();
+
+ if (rows.empty()) {
return;
}
- DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor sync model from order keys, src = %1\n", enum_2_string (src)));
+
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n");
+
+ TreeModel::Children::iterator ri;
+ bool changed = false;
+ bool rid_change = false;
+ uint32_t order = 0;
+ uint32_t rid = 1;
+ uint32_t invisible_key = UINT32_MAX;
+
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
+
+ boost::shared_ptr<Route> route = (*ri)[_columns.route];
+ bool visible = (*ri)[_columns.visible];
- if (src == MixerSort) {
+ uint32_t old_key = route->order_key ();
- if (!Config->get_sync_all_route_ordering()) {
- /* mixer sort keys changed - we don't care */
- return;
+ if (order != old_key) {
+ route->set_order_key (order);
+
+ changed = true;
}
- DEBUG_TRACE (DEBUG::OrderKeys, "reset editor order key to match mixer\n");
+ if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
- /* mixer sort keys were changed, update the editor sort
- * keys since "sync mixer+editor order" is enabled.
- */
+ uint32_t new_rid = (visible ? rid : invisible_key--);
+
+ if (new_rid != route->remote_control_id()) {
+ route->set_remote_control_id_explicit (new_rid);
+ rid_change = true;
+ }
+
+ if (visible) {
+ rid++;
+ }
- boost::shared_ptr<RouteList> r = _session->get_routes ();
-
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- (*i)->sync_order_keys (src);
}
+
+ ++order;
}
+
+ if (changed) {
+ /* tell the world that we changed the editor sort keys */
+ _session->sync_order_keys ();
+ }
+
+ if (rid_change) {
+ /* tell the world that we changed the remote control IDs */
+ _session->notify_remote_id_change ();
+ }
+}
+
+void
+EditorRoutes::sync_treeview_from_order_keys ()
+{
+ /* Some route order key(s) have been changed, make sure that
+ we update out tree/list model and GUI to reflect the change.
+ */
+
+ if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
+ return;
+ }
+
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from order keys.\n");
/* we could get here after either a change in the Mixer or Editor sort
* order, but either way, the mixer order keys reflect the intended
vector<int> neworder;
TreeModel::Children rows = _model->children();
- uint32_t n = 0;
+ uint32_t old_order = 0;
+ bool changed = false;
if (rows.empty()) {
return;
}
- neworder.assign (rows.size(), 0);
+ OrderKeySortedRoutes sorted_routes;
- for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) {
+ for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
boost::shared_ptr<Route> route = (*ri)[_columns.route];
- neworder[route->order_key (EditorSort)] = n;
- DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor change order for %1 to %2\n",
- route->name(), route->order_key (MixerSort)));
+ sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key ()));
+ }
+
+ SortByNewDisplayOrder cmp;
+
+ sort (sorted_routes.begin(), sorted_routes.end(), cmp);
+ neworder.assign (sorted_routes.size(), 0);
+
+ uint32_t n = 0;
+
+ for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
+
+ neworder[n] = sr->old_display_order;
+
+ if (sr->old_display_order != n) {
+ changed = true;
+ }
+
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("EDITOR change order for %1 from %2 to %3\n",
+ sr->route->name(), sr->old_display_order, n));
}
- {
+ if (changed) {
Unwinder<bool> uw (_ignore_reorder, true);
_model->reorder (neworder);
}
}
resume_redisplay ();
-
- /* XXX this seems like a hack and half, but its not clear where to put this
- otherwise.
- */
-
- //reset_scrolling_region ();
}
void
continue;
}
+ tv->set_marked_for_display (yn);
(*i)[_columns.visible] = yn;
}
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
resume_redisplay ();
}
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_model ();
+ sync_order_keys_from_treeview ();
resume_redisplay ();
}
break;
case 's':
- if (Config->get_solo_control_is_listen_control()) {
- _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
- } else {
- _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
+ if (get_relevant_routes (rl)) {
+ if (Config->get_solo_control_is_listen_control()) {
+ _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
+ } else {
+ _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
+ }
}
return true;
break;
int y_pos = tv->y_position();
//Clamp the y pos so that we do not extend beyond the canvas full height.
- if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){
- y_pos = _editor->full_canvas_height - _editor->_canvas_height;
+ if (_editor->_full_canvas_height - y_pos < _editor->_visible_canvas_height){
+ y_pos = _editor->_full_canvas_height - _editor->_visible_canvas_height;
}
//Only scroll to if the track is visible
/* everything else before master */
return false;
}
- return a->order_key (EditorSort) < b->order_key (EditorSort);
+ return a->order_key () < b->order_key ();
}
};
}
for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
- uint32_t order = leading->second->order_key (EditorSort);
+ uint32_t order = leading->second->order_key ();
neworder.push_back (order);
}