Stop bundles disappearing from the port matrix when they
authorCarl Hetherington <carl@carlh.net>
Sat, 13 Aug 2011 20:19:39 +0000 (20:19 +0000)
committerCarl Hetherington <carl@carlh.net>
Sat, 13 Aug 2011 20:19:39 +0000 (20:19 +0000)
have no channels (#4209).  Also fix the remove all
channels menu option.

git-svn-id: svn://localhost/ardour2/branches/3.0@9986 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/global_port_matrix.cc
gtk2_ardour/port_group.cc
gtk2_ardour/port_matrix.cc
gtk2_ardour/port_matrix.h
gtk2_ardour/port_matrix_body.cc
gtk2_ardour/port_matrix_column_labels.cc
gtk2_ardour/port_matrix_component.cc
gtk2_ardour/port_matrix_component.h
gtk2_ardour/port_matrix_grid.cc
gtk2_ardour/port_matrix_row_labels.cc

index df224245201c8140b3f5b2d464db7a55b15b1348..565def896e0618395b998a0286f942ecef8e7a4e 100644 (file)
@@ -90,6 +90,10 @@ GlobalPortMatrix::get_state (BundleChannel c[2]) const
                return PortMatrixNode::NOT_ASSOCIATED;
        }
 
+       if (c[0].bundle->nchannels() == ChanCount::ZERO || c[1].bundle->nchannels() == ChanCount::ZERO) {
+               return PortMatrixNode::NOT_ASSOCIATED;
+       }
+
        Bundle::PortList const & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
        Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].channel);
        if (in_ports.empty() || out_ports.empty()) {
index d164c17782fff281de6c32bb342876e0d6ea9e30..7523e8beea20b204e35539b2c0faf0087d73274f 100644 (file)
@@ -389,12 +389,10 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 
                for (list<boost::shared_ptr<IO> >::iterator j = i->ios.begin(); j != i->ios.end(); ++j) {
                        boost::shared_ptr<Bundle> b = bundle_for_type ((*j)->bundle(), type);
-                       if (b->nchannels() != ChanCount::ZERO) {
-                               if (tv) {
-                                       g->add_bundle (b, *j, tv->color ());
-                               } else {
-                                       g->add_bundle (b, *j);
-                               }
+                       if (tv) {
+                               g->add_bundle (b, *j, tv->color ());
+                       } else {
+                               g->add_bundle (b, *j);
                        }
                }
        }
@@ -408,18 +406,14 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
        for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
                if (boost::dynamic_pointer_cast<UserBundle> (*i) && (*i)->ports_are_inputs() == inputs) {
                        boost::shared_ptr<Bundle> b = bundle_for_type (*i, type);
-                       if (b->nchannels() != ChanCount::ZERO) {
-                               system->add_bundle (b, allow_dups);
-                       }
+                       system->add_bundle (b, allow_dups);
                }
        }
 
        for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
                if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0 && (*i)->ports_are_inputs() == inputs) {
                        boost::shared_ptr<Bundle> b = bundle_for_type (*i, type);
-                       if (b->nchannels() != ChanCount::ZERO) {
-                               system->add_bundle (b, allow_dups);
-                       }
+                       system->add_bundle (b, allow_dups);
                }
        }
 
@@ -427,14 +421,10 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 
        if (!inputs) {
                boost::shared_ptr<Bundle> b = bundle_for_type (session->the_auditioner()->output()->bundle(), type);
-               if (b->nchannels() != ChanCount::ZERO) {
-                       ardour->add_bundle (b);
-               }
+               ardour->add_bundle (b);
 
                b = bundle_for_type (session->click_io()->bundle(), type);
-               if (b->nchannels() != ChanCount::ZERO) {
-                       ardour->add_bundle (b);
-               }
+               ardour->add_bundle (b);
        }
 
        /* Ardour's surfaces */
@@ -570,9 +560,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
                if (!extra_system[*i].empty()) {
                        boost::shared_ptr<Bundle> b = make_bundle_from_ports (extra_system[*i], *i, inputs);
                        boost::shared_ptr<Bundle> bt = bundle_for_type (b, type);
-                       if (bt->nchannels() != ChanCount::ZERO) {
-                               system->add_bundle (bt);
-                       }
+                       system->add_bundle (bt);
                }
        }
 
