fix math bug with numthreads computation
[ardour2.git] / gtk2_ardour / port_matrix_row_labels.cc
blob57e972acd478a8c869025b2b0dcce8e6c35f2f5e
1 /*
2 Copyright (C) 2002-2009 Paul Davis
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.
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.
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.
20 #include <iostream>
21 #include <boost/weak_ptr.hpp>
22 #include <cairo/cairo.h>
23 #include "ardour/bundle.h"
24 #include "port_matrix_row_labels.h"
25 #include "port_matrix.h"
26 #include "port_matrix_body.h"
27 #include "i18n.h"
28 #include "utils.h"
30 using namespace std;
32 PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* m, PortMatrixBody* b)
33 : PortMatrixLabels (m, b)
38 void
39 PortMatrixRowLabels::compute_dimensions ()
41 GdkPixmap* pm = gdk_pixmap_new (NULL, 1, 1, 24);
42 gdk_drawable_set_colormap (pm, gdk_colormap_get_system());
43 cairo_t* cr = gdk_cairo_create (pm);
45 _longest_port_name = 0;
46 _longest_bundle_name = 0;
48 /* Compute maximum dimensions using all port groups, so that we allow for the largest and hence
49 we can change between visible groups without the size of the labels jumping around.
52 for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
54 PortGroup::BundleList const r = (*i)->bundles ();
55 for (PortGroup::BundleList::const_iterator j = r.begin(); j != r.end(); ++j) {
57 for (uint32_t k = 0; k < (*j)->bundle->nchannels(); ++k) {
58 cairo_text_extents_t ext;
59 cairo_text_extents (cr, (*j)->bundle->channel_name(k).c_str(), &ext);
60 if (ext.width > _longest_port_name) {
61 _longest_port_name = ext.width;
65 cairo_text_extents_t ext;
66 cairo_text_extents (cr, (*j)->bundle->name().c_str(), &ext);
67 if (ext.width > _longest_bundle_name) {
68 _longest_bundle_name = ext.width;
74 if (_matrix->visible_rows()) {
75 _height = group_size (_matrix->visible_rows()) * grid_spacing ();
76 } else {
77 _height = 0;
80 cairo_destroy (cr);
81 g_object_unref (pm);
83 _width = _longest_bundle_name +
84 name_pad() * 2;
86 if (!_matrix->show_only_bundles()) {
87 _width += _longest_port_name;
88 _width += name_pad() * 2;
93 void
94 PortMatrixRowLabels::render (cairo_t* cr)
96 /* BACKGROUND */
98 set_source_rgb (cr, background_colour());
99 cairo_rectangle (cr, 0, 0, _width, _height);
100 cairo_fill (cr);
102 /* BUNDLE AND PORT NAMES */
104 double y = 0;
105 int N = 0;
106 int M = 0;
108 PortGroup::BundleList const & bundles = _matrix->visible_rows()->bundles ();
109 for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
110 render_bundle_name (cr, background_colour (), (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N), 0, y, (*i)->bundle);
112 if (!_matrix->show_only_bundles()) {
113 for (uint32_t j = 0; j < (*i)->bundle->nchannels(); ++j) {
114 Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (M);
115 render_channel_name (cr, background_colour (), c, 0, y, ARDOUR::BundleChannel ((*i)->bundle, j));
116 y += grid_spacing();
117 ++M;
119 } else {
120 y += grid_spacing();
123 ++N;
127 void
128 PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t, guint)
130 ARDOUR::BundleChannel w = position_to_channel (y, x, _matrix->visible_rows());
132 if (
133 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_longest_port_name + name_pad() * 2)) ||
134 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < (_longest_bundle_name + name_pad() * 2))
137 w.channel = -1;
140 if (b == 3) {
142 _matrix->popup_menu (
143 ARDOUR::BundleChannel (),
150 double
151 PortMatrixRowLabels::component_to_parent_x (double x) const
153 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
154 return x + _parent_rectangle.get_x();
157 double
158 PortMatrixRowLabels::parent_to_component_x (double x) const
160 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
161 return x - _parent_rectangle.get_x();
164 double
165 PortMatrixRowLabels::component_to_parent_y (double y) const
167 return y - _body->yoffset() + _parent_rectangle.get_y();
170 double
171 PortMatrixRowLabels::parent_to_component_y (double y) const
173 return y + _body->yoffset() - _parent_rectangle.get_y();
177 double
178 PortMatrixRowLabels::bundle_name_x () const
180 double x = 0;
182 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && !_matrix->show_only_bundles ()) {
183 x = _longest_port_name + name_pad() * 2;
186 return x;
189 double
190 PortMatrixRowLabels::port_name_x () const
192 if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
193 return _longest_bundle_name + name_pad() * 2;
194 } else {
195 return 0;
198 return 0;
201 void
202 PortMatrixRowLabels::render_bundle_name (
203 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, boost::shared_ptr<ARDOUR::Bundle> b
206 double const x = bundle_name_x ();
208 int const n = _matrix->show_only_bundles() ? 1 : b->nchannels();
209 set_source_rgb (cr, bg_colour);
210 cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
211 cairo_fill_preserve (cr);
212 set_source_rgb (cr, fg_colour);
213 cairo_set_line_width (cr, label_border_width ());
214 cairo_stroke (cr);
216 cairo_text_extents_t ext;
217 cairo_text_extents (cr, b->name().c_str(), &ext);
218 double const off = (grid_spacing() - ext.height) / 2;
220 set_source_rgb (cr, text_colour());
221 cairo_move_to (cr, xoff + x + name_pad(), yoff + name_pad() + off);
222 cairo_show_text (cr, b->name().c_str());
225 void
226 PortMatrixRowLabels::render_channel_name (
227 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, ARDOUR::BundleChannel const& bc
230 set_source_rgb (cr, bg_colour);
231 cairo_rectangle (cr, port_name_x() + xoff, yoff, _longest_port_name + name_pad() * 2, grid_spacing());
232 cairo_fill_preserve (cr);
233 set_source_rgb (cr, fg_colour);
234 cairo_set_line_width (cr, label_border_width ());
235 cairo_stroke (cr);
237 cairo_text_extents_t ext;
238 cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
239 double const off = (grid_spacing() - ext.height) / 2;
241 if (bc.bundle->nchannels() > 1) {
243 /* only plot the name if the bundle has more than one channel;
244 the name of a single channel is assumed to be redundant */
246 set_source_rgb (cr, text_colour());
247 cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
248 cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
252 double
253 PortMatrixRowLabels::channel_x (ARDOUR::BundleChannel const &) const
255 return 0;
258 double
259 PortMatrixRowLabels::channel_y (ARDOUR::BundleChannel const& bc) const
261 return channel_to_position (bc, _matrix->visible_rows()) * grid_spacing ();
264 void
265 PortMatrixRowLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
267 if (bc.bundle) {
269 if (_matrix->show_only_bundles()) {
270 _body->queue_draw_area (
271 component_to_parent_x (bundle_name_x()) - 1,
272 component_to_parent_y (channel_y (bc)) - 1,
273 _longest_bundle_name + name_pad() * 2 + 2,
274 grid_spacing() + 2
276 } else {
277 _body->queue_draw_area (
278 component_to_parent_x (port_name_x()) - 1,
279 component_to_parent_y (channel_y (bc)) - 1,
280 _longest_port_name + name_pad() * 2 + 2,
281 grid_spacing() + 2
288 void
289 PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
291 list<PortMatrixNode> const m = _body->mouseover ();
292 for (list<PortMatrixNode>::const_iterator i = m.begin(); i != m.end(); ++i) {
294 ARDOUR::BundleChannel c = i->column;
295 ARDOUR::BundleChannel r = i->row;
297 if (c.bundle && r.bundle) {
298 add_channel_highlight (r);
299 } else if (r.bundle) {
300 _body->highlight_associated_channels (_matrix->row_index(), r);
305 void
306 PortMatrixRowLabels::motion (double x, double y)
308 ARDOUR::BundleChannel const w = position_to_channel (y, x, _matrix->visible_rows());
310 uint32_t const bw = _longest_bundle_name + 2 * name_pad();
312 bool done = false;
314 if (w.bundle) {
316 if (
317 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < bw) ||
318 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_width - bw) && x < _width)
322 /* if the mouse is over a bundle name, highlight all channels in the bundle */
324 list<PortMatrixNode> n;
326 for (uint32_t i = 0; i < w.bundle->nchannels(); ++i) {
327 ARDOUR::BundleChannel const bc (w.bundle, i);
328 n.push_back (PortMatrixNode (bc, ARDOUR::BundleChannel ()));
331 _body->set_mouseover (n);
332 done = true;
334 } else if (x < _width) {
336 _body->set_mouseover (PortMatrixNode (w, ARDOUR::BundleChannel ()));
337 done = true;
343 if (!done) {
344 /* not over any bundle */
345 _body->set_mouseover (PortMatrixNode ());
346 return;