#include "pbd/compose.h"
#include "pbd/error.h"
+#include "pbd/stacktrace.h"
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/rgb_macros.h"
, _angle(0)
, _xalign(.5)
, _yalign(.5)
+ , bg_color (0)
, border_color (0)
- , fill_color_active (0)
- , fill_color_inactive (0)
+ , fill_start_inactive_color (0)
+ , fill_end_inactive_color (0)
+ , fill_start_active_color (0)
+ , fill_end_active_color (0)
+ , text_active_color(0)
+ , text_inactive_color(0)
+ , led_active_color(0)
+ , led_inactive_color(0)
, fill_pattern (0)
, fill_pattern_active (0)
, shine_pattern (0)
, _fixed_diameter (true)
, _distinct_led_click (false)
, _hovering (false)
+ , _focused (false)
+ , _fixed_colors_set (false)
{
- ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
+ ARDOUR_UI_UTILS::ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
}
ArdourButton::ArdourButton (const std::string& str, Element e)
, _angle(0)
, _xalign(.5)
, _yalign(.5)
+ , bg_color (0)
, border_color (0)
- , fill_color_active (0)
- , fill_color_inactive (0)
+ , fill_start_inactive_color (0)
+ , fill_end_inactive_color (0)
+ , fill_start_active_color (0)
+ , fill_end_active_color (0)
+ , text_active_color(0)
+ , text_inactive_color(0)
+ , led_active_color(0)
+ , led_inactive_color(0)
, fill_pattern (0)
, fill_pattern_active (0)
, shine_pattern (0)
, _fixed_diameter (true)
, _distinct_led_click (false)
, _hovering (false)
+ , _focused (false)
+ , _fixed_colors_set (false)
{
set_text (str);
}
}
void
-ArdourButton::render (cairo_t* cr)
+ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
{
void (*rounded_function)(cairo_t*, double, double, double, double, double);
if (!(_tweaks & ImplicitUsesSolidColor)) {
//border
- UINT_TO_RGBA (fill_color_active, &r, &g, &b, &a);
+ UINT_TO_RGBA (fill_end_active_color, &r, &g, &b, &a);
cairo_set_line_width (cr, 1.0);
rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 1.5);
cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0);
}
}
- if ( ((_elements & FlatFace)==FlatFace) && (active_state() != Gtkmm2ext::ExplicitActive) ) {
+ if ( ((_elements & Inset)==Inset) && (active_state() != Gtkmm2ext::ExplicitActive) ) {
if ( !_flat_buttons ) {
float rheight = get_height()*0.5-REFLECTION_HEIGHT;
if (active_state() == Gtkmm2ext::ExplicitActive) {
- UINT_TO_RGBA (fill_color_active, &r, &g, &b, &a);
+ UINT_TO_RGBA (fill_start_active_color, &r, &g, &b, &a);
cairo_set_line_width (cr, 2.0);
rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 2.0);
cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0);
} else {
- UINT_TO_RGBA (fill_color_inactive, &r, &g, &b, &a);
+ UINT_TO_RGBA (fill_start_inactive_color, &r, &g, &b, &a);
cairo_set_line_width (cr, 2.0);
rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 2.0);
cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0);
}
if ( ((_elements & Text)==Text) && !_text.empty()) {
+ cairo_save (cr);
+ cairo_rectangle (cr, 2, 1, get_width()-4, get_height()-2);
+ cairo_clip(cr);
cairo_new_path (cr);
cairo_set_source_rgba (cr, text_r, text_g, text_b, text_a);
- if (_elements & Indicator) {
+ if ( (_elements & Menu) == Menu) {
+ cairo_move_to (cr, text_margin, get_height()/2.0 - _text_height/2.0);
+ pango_cairo_show_layout (cr, _layout->gobj());
+ } else if ( (_elements & Indicator) == Indicator) {
if (_led_left) {
cairo_move_to (cr, text_margin + _diameter + 4, get_height()/2.0 - _text_height/2.0);
} else {
/* use old center'ed layout for follow up items - until rotation/aligment code is completed */
cairo_move_to (cr, (get_width() - _text_width)/2.0, get_height()/2.0 - _text_height/2.0);
}
-
+ cairo_restore (cr);
}
+ if (((_elements & Menu)==Menu)) {
+
+ cairo_save (cr);
+
+ cairo_translate (cr, 0,0 );
+
+ //white arrow
+ cairo_set_source_rgba (cr, 1, 1, 1, 0.4);
+ cairo_move_to(cr, get_width() - ((_diameter/2.0) + 6.0), get_height()/2.0 +_diameter/4);
+ cairo_rel_line_to(cr, -_diameter/2, -_diameter/2);
+ cairo_rel_line_to(cr, _diameter, 0);
+ cairo_close_path(cr);
+ cairo_fill(cr);
+
+ cairo_restore (cr);
+ }
+
if (((_elements & Indicator)==Indicator)) {
/* move to the center of the indicator/led */
cairo_fill (cr);
}
}
+ if (_focused) {
+ rounded_function (cr, 1.5, 1.5, get_width() - 3, get_height() - 3, _corner_radius);
+ cairo_set_source_rgba (cr, 0.905, 0.917, 0.925, 0.8);
+ double dashes = 1;
+ cairo_set_dash (cr, &dashes, 1, 0);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+ cairo_set_dash (cr, 0, 0, 0);
+ }
}
void
_fixed_diameter = true;
}
- set_colors ();
+ build_patterns ();
queue_resize ();
}
req->height = _text_height + ypad;
}
}
+ req->width += _corner_radius;
}
+/**
+ * This sets the colors used for rendering based on the name of the button, and
+ * thus uses information from the GUI config data.
+ */
void
ArdourButton::set_colors ()
+{
+ if (_fixed_colors_set) {
+ return;
+ }
+ std::string name = get_name();
+
+ border_color = ARDOUR_UI::config()->color_by_name ("button border");
+
+ fill_start_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", name));
+ fill_end_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", name));
+
+ fill_start_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", name));
+ fill_end_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", name));
+
+ text_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text active", name));
+ text_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text", name));
+
+ led_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", name));
+ led_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led", name));
+}
+/**
+ * This sets the colors used for rendering based on two fixed values, rather
+ * than basing them on the button name, and thus information in the GUI config
+ * data.
+ */
+void ArdourButton::set_fixed_colors (const uint32_t color_active, const uint32_t color_inactive)
+{
+ _fixed_colors_set = true;
+
+ fill_start_active_color = fill_end_active_color = color_active;
+
+ unsigned char r, g, b, a;
+ UINT_TO_RGBA(color_active, &r, &g, &b, &a);
+
+ double white_contrast = (max (double(r), 255.) - min (double(r), 255.)) +
+ (max (double(g), 255.) - min (double(g), 255.)) +
+ (max (double(b), 255.) - min (double(b), 255.));
+
+ double black_contrast = (max (double(r), 0.) - min (double(r), 0.)) +
+ (max (double(g), 0.) - min (double(g), 0.)) +
+ (max (double(b), 0.) - min (double(b), 0.));
+
+ text_active_color =
+ text_inactive_color = (white_contrast > black_contrast) ?
+ RGBA_TO_UINT(255, 255, 255, 255) : /* use white */
+ RGBA_TO_UINT( 0, 0, 0, 255); /* use black */
+
+ fill_start_inactive_color = fill_end_inactive_color = color_inactive;
+
+ /* XXX what about led colors ? */
+
+ build_patterns ();
+ set_name (""); /* this will trigger a "style-changed" message and then set_colors() */
+}
+
+void
+ArdourButton::build_patterns ()
{
uint32_t start_color;
uint32_t end_color;
- uint32_t r, g, b, a;
uint32_t text_color;
uint32_t led_color;
-
- if (active_state() == Gtkmm2ext::ImplicitActive && (_tweaks & ImplicitUsesSolidColor)) {
- fill_color_active = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", get_name()));
- } else {
- fill_color_active = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", get_name()));
- }
- fill_color_inactive = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", get_name()));
- border_color = ARDOUR_UI::config()->color_by_name ( "button border" );
+ uint32_t r, g, b, a;
if (shine_pattern) {
cairo_pattern_destroy (shine_pattern);
if (_elements & Body) {
- start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", get_name()));
-
if (_flat_buttons) {
- end_color = start_color;
+ end_color = start_color = fill_start_active_color;
} else {
- end_color = fill_color_active;
+ start_color = fill_start_active_color;
+ end_color = fill_end_active_color;
}
UINT_TO_RGBA (start_color, &r, &g, &b, &a);
fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height()-3);
if (_flat_buttons) {
- end_color = start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", get_name()));
+ end_color = start_color = fill_start_inactive_color;
} else {
- start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", get_name()));
- end_color = fill_color_inactive;
+ start_color = fill_start_inactive_color;
+ end_color = fill_end_inactive_color;
}
UINT_TO_RGBA (start_color, &r, &g, &b, &a);
cairo_pattern_add_color_stop_rgba (fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
fill_pattern_active = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height()-3);
if (_flat_buttons) {
if (active_state() == Gtkmm2ext::ImplicitActive && (_tweaks & ImplicitUsesSolidColor)) {
- end_color = start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", get_name()));
+ end_color = start_color = led_active_color;
} else {
- end_color = start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", get_name()));
+ end_color = start_color = fill_end_active_color;
}
} else {
if (active_state() == Gtkmm2ext::ImplicitActive && (_tweaks & ImplicitUsesSolidColor)) {
- start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led", get_name()));
- end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", get_name()));
+ end_color = start_color = led_active_color;
} else {
- start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", get_name()));
- end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", get_name()));
+ start_color = fill_start_active_color;
+ end_color = fill_end_active_color;
}
}
UINT_TO_RGBA (start_color, &r, &g, &b, &a);
cairo_pattern_add_color_stop_rgba (reflection_pattern, 0, 1,1,1, active_state() ? 0.4 : 0.2);
cairo_pattern_add_color_stop_rgba (reflection_pattern, 1, 1,1,1, 0.0);
}
-
- /* text and LED colors */
if (active_state() == Gtkmm2ext::ExplicitActive || ((_tweaks & ImplicitUsesSolidColor) && active_state() == Gtkmm2ext::ImplicitActive)) {
- text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text active", get_name()));
- led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", get_name()));
+ text_color = text_active_color;
+ led_color = led_active_color;
} else {
- text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text", get_name()));
- led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led", get_name()));
+ text_color = text_inactive_color;
+ led_color = led_inactive_color;
}
-
+
UINT_TO_RGBA (text_color, &r, &g, &b, &a);
text_r = r/255.0;
text_g = g/255.0;
bool
ArdourButton::on_button_release_event (GdkEventButton *ev)
{
- if ((_elements & Indicator) && _led_rect && _distinct_led_click) {
+ if (_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) {
signal_led_clicked(); /* EMIT SIGNAL */
unset_active_state ();
}
- signal_clicked ();
-
- if (_act_on_release) {
- if (_action) {
- _action->activate ();
- return true;
+ if (_hovering) {
+ signal_clicked ();
+
+ if (_act_on_release) {
+ if (_action) {
+ _action->activate ();
+ return true;
+ }
}
}
-
return false;
}
ArdourButton::color_handler ()
{
set_colors ();
+ build_patterns ();
set_dirty ();
}
{
CairoWidget::on_size_allocate (alloc);
setup_led_rect ();
- set_colors ();
+ build_patterns ();
}
void
ArdourButton::on_style_changed (const RefPtr<Gtk::Style>&)
{
set_colors ();
+ build_patterns ();
+}
+
+void
+ArdourButton::on_name_changed ()
+{
+ set_colors ();
+ build_patterns ();
}
void
CairoWidget::set_active_state (s);
if (changed) {
set_colors ();
+ build_patterns ();
}
}
CairoWidget::set_visual_state (s);
if (changed) {
set_colors ();
+ build_patterns ();
}
}
+
+bool
+ArdourButton::on_focus_in_event (GdkEventFocus* ev)
+{
+ _focused = true;
+ queue_draw ();
+ return CairoWidget::on_focus_in_event (ev);
+}
+
+bool
+ArdourButton::on_focus_out_event (GdkEventFocus* ev)
+{
+ _focused = false;
+ queue_draw ();
+ return CairoWidget::on_focus_out_event (ev);
+}
+
+bool
+ArdourButton::on_key_release_event (GdkEventKey *ev) {
+ if (_focused &&
+ (ev->keyval == GDK_KEY_space || ev->keyval == GDK_Return))
+ {
+ signal_clicked();
+ if (_action) {
+ _action->activate ();
+ }
+ return true;
+ }
+ return CairoWidget::on_key_release_event (ev);
+}
+
bool
ArdourButton::on_enter_notify_event (GdkEventCrossing* ev)
{
ArdourButton::set_elements (Element e)
{
_elements = e;
- set_colors ();
}
void
ArdourButton::add_elements (Element e)
{
_elements = (ArdourButton::Element) (_elements | e);
- set_colors ();
}
void