ArdourButton: add text for measuring decoupled from display text
authorJulien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
Sat, 20 Aug 2016 13:46:41 +0000 (15:46 +0200)
committerJulien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
Sat, 20 Aug 2016 14:00:46 +0000 (16:00 +0200)
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
gtk2_ardour/ardour_button.h

index ae9eb310d5c32f8464265444700e8308f5f67e17..fbc6defdc1b947597a77e221c7baffd0f41458d7 100644 (file)
@@ -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() || !_sizing_text.empty()) {
+
+                       req->height = std::max(req->height, (int) ceil(char_pixel_height() * BASELINESTRETCH + 1.0));
+                       req->width += rint(1.75 * char_pixel_width()); // padding
+
+                       if (!_sizing_text.empty()) {
+                               _layout->set_text (_sizing_text); /* use sizing text */
                        }
 
-               } else if (!_text.empty()) {
+                       int sizing_text_width = 0, sizing_text_height = 0;
+                       _layout->get_pixel_size (sizing_text_width, sizing_text_height);
 
-                       //if _layout does not exist, char_pixel_height() creates it,
+                       req->width += sizing_text_width;
 
-                       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 (_text); /* restore display text */
+                       }
                }
 
                /* XXX hack (surprise). Deal with two common rotation angles */
index 1128dce97a61500c9584932705a3a645783a4b61..c20a62535971e604e9aa32440993c14e6bb66faf 100644 (file)
@@ -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<void, GdkEventButton*> signal_led_clicked;
        sigc::signal<void> signal_clicked;
 
@@ -136,6 +142,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
        Glib::RefPtr<Pango::Layout> _layout;
        Glib::RefPtr<Gdk::Pixbuf>   _pixbuf;
        std::string                 _text;
+       std::string                 _sizing_text;
        Element                     _elements;
        Gtkmm2ext::ArdourIcon::Icon _icon;
        Tweaks                      _tweaks;