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.
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"
32 PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* m, PortMatrixBody* b)
33 : PortMatrixLabels (m, b)
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 ();
81 gdk_pixmap_unref (pm);
83 _width = _longest_bundle_name +
86 if (!_matrix->show_only_bundles()) {
87 _width += _longest_port_name;
88 _width += name_pad() * 2;
94 PortMatrixRowLabels::render (cairo_t* cr)
98 set_source_rgb (cr, background_colour());
99 cairo_rectangle (cr, 0, 0, _width, _height);
102 /* BUNDLE AND PORT NAMES */
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));
128 PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t, guint)
130 ARDOUR::BundleChannel const w = position_to_channel (y, x, _matrix->visible_rows());
134 _matrix->popup_menu (
135 ARDOUR::BundleChannel (),
143 PortMatrixRowLabels::component_to_parent_x (double x) const
145 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
146 return x + _parent_rectangle.get_x();
150 PortMatrixRowLabels::parent_to_component_x (double x) const
152 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
153 return x - _parent_rectangle.get_x();
157 PortMatrixRowLabels::component_to_parent_y (double y) const
159 return y - _body->yoffset() + _parent_rectangle.get_y();
163 PortMatrixRowLabels::parent_to_component_y (double y) const
165 return y + _body->yoffset() - _parent_rectangle.get_y();
170 PortMatrixRowLabels::bundle_name_x () const
174 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && !_matrix->show_only_bundles ()) {
175 x = _longest_port_name + name_pad() * 2;
182 PortMatrixRowLabels::port_name_x () const
184 if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
185 return _longest_bundle_name + name_pad() * 2;
194 PortMatrixRowLabels::render_bundle_name (
195 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, boost::shared_ptr<ARDOUR::Bundle> b
198 double const x = bundle_name_x ();
200 int const n = _matrix->show_only_bundles() ? 1 : b->nchannels();
201 set_source_rgb (cr, bg_colour);
202 cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
203 cairo_fill_preserve (cr);
204 set_source_rgb (cr, fg_colour);
205 cairo_set_line_width (cr, label_border_width ());
208 cairo_text_extents_t ext;
209 cairo_text_extents (cr, b->name().c_str(), &ext);
210 double const off = (grid_spacing() - ext.height) / 2;
212 set_source_rgb (cr, text_colour());
213 cairo_move_to (cr, xoff + x + name_pad(), yoff + name_pad() + off);
214 cairo_show_text (cr, b->name().c_str());
218 PortMatrixRowLabels::render_channel_name (
219 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, ARDOUR::BundleChannel const& bc
222 set_source_rgb (cr, bg_colour);
223 cairo_rectangle (cr, port_name_x() + xoff, yoff, _longest_port_name + name_pad() * 2, grid_spacing());
224 cairo_fill_preserve (cr);
225 set_source_rgb (cr, fg_colour);
226 cairo_set_line_width (cr, label_border_width ());
229 cairo_text_extents_t ext;
230 cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
231 double const off = (grid_spacing() - ext.height) / 2;
233 if (bc.bundle->nchannels() > 1) {
235 /* only plot the name if the bundle has more than one channel;
236 the name of a single channel is assumed to be redundant */
238 set_source_rgb (cr, text_colour());
239 cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
240 cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
245 PortMatrixRowLabels::channel_x (ARDOUR::BundleChannel const &) const
251 PortMatrixRowLabels::channel_y (ARDOUR::BundleChannel const& bc) const
253 return channel_to_position (bc, _matrix->visible_rows()) * grid_spacing ();
257 PortMatrixRowLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
261 if (_matrix->show_only_bundles()) {
262 _body->queue_draw_area (
263 component_to_parent_x (bundle_name_x()) - 1,
264 component_to_parent_y (channel_y (bc)) - 1,
265 _longest_bundle_name + name_pad() * 2 + 2,
269 _body->queue_draw_area (
270 component_to_parent_x (port_name_x()) - 1,
271 component_to_parent_y (channel_y (bc)) - 1,
272 _longest_port_name + name_pad() * 2 + 2,
281 PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
283 list<PortMatrixNode> const m = _body->mouseover ();
284 for (list<PortMatrixNode>::const_iterator i = m.begin(); i != m.end(); ++i) {
286 ARDOUR::BundleChannel c = i->column;
287 ARDOUR::BundleChannel r = i->row;
289 if (c.bundle && r.bundle) {
290 add_channel_highlight (r);
291 } else if (r.bundle) {
292 _body->highlight_associated_channels (_matrix->row_index(), r);
298 PortMatrixRowLabels::motion (double x, double y)
300 ARDOUR::BundleChannel const w = position_to_channel (y, x, _matrix->visible_rows());
302 uint32_t const bw = _longest_bundle_name + 2 * name_pad();
309 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < bw) ||
310 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_width - bw) && x < _width)
314 /* if the mouse is over a bundle name, highlight all channels in the bundle */
316 list<PortMatrixNode> n;
318 for (uint32_t i = 0; i < w.bundle->nchannels(); ++i) {
319 ARDOUR::BundleChannel const bc (w.bundle, i);
320 n.push_back (PortMatrixNode (bc, ARDOUR::BundleChannel ()));
323 _body->set_mouseover (n);
326 } else if (x < _width) {
328 _body->set_mouseover (PortMatrixNode (w, ARDOUR::BundleChannel ()));
336 /* not over any bundle */
337 _body->set_mouseover (PortMatrixNode ());