@@ -580,9 +568,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
                if (!extra_other[*i].empty()) {
                        boost::shared_ptr<Bundle> b = make_bundle_from_ports (extra_other[*i], *i, inputs);
                        boost::shared_ptr<Bundle> bt = bundle_for_type (b, type);
-                       if (bt->nchannels() != ChanCount::ZERO) {
-                               other->add_bundle (bt);
-                       }
+                       other->add_bundle (bt);
                }
        }
 
@@ -789,12 +775,7 @@ PortGroupList::io_from_bundle (boost::shared_ptr<ARDOUR::Bundle> b) const
 bool
 PortGroupList::empty () const
 {
-       List::const_iterator i = _groups.begin ();
-       while (i != _groups.end() && (*i)->total_channels() == ChanCount::ZERO) {
-               ++i;
-       }
-
-       return (i == _groups.end());
+       return _groups.empty ();
 }
 
 /** Take a bundle, and either return it, if it contains only ports of type \a t,
index d537dd18a1589b93027e094a4edc2ef14f128b96..35cfea651f67623595ffc8e5d1ac982285caa895 100644 (file)
@@ -289,8 +289,8 @@ void
 PortMatrix::select_arrangement ()
 {
        uint32_t const N[2] = {
-               count_of_our_type (_ports[0].total_channels()),
-               count_of_our_type (_ports[1].total_channels())
+               count_of_our_type_min_1 (_ports[0].total_channels()),
+               count_of_our_type_min_1 (_ports[1].total_channels())
        };
 
        /* XXX: shirley there's an easier way than this */
@@ -407,14 +407,11 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
 
                        boost::weak_ptr<Bundle> w (bc[dim].bundle);
 
-                       bool can_add_or_rename = false;
-
                        /* Start off with options for the `natural' port type */
                        for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
                                if (should_show (*i)) {
                                        snprintf (buf, sizeof (buf), _("Add %s %s"), (*i).to_i18n_string(), channel_noun().c_str());
                                        sub.push_back (MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::add_channel_proxy), w, *i)));
-                                       can_add_or_rename = true;
                                }
                        }
 
@@ -423,7 +420,6 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
                                if (!should_show (*i)) {
                                        snprintf (buf, sizeof (buf), _("Add %s %s"), (*i).to_i18n_string(), channel_noun().c_str());
                                        sub.push_back (MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::add_channel_proxy), w, *i)));
-                                       can_add_or_rename = true;
                                }
                        }
 
@@ -438,17 +434,12 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
                                                sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc[dim].channel)
                                                )
                                        );
-                               can_add_or_rename = true;
-                       }
-
-                       if (can_add_or_rename) {
-                               sub.push_back (SeparatorElem ());
                        }
 
                        if (can_remove_channels (bc[dim].bundle)) {
                                if (bc[dim].channel != -1) {
                                        add_remove_option (sub, w, bc[dim].channel);
-                               } else {
+                               } else if (bc[dim].bundle->nchannels() != ARDOUR::ChanCount::ZERO) {
 
                                        snprintf (buf, sizeof (buf), _("Remove all"));
                                        sub.push_back (
@@ -465,7 +456,8 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
                                }
                        }
 
-                       if (_show_only_bundles || count_of_our_type (bc[dim].bundle->nchannels()) <= 1) {
+                       uint32_t c = count_of_our_type (bc[dim].bundle->nchannels ());
+                       if ((_show_only_bundles && c > 0) || c == 1) {
                                snprintf (buf, sizeof (buf), _("%s all"), disassociation_verb().c_str());
                                sub.push_back (
                                        MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_channel), w, bc[dim].channel, dim))
@@ -475,7 +467,7 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
 
                                if (bc[dim].channel != -1) {
                                        add_disassociate_option (sub, w, dim, bc[dim].channel);
-                               } else {
+                               } else if (count_of_our_type (bc[dim].bundle->nchannels()) != 0) {
                                        snprintf (buf, sizeof (buf), _("%s all"), disassociation_verb().c_str());
                                        sub.push_back (
                                                MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_bundle), w, dim))
@@ -722,7 +714,10 @@ PortMatrix::remove_all_channels (boost::weak_ptr<Bundle> w)
                return;
        }
 
