OSC: change group sharing to individual commands
[ardour.git] / libs / widgets / ardour_button.cc
index 8c16bcdca114cabfb417f18fce789a7833a9bde0..145d46d94c8a97920bdabf7a422ce4b21e981e4f 100644 (file)
 #include "pbd/error.h"
 #include "pbd/stacktrace.h"
 
-#include "gtkmm2ext/utils.h"
-#include "gtkmm2ext/rgb_macros.h"
+#include "gtkmm2ext/colors.h"
 #include "gtkmm2ext/gui_thread.h"
-
-#include "canvas/utils.h"
-#include "canvas/colors.h"
+#include "gtkmm2ext/rgb_macros.h"
+#include "gtkmm2ext/utils.h"
 
 #include "widgets/ardour_button.h"
 #include "widgets/tooltips.h"
@@ -57,7 +55,7 @@ ArdourButton::Element ArdourButton::default_elements = ArdourButton::Element (Ar
 ArdourButton::Element ArdourButton::led_default_elements = ArdourButton::Element (ArdourButton::default_elements|ArdourButton::Indicator);
 ArdourButton::Element ArdourButton::just_led_default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Indicator);
 
-ArdourButton::ArdourButton (Element e)
+ArdourButton::ArdourButton (Element e, bool toggle)
        : _sizing_text("")
        , _markup (false)
        , _elements (e)
@@ -89,6 +87,7 @@ ArdourButton::ArdourButton (Element e)
        , led_inset_pattern (0)
        , _led_rect (0)
        , _act_on_release (true)
+       , _auto_toggle (toggle)
        , _led_left (false)
        , _distinct_led_click (false)
        , _hovering (false)
@@ -105,7 +104,7 @@ ArdourButton::ArdourButton (Element e)
        signal_grab_broken_event().connect (sigc::mem_fun (*this, &ArdourButton::on_grab_broken_event));
 }
 
-ArdourButton::ArdourButton (const std::string& str, Element e)
+ArdourButton::ArdourButton (const std::string& str, Element e, bool toggle)
        : _sizing_text("")
        , _markup (false)
        , _elements (e)
@@ -135,6 +134,7 @@ ArdourButton::ArdourButton (const std::string& str, Element e)
        , led_inset_pattern (0)
        , _led_rect (0)
        , _act_on_release (true)
+       , _auto_toggle (toggle)
        , _led_left (false)
        , _distinct_led_click (false)
        , _hovering (false)
@@ -223,13 +223,7 @@ ArdourButton::set_sizing_text (const std::string& str)
                return;
        }
        _sizing_text = str;
-       if (!is_realized()) {
-               return;
-       }
-       ensure_layout ();
-       if (_layout) {
-               queue_resize ();
-       }
+       queue_resize ();
 }
 
 void
@@ -314,15 +308,15 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
        if ((_elements & Body)==Body) {
                rounded_function (cr, 1, 1, get_width() - 2, get_height() - 2, corner_radius);
                if (active_state() == Gtkmm2ext::ImplicitActive && !((_elements & Indicator)==Indicator)) {
-                       ArdourCanvas::set_source_rgba (cr, fill_inactive_color);
+                       Gtkmm2ext::set_source_rgba (cr, fill_inactive_color);
                        cairo_fill (cr);
                } else if ( (active_state() == Gtkmm2ext::ExplicitActive) && !((_elements & Indicator)==Indicator) ) {
                        //background color
-                       ArdourCanvas::set_source_rgba (cr, fill_active_color);
+                       Gtkmm2ext::set_source_rgba (cr, fill_active_color);
                        cairo_fill (cr);
                } else {  //inactive, or it has an indicator
                        //background color
-                       ArdourCanvas::set_source_rgba (cr, fill_inactive_color);
+                       Gtkmm2ext::set_source_rgba (cr, fill_inactive_color);
                }
                cairo_fill (cr);
        }
@@ -332,7 +326,7 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
                if (active_state() == Gtkmm2ext::ImplicitActive && !((_elements & Indicator)==Indicator)) {
                        cairo_set_line_width (cr, 2.0);
                        rounded_function (cr, 2, 2, get_width() - 4, get_height() - 4, corner_radius-0.5);
-                       ArdourCanvas::set_source_rgba (cr, fill_active_color);
+                       Gtkmm2ext::set_source_rgba (cr, fill_active_color);
                        cairo_stroke (cr);
                }
        }
@@ -418,7 +412,7 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
                cairo_clip(cr);
 
                cairo_new_path (cr);
