X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fport_matrix_body.cc;h=205e6d4bdd9934116784ca38c756c3530d538d3e;hb=2e1332f74f803a1be4c8bb4911266aef4b63f145;hp=3531712a5643c600fa72f2443537c4bfa109e5c8;hpb=49510ba1d7fc1c85e767c05f10f9481998ef94b0;p=ardour.git diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc index 3531712a56..205e6d4bdd 100644 --- a/gtk2_ardour/port_matrix_body.cc +++ b/gtk2_ardour/port_matrix_body.cc @@ -22,22 +22,32 @@ #include "ardour/types.h" #include "port_matrix_body.h" #include "port_matrix.h" +#include "port_matrix_column_labels.h" +#include "port_matrix_row_labels.h" +#include "port_matrix_grid.h" -PortMatrixBody::PortMatrixBody (PortMatrix* p, Arrangement a) - : _port_matrix (p), - _column_labels (this, a == TOP_AND_RIGHT ? PortMatrixColumnLabels::TOP : PortMatrixColumnLabels::BOTTOM), - _row_labels (p, this, a == BOTTOM_AND_LEFT ? PortMatrixRowLabels::LEFT : PortMatrixRowLabels::RIGHT), - _grid (p, this), - _arrangement (a), +PortMatrixBody::PortMatrixBody (PortMatrix* p) + : _matrix (p), _xoffset (0), _yoffset (0), - _column_ports (_port_matrix->type(), _port_matrix->offering_input()), - _row_ports (_port_matrix->type(), !_port_matrix->offering_input()) + _mouse_over_grid (false) { + _column_labels = new PortMatrixColumnLabels (p, this); + _row_labels = new PortMatrixRowLabels (p, this); + _grid = new PortMatrixGrid (p, this); + modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#00000")); + add_events (Gdk::LEAVE_NOTIFY_MASK | Gdk::POINTER_MOTION_MASK); } +PortMatrixBody::~PortMatrixBody () +{ + delete _column_labels; + delete _row_labels; + delete _grid; +} + bool PortMatrixBody::on_expose_event (GdkEventExpose* event) { @@ -46,16 +56,21 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event) ); bool intersects; + Gdk::Rectangle r = exposure; - r.intersect (_column_labels_rect, intersects); + /* the get_pixmap call may cause things to be rerendered and sizes to change, + so fetch the pixmap before calculating where to put it */ + GdkPixmap* p = _column_labels->get_pixmap (get_window()->gobj()); + r.intersect (_column_labels->parent_rectangle(), intersects); if (intersects) { + gdk_draw_drawable ( get_window()->gobj(), get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(), - _column_labels.get_pixmap (get_window()->gobj()), - r.get_x() - _column_labels_rect.get_x() + _xoffset, - r.get_y() - _column_labels_rect.get_y(), + p, + _column_labels->parent_to_component_x (r.get_x()), + _column_labels->parent_to_component_y (r.get_y()), r.get_x(), r.get_y(), r.get_width(), @@ -64,15 +79,16 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event) } r = exposure; - r.intersect (_row_labels_rect, intersects); + p = _row_labels->get_pixmap (get_window()->gobj()); + r.intersect (_row_labels->parent_rectangle(), intersects); if (intersects) { gdk_draw_drawable ( get_window()->gobj(), get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(), - _row_labels.get_pixmap (get_window()->gobj()), - r.get_x() - _row_labels_rect.get_x(), - r.get_y() - _row_labels_rect.get_y() + _yoffset, + p, + _row_labels->parent_to_component_x (r.get_x()), + _row_labels->parent_to_component_y (r.get_y()), r.get_x(), r.get_y(), r.get_width(), @@ -81,15 +97,16 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event) } r = exposure; - r.intersect (_grid_rect, intersects); + p = _grid->get_pixmap (get_window()->gobj()); + r.intersect (_grid->parent_rectangle(), intersects); if (intersects) { gdk_draw_drawable ( get_window()->gobj(), get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(), - _grid.get_pixmap (get_window()->gobj()), - r.get_x() - _grid_rect.get_x() + _xoffset, - r.get_y() - _grid_rect.get_y() + _yoffset, + p, + _grid->parent_to_component_x (r.get_x()), + _grid->parent_to_component_y (r.get_y()), r.get_x(), r.get_y(), r.get_width(), @@ -97,53 +114,82 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event) ); } + cairo_t* cr = gdk_cairo_create (get_window()->gobj()); + + cairo_save (cr); + set_cairo_clip (cr, _grid->parent_rectangle ()); + _grid->draw_extra (cr); + cairo_restore (cr); + + cairo_save (cr); + set_cairo_clip (cr, _row_labels->parent_rectangle ()); + _row_labels->draw_extra (cr); + cairo_restore (cr); + + cairo_save (cr); + set_cairo_clip (cr, _column_labels->parent_rectangle ()); + _column_labels->draw_extra (cr); + cairo_restore (cr); + + cairo_destroy (cr); + return true; } void PortMatrixBody::on_size_request (Gtk::Requisition *req) { - std::pair const col = _column_labels.dimensions (); - std::pair const row = _row_labels.dimensions (); - std::pair const grid = _grid.dimensions (); + std::pair const col = _column_labels->dimensions (); + std::pair const row = _row_labels->dimensions (); + std::pair const grid = _grid->dimensions (); - req->width = std::max (col.first, grid.first + row.first); - req->height = col.second + grid.second; + /* don't ask for the maximum size of our contents, otherwise GTK won't + let the containing window shrink below this size */ + + /* XXX these shouldn't be hard-coded */ + int const min_width = 512; + int const min_height = 512; + + req->width = std::min (min_width, std::max (col.first, grid.first + row.first)); + req->height = std::min (min_height / _matrix->min_height_divisor(), col.second + grid.second); } void PortMatrixBody::on_size_allocate (Gtk::Allocation& alloc) { Gtk::EventBox::on_size_allocate (alloc); - set_allocation (alloc); _alloc_width = alloc.get_width (); _alloc_height = alloc.get_height (); compute_rectangles (); - _port_matrix->setup_scrollbars (); + _matrix->setup_scrollbars (); } void PortMatrixBody::compute_rectangles () { /* full sizes of components */ - std::pair const col = _column_labels.dimensions (); - std::pair const row = _row_labels.dimensions (); - std::pair const grid = _grid.dimensions (); + std::pair const col = _column_labels->dimensions (); + std::pair const row = _row_labels->dimensions (); + std::pair const grid = _grid->dimensions (); + + Gdk::Rectangle col_rect; + Gdk::Rectangle row_rect; + Gdk::Rectangle grid_rect; - if (_arrangement == TOP_AND_RIGHT) { + if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) { /* build from top left */ - _column_labels_rect.set_x (0); - _column_labels_rect.set_y (0); - _grid_rect.set_x (0); + col_rect.set_x (0); + col_rect.set_y (0); + grid_rect.set_x (0); if (_alloc_width > col.first) { - _column_labels_rect.set_width (col.first); + col_rect.set_width (col.first); } else { - _column_labels_rect.set_width (_alloc_width); + col_rect.set_width (_alloc_width); } /* move down to y division */ @@ -155,11 +201,11 @@ PortMatrixBody::compute_rectangles () y = _alloc_height; } - _column_labels_rect.set_height (y); - _row_labels_rect.set_y (y); - _row_labels_rect.set_height (_alloc_height - y); - _grid_rect.set_y (y); - _grid_rect.set_height (_alloc_height - y); + col_rect.set_height (y); + row_rect.set_y (y); + row_rect.set_height (_alloc_height - y); + grid_rect.set_y (y); + grid_rect.set_height (_alloc_height - y); /* move right to x division */ @@ -170,12 +216,12 @@ PortMatrixBody::compute_rectangles () x = _alloc_width - row.first; } - _grid_rect.set_width (x); - _row_labels_rect.set_x (x); - _row_labels_rect.set_width (_alloc_width - x); + grid_rect.set_width (x); + row_rect.set_x (x); + row_rect.set_width (_alloc_width - x); - } else if (_arrangement == BOTTOM_AND_LEFT) { + } else if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) { /* build from bottom right */ @@ -188,13 +234,13 @@ PortMatrixBody::compute_rectangles () x = _alloc_width - row.first; } - _grid_rect.set_x (_alloc_width - x); - _grid_rect.set_width (x); - _column_labels_rect.set_width (col.first - grid.first + x); - _column_labels_rect.set_x (_alloc_width - _column_labels_rect.get_width()); + grid_rect.set_x (_alloc_width - x); + grid_rect.set_width (x); + col_rect.set_width (col.first - grid.first + x); + col_rect.set_x (_alloc_width - col_rect.get_width()); - _row_labels_rect.set_width (std::min (_alloc_width - x, row.first)); - _row_labels_rect.set_x (_alloc_width - x - _row_labels_rect.get_width()); + row_rect.set_width (std::min (_alloc_width - x, row.first)); + row_rect.set_x (_alloc_width - x - row_rect.get_width()); /* move up to the y division */ @@ -205,76 +251,80 @@ PortMatrixBody::compute_rectangles () y = _alloc_height; } - _column_labels_rect.set_y (_alloc_height - y); - _column_labels_rect.set_height (y); + col_rect.set_y (_alloc_height - y); + col_rect.set_height (y); - _grid_rect.set_height (std::min (grid.second, _alloc_height - y)); - _grid_rect.set_y (_alloc_height - y - _grid_rect.get_height()); - - _row_labels_rect.set_height (_grid_rect.get_height()); - _row_labels_rect.set_y (_grid_rect.get_y()); + grid_rect.set_height (std::min (grid.second, _alloc_height - y)); + grid_rect.set_y (_alloc_height - y - grid_rect.get_height()); + row_rect.set_height (grid_rect.get_height()); + row_rect.set_y (grid_rect.get_y()); } + + _row_labels->set_parent_rectangle (row_rect); + _column_labels->set_parent_rectangle (col_rect); + _grid->set_parent_rectangle (grid_rect); } void -PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column) +PortMatrixBody::setup () { + /* Discard any old connections to bundles */ + for (std::list::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) { i->disconnect (); } - _bundle_connections.clear (); - - _row_ports = row; - _column_ports = column; - ARDOUR::BundleList r = _row_ports.bundles (); + /* Connect to bundles so that we find out when their names change */ + + ARDOUR::BundleList r = _matrix->rows()->bundles (); for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) { _bundle_connections.push_back ( - (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels)) + (*i)->Changed.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels))) ); } - ARDOUR::BundleList c = _column_ports.bundles (); + ARDOUR::BundleList c = _matrix->columns()->bundles (); for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) { _bundle_connections.push_back ( - (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels)) + (*i)->Changed.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels))) ); } - _column_labels.setup (); - _row_labels.setup (); - _grid.setup (); + _column_labels->setup (); + _row_labels->setup (); + _grid->setup (); + set_mouseover (PortMatrixNode ()); compute_rectangles (); } uint32_t PortMatrixBody::full_scroll_width () { - return _grid.dimensions().first; + return _grid->dimensions().first; } uint32_t PortMatrixBody::alloc_scroll_width () { - return _grid_rect.get_width(); + return _grid->parent_rectangle().get_width(); } uint32_t PortMatrixBody::full_scroll_height () { - return _grid.dimensions().second; + return _grid->dimensions().second; } uint32_t PortMatrixBody::alloc_scroll_height () { - return _grid_rect.get_height(); + return _grid->parent_rectangle().get_height(); } void @@ -294,25 +344,42 @@ PortMatrixBody::set_yoffset (uint32_t yo) bool PortMatrixBody::on_button_press_event (GdkEventButton* ev) { - if (Gdk::Region (_grid_rect).point_in (ev->x, ev->y)) { + if (Gdk::Region (_grid->parent_rectangle()).point_in (ev->x, ev->y)) { - _grid.button_press ( - ev->x - _grid_rect.get_x() + _xoffset, - ev->y - _grid_rect.get_y() + _yoffset, + _grid->button_press ( + _grid->parent_to_component_x (ev->x), + _grid->parent_to_component_y (ev->y), ev->button ); - } else if (Gdk::Region (_row_labels_rect).point_in (ev->x, ev->y)) { + } else if (Gdk::Region (_row_labels->parent_rectangle()).point_in (ev->x, ev->y)) { - _row_labels.button_press ( - ev->x - _row_labels_rect.get_x(), - ev->y - _row_labels_rect.get_y() + _yoffset, + _row_labels->button_press ( + _row_labels->parent_to_component_x (ev->x), + _row_labels->parent_to_component_y (ev->y), ev->button, ev->time ); - } else { - - return false; + } else if (Gdk::Region (_column_labels->parent_rectangle()).point_in (ev->x, ev->y)) { + + _column_labels->button_press ( + _column_labels->parent_to_component_x (ev->x), + _column_labels->parent_to_component_y (ev->y), + ev->button, ev->time + ); + } + + return true; +} + +bool +PortMatrixBody::on_button_release_event (GdkEventButton* ev) +{ + if (Gdk::Region (_row_labels->parent_rectangle()).point_in (ev->x, ev->y) || + Gdk::Region (_column_labels->parent_rectangle()).point_in (ev->x, ev->y)) { + + _row_labels->clear_channel_highlights (); + _column_labels->clear_channel_highlights (); } @@ -322,20 +389,122 @@ PortMatrixBody::on_button_press_event (GdkEventButton* ev) void PortMatrixBody::rebuild_and_draw_grid () { - _grid.require_rebuild (); + _grid->require_rebuild (); queue_draw (); } void PortMatrixBody::rebuild_and_draw_column_labels () { - _column_labels.require_rebuild (); + _column_labels->require_rebuild (); queue_draw (); } void PortMatrixBody::rebuild_and_draw_row_labels () { - _row_labels.require_rebuild (); + _row_labels->require_rebuild (); queue_draw (); } + +bool +PortMatrixBody::on_leave_notify_event (GdkEventCrossing* ev) +{ + if (ev->type == GDK_LEAVE_NOTIFY) { + set_mouseover (PortMatrixNode ()); + } + + return true; +} + +bool +PortMatrixBody::on_motion_notify_event (GdkEventMotion* ev) +{ + if (Gdk::Region (_grid->parent_rectangle()).point_in (ev->x, ev->y)) { + _grid->mouseover_event ( + _grid->parent_to_component_x (ev->x), + _grid->parent_to_component_y (ev->y) + ); + _mouse_over_grid = true; + } else { + if (_mouse_over_grid) { + set_mouseover (PortMatrixNode ()); + _mouse_over_grid = false; + } + } + + return true; +} + +void +PortMatrixBody::set_mouseover (PortMatrixNode const & n) +{ + if (n == _mouseover) { + return; + } + + PortMatrixNode old = _mouseover; + _mouseover = n; + + _grid->mouseover_changed (old); + _row_labels->mouseover_changed (old); + _column_labels->mouseover_changed (old); +} + + + +void +PortMatrixBody::highlight_associated_channels (int dim, uint32_t N) +{ + ARDOUR::BundleChannel bc[2]; + + ARDOUR::BundleList const a = _matrix->ports(dim)->bundles (); + for (ARDOUR::BundleList::const_iterator i = a.begin(); i != a.end(); ++i) { + if (N < (*i)->nchannels ()) { + bc[dim] = ARDOUR::BundleChannel (*i, N); + break; + } else { + N -= (*i)->nchannels (); + } + } + + if (!bc[dim].bundle) { + return; + } + + if (dim == _matrix->column_index()) { + _column_labels->add_channel_highlight (bc[dim]); + } else { + _row_labels->add_channel_highlight (bc[dim]); + } + + ARDOUR::BundleList const b = _matrix->ports(1 - dim)->bundles (); + + for (ARDOUR::BundleList::const_iterator i = b.begin(); i != b.end(); ++i) { + for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { + bc[1 - dim] = ARDOUR::BundleChannel (*i, j); + if (_matrix->get_state (bc) == PortMatrix::ASSOCIATED) { + if (dim == _matrix->column_index()) { + _row_labels->add_channel_highlight (bc[1 - dim]); + } else { + _column_labels->add_channel_highlight (bc[1 - dim]); + } + } + } + } +} + +void +PortMatrixBody::set_cairo_clip (cairo_t* cr, Gdk::Rectangle const & r) const +{ + cairo_rectangle (cr, r.get_x(), r.get_y(), r.get_width(), r.get_height()); + cairo_clip (cr); +} + +void +PortMatrixBody::component_size_changed () +{ + compute_rectangles (); + _matrix->setup_scrollbars (); +} +