-       for (uint32_t i = 0; i < b->nchannels().n_total(); ++i) {
+       /* Remove channels backwards so that we don't renumber channels
+          that we are about to remove.
+       */
+       for (int i = (b->nchannels().n_total() - 1); i >= 0; --i) {
                if (should_show (b->channel_type(i))) {
                        remove_channel (ARDOUR::BundleChannel (b, i));
                }
@@ -856,7 +851,9 @@ PortMatrix::body_dimensions_changed ()
        resize_window_to_proportion_of_monitor (_parent, m.first, m.second);
 }
 
-
+/** @return The PortGroup that is currently visible (ie selected by
+ *  the notebook) along a given axis.
+ */
 boost::shared_ptr<const PortGroup>
 PortMatrix::visible_ports (int d) const
 {
@@ -942,6 +939,20 @@ PortMatrix::count_of_our_type (ChanCount c) const
        return c.get (_type);
 }
 
+/** @return The number of ports of our type in the given channel count,
+ *  but returning 1 if there are no ports.
+ */
+uint32_t
+PortMatrix::count_of_our_type_min_1 (ChanCount c) const
+{
+       uint32_t n = count_of_our_type (c);
+       if (n == 0) {
+               n = 1;
+       }
+
+       return n;
+}
+
 PortMatrixNode::State
 PortMatrix::get_association (PortMatrixNode node) const
 {
@@ -1007,3 +1018,9 @@ PortMatrix::get_association (PortMatrixNode node) const
        return PortMatrixNode::NOT_ASSOCIATED;
 }
 
+/** @return true if b is a non-zero pointer and the bundle it points to has some channels */
+bool
+PortMatrix::bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle> b)
+{
+       return b && b->nchannels() != ARDOUR::ChanCount::ZERO;
+}
index 01fb67c0aef6abb1448ef381054be8792cf1ec05..75b2abf2797fbacbe31247a20b9cd373859ebcb3 100644 (file)
@@ -126,6 +126,7 @@ public:
 
        bool should_show (ARDOUR::DataType) const;
        uint32_t count_of_our_type (ARDOUR::ChanCount) const;
+       uint32_t count_of_our_type_min_1 (ARDOUR::ChanCount) const;
 
        PortMatrixNode::State get_association (PortMatrixNode) const;
 
@@ -159,6 +160,8 @@ public:
 
        sigc::signal<void, Result> Finished;
 
