Try to avoid adding system ports to the port matrix twice. Fix some whitespace problems.
[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                                         PortMatrix::State const s = _port_matrix->get_state (*j, l, *i, k);
121                                                 
122                                         switch (s) {
123                                         case PortMatrix::ASSOCIATED:
124                                                 set_source_rgba (cr, association_colour(), 0.5);
125                                                 cairo_arc (
126                                                         cr,
127                                                         x + column_width() / 2,
128                                                         y + column_width() / 2,
129                                                         (column_width() - (2 * connection_indicator_pad())) / 2,
130                                                         0,
131                                                         2 * M_PI
132                                                         );
133
134                                                 cairo_fill (cr);
135                                                 break;
136
137                                         case PortMatrix::UNKNOWN:
138                                                 set_source_rgba (cr, unknown_colour(), 0.5);
139                                                 cairo_rectangle (
140                                                         cr,
141                                                         x + thick_grid_line_width(),
142                                                         y + thick_grid_line_width(),
143                                                         column_width() - 2 * thick_grid_line_width(),
144                                                         row_height() - 2 * thick_grid_line_width()
145                                                         );
146                                                 cairo_fill (cr);
147                                                 break;
148                                         
149                                         case PortMatrix::NOT_ASSOCIATED:
150                                                 break;
151                                         }
152
153                                         y += row_height();
154                                 }
155                                 x += column_width();
156                         }
157                         
158                         by += (*j)->nchannels () * row_height();
159                 }
160                 
161                 bx += (*i)->nchannels () * column_width();
162         }
163 }
164
165
166 void
167 PortMatrixGrid::button_press (double x, double y, int b)
168 {
169         uint32_t grid_column = x / column_width ();
170         uint32_t grid_row = y / row_height ();
171
172         boost::shared_ptr<ARDOUR::Bundle> our_bundle;
173         uint32_t our_channel = 0;
174         boost::shared_ptr<ARDOUR::Bundle> other_bundle;
175         uint32_t other_channel = 0;
176
177         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
178                 if (grid_row < (*i)->nchannels ()) {
179                         our_bundle = *i;
180                         our_channel = grid_row;
181                         break;
182                 } else {
183                         grid_row -= (*i)->nchannels ();
184                 }
185         }
186
187         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->column_bundles().begin(); i != _body->column_bundles().end(); ++i) {
188                 if (grid_column < (*i)->nchannels ()) {
189                         other_bundle = *i;
190                         other_channel = grid_column;
191                         break;
192                 } else {
193                         grid_column -= (*i)->nchannels ();
194                 }
195         }
196
197         
198         if (our_bundle && other_bundle) {
199                 
200                 PortMatrix::State const s = _port_matrix->get_state (
201                         our_bundle, our_channel, other_bundle, other_channel
202                         );
203
204                 if (s == PortMatrix::ASSOCIATED || s == PortMatrix::NOT_ASSOCIATED) {
205
206                         bool const n = !(s == PortMatrix::ASSOCIATED);
207                         
208                         _port_matrix->set_state (
209                                 our_bundle, our_channel, other_bundle, other_channel,
210                                 n, 0
211                                 );
212                 }
213
214                 require_render ();
215                 _body->queue_draw ();
216         }
217 }
218
219