-               ArdourCanvas::set_source_rgba (cr, text_color);
+               Gtkmm2ext::set_source_rgba (cr, text_color);
                const double text_ypos = (get_height() - _text_height) * .5;
 
                if (_elements & Menu) {
@@ -520,7 +514,7 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
                cairo_fill(cr);
 
                //led color
-               ArdourCanvas::set_source_rgba (cr, led_color);
+               Gtkmm2ext::set_source_rgba (cr, led_color);
                cairo_arc (cr, 0, 0, _diameter * .5 - 3 * UIConfigurationBase::instance().get_ui_scale(), 0, 2 * M_PI);
                cairo_fill(cr);
 
@@ -531,7 +525,7 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
        if ((visual_state() & Gtkmm2ext::Insensitive)) {
                rounded_function (cr, 0, 0, get_width(), get_height(), corner_radius);
                uint32_t ins_color = UIConfigurationBase::instance().color ("gtk_background");
-               ArdourCanvas::set_source_rgb_a (cr, ins_color, 0.6);
+               Gtkmm2ext::set_source_rgb_a (cr, ins_color, 0.6);
                cairo_fill (cr);
        }
 
@@ -626,6 +620,11 @@ ArdourButton::on_size_request (Gtk::Requisition* req)
                         * of text.
                         */
 
+               } else if (_layout_ellipsize_width > 0 && _sizing_text.empty()) {
+
+                       req->height = std::max(req->height, (int) ceil(char_pixel_height() * BASELINESTRETCH + 1.0));
+                       req->width += _layout_ellipsize_width / PANGO_SCALE;
+
                } else /*if (!_text.empty() || !_sizing_text.empty()) */ {
 
                        req->height = std::max(req->height, (int) ceil(char_pixel_height() * BASELINESTRETCH + 1.0));
@@ -736,8 +735,8 @@ ArdourButton::set_colors ()
                }
        }
 
-       text_active_color = ArdourCanvas::contrasting_text_color (fill_active_color);
-       text_inactive_color = ArdourCanvas::contrasting_text_color (fill_inactive_color);
+       text_active_color = Gtkmm2ext::contrasting_text_color (fill_active_color);
+       text_inactive_color = Gtkmm2ext::contrasting_text_color (fill_inactive_color);
 
        led_active_color = UIConfigurationBase::instance().color (string_compose ("%1: led active", name), &failed);
        if (failed) {
@@ -748,7 +747,7 @@ ArdourButton::set_colors ()
         * active color.
         */
 
-       ArdourCanvas::HSV inactive (led_active_color);
+       Gtkmm2ext::HSV inactive (led_active_color);
        inactive.v = 0.35;
 
        led_inactive_color = inactive.color ();
@@ -861,6 +860,10 @@ ArdourButton::on_button_press_event (GdkEventButton *ev)
 {
        focus_handler (this);
 
+       if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
+               return _fallthrough_to_parent ? false : true;
+       }
+
        if (ev->button == 1 && (_elements & Indicator) && _led_rect && _distinct_led_click) {
                if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width &&
                    ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) {
@@ -879,18 +882,22 @@ ArdourButton::on_button_press_event (GdkEventButton *ev)
                if (_action) {
                        _action->activate ();
                        return true;
+               } else if (_auto_toggle) {
+                       set_active (!get_active ());
+                       signal_clicked ();
+                       return true;
                }
        }
 
-       if (_fallthrough_to_parent)
-               return false;
-
-       return true;
+       return _fallthrough_to_parent ? false : true;
 }
 
 bool
 ArdourButton::on_button_release_event (GdkEventButton *ev)
 {
+       if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
+               return _fallthrough_to_parent ? false : true;
+       }
        if (ev->button == 1 && _hovering && (_elements & Indicator) && _led_rect && _distinct_led_click) {
                if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width &&
                    ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) {
@@ -903,6 +910,9 @@ ArdourButton::on_button_release_event (GdkEventButton *ev)
        CairoWidget::set_dirty ();
 
        if (ev->button == 1 && _hovering) {
+               if (_act_on_release && _auto_toggle && !_action) {
+                       set_active (!get_active ());
+               }
                signal_clicked ();
                if (_act_on_release) {
                        if (_action) {
@@ -912,10 +922,7 @@ ArdourButton::on_button_release_event (GdkEventButton *ev)
                }
        }
 
-       if (_fallthrough_to_parent)
-               return false;
-
-       return true;
+       return _fallthrough_to_parent ? false : true;
 }
 
 void
@@ -1113,6 +1120,9 @@ ArdourButton::on_key_release_event (GdkEventKey *ev) {
        if (_act_on_release && _focused &&
                        (ev->keyval == GDK_space || ev->keyval == GDK_Return))
        {
+               if (_auto_toggle && !_action) {
+                               set_active (!get_active ());
+               }
                signal_clicked();
                if (_action) {
                        _action->activate ();
@@ -1127,6 +1137,9 @@ ArdourButton::on_key_press_event (GdkEventKey *ev) {
        if (!_act_on_release && _focused &&
                        (ev->keyval == GDK_space || ev->keyval == GDK_Return))
        {
+               if (_auto_toggle && !_action) {
+                               set_active (!get_active ());
+               }
                signal_clicked();
                if (_action) {
                        _action->activate ();