Fix a couple of compiler warnings.
[ardour.git] / gtk2_ardour / port_matrix_row_labels.cc
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 <gtkmm/menu.h>
23 #include <gtkmm/menushell.h>
24 #include <gtkmm/menu_elems.h>
25 #include <cairo/cairo.h>
26 #include "ardour/bundle.h"
27 #include "port_matrix_row_labels.h"
28 #include "port_matrix.h"
29 #include "i18n.h"
30
31 PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* p, PortMatrixBody* b, Location l)
32         : PortMatrixComponent (b), _port_matrix (p), _menu (0), _location (l)
33 {
34         
35 }
36
37 PortMatrixRowLabels::~PortMatrixRowLabels ()
38 {
39         delete _menu;
40 }
41
42 void
43 PortMatrixRowLabels::compute_dimensions ()
44 {
45         GdkPixmap* pm = gdk_pixmap_new (NULL, 1, 1, 24);
46         gdk_drawable_set_colormap (pm, gdk_colormap_get_system());
47         cairo_t* cr = gdk_cairo_create (pm);
48         
49         _longest_port_name = 0;
50         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
51                 for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
52                         cairo_text_extents_t ext;
53                         cairo_text_extents (cr, (*i)->channel_name(j).c_str(), &ext);
54                         if (ext.width > _longest_port_name) {
55                                 _longest_port_name = ext.width;
56                         }
57                 }
58         }
59
60         _longest_bundle_name = 0;
61         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
62                 cairo_text_extents_t ext;
63                 cairo_text_extents (cr, (*i)->name().c_str(), &ext);
64                 if (ext.width > _longest_bundle_name) {
65                         _longest_bundle_name = ext.width;
66                 }
67         }
68
69         cairo_destroy (cr);
70         gdk_pixmap_unref (pm);
71
72         _height = 0;
73         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
74                 _height += (*i)->nchannels() * row_height();
75         }
76
77         _width = _longest_port_name + name_pad() * 4 + _longest_bundle_name;
78 }
79
80
81 void
82 PortMatrixRowLabels::render (cairo_t* cr)
83 {
84         /* BACKGROUND */
85         
86         set_source_rgb (cr, background_colour());
87         cairo_rectangle (cr, 0, 0, _width, _height);
88         cairo_fill (cr);
89
90         /* SIDE BUNDLE NAMES */
91
92         uint32_t x = 0;
93         if (_location == LEFT) {
94                 x = name_pad();
95         } else if (_location == RIGHT) {
96                 x = _longest_port_name + name_pad() * 3;
97         }
98
99         uint32_t y = 0;
100         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
101
102                 Gdk::Color const colour = get_a_bundle_colour (i - _body->row_bundles().begin ());
103                 set_source_rgb (cr, colour);
104                 cairo_rectangle (cr, 0, y, _width, row_height() * (*i)->nchannels());
105                 cairo_fill_preserve (cr);
106                 set_source_rgb (cr, background_colour());
107                 cairo_set_line_width (cr, label_border_width ());
108                 cairo_stroke (cr);
109
110                 uint32_t off = 0;
111                 if ((*i)->nchannels () > 0) {
112                         /* use the extent of our first channel name so that the bundle name is vertically aligned with it */
113                         cairo_text_extents_t ext;
114                         cairo_text_extents (cr, (*i)->channel_name(0).c_str(), &ext);
115                         off = (row_height() - ext.height) / 2;
116                 } else {
117                         off = row_height() / 2;
118                 }
119
120                 set_source_rgb (cr, text_colour());
121                 cairo_move_to (cr, x, y + name_pad() + off);
122                 cairo_show_text (cr, (*i)->name().c_str());
123                 
124                 y += row_height() * (*i)->nchannels ();
125         }
126         
127
128         /* SIDE PORT NAMES */
129
130         y = 0;
131         for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
132                 for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
133
134                         uint32_t x = 0;
135                         if (_location == LEFT) {
136                                 x = _longest_bundle_name + name_pad() * 2;
137                         } else if (_location == RIGHT) {
138                                 x = 0;
139                         }
140
141                         Gdk::Color const colour = get_a_bundle_colour (i - _body->row_bundles().begin ());
142                         set_source_rgb (cr, colour);
143                         cairo_rectangle (
144                                 cr,
145                                 x,
146                                 y,
147                                 _longest_port_name + (name_pad() * 2),
148                                 row_height()
149                                 );
150                         cairo_fill_preserve (cr);
151                         set_source_rgb (cr, background_colour());
152                         cairo_set_line_width (cr, label_border_width ());
153                         cairo_stroke (cr);
154
155                         cairo_text_extents_t ext;
156                         cairo_text_extents (cr, (*i)->channel_name(j).c_str(), &ext);
157                         uint32_t const off = (row_height() - ext.height) / 2;
158
159                         set_source_rgb (cr, text_colour());
160                         cairo_move_to (cr, x + name_pad(), y + name_pad() + off);
161                         cairo_show_text (cr, (*i)->channel_name(j).c_str());
162
163                         y += row_height();
164                 }
165         }
166 }
167
168 void
169 PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t)
170 {
171         if (b != 3) {
172                 return;
173         }
174
175         if ( (_location ==  LEFT && x > (_longest_bundle_name + name_pad() * 2)) ||
176              (_location == RIGHT && x < (_longest_port_name + name_pad() * 2))
177                 ) {
178
179                 delete _menu;
180                 
181                 _menu = new Gtk::Menu;
182                 _menu->set_name ("ArdourContextMenu");
183                 
184                 Gtk::Menu_Helpers::MenuList& items = _menu->items ();
185                 
186                 uint32_t row = y / row_height ();
187
188                 boost::shared_ptr<ARDOUR::Bundle> bundle;
189                 uint32_t channel = 0;
190                 
191                 for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) {
192                         if (row < (*i)->nchannels ()) {
193                                 bundle = *i;
194                                 channel = row;
195                                 break;
196                         } else {
197                                 row -= (*i)->nchannels ();
198                         }
199                 }
200
201                 if (bundle) {
202                         char buf [64];
203
204                         if (_port_matrix->can_rename_channels ()) {
205                                 snprintf (buf, sizeof (buf), _("Rename '%s'..."), bundle->channel_name (channel).c_str());
206                                 items.push_back (
207                                         Gtk::Menu_Helpers::MenuElem (
208                                                 buf,
209                                                 sigc::bind (sigc::mem_fun (*this, &PortMatrixRowLabels::rename_channel_proxy), bundle, channel)
210                                                 )
211                                         );
212                         }
213                         
214                         snprintf (buf, sizeof (buf), _("Remove '%s'"), bundle->channel_name (channel).c_str());
215                         items.push_back (
216                                 Gtk::Menu_Helpers::MenuElem (
217                                         buf,
218                                         sigc::bind (sigc::mem_fun (*this, &PortMatrixRowLabels::remove_channel_proxy), bundle, channel)
219                                         )
220                                 );
221
222                         _menu->popup (1, t);
223                 }
224         }
225 }
226
227
228 void
229 PortMatrixRowLabels::remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
230 {
231         boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
232         if (!sb) {
233                 return;
234         }
235
236         _port_matrix->remove_channel (sb, c);
237
238 }
239
240 void
241 PortMatrixRowLabels::rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
242 {
243         boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
244         if (!sb) {
245                 return;
246         }
247
248         _port_matrix->rename_channel (sb, c);
249 }