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 "ardour/bundle.h"
22 #include "ardour/types.h"
23 #include "port_matrix_body.h"
24 #include "port_matrix.h"
26 PortMatrixBody::PortMatrixBody (PortMatrix* p, Arrangement a)
28 _column_labels (this, a == TOP_AND_RIGHT ? PortMatrixColumnLabels::TOP : PortMatrixColumnLabels::BOTTOM),
29 _row_labels (p, this, a == BOTTOM_AND_LEFT ? PortMatrixRowLabels::LEFT : PortMatrixRowLabels::RIGHT),
34 _pointer_inside (false),
35 _column_ports (_port_matrix->type(), _port_matrix->offering_input()),
36 _row_ports (_port_matrix->type(), !_port_matrix->offering_input())
38 modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#00000"));
39 add_events (Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::POINTER_MOTION_MASK);
44 PortMatrixBody::on_expose_event (GdkEventExpose* event)
46 Gdk::Rectangle const exposure (
47 event->area.x, event->area.y, event->area.width, event->area.height
51 Gdk::Rectangle r = exposure;
52 r.intersect (_column_labels.parent_rectangle(), intersects);
57 get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
58 _column_labels.get_pixmap (get_window()->gobj()),
59 _column_labels.parent_to_component_x (r.get_x()),
60 _column_labels.parent_to_component_y (r.get_y()),
69 r.intersect (_row_labels.parent_rectangle(), intersects);
74 get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
75 _row_labels.get_pixmap (get_window()->gobj()),
76 _row_labels.parent_to_component_x (r.get_x()),
77 _row_labels.parent_to_component_y (r.get_y()),
86 r.intersect (_grid.parent_rectangle(), intersects);
91 get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
92 _grid.get_pixmap (get_window()->gobj()),
93 _grid.parent_to_component_x (r.get_x()),
94 _grid.parent_to_component_y (r.get_y()),
102 cairo_t* cr = gdk_cairo_create (get_window()->gobj());
103 _grid.draw_extra (cr);
104 _row_labels.draw_extra (cr);
105 _column_labels.draw_extra (cr);
112 PortMatrixBody::on_size_request (Gtk::Requisition *req)
114 std::pair<int, int> const col = _column_labels.dimensions ();
115 std::pair<int, int> const row = _row_labels.dimensions ();
116 std::pair<int, int> const grid = _grid.dimensions ();
118 req->width = std::max (col.first, grid.first + row.first);
119 req->height = col.second + grid.second;
123 PortMatrixBody::on_size_allocate (Gtk::Allocation& alloc)
125 Gtk::EventBox::on_size_allocate (alloc);
126 set_allocation (alloc);
128 _alloc_width = alloc.get_width ();
129 _alloc_height = alloc.get_height ();
131 compute_rectangles ();
132 _port_matrix->setup_scrollbars ();
136 PortMatrixBody::compute_rectangles ()
138 /* full sizes of components */
139 std::pair<uint32_t, uint32_t> const col = _column_labels.dimensions ();
140 std::pair<uint32_t, uint32_t> const row = _row_labels.dimensions ();
141 std::pair<uint32_t, uint32_t> const grid = _grid.dimensions ();
143 Gdk::Rectangle col_rect;
144 Gdk::Rectangle row_rect;
145 Gdk::Rectangle grid_rect;
147 if (_arrangement == TOP_AND_RIGHT) {
149 /* build from top left */
155 if (_alloc_width > col.first) {
156 col_rect.set_width (col.first);
158 col_rect.set_width (_alloc_width);
161 /* move down to y division */
164 if (_alloc_height > col.second) {
170 col_rect.set_height (y);
172 row_rect.set_height (_alloc_height - y);
174 grid_rect.set_height (_alloc_height - y);
176 /* move right to x division */
179 if (_alloc_width > (grid.first + row.first)) {
181 } else if (_alloc_width > row.first) {
182 x = _alloc_width - row.first;
185 grid_rect.set_width (x);
187 row_rect.set_width (_alloc_width - x);
190 } else if (_arrangement == BOTTOM_AND_LEFT) {
192 /* build from bottom right */
194 /* move left to x division */
197 if (_alloc_width > (grid.first + row.first)) {
199 } else if (_alloc_width > row.first) {
200 x = _alloc_width - row.first;
203 grid_rect.set_x (_alloc_width - x);
204 grid_rect.set_width (x);
205 col_rect.set_width (col.first - grid.first + x);
206 col_rect.set_x (_alloc_width - col_rect.get_width());
208 row_rect.set_width (std::min (_alloc_width - x, row.first));
209 row_rect.set_x (_alloc_width - x - row_rect.get_width());
211 /* move up to the y division */
214 if (_alloc_height > col.second) {
220 col_rect.set_y (_alloc_height - y);
221 col_rect.set_height (y);
223 grid_rect.set_height (std::min (grid.second, _alloc_height - y));
224 grid_rect.set_y (_alloc_height - y - grid_rect.get_height());
226 row_rect.set_height (grid_rect.get_height());
227 row_rect.set_y (grid_rect.get_y());
230 _row_labels.set_parent_rectangle (row_rect);
231 _column_labels.set_parent_rectangle (col_rect);
232 _grid.set_parent_rectangle (grid_rect);
236 PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column)
238 for (std::list<sigc::connection>::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) {
242 _bundle_connections.clear ();
245 _column_ports = column;
247 ARDOUR::BundleList r = _row_ports.bundles ();
248 for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) {
250 _bundle_connections.push_back (
251 (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels))
256 ARDOUR::BundleList c = _column_ports.bundles ();
257 for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) {
258 _bundle_connections.push_back (
259 (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels))
263 _column_labels.setup ();
264 _row_labels.setup ();
267 compute_rectangles ();
271 PortMatrixBody::full_scroll_width ()
273 return _grid.dimensions().first;
278 PortMatrixBody::alloc_scroll_width ()
280 return _grid.parent_rectangle().get_width();
284 PortMatrixBody::full_scroll_height ()
286 return _grid.dimensions().second;
290 PortMatrixBody::alloc_scroll_height ()
292 return _grid.parent_rectangle().get_height();
296 PortMatrixBody::set_xoffset (uint32_t xo)
303 PortMatrixBody::set_yoffset (uint32_t yo)
310 PortMatrixBody::on_button_press_event (GdkEventButton* ev)
312 if (Gdk::Region (_grid.parent_rectangle()).point_in (ev->x, ev->y)) {
315 _grid.parent_to_component_x (ev->x),
316 _grid.parent_to_component_y (ev->y),
320 } else if (Gdk::Region (_row_labels.parent_rectangle()).point_in (ev->x, ev->y)) {
322 _row_labels.button_press (
323 _row_labels.parent_to_component_x (ev->x),
324 _row_labels.parent_to_component_y (ev->y),
338 PortMatrixBody::rebuild_and_draw_grid ()
340 _grid.require_rebuild ();
345 PortMatrixBody::rebuild_and_draw_column_labels ()
347 _column_labels.require_rebuild ();
352 PortMatrixBody::rebuild_and_draw_row_labels ()
354 _row_labels.require_rebuild ();
359 PortMatrixBody::on_enter_notify_event (GdkEventCrossing* ev)
361 if (ev->type == GDK_ENTER_NOTIFY) {
362 _pointer_inside = true;
363 } else if (ev->type == GDK_LEAVE_NOTIFY) {
364 _pointer_inside = false;
371 PortMatrixBody::on_motion_notify_event (GdkEventMotion* ev)
373 if (_pointer_inside && Gdk::Region (_grid.parent_rectangle()).point_in (ev->x, ev->y)) {
374 _grid.mouseover_event (
375 _grid.parent_to_component_x (ev->x),
376 _grid.parent_to_component_y (ev->y)
384 PortMatrixBody::set_mouseover (PortMatrixNode const & n)
386 if (n == _mouseover) {
390 PortMatrixNode old = _mouseover;
393 _grid.mouseover_changed (old);
394 _row_labels.mouseover_changed (old);
395 _column_labels.mouseover_changed (old);