put the issue of using a monitor section into ~/.config/ardour.rc, not the session...
[ardour2.git] / gtk2_ardour / port_matrix_column_labels.cc
blob522015548f5b35a967130fdd37cf54c823b0607a
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 "ardour/bundle.h"
22 #include "ardour/types.h"
23 #include "port_matrix_column_labels.h"
24 #include "port_matrix.h"
25 #include "port_matrix_body.h"
26 #include "utils.h"
28 using namespace std;
30 PortMatrixColumnLabels::PortMatrixColumnLabels (PortMatrix* m, PortMatrixBody* b)
31 : PortMatrixLabels (m, b),
32 _overhang (0)
37 void
38 PortMatrixColumnLabels::compute_dimensions ()
40 GdkPixmap* pm = gdk_pixmap_new (NULL, 1, 1, 24);
41 gdk_drawable_set_colormap (pm, gdk_colormap_get_system());
42 cairo_t* cr = gdk_cairo_create (pm);
44 /* width of the longest bundle name */
45 _longest_bundle_name = 0;
46 /* width of the longest channel name */
47 _longest_channel_name = 0;
49 /* Compute dimensions using all port groups, so that we allow for the largest and hence
50 we can change between visible groups without the size of the labels jumping around.
53 for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
54 PortGroup::BundleList const c = _matrix->columns()->bundles();
55 for (PortGroup::BundleList::const_iterator j = c.begin (); j != c.end(); ++j) {
57 cairo_text_extents_t ext;
58 cairo_text_extents (cr, (*j)->bundle->name().c_str(), &ext);
59 if (ext.width > _longest_bundle_name) {
60 _longest_bundle_name = ext.width;
63 for (uint32_t k = 0; k < (*j)->bundle->nchannels (); ++k) {
65 cairo_text_extents (
66 cr,
67 (*j)->bundle->channel_name (k).c_str(),
68 &ext
71 if (ext.width > _longest_channel_name) {
72 _longest_channel_name = ext.width;
78 /* height metrics */
79 cairo_text_extents_t ext;
80 cairo_text_extents (cr, X_("AQRjpy"), &ext);
81 _text_height = ext.height;
82 _descender_height = ext.height + ext.y_bearing;
84 /* width of the whole thing */
85 if (_matrix->visible_columns()) {
86 _width = group_size (_matrix->visible_columns()) * grid_spacing ();
87 } else {
88 _width = 0;
91 cairo_destroy (cr);
92 gdk_pixmap_unref (pm);
94 /* height of the whole thing */
96 int a = _longest_bundle_name + 4 * name_pad();
97 if (!_matrix->show_only_bundles()) {
98 a += _longest_channel_name;
101 _height = a * sin (angle()) + _text_height * cos (angle());
102 _overhang = _height / tan (angle ());
103 _width += _overhang;
106 double
107 PortMatrixColumnLabels::basic_text_x_pos (int) const
109 return grid_spacing() / 2 +
110 _text_height / (2 * sin (angle ()));
113 void
114 PortMatrixColumnLabels::render (cairo_t* cr)
116 /* BACKGROUND */
118 set_source_rgb (cr, background_colour());
119 cairo_rectangle (cr, 0, 0, _width, _height);
120 cairo_fill (cr);
122 /* BUNDLE PARALLELOGRAM-TYPE-THING AND NAME */
124 double x = 0;
125 int N = 0;
127 PortGroup::BundleList const & bundles = _matrix->visible_columns()->bundles ();
128 for (PortGroup::BundleList::const_iterator i = bundles.begin (); i != bundles.end(); ++i) {
130 Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N);
131 render_bundle_name (cr, background_colour (), c, x, 0, (*i)->bundle);
133 if (_matrix->show_only_bundles()) {
134 x += grid_spacing();
135 } else {
136 x += (*i)->bundle->nchannels () * grid_spacing();
139 ++N;
142 /* PORT NAMES */
144 if (!_matrix->show_only_bundles()) {
145 x = 0;
146 N = 0;
148 for (PortGroup::BundleList::const_iterator i = bundles.begin (); i != bundles.end(); ++i) {
150 for (uint32_t j = 0; j < (*i)->bundle->nchannels(); ++j) {
151 Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N);
152 render_channel_name (cr, background_colour (), c, x, 0, ARDOUR::BundleChannel ((*i)->bundle, j));
153 x += grid_spacing();
156 ++N;
161 double
162 PortMatrixColumnLabels::component_to_parent_x (double x) const
164 return x - _body->xoffset() + _parent_rectangle.get_x();
167 double
168 PortMatrixColumnLabels::parent_to_component_x (double x) const
170 return x + _body->xoffset() - _parent_rectangle.get_x();
173 double
174 PortMatrixColumnLabels::component_to_parent_y (double y) const
176 /* Column labels don't scroll vertically, so y conversion does not depend on yoffset */
177 return y + _parent_rectangle.get_y();
180 double
181 PortMatrixColumnLabels::parent_to_component_y (double y) const
183 /* Column labels don't scroll vertically, so y conversion does not depend on yoffset */
184 return y - _parent_rectangle.get_y();
187 void
188 PortMatrixColumnLabels::mouseover_changed (list<PortMatrixNode> const &)
190 list<PortMatrixNode> const m = _body->mouseover ();
191 for (list<PortMatrixNode>::const_iterator i = m.begin(); i != m.end(); ++i) {
193 ARDOUR::BundleChannel c = i->column;
194 ARDOUR::BundleChannel r = i->row;
196 if (c.bundle && r.bundle) {
197 add_channel_highlight (c);
198 } else if (c.bundle) {
199 _body->highlight_associated_channels (_matrix->column_index(), c);
204 vector<pair<double, double> >
205 PortMatrixColumnLabels::port_name_shape (double xoff, double yoff) const
207 vector<pair<double, double> > shape;
209 double const lc = _longest_channel_name + name_pad();
210 double const w = grid_spacing();
212 if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
214 double x_ = xoff + _height / tan (angle()) + w;
215 double y_ = yoff;
216 shape.push_back (make_pair (x_, y_));
217 x_ -= w;
218 shape.push_back (make_pair (x_, y_));
219 x_ -= lc * cos (angle());
220 y_ += lc * sin (angle());
221 shape.push_back (make_pair (x_, y_));
222 x_ += w * pow (sin (angle()), 2);
223 y_ += w * sin (angle()) * cos (angle());
224 shape.push_back (make_pair (x_, y_));
226 } else {
228 double x_ = xoff;
229 double y_ = yoff + _height;
230 shape.push_back (make_pair (x_, y_));
231 x_ += w;
232 shape.push_back (make_pair (x_, y_));
233 x_ += lc * cos (angle());
234 y_ -= lc * sin (angle());
235 shape.push_back (make_pair (x_, y_));
236 x_ -= grid_spacing() * pow (sin (angle()), 2);
237 y_ -= grid_spacing() * sin (angle()) * cos (angle());
238 shape.push_back (make_pair (x_, y_));
241 return shape;
244 void
245 PortMatrixColumnLabels::render_bundle_name (
246 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, boost::shared_ptr<ARDOUR::Bundle> b
249 set_source_rgb (cr, bg_colour);
251 double w = 0;
252 if (_matrix->show_only_bundles()) {
253 w = grid_spacing ();
254 } else {
255 w = b->nchannels() * grid_spacing();
258 double x_ = xoff;
260 uint32_t y = yoff;
261 y += _height;
263 double y_ = y;
264 cairo_move_to (cr, x_, y_);
265 x_ += w;
266 cairo_line_to (cr, x_, y_);
267 x_ += _height / tan (angle ());
268 y_ -= _height;
269 cairo_line_to (cr, x_, y_);
270 x_ -= w;
271 cairo_line_to (cr, x_, y_);
272 cairo_line_to (cr, xoff, y);
273 cairo_fill_preserve (cr);
274 set_source_rgb (cr, fg_colour);
275 cairo_set_line_width (cr, label_border_width());
276 cairo_stroke (cr);
278 set_source_rgb (cr, text_colour());
280 double const q = ((grid_spacing() * sin (angle())) - _text_height) / 2 + _descender_height;
282 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
284 double rl = 0;
285 if (_matrix->show_only_bundles()) {
286 rl = name_pad();
287 } else {
288 rl = 3 * name_pad() + _longest_channel_name;
290 cairo_move_to (
292 xoff + grid_spacing() - q * sin (angle ()) + rl * cos (angle()),
293 yoff + _height - q * cos (angle ()) - rl * sin (angle())
296 } else {
298 cairo_move_to (
300 xoff + grid_spacing() - q * sin (angle ()),
301 yoff + _height - q * cos (angle ())
305 cairo_save (cr);
306 cairo_rotate (cr, -angle());
307 cairo_show_text (cr, b->name().c_str());
308 cairo_restore (cr);
311 void
312 PortMatrixColumnLabels::render_channel_name (
313 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, ARDOUR::BundleChannel const &bc
316 vector<pair<double, double> > const shape = port_name_shape (xoff, yoff);
318 cairo_move_to (cr, shape[0].first, shape[0].second);
319 for (uint32_t i = 1; i < 4; ++i) {
320 cairo_line_to (cr, shape[i].first, shape[i].second);
322 cairo_line_to (cr, shape[0].first, shape[0].second);
324 set_source_rgb (cr, bg_colour);
325 cairo_fill_preserve (cr);
326 set_source_rgb (cr, fg_colour);
327 cairo_set_line_width (cr, label_border_width());
328 cairo_stroke (cr);
330 set_source_rgb (cr, text_colour());
332 double const q = ((grid_spacing() * sin (angle())) - _text_height) / 2 + _descender_height;
334 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
336 cairo_move_to (
338 xoff + grid_spacing() - q * sin (angle ()),
339 yoff + _height - q * cos (angle ())
343 } else {
345 double const rl = 3 * name_pad() + _longest_bundle_name;
346 cairo_move_to (
348 xoff + grid_spacing() - q * sin (angle ()) + rl * cos (angle ()),
349 yoff + _height - q * cos (angle ()) - rl * sin (angle())
353 if (bc.bundle->nchannels() > 1) {
355 /* only plot the name if the bundle has more than one channel;
356 the name of a single channel is assumed to be redundant */
358 cairo_save (cr);
359 cairo_rotate (cr, -angle());
361 cairo_show_text (
363 bc.bundle->channel_name(bc.channel).c_str()
366 cairo_restore (cr);
370 double
371 PortMatrixColumnLabels::channel_x (ARDOUR::BundleChannel const &bc) const
373 return channel_to_position (bc, _matrix->visible_columns()) * grid_spacing ();
376 double
377 PortMatrixColumnLabels::channel_y (ARDOUR::BundleChannel const &) const
379 return 0;
382 void
383 PortMatrixColumnLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
385 if (!bc.bundle) {
386 return;
389 if (_matrix->show_only_bundles()) {
391 _body->queue_draw_area (
392 component_to_parent_x (channel_x (bc)) - 1,
393 component_to_parent_y (0) - 1,
394 grid_spacing() + _height * tan (angle()) + 2,
395 _height + 2
398 } else {
400 double const x = channel_x (bc);
401 double const lc = _longest_channel_name + name_pad();
402 double const h = lc * sin (angle ()) + grid_spacing() * sin (angle()) * cos (angle());
404 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
406 _body->queue_draw_area (
407 component_to_parent_x (x) - 1,
408 component_to_parent_y (_height - h) - 1,
409 grid_spacing() + lc * cos (angle()) + 2,
410 h + 2
413 } else if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
415 double const x_ = x + _height / tan (angle()) - lc * cos (angle());
417 _body->queue_draw_area (
418 component_to_parent_x (x_) - 1,
419 component_to_parent_y (0) - 1,
420 grid_spacing() + lc * cos (angle()) + 2,
421 h + 2
429 ARDOUR::BundleChannel
430 PortMatrixColumnLabels::position_to_channel (double p, double o, boost::shared_ptr<const PortGroup> group) const
432 uint32_t const cx = p - (_height - o) * tan (angle ());
433 return PortMatrixComponent::position_to_channel (cx, o, group);
436 void
437 PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t, guint)
439 ARDOUR::BundleChannel w = position_to_channel (x, y, _matrix->visible_columns());
441 if (
442 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && y > (_height - _longest_bundle_name * sin (angle ()))) ||
443 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && y < (_longest_bundle_name * sin (angle ())))
446 w.channel = -1;
449 if (b == 3) {
450 _matrix->popup_menu (
452 ARDOUR::BundleChannel (),
458 void
459 PortMatrixColumnLabels::motion (double x, double y)
461 ARDOUR::BundleChannel const w = position_to_channel (x, y, _matrix->visible_columns());
463 if (w.bundle == 0) {
464 _body->set_mouseover (PortMatrixNode ());
465 return;
468 uint32_t const bh = _longest_channel_name * sin (angle ()) + _text_height / cos (angle ());
470 if (
471 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && y > bh) ||
472 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && y < (_height - bh))
475 /* if the mouse is over a bundle name, highlight all channels in the bundle */
477 list<PortMatrixNode> n;
479 for (uint32_t i = 0; i < w.bundle->nchannels(); ++i) {
480 ARDOUR::BundleChannel const bc (w.bundle, i);
481 n.push_back (PortMatrixNode (ARDOUR::BundleChannel (), bc));
484 _body->set_mouseover (n);
486 } else {
488 _body->set_mouseover (PortMatrixNode (ARDOUR::BundleChannel (), w));