ardour
port_matrix_row_labels.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2009 Paul Davis
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #include <iostream>
21 #include <boost/weak_ptr.hpp>
22 #include <cairo.h>
23 #include "gtkmm2ext/keyboard.h"
24 #include "ardour/bundle.h"
25 #include "canvas/colors.h"
26 #include "utils.h"
27 #include "port_matrix_row_labels.h"
28 #include "port_matrix.h"
29 #include "port_matrix_body.h"
30 #include "i18n.h"
31 
32 using namespace std;
33 
35  : PortMatrixLabels (m, b)
36 {
37 
38 }
39 
40 void
42 {
43  cairo_surface_t* surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 200, 200);
44  cairo_t* cr = cairo_create (surface);
45 
48 
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.
51  */
52 
53  for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
54 
55  PortGroup::BundleList const r = (*i)->bundles ();
56  for (PortGroup::BundleList::const_iterator j = r.begin(); j != r.end(); ++j) {
57 
58  for (uint32_t k = 0; k < (*j)->bundle->nchannels().n_total(); ++k) {
59 
60  if (!_matrix->should_show ((*j)->bundle->channel_type(k))) {
61  continue;
62  }
63 
64  cairo_text_extents_t ext;
65  cairo_text_extents (cr, (*j)->bundle->channel_name(k).c_str(), &ext);
66  if (ext.width > _longest_port_name) {
67  _longest_port_name = ext.width;
68  }
69  }
70 
71  cairo_text_extents_t ext;
72  cairo_text_extents (cr, (*j)->bundle->name().c_str(), &ext);
73  if (ext.width > _longest_bundle_name) {
74  _longest_bundle_name = ext.width;
75  }
76  }
77  }
78 
79 
80  if (_matrix->visible_rows()) {
82  } else {
83  _height = 0;
84  }
85 
86  cairo_destroy (cr);
87  cairo_surface_destroy (surface);
88 
90  name_pad() * 2;
91 
92  if (!_matrix->show_only_bundles()) {
94  _width += name_pad() * 2;
95  }
96 }
97 
98 
99 void
101 {
102  /* BACKGROUND */
103 
105  cairo_rectangle (cr, 0, 0, _width, _height);
106  cairo_fill (cr);
107 
108  /* BUNDLE AND PORT NAMES */
109 
110  double y = 0;
111  int N = 0;
112  int M = 0;
113 
114  PortGroup::BundleList const & bundles = _matrix->visible_rows()->bundles ();
115  for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
116  render_bundle_name (cr, background_colour (), (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N), 0, y, (*i)->bundle);
117 
118  if (!_matrix->show_only_bundles()) {
119  uint32_t const N = _matrix->count_of_our_type ((*i)->bundle->nchannels());
120  for (uint32_t j = 0; j < N; ++j) {
121  Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (M);
123  (*i)->bundle,
124  (*i)->bundle->type_channel_to_overall (_matrix->type (), j)
125  );
126 
127  render_channel_name (cr, background_colour (), c, 0, y, bc);
128  y += grid_spacing();
129  ++M;
130  }
131 
132  if (N == 0) {
133  y += grid_spacing ();
134  }
135 
136  } else {
137  y += grid_spacing();
138  }
139 
140  ++N;
141  }
142 }
143 
144 void
145 PortMatrixRowLabels::button_press (double x, double y, GdkEventButton* ev)
146 {
148 
149  if (
152 
153  ) {
154  w.channel = -1;
155  }
156 
157  if (Gtkmm2ext::Keyboard::is_delete_event (ev) && w.channel != -1) {
158  _matrix->remove_channel (w);
159  } else if (ev->button == 3) {
162  w,
163  ev->time
164  );
165  }
166 }
167 
168 double
170 {
171  /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
172  return x + _parent_rectangle.get_x();
173 }
174 
175 double
177 {
178  /* Row labels don't scroll horizontally, so x conversion does not depend on xoffset */
179  return x - _parent_rectangle.get_x();
180 }
181 
182 double
184 {
185  return y - _body->yoffset() + _parent_rectangle.get_y();
186 }
187 
188 double
190 {
191  return y + _body->yoffset() - _parent_rectangle.get_y();
192 }
193 
194 
195 double
197 {
198  double x = 0;
199 
201  x = _longest_port_name + name_pad() * 2;
202  }
203 
204  return x;
205 }
206 
207 double
209 {
211  return _longest_bundle_name + name_pad() * 2;
212  } else {
213  return 0;
214  }
215 
216  return 0;
217 }
218 
219 void
221  cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, boost::shared_ptr<ARDOUR::Bundle> b
222  )
223 {
224  double const x = bundle_name_x ();
225 
226  int const n = _matrix->show_only_bundles() ? 1 : _matrix->count_of_our_type_min_1 (b->nchannels());
227  set_source_rgb (cr, bg_colour);
228  cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
229  cairo_fill_preserve (cr);
230  set_source_rgb (cr, fg_colour);
231  cairo_set_line_width (cr, label_border_width ());
232  cairo_stroke (cr);
233 
234  cairo_text_extents_t ext;
235  cairo_text_extents (cr, b->name().c_str(), &ext);
236  double const off = (grid_spacing() - ext.height) / 2;
237 
238  Gdk::Color textcolor;
240  set_source_rgb (cr, textcolor);
241  cairo_move_to (cr, xoff + x + name_pad(), yoff + name_pad() + off);
242  cairo_show_text (cr, b->name().c_str());
243 }
244 
245 void
247  cairo_t* cr, Gdk::Color fg_colour, Gdk::Color bg_colour, double xoff, double yoff, ARDOUR::BundleChannel const& bc
248  )
249 {
250  set_source_rgb (cr, bg_colour);
251  cairo_rectangle (cr, port_name_x() + xoff, yoff, _longest_port_name + name_pad() * 2, grid_spacing());
252  cairo_fill_preserve (cr);
253  set_source_rgb (cr, fg_colour);
254  cairo_set_line_width (cr, label_border_width ());
255  cairo_stroke (cr);
256 
257  if (_matrix->count_of_our_type (bc.bundle->nchannels()) > 1) {
258 
259  /* only plot the name if the bundle has more than one channel;
260  the name of a single channel is assumed to be redundant */
261 
262  cairo_text_extents_t ext;
263  cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
264  double const off = (grid_spacing() - ext.height) / 2;
265 
266  Gdk::Color textcolor;
268  set_source_rgb (cr, textcolor);
269  cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
270  cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
271  }
272 }
273 
274 double
276 {
277  return 0;
278 }
279 
280 double
282 {
284 }
285 
286 void
288 {
289  if (bc.bundle) {
290 
291  if (_matrix->show_only_bundles()) {
292  _body->queue_draw_area (
294  component_to_parent_y (channel_y (bc)) - 1,
295  _longest_bundle_name + name_pad() * 2 + 2,
296  grid_spacing() + 2
297  );
298  } else {
299  _body->queue_draw_area (
301  component_to_parent_y (channel_y (bc)) - 1,
302  _longest_port_name + name_pad() * 2 + 2,
303  grid_spacing() + 2
304  );
305  }
306  }
307 
308 }
309 
310 void
311 PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
312 {
313  list<PortMatrixNode> const m = _body->mouseover ();
314  for (list<PortMatrixNode>::const_iterator i = m.begin(); i != m.end(); ++i) {
315 
316  ARDOUR::BundleChannel c = i->column;
317  ARDOUR::BundleChannel r = i->row;
318 
321  } else if (r.bundle) {
323  }
324  }
325 }
326 
327 void
328 PortMatrixRowLabels::motion (double x, double y)
329 {
331 
332  uint32_t const bw = _longest_bundle_name + 2 * name_pad();
333 
334  bool done = false;
335 
336  if (w.bundle) {
337 
338  if (
339  (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < bw) ||
340  (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_width - bw) && x < _width)
341 
342  ) {
343 
344  /* if the mouse is over a bundle name, highlight all channels in the bundle */
345 
346  list<PortMatrixNode> n;
347 
348  for (uint32_t i = 0; i < w.bundle->nchannels().n_total(); ++i) {
349  if (!_matrix->should_show (w.bundle->channel_type (i))) {
350  continue;
351  }
352 
353  ARDOUR::BundleChannel const bc (w.bundle, i);
354  n.push_back (PortMatrixNode (bc, ARDOUR::BundleChannel ()));
355  }
356 
357  _body->set_mouseover (n);
358  done = true;
359 
360  } else if (x < _width) {
361 
363  done = true;
364 
365  }
366 
367  }
368 
369  if (!done) {
370  /* not over any bundle */
372  return;
373  }
374 }
void popup_menu(ARDOUR::BundleChannel, ARDOUR::BundleChannel, uint32_t)
Definition: port_matrix.cc:418
void add_channel_highlight(ARDOUR::BundleChannel const &)
void set_source_rgb(cairo_t *, Gdk::Color const &)
List::const_iterator begin() const
Definition: port_group.h:123
static uint32_t name_pad()
double component_to_parent_x(double x) const
virtual void remove_channel(ARDOUR::BundleChannel)
Definition: port_matrix.cc:747
double channel_y(ARDOUR::BundleChannel const &) const
std::list< BundleRecord * > BundleList
Definition: port_group.h:86
static int N
Definition: signals_test.cc:27
bool should_show(ARDOUR::DataType) const
Definition: Beats.hpp:239
static uint32_t grid_spacing()
std::list< PortMatrixNode > mouseover() const
uint32_t count_of_our_type(ARDOUR::ChanCount) const
static Gdk::Color get_a_bundle_colour(int x)
List::const_iterator end() const
Definition: port_group.h:127
void render_bundle_name(cairo_t *, Gdk::Color, Gdk::Color, double, double, boost::shared_ptr< ARDOUR::Bundle >)
column labels on top, row labels to the right
Definition: port_matrix.h:84
uint32_t _height
full height of the contents
uint32_t gdk_color_to_rgba(Gdk::Color const &)
Definition: utils.cc:285
uint32_t contrasting_text_color(uint32_t c)
void set_color_from_rgba(Gdk::Color &, uint32_t)
Definition: utils.cc:276
void motion(double, double)
double component_to_parent_y(double y) const
uint32_t group_size(boost::shared_ptr< const PortGroup >) const
void render_channel_name(cairo_t *, Gdk::Color, Gdk::Color, double, double, ARDOUR::BundleChannel const &)
virtual ARDOUR::BundleChannel position_to_channel(double, double, boost::shared_ptr< const PortGroup >) const
ChanCount nchannels() const
Definition: bundle.cc:68
uint32_t channel_to_position(ARDOUR::BundleChannel, boost::shared_ptr< const PortGroup >) const
uint32_t yoffset() const
uint32_t count_of_our_type_min_1(ARDOUR::ChanCount) const
void mouseover_changed(std::list< PortMatrixNode > const &)
Gdk::Rectangle _parent_rectangle
std::string name() const
Definition: bundle.h:110
double channel_x(ARDOUR::BundleChannel const &) const
void highlight_associated_channels(int, ARDOUR::BundleChannel)
static uint32_t label_border_width()
PortMatrixBody * _body
the PortMatrixBody that we're in
row labels to the left, column labels on the bottom
Definition: port_matrix.h:85
bool show_only_bundles() const
Definition: port_matrix.h:94
double parent_to_component_y(double y) const
ARDOUR::DataType type() const
Definition: port_matrix.h:68
static bool is_delete_event(GdkEventButton *)
Definition: keyboard.cc:498
PortMatrixRowLabels(PortMatrix *, PortMatrixBody *)
double parent_to_component_x(double x) const
void set_mouseover(PortMatrixNode const &)
uint32_t _width
full width of the contents
int row_index() const
Definition: port_matrix.h:110
boost::shared_ptr< Bundle > bundle
Definition: bundle.h:168
void queue_draw_for(ARDOUR::BundleChannel const &)
int channel
channel index, or -1 for "all"
Definition: bundle.h:169
boost::shared_ptr< const PortGroup > visible_rows() const
Definition: port_matrix.cc:409
void button_press(double, double, GdkEventButton *)
static bool bundle_with_channels(boost::shared_ptr< ARDOUR::Bundle >)
Arrangement arrangement() const
Definition: port_matrix.h:90
PortGroupList const * rows() const
Definition: port_matrix.cc:403