Allow region-based automation axes to report whether they
[ardour.git] / gtk2_ardour / port_matrix_grid.cc
index 53b4b50b50e0176b55f2650bedb15f3ec7ab38ad..fdfe45b2248066a90ce0eba2e496c4f6bb9f2042 100644 (file)
 #include "port_matrix_grid.h"
 #include "port_matrix.h"
 #include "port_matrix_body.h"
+#include "keyboard.h"
 
 using namespace std;
+using Gtkmm2ext::Keyboard;
 
 PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b)
        : PortMatrixComponent (m, b),
@@ -39,16 +41,16 @@ PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b)
 void
 PortMatrixGrid::compute_dimensions ()
 {
-       if (_matrix->visible_columns() == 0) {
-               _width = 0;
-       } else {
+       if (_matrix->visible_columns()) {
                _width = group_size (_matrix->visible_columns()) * grid_spacing ();
+       } else {
+               _width = 0;
        }
 
-       if (_matrix->visible_rows() == 0) {
-               _height = 0;
-       } else {
+       if (_matrix->visible_rows()) {
                _height = group_size (_matrix->visible_rows()) * grid_spacing ();
+       } else {
+               _height = 0;
        }
 }
 
@@ -79,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 < i->bundle->nchannels(); ++j) {
+                       for (uint32_t j = 0; j < (*i)->bundle->nchannels(); ++j) {
                                x += grid_spacing ();
                                cairo_move_to (cr, x, 0);
                                cairo_line_to (cr, x, _height);
@@ -109,7 +111,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 < i->bundle->nchannels(); ++j) {
+                       for (uint32_t j = 0; j < (*i)->bundle->nchannels(); ++j) {
                                y += grid_spacing ();
                                cairo_move_to (cr, 0, y);
                                cairo_line_to (cr, _width, y);
@@ -138,8 +140,8 @@ PortMatrixGrid::render (cairo_t* cr)
                        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)
+                                                                                  ARDOUR::BundleChannel ((*i)->bundle, 0),
+                                                                                  ARDOUR::BundleChannel ((*j)->bundle, 0)
                                                                                   ));
                                switch (s) {
                                case PortMatrixNode::ASSOCIATED:
@@ -167,14 +169,14 @@ 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 (); ++k) {
+                               for (uint32_t k = 0; k < (*i)->bundle->nchannels (); ++k) {
 
                                        y = by;
-                                       for (uint32_t l = 0; l < j->bundle->nchannels (); ++l) {
+                                       for (uint32_t l = 0; l < (*j)->bundle->nchannels (); ++l) {
 
                                                ARDOUR::BundleChannel c[2];
-                                               c[_matrix->column_index()] = ARDOUR::BundleChannel (i->bundle, k);
-                                               c[_matrix->row_index()] = ARDOUR::BundleChannel (j->bundle, l);
+                                               c[_matrix->column_index()] = ARDOUR::BundleChannel ((*i)->bundle, k);
+                                               c[_matrix->row_index()] = ARDOUR::BundleChannel ((*j)->bundle, l);
 
                                                PortMatrixNode::State const s = _matrix->get_state (c);
 
@@ -196,10 +198,10 @@ PortMatrixGrid::render (cairo_t* cr)
                                        x += grid_spacing();
                                }
 
-                               by += j->bundle->nchannels () * grid_spacing();
+                               by += (*j)->bundle->nchannels () * grid_spacing();
                        }
 
-                       bx += i->bundle->nchannels () * grid_spacing();
+                       bx += (*i)->bundle->nchannels () * grid_spacing();
                }
        }
 }
@@ -245,16 +247,16 @@ PortMatrixGrid::position_to_node (double x, double y) const
 }
 
 void
-PortMatrixGrid::button_press (double x, double y, int b, uint32_t t)
+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) {
-
+               
                _dragging = true;
                _drag_valid = (px.bundle && py.bundle);
-
+               
                _moved = false;
                _drag_start_x = x / grid_spacing ();
                _drag_start_y = y / grid_spacing ();
@@ -355,33 +357,57 @@ PortMatrixGrid::set_association (PortMatrixNode node, bool s)
 }
 
 void
-PortMatrixGrid::button_release (double x, double y, int b, uint32_t /*t*/)
+PortMatrixGrid::button_release (double x, double y, int b, uint32_t /*t*/, guint s)
 {
        if (b == 1) {
 
-               if (_dragging && _moved) {
-
-                       if (_drag_valid) {
-                               list<PortMatrixNode> const p = nodes_on_line (_drag_start_x, _drag_start_y, _drag_x, _drag_y);
-
-                               if (!p.empty()) {
-                                       PortMatrixNode::State const s = get_association (p.front());
-                                       for (list<PortMatrixNode>::const_iterator i = p.begin(); i != p.end(); ++i) {
-                                               set_association (*i, toggle_state (s));
+               if (x != -1) {
+                       
+                       if (_dragging && _moved) {
+                               
+                               if (_drag_valid) {
+                                       list<PortMatrixNode> const p = nodes_on_line (_drag_start_x, _drag_start_y, _drag_x, _drag_y);
+                                       
+                                       if (!p.empty()) {
+                                               PortMatrixNode::State const s = get_association (p.front());
+                                               for (list<PortMatrixNode>::const_iterator i = p.begin(); i != p.end(); ++i) {
+                                                       set_association (*i, toggle_state (s));
+                                               }
+                                       }
+                               }
+                               
+                       } else {
+                               
+                               if (Keyboard::modifier_state_equals (s, Keyboard::PrimaryModifier)) {
+                                       /* associate/disassociate things diagonally down and right until we run out */
+                                       PortMatrixNode::State s = (PortMatrixNode::State) 0;
+                                       while (1) {
+                                               PortMatrixNode const n = position_to_node (x, y);
+                                               if (n.row.bundle && n.column.bundle) {
+                                                       if (s == (PortMatrixNode::State) 0) {
+                                                               s = get_association (n);
+                                                       }
+                                                       set_association (n, toggle_state (s));
+                                               } else {
+                                                       break;
+                                               }
+                                               x += grid_spacing ();
+                                               y += grid_spacing ();
+                                       }
+                                       
+                               } else {
+                                       
+                                       PortMatrixNode const n = position_to_node (x, y);
+                                       if (n.row.bundle && n.column.bundle) {
+                                               PortMatrixNode::State const s = get_association (n);
+                                               set_association (n, toggle_state (s));
                                        }
                                }
                        }
 
-               } else {
-
-                       PortMatrixNode const n = position_to_node (x, y);
-                       if (n.row.bundle && n.column.bundle) {
-                               PortMatrixNode::State const s = get_association (n);
-                               set_association (n, toggle_state (s));
-                       }
+                       require_render ();
                }
-
-               require_render ();
+               
                _body->queue_draw ();
        }