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;
49 /* Compute maximum 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->rows()->begin(); i != _matrix->rows()->end(); ++i) {
55 PortGroup::BundleList const r = (*i)->bundles ();
56 for (PortGroup::BundleList::const_iterator j = r.begin(); j != r.end(); ++j) {
58 for (uint32_t k = 0; k < j->bundle->nchannels(); ++k) {
59 cairo_text_extents_t ext;
60 cairo_text_extents (cr, j->bundle->channel_name(k).c_str(), &ext);
61 if (ext.width > _longest_port_name) {
62 _longest_port_name = ext.width;
66 cairo_text_extents_t ext;
67 cairo_text_extents (cr, j->bundle->name().c_str(), &ext);
68 if (ext.width > _longest_bundle_name) {
69 _longest_bundle_name = ext.width;
75 _height += group_size (_matrix->visible_rows()) * grid_spacing ();
78 gdk_pixmap_unref (pm);
80 _width = _longest_bundle_name +
83 if (!_matrix->show_only_bundles()) {
84 _width += _longest_port_name;
85 _width += name_pad() * 2;
91 PortMatrixRowLabels::render (cairo_t* cr)
95 set_source_rgb (cr, background_colour());
96 cairo_rectangle (cr, 0, 0, _width, _height);
99 /* BUNDLE AND PORT NAMES */
105 PortGroup::BundleList const & bundles = _matrix->visible_rows()->bundles ();
106 for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
107 render_bundle_name (cr, background_colour (), i->has_colour ? i->colour : get_a_bundle_colour (N), 0, y, i->bundle);
109 if (!_matrix->show_only_bundles()) {
110 for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
111 Gdk::Color c = i->has_colour ? i->colour : get_a_bundle_colour (M);
112 render_channel_name (cr, background_colour (), c, 0, y, ARDOUR::BundleChannel (i->bundle, j));
125 PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t, guint)
127 ARDOUR::BundleChannel const w = position_to_channel (y, x, _matrix->visible_rows());
131 _matrix->popup_menu (
132 ARDOUR::BundleChannel (),
140 PortMatrixRowLabels::component_to_parent_x (double x) const
142 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
143 return x + _parent_rectangle.get_x();
147 PortMatrixRowLabels::parent_to_component_x (double x) const
149 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
150 return x - _parent_rectangle.get_x();
154 PortMatrixRowLabels::component_to_parent_y (double y) const
156 return y - _body->yoffset() + _parent_rectangle.get_y();
160 PortMatrixRowLabels::parent_to_component_y (double y) const
162 return y + _body->yoffset() - _parent_rectangle.get_y();
167 PortMatrixRowLabels::bundle_name_x () const
171 if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && !_matrix->show_only_bundles ()) {
172 x = _longest_port_name + name_pad() * 2;
179 PortMatrixRowLabels::port_name_x () const
181 if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
182 return _longest_bundle_name + name_pad() * 2;
191 PortMatrixRowLabels::render_bundle_name (
192 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, boost::shared_ptr<ARDOUR::Bundle> b
195 double const x = bundle_name_x ();
197 int const n = _matrix->show_only_bundles() ? 1 : b->nchannels();
198 set_source_rgb (cr, bg_colour);
199 cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
200 cairo_fill_preserve (cr);
201 set_source_rgb (cr, fg_colour);
202 cairo_set_line_width (cr, label_border_width ());
205 cairo_text_extents_t ext;
206 cairo_text_extents (cr, b->name().c_str(), &ext);
207 double const off = (grid_spacing() - ext.height) / 2;
209 set_source_rgb (cr, text_colour());
210 cairo_move_to (cr, xoff + x + name_pad(), yoff + name_pad() + off);
211 cairo_show_text (cr, b->name().c_str());
215 PortMatrixRowLabels::render_channel_name (
216 cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, ARDOUR::BundleChannel const& bc
219 set_source_rgb (cr, bg_colour);
220 cairo_rectangle (cr, port_name_x() + xoff, yoff, _longest_port_name + name_pad() * 2, grid_spacing());
221 cairo_fill_preserve (cr);
222 set_source_rgb (cr, fg_colour);
223 cairo_set_line_width (cr, label_border_width ());
226 cairo_text_extents_t ext;
227 cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
228 double const off = (grid_spacing() - ext.height) / 2;
230 if (bc.bundle->nchannels() > 1) {
232 /* only plot the name if the bundle has more than one channel;
233 the name of a single channel is assumed to be redundant */
235 set_source_rgb (cr, text_colour());
236 cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
237 cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
242 PortMatrixRowLabels::channel_x (ARDOUR::BundleChannel const &) const
248 PortMatrixRowLabels::channel_y (ARDOUR::BundleChannel const& bc) const
250 return channel_to_position (bc, _matrix->visible_rows()) * grid_spacing ();
254 PortMatrixRowLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
258 if (_matrix->show_only_bundles()) {
259 _body->queue_draw_area (
260 component_to_parent_x (bundle_name_x()) - 1,
261 component_to_parent_y (channel_y (bc)) - 1,
262 _longest_bundle_name + name_pad() * 2 + 2,
266 _body->queue_draw_area (
267 component_to_parent_x (port_name_x()) - 1,
268 component_to_parent_y (channel_y (bc)) - 1,
269 _longest_port_name + name_pad() * 2 + 2,
278 PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
280 list<PortMatrixNode> const m = _body->mouseover ();
281 for (list<PortMatrixNode>::const_iterator i = m.begin(); i != m.end(); ++i) {
283 ARDOUR::BundleChannel c = i->column;
284 ARDOUR::BundleChannel r = i->row;
286 if (c.bundle && r.bundle) {
287 add_channel_highlight (r);
288 } else if (r.bundle) {
289 _body->highlight_associated_channels (_matrix->row_index(), r);
295 PortMatrixRowLabels::motion (double x, double y)
297 ARDOUR::BundleChannel const w = position_to_channel (y, x, _matrix->visible_rows());
300 /* not over any bundle */
301 _body->set_mouseover (PortMatrixNode ());
305 uint32_t const bw = _longest_bundle_name + 2 * name_pad();
308 (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < bw) ||
309 (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_width - bw))
313 /* if the mouse is over a bundle name, highlight all channels in the bundle */
315 list<PortMatrixNode> n;
317 for (uint32_t i = 0; i < w.bundle->nchannels(); ++i) {
318 ARDOUR::BundleChannel const bc (w.bundle, i);
319 n.push_back (PortMatrixNode (bc, ARDOUR::BundleChannel ()));
322 _body->set_mouseover (n);
326 _body->set_mouseover (PortMatrixNode (w, ARDOUR::BundleChannel ()));