+
+ if (_matrix->show_only_bundles()) {
+
+ for (PortGroup::BundleList::const_iterator i = column_bundles.begin(); i != column_bundles.end(); ++i) {
+ by = 0;
+
+ for (PortGroup::BundleList::const_iterator j = row_bundles.begin(); j != row_bundles.end(); ++j) {
+
+ PortMatrixNode::State s = get_association (PortMatrixNode (
+ ARDOUR::BundleChannel ((*i)->bundle, 0),
+ ARDOUR::BundleChannel ((*j)->bundle, 0)
+ ));
+ switch (s) {
+ case PortMatrixNode::ASSOCIATED:
+ draw_association_indicator (cr, bx, by);
+ break;
+ case PortMatrixNode::PARTIAL:
+ draw_association_indicator (cr, bx, by, 0.5);
+ break;
+ default:
+ break;
+ }
+
+ by += grid_spacing();
+ }
+
+ bx += grid_spacing();
+
+ }
+
+ } else {
+
+ for (PortGroup::BundleList::const_iterator i = column_bundles.begin(); i != column_bundles.end(); ++i) {
+ by = 0;
+
+ 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) {
+
+ 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;
+ }
+
+ ARDOUR::BundleChannel c[2];
+ c[_matrix->column_index()] = ARDOUR::BundleChannel ((*i)->bundle, k);
+ c[_matrix->row_index()] = ARDOUR::BundleChannel ((*j)->bundle, l);
+
+ if (c[0].bundle->channel_type (c[0].channel) != c[1].bundle->channel_type (c[1].channel)) {
+ /* these two channels are of different types */
+ draw_non_connectable_indicator (cr, x, y);
+ } else {
+ /* these two channels might be associated */
+ PortMatrixNode::State const s = _matrix->get_state (c);
+
+ switch (s) {
+ case PortMatrixNode::ASSOCIATED:
+ draw_association_indicator (cr, x, y);
+ break;
+
+ case PortMatrixNode::NOT_ASSOCIATED:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ y += grid_spacing();
+ }
+
+ x += grid_spacing();
+ }
+
+ by += _matrix->count_of_our_type ((*j)->bundle->nchannels()) * grid_spacing();
+ }
+
+ bx += _matrix->count_of_our_type ((*i)->bundle->nchannels()) * grid_spacing();
+ }
+ }
+}
+
+void
+PortMatrixGrid::draw_association_indicator (cairo_t* cr, uint32_t x, uint32_t y, double p)
+{
+ set_source_rgba (cr, association_colour(), 0.5);
+
+ cairo_arc (
+ cr,
+ x + grid_spacing() / 2,
+ y + grid_spacing() / 2,
+ (grid_spacing() - (2 * connection_indicator_pad())) / 2,
+ 0,
+ p * 2 * M_PI
+ );
+
+ cairo_fill (cr);
+}
+
+void
+PortMatrixGrid::draw_empty_square (cairo_t* cr, uint32_t x, uint32_t y)
+{
+ set_source_rgb (cr, background_colour());
+ cairo_rectangle (
+ cr,
+ x + thick_grid_line_width(),
+ y + thick_grid_line_width(),
+ grid_spacing() - 2 * thick_grid_line_width(),
+ grid_spacing() - 2 * thick_grid_line_width()
+ );
+ cairo_fill (cr);
+}
+
+/** Draw a square to indicate that two channels in a matrix cannot be associated
+ * with each other.
+ */
+void
+PortMatrixGrid::draw_non_connectable_indicator (cairo_t* cr, uint32_t x, uint32_t y)
+{
+ set_source_rgb (cr, non_connectable_colour ());
+ cairo_rectangle (
+ cr,
+ x + thick_grid_line_width(),
+ y + thick_grid_line_width(),
+ grid_spacing() - 2 * thick_grid_line_width(),
+ grid_spacing() - 2 * thick_grid_line_width()
+ );
+ cairo_fill (cr);
+}
+
+PortMatrixNode
+PortMatrixGrid::position_to_node (double x, double y) const
+{
+ return PortMatrixNode (
+ position_to_channel (y, x, _matrix->visible_rows()),
+ position_to_channel (x, y, _matrix->visible_columns())
+ );
+}
+
+void
+PortMatrixGrid::button_press (double x, double y, int b, uint32_t t, guint)
+{
+ ARDOUR::BundleChannel const px = position_to_channel (x, y, _matrix->visible_columns());
+ ARDOUR::BundleChannel const py = position_to_channel (y, x, _matrix->visible_rows());
+
+ if (b == 1) {