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().n_total(); ++k
) {
59 if (!_matrix
->should_show ((*j
)->bundle
->channel_type(k
))) {
63 cairo_text_extents_t ext
;
64 cairo_text_extents (cr
, (*j
)->bundle
->channel_name(k
).c_str(), &ext
);
65 if (ext
.width
> _longest_port_name
) {
66 _longest_port_name
= ext
.width
;
70 cairo_text_extents_t ext
;
71 cairo_text_extents (cr
, (*j
)->bundle
->name().c_str(), &ext
);
72 if (ext
.width
> _longest_bundle_name
) {
73 _longest_bundle_name
= ext
.width
;
79 if (_matrix
->visible_rows()) {
80 _height
= group_size (_matrix
->visible_rows()) * grid_spacing ();
88 _width
= _longest_bundle_name
+
91 if (!_matrix
->show_only_bundles()) {
92 _width
+= _longest_port_name
;
93 _width
+= name_pad() * 2;
99 PortMatrixRowLabels::render (cairo_t
* cr
)
103 set_source_rgb (cr
, background_colour());
104 cairo_rectangle (cr
, 0, 0, _width
, _height
);
107 /* BUNDLE AND PORT NAMES */
113 PortGroup::BundleList
const & bundles
= _matrix
->visible_rows()->bundles ();
114 for (PortGroup::BundleList::const_iterator i
= bundles
.begin(); i
!= bundles
.end(); ++i
) {
115 render_bundle_name (cr
, background_colour (), (*i
)->has_colour
? (*i
)->colour
: get_a_bundle_colour (N
), 0, y
, (*i
)->bundle
);
117 if (!_matrix
->show_only_bundles()) {
118 for (uint32_t j
= 0; j
< (*i
)->bundle
->nchannels().n_total(); ++j
) {
120 if (!_matrix
->should_show ((*i
)->bundle
->channel_type(j
))) {
124 Gdk::Color c
= (*i
)->has_colour
? (*i
)->colour
: get_a_bundle_colour (M
);
125 render_channel_name (cr
, background_colour (), c
, 0, y
, ARDOUR::BundleChannel ((*i
)->bundle
, j
));
138 PortMatrixRowLabels::button_press (double x
, double y
, int b
, uint32_t t
, guint
)
140 ARDOUR::BundleChannel w
= position_to_channel (y
, x
, _matrix
->visible_rows());
143 (_matrix
->arrangement() == PortMatrix::TOP_TO_RIGHT
&& x
> (_longest_port_name
+ name_pad() * 2)) ||
144 (_matrix
->arrangement() == PortMatrix::LEFT_TO_BOTTOM
&& x
< (_longest_bundle_name
+ name_pad() * 2))
152 _matrix
->popup_menu (
153 ARDOUR::BundleChannel (),
161 PortMatrixRowLabels::component_to_parent_x (double x
) const
163 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
164 return x
+ _parent_rectangle
.get_x();
168 PortMatrixRowLabels::parent_to_component_x (double x
) const
170 /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
171 return x
- _parent_rectangle
.get_x();
175 PortMatrixRowLabels::component_to_parent_y (double y
) const
177 return y
- _body
->yoffset() + _parent_rectangle
.get_y();
181 PortMatrixRowLabels::parent_to_component_y (double y
) const
183 return y
+ _body
->yoffset() - _parent_rectangle
.get_y();
188 PortMatrixRowLabels::bundle_name_x () const
192 if (_matrix
->arrangement() == PortMatrix::TOP_TO_RIGHT
&& !_matrix
->show_only_bundles ()) {
193 x
= _longest_port_name
+ name_pad() * 2;
200 PortMatrixRowLabels::port_name_x () const
202 if (_matrix
->arrangement() == PortMatrix::LEFT_TO_BOTTOM
) {
203 return _longest_bundle_name
+ name_pad() * 2;
212 PortMatrixRowLabels::render_bundle_name (
213 cairo_t
* cr
, Gdk::Color fg_colour
, Gdk::Color bg_colour
, double xoff
, double yoff
, boost::shared_ptr
<ARDOUR::Bundle
> b
216 double const x
= bundle_name_x ();
218 int const n
= _matrix
->show_only_bundles() ? 1 : _matrix
->count_of_our_type (b
->nchannels());
219 set_source_rgb (cr
, bg_colour
);
220 cairo_rectangle (cr
, xoff
+ x
, yoff
, _longest_bundle_name
+ name_pad() * 2, grid_spacing() * n
);
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
, b
->name().c_str(), &ext
);
228 double const off
= (grid_spacing() - ext
.height
) / 2;
230 set_source_rgb (cr
, text_colour());
231 cairo_move_to (cr
, xoff
+ x
+ name_pad(), yoff
+ name_pad() + off
);
232 cairo_show_text (cr
, b
->name().c_str());
236 PortMatrixRowLabels::render_channel_name (
237 cairo_t
* cr
, Gdk::Color fg_colour
, Gdk::Color bg_colour
, double xoff
, double yoff
, ARDOUR::BundleChannel
const& bc
240 set_source_rgb (cr
, bg_colour
);
241 cairo_rectangle (cr
, port_name_x() + xoff
, yoff
, _longest_port_name
+ name_pad() * 2, grid_spacing());
242 cairo_fill_preserve (cr
);
243 set_source_rgb (cr
, fg_colour
);
244 cairo_set_line_width (cr
, label_border_width ());
247 cairo_text_extents_t ext
;
248 cairo_text_extents (cr
, bc
.bundle
->channel_name(bc
.channel
).c_str(), &ext
);
249 double const off
= (grid_spacing() - ext
.height
) / 2;
251 if (_matrix
->count_of_our_type (bc
.bundle
->nchannels()) > 1) {
253 /* only plot the name if the bundle has more than one channel;
254 the name of a single channel is assumed to be redundant */
256 set_source_rgb (cr
, text_colour());
257 cairo_move_to (cr
, port_name_x() + xoff
+ name_pad(), yoff
+ name_pad() + off
);
258 cairo_show_text (cr
, bc
.bundle
->channel_name(bc
.channel
).c_str());
263 PortMatrixRowLabels::channel_x (ARDOUR::BundleChannel
const &) const
269 PortMatrixRowLabels::channel_y (ARDOUR::BundleChannel
const& bc
) const
271 return channel_to_position (bc
, _matrix
->visible_rows()) * grid_spacing ();
275 PortMatrixRowLabels::queue_draw_for (ARDOUR::BundleChannel
const & bc
)
279 if (_matrix
->show_only_bundles()) {
280 _body
->queue_draw_area (
281 component_to_parent_x (bundle_name_x()) - 1,
282 component_to_parent_y (channel_y (bc
)) - 1,
283 _longest_bundle_name
+ name_pad() * 2 + 2,
287 _body
->queue_draw_area (
288 component_to_parent_x (port_name_x()) - 1,
289 component_to_parent_y (channel_y (bc
)) - 1,
290 _longest_port_name
+ name_pad() * 2 + 2,
299 PortMatrixRowLabels::mouseover_changed (list
<PortMatrixNode
> const &)
301 list
<PortMatrixNode
> const m
= _body
->mouseover ();
302 for (list
<PortMatrixNode
>::const_iterator i
= m
.begin(); i
!= m
.end(); ++i
) {
304 ARDOUR::BundleChannel c
= i
->column
;
305 ARDOUR::BundleChannel r
= i
->row
;
307 if (c
.bundle
&& r
.bundle
) {
308 add_channel_highlight (r
);
309 } else if (r
.bundle
) {
310 _body
->highlight_associated_channels (_matrix
->row_index(), r
);
316 PortMatrixRowLabels::motion (double x
, double y
)
318 ARDOUR::BundleChannel
const w
= position_to_channel (y
, x
, _matrix
->visible_rows());
320 uint32_t const bw
= _longest_bundle_name
+ 2 * name_pad();
327 (_matrix
->arrangement() == PortMatrix::LEFT_TO_BOTTOM
&& x
< bw
) ||
328 (_matrix
->arrangement() == PortMatrix::TOP_TO_RIGHT
&& x
> (_width
- bw
) && x
< _width
)
332 /* if the mouse is over a bundle name, highlight all channels in the bundle */
334 list
<PortMatrixNode
> n
;
336 for (uint32_t i
= 0; i
< w
.bundle
->nchannels().n_total(); ++i
) {
338 if (!_matrix
->should_show (w
.bundle
->channel_type(i
))) {
342 ARDOUR::BundleChannel
const bc (w
.bundle
, i
);
343 n
.push_back (PortMatrixNode (bc
, ARDOUR::BundleChannel ()));
346 _body
->set_mouseover (n
);
349 } else if (x
< _width
) {
351 _body
->set_mouseover (PortMatrixNode (w
, ARDOUR::BundleChannel ()));
359 /* not over any bundle */
360 _body
->set_mouseover (PortMatrixNode ());