Remove unnecessary/unused template parameter from canvas sysex flags.
[ardour.git] / gtk2_ardour / port_matrix_grid.cc
index 13e1dcf4c200fac8980fa6cfac5c1a8dc8c77c11..6e7fad70915a66ddedef23dd8d59100176154aff 100644 (file)
 #include <iostream>
 #include <cairo/cairo.h>
 #include "ardour/bundle.h"
+#include "ardour/types.h"
 #include "port_matrix_grid.h"
 #include "port_matrix.h"
+#include "port_matrix_body.h"
 
-PortMatrixGrid::PortMatrixGrid (PortMatrix* p, PortMatrixBody* b)
-       : PortMatrixComponent (b),
-         _port_matrix (p)
+PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b)
+       : PortMatrixComponent (m, b)
 {
        
 }
@@ -34,13 +35,15 @@ void
 PortMatrixGrid::compute_dimensions ()
 {
        _width = 0;
-       for (uint32_t i = 0; i < _body->column_bundles().size(); ++i) {
-               _width += _body->column_bundles()[i]->nchannels() * column_width();
+       ARDOUR::BundleList const c = _matrix->columns()->bundles();
+       for (ARDOUR::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
+               _width += (*i)->nchannels() * column_width();
        }
 
        _height = 0;
-       for (uint32_t i = 0; i < _body->row_bundles().size(); ++i) {
-               _height += _body->row_bundles()[i]->nchannels() * row_height();
+       ARDOUR::BundleList const r = _matrix->rows()->bundles();
+       for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
+               _height += (*i)->nchannels() * row_height();
        }
 }
 
@@ -58,17 +61,18 @@ PortMatrixGrid::render (cairo_t* cr)
        
        set_source_rgb (cr, grid_colour());
        uint32_t x = 0;
-       for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::size_type i = 0; i < _body->column_bundles().size(); ++i) {
+       ARDOUR::BundleList const c = _matrix->columns()->bundles();
+       for (ARDOUR::BundleList::size_type i = 0; i < c.size(); ++i) {
 
                cairo_set_line_width (cr, thin_grid_line_width());
-               for (uint32_t j = 1; j < _body->column_bundles()[i]->nchannels(); ++j) {
+               for (uint32_t j = 1; j < c[i]->nchannels(); ++j) {
                        x += column_width();
                        cairo_move_to (cr, x, 0);
                        cairo_line_to (cr, x, _height);
                        cairo_stroke (cr);
                }
 
-               if (i < (_body->column_bundles().size() - 1)) {
+               if (i < (c.size() - 1)) {
                        x += column_width();
                        cairo_set_line_width (cr, thick_grid_line_width());
                        cairo_move_to (cr, x, 0);
@@ -82,17 +86,18 @@ PortMatrixGrid::render (cairo_t* cr)
        /* HORIZONTAL GRID LINES */
        
        uint32_t y = 0;
-       for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::size_type i = 0; i < _body->row_bundles().size(); ++i) {
+       ARDOUR::BundleList const r = _matrix->rows()->bundles();
+       for (ARDOUR::BundleList::size_type i = 0; i < r.size(); ++i) {
 
                cairo_set_line_width (cr, thin_grid_line_width());
-               for (uint32_t j = 1; j < _body->row_bundles()[i]->nchannels(); ++j) {
+               for (uint32_t j = 1; j < r[i]->nchannels(); ++j) {
                        y += row_height();
                        cairo_move_to (cr, 0, y);
                        cairo_line_to (cr, grid_width, y);
                        cairo_stroke (cr);
                }
 
-               if (i < (_body->row_bundles().size() - 1)) {
+               if (i < (r.size() - 1)) {
                        y += row_height();
                        cairo_set_line_width (cr, thick_grid_line_width());
                        cairo_move_to (cr, 0, y);
@@ -106,18 +111,22 @@ PortMatrixGrid::render (cairo_t* cr)
        uint32_t bx = 0;
        uint32_t by = 0;
        
-       for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->column_bundles().begin(); i < _body->column_bundles().end(); ++i) {
+       for (ARDOUR::BundleList::const_iterator i = c.begin(); i < c.end(); ++i) {
                by = 0;
                
-               for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator j = _body->row_bundles().begin(); j < _body->row_bundles().end(); ++j) {
+               for (ARDOUR::BundleList::const_iterator j = r.begin(); j < r.end(); ++j) {
 
                        x = bx;
                        for (uint32_t k = 0; k < (*i)->nchannels (); k++) {
 
                                y = by;
                                for (uint32_t l = 0; l < (*j)->nchannels (); ++l) {
+
+                                       ARDOUR::BundleChannel c[2];
+                                       c[_matrix->column_index()] = ARDOUR::BundleChannel (*i, k);
+                                       c[_matrix->row_index()] = ARDOUR::BundleChannel (*j, l);
                                        
-                                       PortMatrix::State const s = _port_matrix->get_state (*j, l, *i, k);
+                                       PortMatrix::State const s = _matrix->get_state (c);
                                                
                                        switch (s) {
                                        case PortMatrix::ASSOCIATED:
@@ -163,52 +172,78 @@ PortMatrixGrid::render (cairo_t* cr)
 }
 
 
-void
-PortMatrixGrid::button_press (double x, double y, int b)
+PortMatrixNode
+PortMatrixGrid::position_to_node (double x, double y) const
 {
-       uint32_t grid_column = x / column_width ();
-       uint32_t grid_row = y / row_height ();
-
-       boost::shared_ptr<ARDOUR::Bundle> our_bundle;
-       uint32_t our_channel = 0;
-       boost::shared_ptr<ARDOUR::Bundle> other_bundle;
-       uint32_t other_channel = 0;
-
-       for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
-               if (grid_row < (*i)->nchannels ()) {
-                       our_bundle = *i;
-                       our_channel = grid_row;
-                       break;
+       return PortMatrixNode (
+               position_to_channel (y, _matrix->rows()->bundles(), row_height()),
+               position_to_channel (x, _matrix->columns()->bundles(), column_width())
+               );
+}
+
+
+ARDOUR::BundleChannel
+PortMatrixGrid::position_to_channel (double p, ARDOUR::BundleList const& bundles, double inc) const
+{
+       uint32_t pos = p / inc;
+
+       for (ARDOUR::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
+               if (pos < (*i)->nchannels()) {
+                       return ARDOUR::BundleChannel (*i, pos);
                } else {
-                       grid_row -= (*i)->nchannels ();
+                       pos -= (*i)->nchannels();
                }
        }
+                       
+       return ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0);
+}
+
+
+double
+PortMatrixGrid::channel_position (
+       ARDOUR::BundleChannel bc,
+       ARDOUR::BundleList const& bundles,
+       double inc) const
+{
+       double p = 0;
+       
+       ARDOUR::BundleList::const_iterator i = bundles.begin ();
+       while (i != bundles.end() && *i != bc.bundle) {
+               p += inc * (*i)->nchannels();
+               ++i;
+       }
 
-       for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->column_bundles().begin(); i != _body->column_bundles().end(); ++i) {
-               if (grid_column < (*i)->nchannels ()) {
-                       other_bundle = *i;
-                       other_channel = grid_column;
-                       break;
-               } else {
-                       grid_column -= (*i)->nchannels ();
-               }
+       if (i == bundles.end()) {
+               return 0;
        }
 
+       p += inc * bc.channel;
+
+       return p;
+}
+
+void
+PortMatrixGrid::button_press (double x, double y, int b)
+{
+       PortMatrixNode const node = position_to_node (x, y);
        
-       if (our_bundle && other_bundle) {
+       if (node.row.bundle && node.column.bundle) {
+
+               ARDOUR::BundleChannel c[2];
+               c[_matrix->row_index()] = node.row;
+               c[_matrix->column_index()] = node.column;
+               
+               PortMatrix::State const s = _matrix->get_state (c);
                
-               PortMatrix::State const s = _port_matrix->get_state (
-                       our_bundle, our_channel, other_bundle, other_channel
-                       );
-                               
                if (s == PortMatrix::ASSOCIATED || s == PortMatrix::NOT_ASSOCIATED) {
 
                        bool const n = !(s == PortMatrix::ASSOCIATED);
+
+                       ARDOUR::BundleChannel c[2];
+                       c[_matrix->row_index()] = node.row;
+                       c[_matrix->column_index()] = node.column;
                        
-               _port_matrix->set_state (
-                       our_bundle, our_channel, other_bundle, other_channel,
-                               n, 0
-                       );
+                       _matrix->set_state (c, n);
                }
 
                require_render ();
@@ -216,4 +251,104 @@ PortMatrixGrid::button_press (double x, double y, int b)
        }
 }
 
+void
+PortMatrixGrid::draw_extra (cairo_t* cr)
+{
+       set_source_rgba (cr, mouseover_line_colour(), 0.3);
+       cairo_set_line_width (cr, mouseover_line_width());
+
+       double const x = component_to_parent_x (
+               channel_position (_body->mouseover().column, _matrix->columns()->bundles(), column_width()) + column_width() / 2
+               );
+       
+       double const y = component_to_parent_y (
+               channel_position (_body->mouseover().row, _matrix->rows()->bundles(), row_height()) + row_height() / 2
+               );
+       
+       if (_body->mouseover().row.bundle) {
+
+               cairo_move_to (cr, x, y);
+               if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
+                       cairo_line_to (cr, component_to_parent_x (0), y);
+               } else if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
+                       cairo_line_to (cr, _parent_rectangle.get_x() + _parent_rectangle.get_width(), y);
+               }
+               cairo_stroke (cr);
+       }
+
+       if (_body->mouseover().column.bundle) {
+
+               cairo_move_to (cr, x, y);
+               if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
+                       cairo_line_to (cr, x, _parent_rectangle.get_y() + _parent_rectangle.get_height());
+               } else if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
+                       cairo_line_to (cr, x, component_to_parent_y (0));
+               }
+               cairo_stroke (cr);
+       }
+}
+
+void
+PortMatrixGrid::mouseover_changed (PortMatrixNode const& old)
+{
+       queue_draw_for (old);
+       queue_draw_for (_body->mouseover());
+}
+
+void
+PortMatrixGrid::mouseover_event (double x, double y)
+{
+       _body->set_mouseover (position_to_node (x, y));
+}
+
+void
+PortMatrixGrid::queue_draw_for (PortMatrixNode const &n)
+{
+       if (n.row.bundle) {
+
+               double const y = channel_position (n.row, _matrix->rows()->bundles(), row_height());
+               _body->queue_draw_area (
+                       _parent_rectangle.get_x(),
+                       component_to_parent_y (y),
+                       _parent_rectangle.get_width(),
+                       row_height()
+                       );
+       }
+
+       if (n.column.bundle) {
+
+               double const x = channel_position (n.column, _matrix->columns()->bundles(), column_width());
+               
+               _body->queue_draw_area (
+                       component_to_parent_x (x),
+                       _parent_rectangle.get_y(),
+                       column_width(),
+                       _parent_rectangle.get_height()
+                       );
+       }
+}
+
+double
+PortMatrixGrid::component_to_parent_x (double x) const
+{
+       return x - _body->xoffset() + _parent_rectangle.get_x();
+}
+
+double
+PortMatrixGrid::parent_to_component_x (double x) const
+{
+       return x + _body->xoffset() - _parent_rectangle.get_x();
+}
+
+double
+PortMatrixGrid::component_to_parent_y (double y) const
+{
+       return y - _body->yoffset() + _parent_rectangle.get_y();
+}
+
+double
+PortMatrixGrid::parent_to_component_y (double y) const
+{
+       return y + _body->yoffset() - _parent_rectangle.get_y();
+}