+       static bool bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle>);
+
 protected:
 
        /** We have two port group lists.  One will be presented on the rows of the matrix,
index 2b12ed092ac5d68ca8b96a3dbe34f4c76783bb9a..5d7bb0c4b6a32c59b9afdfc93a4a6d71d41f3e90 100644 (file)
@@ -458,7 +458,7 @@ PortMatrixBody::highlight_associated_channels (int dim, ARDOUR::BundleChannel h)
        ARDOUR::BundleChannel bc[2];
        bc[dim] = h;
 
-       if (!bc[dim].bundle) {
+       if (!PortMatrix::bundle_with_channels (bc[dim].bundle)) {
                return;
        }
 
index f9b5b6aef8101df16011a28e8497e62a749988f3..eba2fffddf632f10e0da4f4c2d5560021267518b 100644 (file)
@@ -149,7 +149,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
                if (_matrix->show_only_bundles()) {
                        x += grid_spacing();
                } else {
-                       x += _matrix->count_of_our_type ((*i)->bundle->nchannels()) * grid_spacing();
+                       x += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()) * grid_spacing();
                }
 
                ++N;
@@ -214,7 +214,7 @@ PortMatrixColumnLabels::mouseover_changed (list<PortMatrixNode> const &)
                ARDOUR::BundleChannel c = i->column;
                ARDOUR::BundleChannel r = i->row;
 
-               if (c.bundle && r.bundle) {
+               if (PortMatrix::bundle_with_channels (c.bundle) && PortMatrix::bundle_with_channels (r.bundle)) {
                        add_channel_highlight (c);
                } else if (c.bundle) {
                        _body->highlight_associated_channels (_matrix->column_index(), c);
@@ -273,7 +273,7 @@ PortMatrixColumnLabels::render_bundle_name (
        if (_matrix->show_only_bundles()) {
                w = grid_spacing ();
        } else {
-               w = _matrix->count_of_our_type (b->nchannels()) * grid_spacing();
+               w = _matrix->count_of_our_type_min_1 (b->nchannels()) * grid_spacing();
        }
 
        double x_ = xoff;
index 38a07479b0f04749958881e605f2ee65c65c2781..166488bef0bc256b632e2a50dfaa997e35c10941 100644 (file)
@@ -132,7 +132,7 @@ PortMatrixComponent::group_size (boost::shared_ptr<const PortGroup> g) const
                s = bundles.size();
        } else {
                for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
-                       s += _matrix->count_of_our_type ((*i)->bundle->nchannels());
+                       s += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels());
                }
        }
 
@@ -169,7 +169,7 @@ PortMatrixComponent::channel_to_position (ARDOUR::BundleChannel bc, boost::share
                if (_matrix->show_only_bundles()) {
                        p += 1;
                } else {
-                       p += _matrix->count_of_our_type ((*i)->bundle->nchannels());
+                       p += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels());
                }
        }
 
@@ -195,7 +195,7 @@ PortMatrixComponent::position_to_channel (double p, double, boost::shared_ptr<co
 
                } else {
 
-                       uint32_t const s = _matrix->count_of_our_type ((*j)->bundle->nchannels());
+                       uint32_t const s = _matrix->count_of_our_type_min_1 ((*j)->bundle->nchannels());
                        if (p < s) {
                                return ARDOUR::BundleChannel ((*j)->bundle, p);
                        } else {
index 3fdd26394a94fbf11657cdd7c33ba35b2cea5f0e..a574d20341a2456c045a32e920a4232041b7cb02 100644 (file)
@@ -31,6 +31,7 @@ class PortGroup;
 class PortGroupList;
 
 namespace ARDOUR {
+       class Bundle;
        class BundleChannel;
 }
 
index 4a2f569d5c35aac875139d311a1d5d58d587cf24..b87f560984539c0a5b560f2d0d0a82bd51e7ff21 100644 (file)
@@ -81,7 +81,7 @@ PortMatrixGrid::render (cairo_t* cr)
 
                if (!_matrix->show_only_bundles()) {
                        cairo_set_line_width (cr, thin_grid_line_width());
-                       for (uint32_t j = 0; j < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++j) {
+                       for (uint32_t j = 0; j < _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()); ++j) {
                                x += grid_spacing ();
                                cairo_move_to (cr, x, 0);
                                cairo_line_to (cr, x, _height);
@@ -97,6 +97,12 @@ PortMatrixGrid::render (cairo_t* cr)
                ++N;
        }
 
+       if (_matrix->show_only_bundles ()) {
+               cairo_move_to (cr, x, 0);
+               cairo_line_to (cr, x, _height);
+               cairo_stroke (cr);
+       }
+
        uint32_t y = 0;
 
        /* HORIZONTAL GRID LINES */
