diff --git a/doc/port_matrix/cairo_text.svg b/doc/port_matrix/cairo_text.svg new file mode 100644 index 0000000000..d623ccc01e --- /dev/null +++ b/doc/port_matrix/cairo_text.svg @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ABCjpq + + + y + + + + + + origin + + + + y_bearing + + height + ABCjpq + + + + origin + + cairo_rotate (c, - M_PI / 4); + + diff --git a/doc/port_matrix/top_column_bundle_name.svg b/doc/port_matrix/top_column_bundle_name.svg new file mode 100644 index 0000000000..d5669c3e8d --- /dev/null +++ b/doc/port_matrix/top_column_bundle_name.svg @@ -0,0 +1,801 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Bundle name (top) + ϑ + + + h + + y + + + g + + x + + + p + + ϑ + + d + + q + Port name (bottom) + + + + f + + diff --git a/doc/port_matrix/top_column_port_name.svg b/doc/port_matrix/top_column_port_name.svg new file mode 100644 index 0000000000..0a05f15b85 --- /dev/null +++ b/doc/port_matrix/top_column_port_name.svg @@ -0,0 +1,670 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Column name (top) + ϑ + + + g + + h + + + y + + x + + p + + ϑ + + d + + q + Bundle name (bottom) + + diff --git a/gtk2_ardour/ardour3_ui_dark.rc.in b/gtk2_ardour/ardour3_ui_dark.rc.in index 393ce3c841..0e81e576e9 100644 --- a/gtk2_ardour/ardour3_ui_dark.rc.in +++ b/gtk2_ardour/ardour3_ui_dark.rc.in @@ -1669,3 +1669,4 @@ widget "*OddPortGroups" style:highest "odd_port_groups" widget "*EvenPortGroups" style:highest "even_port_groups" widget "*MidiListView*" style:highest "white_tree_view" widget "*ProcessorSelector*" style:highest "processor_list_display" +widget "*PortMatrixLabel*" style:highest "small_text" \ No newline at end of file diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index 3fe27b4fdf..58c8a099bd 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -60,33 +60,41 @@ PortMatrix::PortMatrix (Window* parent, Session* session, DataType type) _ignore_notebook_page_selected (false) { _body = new PortMatrixBody (this); + _body->DimensionsChanged.connect (mem_fun (*this, &PortMatrix::body_dimensions_changed)); - _vbox.pack_start (_vnotebook); - _vbox.pack_start (_vlabel); - _hbox.pack_start (_hnotebook); - _hbox.pack_start (_hlabel); + _vbox.pack_start (_vspacer, false, false); + _vbox.pack_start (_vnotebook, false, false); + _vbox.pack_start (_vlabel, true, true); + _hbox.pack_start (_hspacer, false, false); + _hbox.pack_start (_hnotebook, false, false); + _hbox.pack_start (_hlabel, true, true); _vnotebook.signal_switch_page().connect (mem_fun (*this, &PortMatrix::v_page_selected)); _vnotebook.property_tab_border() = 4; + _vnotebook.set_name (X_("PortMatrixLabel")); _hnotebook.signal_switch_page().connect (mem_fun (*this, &PortMatrix::h_page_selected)); _hnotebook.property_tab_border() = 4; + _hnotebook.set_name (X_("PortMatrixLabel")); for (int i = 0; i < 2; ++i) { _ports[i].set_type (type); } _vlabel.set_use_markup (); - _vlabel.set_alignment (0.5, 0); + _vlabel.set_alignment (1, 1); _vlabel.set_padding (4, 16); + _vlabel.set_name (X_("PortMatrixLabel")); _hlabel.set_use_markup (); - _hlabel.set_alignment (0, 0.5); + _hlabel.set_alignment (1, 0.5); _hlabel.set_padding (16, 4); + _hlabel.set_name (X_("PortMatrixLabel")); _body->show (); _vbox.show (); _hbox.show (); _vlabel.show (); _hlabel.show (); + _hspacer.show (); } PortMatrix::~PortMatrix () @@ -106,7 +114,6 @@ void PortMatrix::init () { select_arrangement (); - setup_notebooks (); if (!_ports[0].empty()) { _visible_ports[0] = *_ports[0].begin(); @@ -674,15 +681,15 @@ PortMatrix::setup_notebooks () } if (_hnotebook.get_n_pages() <= 1) { - _hnotebook.hide (); + _hbox.hide (); } else { - _hnotebook.show (); + _vbox.show (); } if (_vnotebook.get_n_pages() <= 1) { - _vnotebook.hide (); + _vbox.hide (); } else { - _vnotebook.show (); + _vbox.show (); } } @@ -751,3 +758,16 @@ PortMatrix::session_going_away () { _session = 0; } + +void +PortMatrix::body_dimensions_changed () +{ + _hspacer.set_size_request (_body->column_labels_border_x (), -1); + if (_arrangement == TOP_TO_RIGHT) { + _vspacer.set_size_request (-1, _body->column_labels_height ()); + _vspacer.show (); + } else { + _vspacer.hide (); + } + +} diff --git a/gtk2_ardour/port_matrix.h b/gtk2_ardour/port_matrix.h index 268c898684..f228a4101f 100644 --- a/gtk2_ardour/port_matrix.h +++ b/gtk2_ardour/port_matrix.h @@ -179,6 +179,7 @@ private: void v_page_selected (GtkNotebookPage *, guint); void h_page_selected (GtkNotebookPage *, guint); void route_processors_changed (ARDOUR::RouteProcessorChange); + void body_dimensions_changed (); void session_going_away (); Gtk::Window* _parent; @@ -196,6 +197,8 @@ private: Gtk::Label _hlabel; Gtk::VBox _vbox; Gtk::HBox _hbox; + Gtk::Label _hspacer; + Gtk::Label _vspacer; Gtk::Menu* _menu; Arrangement _arrangement; int _row_index; diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc index 41faaa31ef..72da040ed7 100644 --- a/gtk2_ardour/port_matrix_body.cc +++ b/gtk2_ardour/port_matrix_body.cc @@ -34,6 +34,8 @@ PortMatrixBody::PortMatrixBody (PortMatrix* p) _alloc_height (0), _xoffset (0), _yoffset (0), + _column_labels_border_x (0), + _column_labels_height (0), _ignore_component_size_changed (false) { _column_labels = new PortMatrixColumnLabels (p, this); @@ -58,7 +60,10 @@ PortMatrixBody::~PortMatrixBody () bool PortMatrixBody::on_expose_event (GdkEventExpose* event) { - if (_matrix->visible_columns()->bundles().empty() || _matrix->visible_rows()->bundles().empty()) { + if ( + _matrix->visible_columns() == 0 || _matrix->visible_rows() == 0 || + _matrix->visible_columns()->bundles().empty() || _matrix->visible_rows()->bundles().empty() + ) { /* nothing to connect */ @@ -171,7 +176,7 @@ PortMatrixBody::compute_rectangles () { /* full sizes of components */ pair const col = _column_labels->dimensions (); - uint32_t col_overhang = _column_labels->overhang (); + uint32_t const col_overhang = _column_labels->overhang (); pair const row = _row_labels->dimensions (); pair const grid = _grid->dimensions (); @@ -182,6 +187,7 @@ PortMatrixBody::compute_rectangles () if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) { col_rect.set_x (0); + _column_labels_border_x = col_overhang; col_rect.set_y (0); grid_rect.set_x (0); @@ -222,13 +228,17 @@ PortMatrixBody::compute_rectangles () col_rect.set_width (grid_rect.get_width () + col_overhang); col_rect.set_x (row_rect.get_width() + grid_rect.get_width() - col_rect.get_width()); + _column_labels_border_x = col_rect.get_x () >= 0 ? col_rect.get_x () : 0; col_rect.set_y (row_rect.get_height()); - } + _column_labels_height = col_rect.get_height (); + _row_labels->set_parent_rectangle (row_rect); _column_labels->set_parent_rectangle (col_rect); _grid->set_parent_rectangle (grid_rect); + + DimensionsChanged (); /* EMIT SIGNAL */ } void @@ -243,7 +253,7 @@ PortMatrixBody::setup () /* Connect to bundles so that we find out when their names change */ - PortGroup::BundleList r = _matrix->rows()->bundles (); + PortGroup::BundleList r = _matrix->visible_rows()->bundles (); for (PortGroup::BundleList::iterator i = r.begin(); i != r.end(); ++i) { _bundle_connections.push_back ( @@ -252,7 +262,7 @@ PortMatrixBody::setup () } - PortGroup::BundleList c = _matrix->columns()->bundles (); + PortGroup::BundleList c = _matrix->visible_columns()->bundles (); for (PortGroup::BundleList::iterator i = c.begin(); i != c.end(); ++i) { _bundle_connections.push_back ( i->bundle->Changed.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels))) @@ -295,6 +305,7 @@ PortMatrixBody::alloc_scroll_height () return _grid->parent_rectangle().get_height(); } +/** Set x offset (for scrolling) */ void PortMatrixBody::set_xoffset (uint32_t xo) { @@ -302,6 +313,7 @@ PortMatrixBody::set_xoffset (uint32_t xo) queue_draw (); } +/** Set y offset (for scrolling) */ void PortMatrixBody::set_yoffset (uint32_t yo) { @@ -494,3 +506,16 @@ PortMatrixBody::max_size () const return make_pair (std::max (row.first, _column_labels->overhang()) + grid.first, col.second + grid.second); } + +/** @return x position at which the column labels meet the border of the matrix */ +uint32_t +PortMatrixBody::column_labels_border_x () const +{ + return _column_labels_border_x; +} + +uint32_t +PortMatrixBody::column_labels_height () const +{ + return _column_labels_height; +} diff --git a/gtk2_ardour/port_matrix_body.h b/gtk2_ardour/port_matrix_body.h index c8dc0cce29..0b8facda45 100644 --- a/gtk2_ardour/port_matrix_body.h +++ b/gtk2_ardour/port_matrix_body.h @@ -67,6 +67,11 @@ public: void component_size_changed (); std::pair max_size () const; + uint32_t column_labels_border_x () const; + uint32_t column_labels_height () const; + + sigc::signal DimensionsChanged; + protected: bool on_expose_event (GdkEventExpose *); void on_size_request (Gtk::Requisition *); @@ -91,11 +96,10 @@ private: uint32_t _alloc_width; ///< allocated width uint32_t _alloc_height; ///< allocated height - Gdk::Rectangle _column_labels_rect; - Gdk::Rectangle _row_labels_rect; - Gdk::Rectangle _grid_rect; uint32_t _xoffset; uint32_t _yoffset; + uint32_t _column_labels_border_x; + uint32_t _column_labels_height; std::list _mouseover; bool _ignore_component_size_changed; diff --git a/gtk2_ardour/port_matrix_column_labels.cc b/gtk2_ardour/port_matrix_column_labels.cc index 2aeb084b9f..c10bb01a2b 100644 --- a/gtk2_ardour/port_matrix_column_labels.cc +++ b/gtk2_ardour/port_matrix_column_labels.cc @@ -45,10 +45,6 @@ PortMatrixColumnLabels::compute_dimensions () _longest_bundle_name = 0; /* width of the longest channel name */ _longest_channel_name = 0; - /* height of highest bit of text (apart from group names) */ - _highest_text = 0; - /* width of the whole thing */ - _width = 0; /* Compute dimensions using all port groups, so that we allow for the largest and hence we can change between visible groups without the size of the labels jumping around. @@ -64,10 +60,6 @@ PortMatrixColumnLabels::compute_dimensions () _longest_bundle_name = ext.width; } - if (ext.height > _highest_text) { - _highest_text = ext.height; - } - for (uint32_t k = 0; k < j->bundle->nchannels (); ++k) { cairo_text_extents ( @@ -79,14 +71,21 @@ PortMatrixColumnLabels::compute_dimensions () if (ext.width > _longest_channel_name) { _longest_channel_name = ext.width; } - - if (ext.height > _highest_text) { - _highest_text = ext.height; - } } } + } - _width += group_size (*i) * grid_spacing (); + /* height metrics */ + cairo_text_extents_t ext; + cairo_text_extents (cr, X_("AQRjpy"), &ext); + _text_height = ext.height; + _descender_height = ext.height + ext.y_bearing; + + /* width of the whole thing */ + if (_matrix->visible_columns()) { + _width = group_size (_matrix->visible_columns()) * grid_spacing (); + } else { + _width = 0; } cairo_destroy (cr); @@ -99,7 +98,7 @@ PortMatrixColumnLabels::compute_dimensions () a += _longest_channel_name; } - _height = a * sin (angle()) + _highest_text * cos (angle()); + _height = a * sin (angle()) + _text_height * cos (angle()); _overhang = _height / tan (angle ()); _width += _overhang; } @@ -108,7 +107,7 @@ double PortMatrixColumnLabels::basic_text_x_pos (int) const { return grid_spacing() / 2 + - _highest_text / (2 * sin (angle ())); + _text_height / (2 * sin (angle ())); } void @@ -278,6 +277,8 @@ PortMatrixColumnLabels::render_bundle_name ( set_source_rgb (cr, text_colour()); + double const q = ((grid_spacing() * sin (angle())) - _text_height) / 2 + _descender_height; + if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) { double rl = 0; @@ -288,16 +289,16 @@ PortMatrixColumnLabels::render_bundle_name ( } cairo_move_to ( cr, - xoff + basic_text_x_pos (0) + rl * cos (angle()), - yoff + _height - rl * sin (angle()) + xoff + grid_spacing() - q * sin (angle ()) + rl * cos (angle()), + yoff + _height - q * cos (angle ()) - rl * sin (angle()) ); } else { cairo_move_to ( cr, - xoff + basic_text_x_pos (0) + name_pad() * cos (angle ()), - yoff + _height - name_pad() * sin (angle()) + xoff + grid_spacing() - q * sin (angle ()), + yoff + _height - q * cos (angle ()) ); } @@ -328,21 +329,24 @@ PortMatrixColumnLabels::render_channel_name ( set_source_rgb (cr, text_colour()); + double const q = ((grid_spacing() * sin (angle())) - _text_height) / 2 + _descender_height; + if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) { cairo_move_to ( cr, - xoff + basic_text_x_pos(bc.channel), - yoff + _height - name_pad() * sin (angle()) + xoff + grid_spacing() - q * sin (angle ()), + yoff + _height - q * cos (angle ()) ); + } else { double const rl = 3 * name_pad() + _longest_bundle_name; cairo_move_to ( cr, - xoff + basic_text_x_pos(bc.channel) + rl * cos (angle ()), - yoff + _height - rl * sin (angle()) + xoff + grid_spacing() - q * sin (angle ()) + rl * cos (angle ()), + yoff + _height - q * cos (angle ()) - rl * sin (angle()) ); } @@ -453,7 +457,7 @@ PortMatrixColumnLabels::motion (double x, double y) return; } - uint32_t const bh = _longest_channel_name * sin (angle ()) + _highest_text / cos (angle ()); + uint32_t const bh = _longest_channel_name * sin (angle ()) + _text_height / cos (angle ()); if ( (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && y > bh) || diff --git a/gtk2_ardour/port_matrix_column_labels.h b/gtk2_ardour/port_matrix_column_labels.h index 0c725a0803..9ff59ec33b 100644 --- a/gtk2_ardour/port_matrix_column_labels.h +++ b/gtk2_ardour/port_matrix_column_labels.h @@ -64,7 +64,8 @@ private: double _longest_bundle_name; double _longest_channel_name; - double _highest_text; + double _text_height; + double _descender_height; uint32_t _overhang; }; diff --git a/gtk2_ardour/port_matrix_grid.cc b/gtk2_ardour/port_matrix_grid.cc index 5136285e48..3e5d171690 100644 --- a/gtk2_ardour/port_matrix_grid.cc +++ b/gtk2_ardour/port_matrix_grid.cc @@ -41,16 +41,16 @@ PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b) void PortMatrixGrid::compute_dimensions () { - if (_matrix->visible_columns() == 0) { - _width = 0; - } else { + if (_matrix->visible_columns()) { _width = group_size (_matrix->visible_columns()) * grid_spacing (); + } else { + _width = 0; } - if (_matrix->visible_rows() == 0) { - _height = 0; - } else { + if (_matrix->visible_rows()) { _height = group_size (_matrix->visible_rows()) * grid_spacing (); + } else { + _height = 0; } } diff --git a/gtk2_ardour/port_matrix_row_labels.cc b/gtk2_ardour/port_matrix_row_labels.cc index 6528f31d76..9878dc23dd 100644 --- a/gtk2_ardour/port_matrix_row_labels.cc +++ b/gtk2_ardour/port_matrix_row_labels.cc @@ -44,7 +44,6 @@ PortMatrixRowLabels::compute_dimensions () _longest_port_name = 0; _longest_bundle_name = 0; - _height = 0; /* Compute maximum dimensions using all port groups, so that we allow for the largest and hence we can change between visible groups without the size of the labels jumping around. @@ -71,8 +70,12 @@ PortMatrixRowLabels::compute_dimensions () } } - - _height += group_size (_matrix->visible_rows()) * grid_spacing (); + + if (_matrix->visible_rows()) { + _height = group_size (_matrix->visible_rows()) * grid_spacing (); + } else { + _height = 0; + } cairo_destroy (cr); gdk_pixmap_unref (pm);