X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_button.cc;h=c1626e6aad693c4fcb669d9182354946acc87083;hb=c3d8967870f4a973945e6e6c723bbd8c24ad76eb;hp=6390449adb7f889b474e0c7c636b0565d20cf1b0;hpb=602b1597a4ee4f7389e4ffb6d69fb6d66a8f3d52;p=ardour.git diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc index 6390449adb..c1626e6aad 100644 --- a/gtk2_ardour/ardour_button.cc +++ b/gtk2_ardour/ardour_button.cc @@ -39,7 +39,7 @@ #include "tooltips.h" #include "ui_config.h" -#include "i18n.h" +#include "pbd/i18n.h" #define BASELINESTRETCH (1.25) #define TRACKHEADERBTNW (3.10) @@ -58,7 +58,9 @@ ArdourButton::Element ArdourButton::led_default_elements = ArdourButton::Element ArdourButton::Element ArdourButton::just_led_default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Indicator); ArdourButton::ArdourButton (Element e) - : _elements (e) + : _sizing_text("") + , _markup (false) + , _elements (e) , _icon (Gtkmm2ext::ArdourIcon::NoIcon) , _tweaks (Tweaks (0)) , _char_pixel_width (0) @@ -67,7 +69,7 @@ ArdourButton::ArdourButton (Element e) , _text_width (0) , _text_height (0) , _diameter (0) - , _corner_radius (2.5) + , _corner_radius (3.5) , _corner_mask (0xf) , _angle(0) , _xalign(.5) @@ -97,10 +99,15 @@ ArdourButton::ArdourButton (Element e) , _pattern_height (0) { UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler)); + /* This is not provided by gtkmm */ + signal_grab_broken_event().connect (sigc::mem_fun (*this, &ArdourButton::on_grab_broken_event)); } ArdourButton::ArdourButton (const std::string& str, Element e) - : _elements (e) + : _sizing_text("") + , _markup (false) + , _elements (e) + , _icon (Gtkmm2ext::ArdourIcon::NoIcon) , _tweaks (Tweaks (0)) , _char_pixel_width (0) , _char_pixel_height (0) @@ -108,7 +115,7 @@ ArdourButton::ArdourButton (const std::string& str, Element e) , _text_width (0) , _text_height (0) , _diameter (0) - , _corner_radius (2.5) + , _corner_radius (3.5) , _corner_mask (0xf) , _angle(0) , _xalign(.5) @@ -140,6 +147,8 @@ ArdourButton::ArdourButton (const std::string& str, Element e) set_text (str); UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler)); UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ArdourButton::on_name_changed)); + /* This is not provided by gtkmm */ + signal_grab_broken_event().connect (sigc::mem_fun (*this, &ArdourButton::on_grab_broken_event)); } ArdourButton::~ArdourButton() @@ -166,22 +175,57 @@ ArdourButton::set_layout_font (const Pango::FontDescription& fd) if (_layout) { _layout->set_font_description (fd); queue_resize (); + _char_pixel_width = 0; + _char_pixel_height = 0; + } +} + +void +ArdourButton::set_text_internal () { + assert (_layout); + if (_markup) { + _layout->set_markup (_text); + } else { + _layout->set_text (_text); } } void -ArdourButton::set_text (const std::string& str) +ArdourButton::set_text (const std::string& str, bool markup) { - if (_text == str) { + if (!(_elements & Text)) { return; } + if (_text == str && _markup == markup) { + return; + } + _text = str; + _markup = markup; if (!is_realized()) { return; } ensure_layout (); if (_layout && _layout->get_text() != _text) { - _layout->set_text (_text); + set_text_internal (); + /* 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 (); } } @@ -326,7 +370,12 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *) } else /* VectorIcons are exclusive to Pixbuf Icons */ if (_elements & VectorIcon) { - Gtkmm2ext::ArdourIcon::render (cr, _icon, get_width(), get_height(), active_state(), text_color); + int vw = get_width(); + int vh = get_height(); + if (_elements & Menu) { + vw -= _diameter + 4; + } + Gtkmm2ext::ArdourIcon::render (cr, _icon, vw, vh, active_state(), text_color); } const int text_margin = char_pixel_width(); @@ -379,10 +428,19 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *) ww = get_width(); wh = get_height(); - cairo_save (cr); - cairo_rotate(cr, _angle * M_PI / 180.0); + cairo_matrix_t m1; + cairo_get_matrix (cr, &m1); + cairo_matrix_t m2 = m1; + m2.x0 = 0; + m2.y0 = 0; + cairo_set_matrix (cr, &m2); + + if (_angle) { + cairo_rotate(cr, _angle * M_PI / 180.0); + } + cairo_device_to_user(cr, &ww, &wh); - xa = (ww - _text_width) * _xalign; + xa = text_margin + (ww - _text_width - 2 * text_margin) * _xalign; ya = (wh - _text_height) * _yalign; /* quick hack for left/bottom alignment at -90deg @@ -391,10 +449,9 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *) */ if (_xalign < 0) xa = ceil(.5 + (ww * fabs(_xalign) + text_margin)); - cairo_move_to (cr, xa, ya); + cairo_move_to (cr, xa + m1.x0, ya + m1.y0); pango_cairo_update_layout(cr, _layout->gobj()); pango_cairo_show_layout (cr, _layout->gobj()); - cairo_restore (cr); } cairo_restore (cr); } @@ -521,9 +578,11 @@ ArdourButton::on_realize() { CairoWidget::on_realize (); ensure_layout (); - if (_layout && _layout->get_text() != _text) { - _layout->set_text (_text); - queue_resize (); + if (_layout) { + if (_layout->get_text() != _text) { + set_text_internal (); + queue_resize (); + } } } @@ -543,27 +602,35 @@ ArdourButton::on_size_request (Gtk::Requisition* req) if (_elements & Text) { + ensure_layout(); + set_text_internal (); + + /* 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()) { + set_text_internal (); /* restore display text */ + } } /* XXX hack (surprise). Deal with two common rotation angles */ @@ -616,7 +683,7 @@ ArdourButton::on_size_request (Gtk::Requisition* req) req->width = req->height; if (req->height < req->width) req->height = req->width; - } else if (_text_width > 0 && !(_elements & (Menu | Indicator))) { + } else if (_sizing_text.empty() && _text_width > 0 && !(_elements & Menu)) { // properly centered text for those elements that are centered // (no sub-pixel offset) if ((req->width - _text_width) & 1) { ++req->width; } @@ -932,6 +999,11 @@ ArdourButton::on_style_changed (const RefPtr&) { _update_colors = true; CairoWidget::set_dirty (); + _char_pixel_width = 0; + _char_pixel_height = 0; + if (is_realized()) { + queue_resize (); + } } void @@ -978,6 +1050,7 @@ ArdourButton::setup_led_rect () void ArdourButton::set_image (const RefPtr& img) { + _elements = (ArdourButton::Element) (_elements & ~ArdourButton::Text); _pixbuf = img; if (is_realized()) { queue_resize (); @@ -1060,6 +1133,16 @@ ArdourButton::on_leave_notify_event (GdkEventCrossing* ev) return CairoWidget::on_leave_notify_event (ev); } +bool +ArdourButton::on_grab_broken_event(GdkEventGrabBroken* grab_broken_event) { + /* Our implicit grab due to a button_press was broken by another grab: + * the button will not get any button_release event if the mouse leaves + * while the grab is taken, so unpress ourselves */ + _grabbed = false; + CairoWidget::set_dirty (); + return true; +} + void ArdourButton::set_tweaks (Tweaks t) { @@ -1141,7 +1224,7 @@ ArdourButton::recalc_char_pixel_geometry () // NB. this is not static, since the geometry is different // depending on the font used. int w, h; - std::string x = _("ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + std::string x = _("@ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); _layout->set_text (x); _layout->get_pixel_size (w, h); _char_pixel_height = std::max(4, h); @@ -1150,7 +1233,7 @@ ArdourButton::recalc_char_pixel_geometry () Glib::ustring gx(x); _char_avg_pixel_width = w / (float)gx.size(); _char_pixel_width = std::max(4, (int) ceil (_char_avg_pixel_width)); - _layout->set_text (_text); + set_text_internal (); /* restore display text */ } void