More logical arrangement of port matrix inputs and outputs, hopefully;
[ardour.git] / gtk2_ardour / port_matrix_grid.cc
1 /*
2     Copyright (C) 2002-2009 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <iostream>
21 #include <cairo/cairo.h>
22 #include "ardour/bundle.h"
23 #include "port_matrix_grid.h"
24 #include "port_matrix.h"
25
26 PortMatrixGrid::PortMatrixGrid (PortMatrix* p, PortMatrixBody* b)
27         : PortMatrixComponent (b),
28           _port_matrix (p)
29 {
30         
31 }
32
33 void
34 PortMatrixGrid::compute_dimensions ()
35 {
36         _width = 0;
37         for (uint32_t i = 0; i < _body->column_bundles().size(); ++i) {
38                 _width += _body->column_bundles()[i]->nchannels() * column_width();
39         }
40
41         _height = 0;
42         for (uint32_t i = 0; i < _body->row_bundles().size(); ++i) {
43                 _height += _body->row_bundles()[i]->nchannels() * row_height();
44         }
45 }
46
47
48 void
49 PortMatrixGrid::render (cairo_t* cr)
50 {
51         /* BACKGROUND */
52         
53         set_source_rgb (cr, background_colour());
54         cairo_rectangle (cr, 0, 0, _width, _height);
55         cairo_fill (cr);
56
57         /* VERTICAL GRID LINES */
58         
59         set_source_rgb (cr, grid_colour());
60         uint32_t x = 0;
61         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::size_type i = 0; i < _body->column_bundles().size(); ++i) {
62
63                 cairo_set_line_width (cr, thin_grid_line_width());
64                 for (uint32_t j = 1; j < _body->column_bundles()[i]->nchannels(); ++j) {
65                         x += column_width();
66                         cairo_move_to (cr, x, 0);
67                         cairo_line_to (cr, x, _height);
68                         cairo_stroke (cr);
69                 }
70
71                 if (i < (_body->column_bundles().size() - 1)) {
72                         x += column_width();
73                         cairo_set_line_width (cr, thick_grid_line_width());
74                         cairo_move_to (cr, x, 0);
75                         cairo_line_to (cr, x, _height);
76                         cairo_stroke (cr);
77                 }
78         }
79                 
80         uint32_t grid_width = x + column_width();
81
82         /* HORIZONTAL GRID LINES */
83         
84         uint32_t y = 0;
85         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::size_type i = 0; i < _body->row_bundles().size(); ++i) {
86
87                 cairo_set_line_width (cr, thin_grid_line_width());
88                 for (uint32_t j = 1; j < _body->row_bundles()[i]->nchannels(); ++j) {
89                         y += row_height();
90                         cairo_move_to (cr, 0, y);
91                         cairo_line_to (cr, grid_width, y);
92                         cairo_stroke (cr);
93                 }
94
95                 if (i < (_body->row_bundles().size() - 1)) {
96                         y += row_height();
97                         cairo_set_line_width (cr, thick_grid_line_width());
98                         cairo_move_to (cr, 0, y);
99                         cairo_line_to (cr, grid_width, y);
100                         cairo_stroke (cr);
101                 }
102         }
103
104         /* ASSOCIATION INDICATORS */
105         
106         uint32_t bx = 0;
107         uint32_t by = 0;
108         
109         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->column_bundles().begin(); i < _body->column_bundles().end(); ++i) {
110                 by = 0;
111                 
112                 for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator j = _body->row_bundles().begin(); j < _body->row_bundles().end(); ++j) {
113
114                         x = bx;
115                         for (uint32_t k = 0; k < (*i)->nchannels (); k++) {
116
117                                 y = by;
118                                 for (uint32_t l = 0; l < (*j)->nchannels (); ++l) {
119                                         
120                                         if (_port_matrix->get_state (*j, l, *i, k)) {
121                                                 
122                                                 set_source_rgba (cr, association_colour(), 0.5);
123                                                 cairo_arc (
124                                                         cr,
125                                                         x + column_width() / 2,
126                                                         y + column_width() / 2,
127                                                         (column_width() - (2 * connection_indicator_pad())) / 2,
128                                                         0,
129                                                         2 * M_PI
130                                                         );
131
132                                                 cairo_fill (cr);
133                                         
134                                         }
135                                         y += row_height();
136                                 }
137                                 x += column_width();
138                         }
139                         
140                         by += (*j)->nchannels () * row_height();
141                 }
142                 
143                 bx += (*i)->nchannels () * column_width();
144         }
145 }
146
147
148 void
149 PortMatrixGrid::button_press (double x, double y, int b)
150 {
151         uint32_t grid_column = x / column_width ();
152         uint32_t grid_row = y / row_height ();
153
154         boost::shared_ptr<ARDOUR::Bundle> our_bundle;
155         uint32_t our_channel = 0;
156         boost::shared_ptr<ARDOUR::Bundle> other_bundle;
157         uint32_t other_channel = 0;
158
159         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
160                 if (grid_row < (*i)->nchannels ()) {
161                         our_bundle = *i;
162                         our_channel = grid_row;
163                         break;
164                 } else {
165                         grid_row -= (*i)->nchannels ();
166                 }
167         }
168
169         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->column_bundles().begin(); i != _body->column_bundles().end(); ++i) {
170                 if (grid_column < (*i)->nchannels ()) {
171                         other_bundle = *i;
172                         other_channel = grid_column;
173                         break;
174                 } else {
175                         grid_column -= (*i)->nchannels ();
176                 }
177         }
178
179         if (our_bundle && other_bundle) {
180                 
181                 bool const s = _port_matrix->get_state (
182                         our_bundle, our_channel, other_bundle, other_channel
183                         );
184                                 
185                 _port_matrix->set_state (
186                         our_bundle, our_channel, other_bundle, other_channel,
187                         !s, 0
188                         );
189
190                 require_render ();
191                 _body->queue_draw ();
192         }
193 }
194
195