@@ -111,7 +117,7 @@ PortMatrixGrid::render (cairo_t* cr)
 
                if (!_matrix->show_only_bundles()) {
                        cairo_set_line_width (cr, thin_grid_line_width());
-                       for (uint32_t j = 0; j < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++j) {
+                       for (uint32_t j = 0; j < _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()); ++j) {
                                y += grid_spacing ();
                                cairo_move_to (cr, 0, y);
                                cairo_line_to (cr, _width, y);
@@ -127,6 +133,12 @@ PortMatrixGrid::render (cairo_t* cr)
                ++N;
        }
 
+       if (_matrix->show_only_bundles ()) {
+               cairo_move_to (cr, 0, y);
+               cairo_line_to (cr, _width, y);
+               cairo_stroke (cr);
+       }
+       
        /* ASSOCIATION INDICATORS and NON-CONNECTABLE INDICATORS */
 
        /* we draw a grey square in a matrix box if the two ports that intersect at that box
@@ -173,14 +185,10 @@ PortMatrixGrid::render (cairo_t* cr)
                        for (PortGroup::BundleList::const_iterator j = row_bundles.begin(); j != row_bundles.end(); ++j) {
 
                                x = bx;
-                               for (uint32_t k = 0; k < (*i)->bundle->nchannels().n_total(); ++k) {
+                               for (uint32_t k = 0; k < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++k) {
 
                                        y = by;
-                                       for (uint32_t l = 0; l < (*j)->bundle->nchannels().n_total(); ++l) {
-
-                                               if (!_matrix->should_show ((*i)->bundle->channel_type(k)) || !_matrix->should_show ((*j)->bundle->channel_type(l))) {
-                                                       continue;
-                                               }
+                                       for (uint32_t l = 0; l < _matrix->count_of_our_type ((*j)->bundle->nchannels()); ++l) {
 
                                                ARDOUR::BundleChannel c[2];
                                                c[_matrix->column_index()] = ARDOUR::BundleChannel ((*i)->bundle, k);
@@ -209,13 +217,21 @@ PortMatrixGrid::render (cairo_t* cr)
                                                y += grid_spacing();
                                        }
 
+                                       if ((*j)->bundle->nchannels() == ARDOUR::ChanCount::ZERO) {
+                                               draw_non_connectable_indicator (cr, x, y);
+                                       }
+                                       
                                        x += grid_spacing();
                                }
 
-                               by += _matrix->count_of_our_type ((*j)->bundle->nchannels()) * grid_spacing();
+                               if ((*i)->bundle->nchannels() == ARDOUR::ChanCount::ZERO) {
+                                       draw_non_connectable_indicator (cr, x, y);
+                               }
+
+                               by += _matrix->count_of_our_type_min_1 ((*j)->bundle->nchannels()) * grid_spacing();
                        }
 
-                       bx += _matrix->count_of_our_type ((*i)->bundle->nchannels()) * grid_spacing();
+                       bx += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()) * grid_spacing();
                }
        }
 }
@@ -402,7 +418,7 @@ PortMatrixGrid::draw_extra (cairo_t* cr)
                double const x = component_to_parent_x (channel_to_position (i->column, _matrix->visible_columns()) * grid_spacing()) + grid_spacing() / 2;
                double const y = component_to_parent_y (channel_to_position (i->row, _matrix->visible_rows()) * grid_spacing()) + grid_spacing() / 2;
 
-               if (i->row.bundle && i->column.bundle) {
+               if (PortMatrix::bundle_with_channels (i->row.bundle) && PortMatrix::bundle_with_channels (i->column.bundle)) {
 
                        cairo_move_to (cr, x, y);
                        if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
index bc6e2a2fa19005f50259b81b5c23270402dbb065..8c8dcd4dfff5ab09d6f4a0945f54e694168493de 100644 (file)
@@ -115,17 +115,18 @@ PortMatrixRowLabels::render (cairo_t* cr)
                render_bundle_name (cr, background_colour (), (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N), 0, y, (*i)->bundle);
 
                if (!_matrix->show_only_bundles()) {
-                       for (uint32_t j = 0; j < (*i)->bundle->nchannels().n_total(); ++j) {
-
-                               if (!_matrix->should_show ((*i)->bundle->channel_type(j))) {
-                                       continue;
-                               }
-
+                       uint32_t const N = _matrix->count_of_our_type ((*i)->bundle->nchannels());
+                       for (uint32_t j = 0; j < N; ++j) {
                                Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (M);
                                render_channel_name (cr, background_colour (), c, 0, y, ARDOUR::BundleChannel ((*i)->bundle, j));
                                y += grid_spacing();
                                ++M;
                        }
+
+                       if (N == 0) {
+                               y += grid_spacing ();
+                       }
+                       
                } else {
                        y += grid_spacing();
                }
@@ -215,7 +216,7 @@ PortMatrixRowLabels::render_bundle_name (
 {
        double const x = bundle_name_x ();
 
-       int const n = _matrix->show_only_bundles() ? 1 : _matrix->count_of_our_type (b->nchannels());
+       int const n = _matrix->show_only_bundles() ? 1 : _matrix->count_of_our_type_min_1 (b->nchannels());
        set_source_rgb (cr, bg_colour);
        cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
        cairo_fill_preserve (cr);
@@ -244,15 +245,15 @@ PortMatrixRowLabels::render_channel_name (
        cairo_set_line_width (cr, label_border_width ());
        cairo_stroke (cr);
 
-       cairo_text_extents_t ext;
-       cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
-       double const off = (grid_spacing() - ext.height) / 2;
-
        if (_matrix->count_of_our_type (bc.bundle->nchannels()) > 1) {
 
                /* only plot the name if the bundle has more than one channel;
                   the name of a single channel is assumed to be redundant */
 
+               cairo_text_extents_t ext;
+               cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
+               double const off = (grid_spacing() - ext.height) / 2;
+
                set_source_rgb (cr, text_colour());
                cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
                cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
@@ -304,7 +305,7 @@ PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
                ARDOUR::BundleChannel c = i->column;
                ARDOUR::BundleChannel r = i->row;
 
-               if (c.bundle && r.bundle) {
+               if (PortMatrix::bundle_with_channels (c.bundle) && PortMatrix::bundle_with_channels (r.bundle)) {
                        add_channel_highlight (r);
                } else if (r.bundle) {
                        _body->highlight_associated_channels (_matrix->row_index(), r);