From f108bf1373f8fdcf4c5a712756281ac265825b71 Mon Sep 17 00:00:00 2001 From: "Julien \"_FrnchFrgg_\" RIVAUD" Date: Sat, 20 Aug 2016 15:46:41 +0200 Subject: [PATCH] ArdourButton: add text for measuring decoupled from display text In the normal course of events, an ArdourButton requests just enough space to display its elements. In particular the size will change when the text does. Yet, in several cases it is better to avoid layout jittering; until now ArdourButton users manually set a static size on the button at creation time. Introduce new API to set the text used for measuring the button size separately from the text that will be displayed. In most cases this enables the callers to replace set_size_request_to_display_given_text(button, text, w, h); where w and h were hard-coded to cater for other button elements, by button.set_sizing_text(text); which will make ArdourButton correctly compute the size request in all cases with its real elements and padding. ArdourButton users can call button.set_sizing_text(""); to get the size request depend on displayed text (which is the default). --- gtk2_ardour/ardour_button.cc | 57 +++++++++++++++++++++++++++--------- gtk2_ardour/ardour_button.h | 7 +++++ 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc index ae9eb310d5..fbc6defdc1 100644 --- a/gtk2_ardour/ardour_button.cc +++ b/gtk2_ardour/ardour_button.cc @@ -95,6 +95,7 @@ ArdourButton::ArdourButton (Element e) , _ellipsis (Pango::ELLIPSIZE_NONE) , _update_colors (true) , _pattern_height (0) + , _sizing_text("") { UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler)); /* This is not provided by gtkmm */ @@ -138,6 +139,7 @@ ArdourButton::ArdourButton (const std::string& str, Element e) , _ellipsis (Pango::ELLIPSIZE_NONE) , _update_colors (true) , _pattern_height (0) + , _sizing_text("") { set_text (str); UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler)); @@ -186,6 +188,24 @@ ArdourButton::set_text (const std::string& str) ensure_layout (); if (_layout && _layout->get_text() != _text) { _layout->set_text (_text); + /* on_size_request() will fill in _text_width/height + * so queue it even if _sizing_text != "" */ + queue_resize (); + } +} + +void +ArdourButton::set_sizing_text (const std::string& str) +{ + if (_sizing_text == str) { + return; + } + _sizing_text = str; + if (!is_realized()) { + return; + } + ensure_layout (); + if (_layout) { queue_resize (); } } @@ -525,8 +545,10 @@ ArdourButton::on_realize() { CairoWidget::on_realize (); ensure_layout (); - if (_layout && _layout->get_text() != _text) { - _layout->set_text (_text); + if (_layout) { + if (_layout->get_text() != _text) { + _layout->set_text (_text); + } queue_resize (); } } @@ -547,27 +569,34 @@ ArdourButton::on_size_request (Gtk::Requisition* req) if (_elements & Text) { + ensure_layout(); + _layout->set_text (_text); + /* render() needs the size of the displayed text */ + _layout->get_pixel_size (_text_width, _text_height); + if (_tweaks & OccasionalText) { /* size should not change based on presence or absence * of text. */ - if (!_text.empty()) { - ensure_layout (); - _layout->set_text (_text); - _layout->get_pixel_size (_text_width, _text_height); - } - - } else if (!_text.empty()) { - - //if _layout does not exist, char_pixel_height() creates it, + } else { //if (!_text.empty() || !_sizing_text.empty()) { req->height = std::max(req->height, (int) ceil(char_pixel_height() * BASELINESTRETCH + 1.0)); - assert (_layout); - _layout->get_pixel_size (_text_width, _text_height); req->width += rint(1.75 * char_pixel_width()); // padding - req->width += _text_width; + + if (!_sizing_text.empty()) { + _layout->set_text (_sizing_text); /* use sizing text */ + } + + int sizing_text_width = 0, sizing_text_height = 0; + _layout->get_pixel_size (sizing_text_width, sizing_text_height); + + req->width += sizing_text_width; + + if (!_sizing_text.empty()) { + _layout->set_text (_text); /* restore display text */ + } } /* XXX hack (surprise). Deal with two common rotation angles */ diff --git a/gtk2_ardour/ardour_button.h b/gtk2_ardour/ardour_button.h index 1128dce97a..c20a625359 100644 --- a/gtk2_ardour/ardour_button.h +++ b/gtk2_ardour/ardour_button.h @@ -91,6 +91,12 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable void set_layout_font (const Pango::FontDescription&); void set_text_ellipsize (Pango::EllipsizeMode); + /* Sets the text used for size request computation. Pass an + * empty string to return to the default behavior which uses + * the currently displayed text for measurement. */ + void set_sizing_text (const std::string&); + const std::string& get_sizing_text () {return _sizing_text;} + sigc::signal signal_led_clicked; sigc::signal signal_clicked; @@ -136,6 +142,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable Glib::RefPtr _layout; Glib::RefPtr _pixbuf; std::string _text; + std::string _sizing_text; Element _elements; Gtkmm2ext::ArdourIcon::Icon _icon; Tweaks _tweaks;