switch to using boost::signals2 instead of sigc++, at least for libardour. not finish...
[ardour.git] / gtk2_ardour / port_matrix_component.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 "port_matrix_component.h"
21 #include "port_matrix.h"
22 #include "port_matrix_body.h"
23
24 using namespace std;
25
26 /** Constructor.
27  *  @param p Port matrix that we're in.
28  */
29 PortMatrixComponent::PortMatrixComponent (PortMatrix* m, PortMatrixBody* b)
30         : _matrix (m),
31           _body (b),
32           _pixmap (0),
33           _render_required (true),
34           _dimension_computation_required (true)
35 {
36
37 }
38
39 /** Destructor */
40 PortMatrixComponent::~PortMatrixComponent ()
41 {
42         if (_pixmap) {
43                 gdk_pixmap_unref (_pixmap);
44         }
45 }
46
47 void
48 PortMatrixComponent::setup ()
49 {
50         _dimension_computation_required = true;
51         _render_required = true;
52 }
53
54 GdkPixmap *
55 PortMatrixComponent::get_pixmap (GdkDrawable *drawable)
56 {
57         if (_render_required) {
58
59                 if (_dimension_computation_required) {
60                         compute_dimensions ();
61                         _dimension_computation_required = false;
62                         _body->component_size_changed ();
63                 }
64
65                 /* we may be zero width or height; if so, just
66                    use the smallest allowable pixmap */
67                 if (_width == 0) {
68                         _width = 1;
69                 }
70                 if (_height == 0) {
71                         _height = 1;
72                 }
73
74                 /* make a pixmap of the right size */
75                 if (_pixmap) {
76                         gdk_pixmap_unref (_pixmap);
77                 }
78                 _pixmap = gdk_pixmap_new (drawable, _width, _height, -1);
79
80                 /* render */
81                 cairo_t* cr = gdk_cairo_create (_pixmap);
82                 render (cr);
83                 cairo_destroy (cr);
84
85                 _render_required = false;
86         }
87
88         return _pixmap;
89 }
90
91 void
92 PortMatrixComponent::set_source_rgb (cairo_t *cr, Gdk::Color const & c)
93 {
94         cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
95 }
96
97 void
98 PortMatrixComponent::set_source_rgba (cairo_t *cr, Gdk::Color const & c, double a)
99 {
100         cairo_set_source_rgba (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p(), a);
101 }
102
103 pair<uint32_t, uint32_t>
104 PortMatrixComponent::dimensions ()
105 {
106         if (_dimension_computation_required) {
107                 compute_dimensions ();
108                 _dimension_computation_required = false;
109                 _body->component_size_changed ();
110         }
111
112         return make_pair (_width, _height);
113 }
114
115 Gdk::Color
116 PortMatrixComponent::background_colour ()
117 {
118         return _matrix->get_style()->get_bg (Gtk::STATE_NORMAL);
119 }
120
121 /** @param g Group.
122  *  @return Visible size of the group in grid units, taking visibility and show_only_bundles into account.
123  */
124 uint32_t
125 PortMatrixComponent::group_size (boost::shared_ptr<const PortGroup> g) const
126 {
127         uint32_t s = 0;
128
129         PortGroup::BundleList const & bundles = g->bundles ();
130         if (_matrix->show_only_bundles()) {
131                 s = bundles.size();
132         } else {
133                 for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
134                         s += (*i)->bundle->nchannels();
135                 }
136         }
137
138         return s;
139 }
140
141 /** @param bc Channel.
142  *  @param groups List of groups.
143  *  @return Position of bc in groups in grid units, taking show_only_bundles into account.
144  */
145 uint32_t
146 PortMatrixComponent::channel_to_position (ARDOUR::BundleChannel bc, boost::shared_ptr<const PortGroup> group) const
147 {
148         uint32_t p = 0;
149
150         PortGroup::BundleList const & bundles = group->bundles ();
151
152         for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
153
154                 if ((*i)->bundle == bc.bundle) {
155
156                         /* found the bundle */
157                         
158                         if (_matrix->show_only_bundles()) {
159                                 return p;
160                         } else {
161                                 return p + bc.channel;
162                         }
163                         
164                 }
165
166                 /* move past this bundle */
167                 
168                 if (_matrix->show_only_bundles()) {
169                         p += 1;
170                 } else {
171                         p += (*i)->bundle->nchannels ();
172                 }
173         }
174
175         return 0;
176 }
177
178
179 ARDOUR::BundleChannel
180 PortMatrixComponent::position_to_channel (double p, double, boost::shared_ptr<const PortGroup> group) const
181 {
182         p /= grid_spacing ();
183         
184         PortGroup::BundleList const & bundles = group->bundles ();
185         for (PortGroup::BundleList::const_iterator j = bundles.begin(); j != bundles.end(); ++j) {
186
187                 if (_matrix->show_only_bundles()) {
188                         
189                         if (p < 1) {
190                                 return ARDOUR::BundleChannel ((*j)->bundle, -1);
191                         } else {
192                                 p -= 1;
193                         }
194                         
195                 } else {
196                         
197                         uint32_t const s = (*j)->bundle->nchannels ();
198                         if (p < s) {
199                                 return ARDOUR::BundleChannel ((*j)->bundle, p);
200                         } else {
201                                 p -= s;
202                         }
203                         
204                 }
205                 
206         }
207         
208         return ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), -1);
209 }