_session->engine().PortRegisteredOrUnregistered.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context());
/* watch for route order keys changing, which changes the order of things in our global ports list(s) */
- _session->RouteOrderKeyChanged.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports_proxy, this), gui_context());
+ Route::SyncOrderKeys.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports_proxy, this, _1), gui_context());
/* Part 3: other stuff */
void
PortMatrix::setup ()
{
+ if (!_session) return; // session went away
+
/* this needs to be done first, as the visible_ports() method uses the
notebook state to decide which ports are being shown */
_body->setup ();
setup_scrollbars ();
+ update_tab_highlighting ();
queue_draw ();
}
}
}
- if (can_rename_channels (bc[dim].bundle)) {
+ if (can_rename_channels (bc[dim].bundle) && bc[dim].channel != -1) {
snprintf (
buf, sizeof (buf), _("Rename '%s'..."),
escape_underscores (bc[dim].bundle->channel_name (bc[dim].channel)).c_str()
}
items.push_back (MenuElem (_("Rescan"), sigc::mem_fun (*this, &PortMatrix::setup_all_ports)));
+
items.push_back (CheckMenuElem (_("Show individual ports"), sigc::mem_fun (*this, &PortMatrix::toggle_show_only_bundles)));
- CheckMenuItem* i = dynamic_cast<CheckMenuItem*> (&items.back());
+ Gtk::CheckMenuItem* i = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
_inhibit_toggle_show_only_bundles = true;
i->set_active (!_show_only_bundles);
_inhibit_toggle_show_only_bundles = false;
+ items.push_back (MenuElem (_("Flip"), sigc::mem_fun (*this, &PortMatrix::flip)));
+ items.back().set_sensitive (can_flip ());
+
_menu->popup (1, t);
}
}
void
-PortMatrix::setup_global_ports_proxy ()
+PortMatrix::setup_global_ports_proxy (RouteSortOrderKey sk)
{
- /* Avoid a deadlock by calling this in an idle handler: see IOSelector::io_changed_proxy
- for a discussion.
- */
-
- Glib::signal_idle().connect_once (sigc::mem_fun (*this, &PortMatrix::setup_global_ports));
+ if (sk == EditorSort) {
+ /* Avoid a deadlock by calling this in an idle handler: see IOSelector::io_changed_proxy
+ for a discussion.
+ */
+
+ Glib::signal_idle().connect_once (sigc::mem_fun (*this, &PortMatrix::setup_global_ports));
+ }
}
void
dummy->show ();
Label* label = manage (new Label ((*i)->name));
label->set_angle (_arrangement == LEFT_TO_BOTTOM ? 90 : -90);
+ label->set_use_markup ();
label->show ();
if (_arrangement == LEFT_TO_BOTTOM) {
_vnotebook.prepend_page (*dummy, *label);
for (PortGroupList::List::const_iterator i = _ports[_column_index].begin(); i != _ports[_column_index].end(); ++i) {
HBox* dummy = manage (new HBox);
dummy->show ();
- _hnotebook.append_page (*dummy, (*i)->name);
+ Label* label = manage (new Label ((*i)->name));
+ label->set_use_markup ();
+ label->show ();
+ _hnotebook.append_page (*dummy, *label);
}
_ignore_notebook_page_selected = false;
PortMatrix::port_connected_or_disconnected ()
{
_body->rebuild_and_draw_grid ();
+ update_tab_highlighting ();
+}
+
+/** Update the highlighting of tab names to reflect which ones
+ * have connections. This is pretty inefficient, unfortunately,
+ * but maybe that doesn't matter too much.
+ */
+void
+PortMatrix::update_tab_highlighting ()
+{
+ if (!_session) {
+ return;
+ }
+
+ for (int i = 0; i < 2; ++i) {
+
+ Gtk::Notebook* notebook = row_index() == i ? &_vnotebook : &_hnotebook;
+
+ PortGroupList const * gl = ports (i);
+ int p = 0;
+ for (PortGroupList::List::const_iterator j = gl->begin(); j != gl->end(); ++j) {
+ bool has_connection = false;
+ PortGroup::BundleList const & bl = (*j)->bundles ();
+ PortGroup::BundleList::const_iterator k = bl.begin ();
+ while (k != bl.end()) {
+ if ((*k)->bundle->connected_to_anything (_session->engine())) {
+ has_connection = true;
+ break;
+ }
+ ++k;
+ }
+
+ /* Find the page index that we should update; this is backwards
+ for the vertical tabs in the LEFT_TO_BOTTOM arrangement.
+ */
+ int page = p;
+ if (i == row_index() && _arrangement == LEFT_TO_BOTTOM) {
+ page = notebook->get_n_pages() - p - 1;
+ }
+
+ Gtk::Label* label = dynamic_cast<Gtk::Label*> (notebook->get_tab_label(*notebook->get_nth_page (page)));
+ string c = label->get_label ();
+ if (c.length() && c[0] == '<' && !has_connection) {
+ /* this label is marked up with <b> but shouldn't be */
+ label->set_text ((*j)->name);
+ } else if (c.length() && c[0] != '<' && has_connection) {
+ /* this label is not marked up with <b> but should be */
+ label->set_markup (string_compose ("<b>%1</b>", Glib::Markup::escape_text ((*j)->name)));
+ }
+
+ ++p;
+ }
+ }
}
string
{
return b && b->nchannels() != ARDOUR::ChanCount::ZERO;
}
+
+/** See if a `flip' is possible.
+ * @return If flip is possible, the new (row, column) notebook indices that
+ * should be selected; otherwise, (-1, -1)
+ */
+pair<int, int>
+PortMatrix::check_flip () const
+{
+ /* Look for the row's port group name in the columns */
+
+ int new_column = 0;
+ boost::shared_ptr<const PortGroup> r = visible_ports (_row_index);
+ PortGroupList::List::const_iterator i = _ports[_column_index].begin();
+ while (i != _ports[_column_index].end() && (*i)->name != r->name) {
+ ++i;
+ ++new_column;
+ }
+
+ if (i == _ports[_column_index].end ()) {
+ return make_pair (-1, -1);
+ }
+
+ /* Look for the column's port group name in the rows */
+
+ int new_row = 0;
+ boost::shared_ptr<const PortGroup> c = visible_ports (_column_index);
+ i = _ports[_row_index].begin();
+ while (i != _ports[_row_index].end() && (*i)->name != c->name) {
+ ++i;
+ ++new_row;
+ }
+
+ if (i == _ports[_row_index].end ()) {
+ return make_pair (-1, -1);
+ }
+
+ if (_arrangement == LEFT_TO_BOTTOM) {
+ new_row = _ports[_row_index].size() - new_row - 1;
+ }
+
+ return make_pair (new_row, new_column);
+}
+
+bool
+PortMatrix::can_flip () const
+{
+ return check_flip().first != -1;
+}
+
+/** Flip the column and row pages around, if possible */
+void
+PortMatrix::flip ()
+{
+ pair<int, int> n = check_flip ();
+ if (n.first == -1) {
+ return;
+ }
+
+ _vnotebook.set_current_page (n.first);
+ _hnotebook.set_current_page (n.second);
+}
+
+bool
+PortMatrix::key_press (GdkEventKey* k)
+{
+ if (k->keyval == GDK_f) {
+ flip ();
+ return true;
+ }
+
+ return false;
+}