summaryrefslogtreecommitdiff
path: root/gtk2_ardour/ardour_button.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-05-24 19:35:45 +0200
committerRobin Gareus <robin@gareus.org>2015-05-24 19:35:45 +0200
commitff5b1b0c999b261d04e6e11c479e33c1178d1a10 (patch)
treec973197c0518bd55b5266040f0d034ab91634b6c /gtk2_ardour/ardour_button.cc
parentfb649f43ea3266280c01a94471a7069b1dca4a3e (diff)
prepare cleanup of ArdourButton rendering
Diffstat (limited to 'gtk2_ardour/ardour_button.cc')
-rw-r--r--gtk2_ardour/ardour_button.cc406
1 files changed, 228 insertions, 178 deletions
diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc
index 89f19b001e..8d4e9dca3e 100644
--- a/gtk2_ardour/ardour_button.cc
+++ b/gtk2_ardour/ardour_button.cc
@@ -193,99 +193,23 @@ ArdourButton::set_alignment (const float xa, const float ya)
_yalign = ya;
}
-void
-ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
-{
- uint32_t text_color;
- uint32_t led_color;
-
- const float corner_radius = std::max(2.f, _corner_radius * ARDOUR_UI::ui_scale);
-
- if (_update_colors) {
- set_colors ();
- }
- if (get_height() != _pattern_height) {
- build_patterns ();
- }
-
- if ( active_state() == Gtkmm2ext::ExplicitActive ) {
- text_color = text_active_color;
- led_color = led_active_color;
- } else {
- text_color = text_inactive_color;
- led_color = led_inactive_color;
- }
-
- if (use_custom_led_color) {
- led_color = led_custom_color;
- }
-
- void (*rounded_function)(cairo_t*, double, double, double, double, double);
-
- switch (_corner_mask) {
- case 0x1: /* upper left only */
- rounded_function = Gtkmm2ext::rounded_top_left_rectangle;
- break;
- case 0x2: /* upper right only */
- rounded_function = Gtkmm2ext::rounded_top_right_rectangle;
- break;
- case 0x3: /* upper only */
- rounded_function = Gtkmm2ext::rounded_top_rectangle;
- break;
- /* should really have functions for lower right, lower left,
- lower only, but for now, we don't
- */
- default:
- rounded_function = Gtkmm2ext::rounded_rectangle;
- }
-
- // draw edge (filling a rect underneath, rather than stroking a border on top, allows the corners to be lighter-weight.
- if ((_elements & (Body|Edge)) == (Body|Edge)) {
- rounded_function (cr, 0, 0, get_width(), get_height(), corner_radius + 1.5);
- cairo_set_source_rgba (cr, 0, 0, 0, 1);
- cairo_fill(cr);
- }
- // background fill
- 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);
- cairo_fill (cr);
- } else if ( (active_state() == Gtkmm2ext::ExplicitActive) && !((_elements & Indicator)==Indicator) ) {
- //background color
- ArdourCanvas::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);
- }
- cairo_fill (cr);
- }
-
- // IMPLICIT ACTIVE: draw a border of the active color
- if ((_elements & Body)==Body) {
- 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);
- cairo_stroke (cr);
- }
- }
-
- //show the "convex" or "concave" gradient
- if (!_flat_buttons) {
- if ( active_state() == Gtkmm2ext::ExplicitActive && ( !((_elements & Indicator)==Indicator) || use_custom_led_color) ) {
- //concave
- cairo_set_source (cr, concave_pattern);
- Gtkmm2ext::rounded_rectangle (cr, 1, 1, get_width() - 2, get_height() - 2, corner_radius);
- cairo_fill (cr);
- } else {
- cairo_set_source (cr, convex_pattern);
- Gtkmm2ext::rounded_rectangle (cr, 1, 1, get_width() - 2, get_height() - 2, corner_radius);
- cairo_fill (cr);
- }
- }
+/* TODO make this a dedicated function elsewhere.
+ *
+ * Option 1:
+ * virtual ArdourButton::render_vector_icon()
+ * ArdourIconButton::render_vector_icon
+ *
+ * Option 2:
+ * ARDOUR_UI_UTILS::render_vector_icon()
+ */
+static void
+render_vector_icon (cairo_t *cr,
+ const enum ArdourButton::Icon icon,
+ const int width, const int height,
+ const Gtkmm2ext::ActiveState state,
+ const ArdourCanvas::Color fg_color)
+{
#define VECTORICONSTROKEFILL(fillalpha) \
cairo_set_line_width(cr, 1.5); \
@@ -294,40 +218,22 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_set_source_rgba (cr, 1, 1, 1, (fillalpha)); \
cairo_fill(cr);
- //Pixbuf, if any
- if (_pixbuf) {
- double x = rint((get_width() - _pixbuf->get_width()) * .5);
- const double y = rint((get_height() - _pixbuf->get_height()) * .5);
-#if 0 // DEBUG style (print on hover)
- if (_hovering || (_elements & Inactive)) {
- printf("%s: p:%dx%d (%dx%d)\n",
- get_name().c_str(),
- _pixbuf->get_width(), _pixbuf->get_height(),
- get_width(), get_height());
- }
-#endif
- if (_elements & Menu) {
- //if this is a DropDown with an icon, then we need to
- //move the icon left slightly to accomomodate the arrow
- x -= _diameter - 2;
- }
- cairo_rectangle (cr, x, y, _pixbuf->get_width(), _pixbuf->get_height());
- gdk_cairo_set_source_pixbuf (cr, _pixbuf->gobj(), x, y);
- cairo_fill (cr);
- }
- else /* VectorIcons are exclusive to Pixbuf Icons */
+
/* TODO separate these into dedicated class
* it may also be efficient to render them only once for every size (image-surface) */
- if ((_elements & VectorIcon) && _icon == RecTapeMode) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ switch (icon) {
+
+ case ArdourButton::RecTapeMode:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double r = std::min(x, y) * .6;
const double slit = .11 * M_PI;
cairo_save(cr);
cairo_translate(cr, x, y);
cairo_arc (cr, 0, 0, r, 0, 2 * M_PI);
- if (active_state() == Gtkmm2ext::ExplicitActive) {
+ if (state == Gtkmm2ext::ExplicitActive) {
cairo_set_source_rgba (cr, .95, .1, .1, 1.);
} else {
cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
@@ -365,7 +271,7 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_restore(cr);
cairo_arc (cr, 0, 0, r * .3, 0, 2 * M_PI);
- if (active_state() == Gtkmm2ext::ExplicitActive)
+ if (state == Gtkmm2ext::ExplicitActive)
cairo_set_source_rgba (cr, .95, .1, .1, 1.);
else
cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
@@ -376,12 +282,14 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_restore(cr);
}
- else if ((_elements & VectorIcon) && _icon == RecButton) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ break;
+ case ArdourButton::RecButton:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double r = std::min(x, y) * .55;
cairo_arc (cr, x, y, r, 0, 2 * M_PI);
- if (active_state() == Gtkmm2ext::ExplicitActive)
+ if (state == Gtkmm2ext::ExplicitActive)
cairo_set_source_rgba (cr, .95, .1, .1, 1.);
else
cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
@@ -390,11 +298,13 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_set_line_width(cr, 1);
cairo_stroke(cr);
}
- else if ((_elements & VectorIcon) && _icon == CloseCross) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ break;
+ case ArdourButton::CloseCross:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double o = .5 + std::min(x, y) * .4;
- ArdourCanvas::set_source_rgba (cr, text_color);
+ ArdourCanvas::set_source_rgba (cr, fg_color);
cairo_set_line_width(cr, 1);
cairo_move_to(cr, x-o, y-o);
cairo_line_to(cr, x+o, y+o);
@@ -402,22 +312,24 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_line_to(cr, x-o, y+o);
cairo_stroke(cr);
}
- else if ((_elements & VectorIcon) && _icon == StripWidth) {
- const double x0 = get_width() * .2;
- const double x1 = get_width() * .8;
+ break;
+ case ArdourButton::StripWidth:
+ {
+ const double x0 = width * .2;
+ const double x1 = width * .8;
- const double y0 = get_height() * .25;
- const double y1= get_height() * .75;
+ const double y0 = height * .25;
+ const double y1= height * .75;
- const double ym= get_height() * .5;
+ const double ym= height * .5;
// arrow
- const double xa0= get_height() * .39;
- const double xa1= get_height() * .61;
- const double ya0= get_height() * .35;
- const double ya1= get_height() * .65;
+ const double xa0= height * .39;
+ const double xa1= height * .61;
+ const double ya0= height * .35;
+ const double ya1= height * .65;
- ArdourCanvas::set_source_rgba (cr, text_color);
+ ArdourCanvas::set_source_rgba (cr, fg_color);
cairo_set_line_width(cr, 1);
// left + right
@@ -443,11 +355,13 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_line_to(cr, xa1, ya1);
cairo_stroke(cr);
}
- else if ((_elements & VectorIcon) && _icon == DinMidi) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ break;
+ case ArdourButton::DinMidi:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double r = std::min(x, y) * .75;
- ArdourCanvas::set_source_rgba (cr, text_color);
+ ArdourCanvas::set_source_rgba (cr, fg_color);
cairo_set_line_width(cr, 1);
cairo_arc (cr, x, y, r, .57 * M_PI, 2.43 * M_PI);
cairo_stroke(cr);
@@ -469,19 +383,23 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_arc (cr, x, y+r, r * .26, 1.05 * M_PI, 1.95 * M_PI);
cairo_stroke(cr);
}
- else if ((_elements & VectorIcon) && _icon == TransportStop) {
- const int wh = std::min (get_width(), get_height());
+ break;
+ case ArdourButton::TransportStop:
+ {
+ const int wh = std::min (width, height);
cairo_rectangle (cr,
- (get_width() - wh) * .5 + wh * .25,
- (get_height() - wh) * .5 + wh * .25,
+ (width - wh) * .5 + wh * .25,
+ (height - wh) * .5 + wh * .25,
wh * .5, wh * .5);
VECTORICONSTROKEFILL(0.8);
}
- else if ((_elements & VectorIcon) && _icon == TransportPlay) {
- const int wh = std::min (get_width(), get_height()) * .5;
- const double y = get_height() * .5;
- const double x = get_width() - wh;
+ break;
+ case ArdourButton::TransportPlay:
+ {
+ const int wh = std::min (width, height) * .5;
+ const double y = height * .5;
+ const double x = width - wh;
const float tri = ceil(.577 * wh); // 1/sqrt(3)
@@ -492,10 +410,12 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
VECTORICONSTROKEFILL(0.8);
}
- else if ((_elements & VectorIcon) && _icon == TransportPanic) {
- const int wh = std::min (get_width(), get_height()) * .1;
- const double xc = get_width() * .5;
- const double yh = get_height();
+ break;
+ case ArdourButton::TransportPanic:
+ {
+ const int wh = std::min (width, height) * .1;
+ const double xc = width * .5;
+ const double yh = height;
cairo_rectangle (cr,
xc - wh, yh *.19,
wh * 2, yh *.41);
@@ -504,33 +424,37 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_arc (cr, xc, yh *.75, wh, 0, 2 * M_PI);
VECTORICONSTROKEFILL(0.8);
}
- else if ((_elements & VectorIcon) && (_icon == TransportStart || _icon == TransportEnd || _icon == TransportRange)) {
+ break;
+ case ArdourButton::TransportStart:
+ case ArdourButton::TransportEnd:
+ case ArdourButton::TransportRange:
+ {
// small play triangle
- int wh = std::min (get_width(), get_height());
- const double y = get_height() * .5;
- const double x = get_width() - wh * .5;
+ int wh = std::min (width, height);
+ const double y = height * .5;
+ const double x = width - wh * .5;
wh *= .18;
const float tri = ceil(.577 * wh * 2); // 1/sqrt(3)
- const float ln = std::min (get_width(), get_height()) * .07;
+ const float ln = std::min (width, height) * .07;
- if (_icon == TransportStart || _icon == TransportRange) {
+ if (icon == ArdourButton::TransportStart || icon == ArdourButton::TransportRange) {
cairo_rectangle (cr,
- x - wh - ln, y - tri * 1.7,
- ln * 2, tri * 3.4);
+ x - wh - ln, y - tri * 1.7,
+ ln * 2, tri * 3.4);
VECTORICONSTROKEFILL(1.0);
}
- if (_icon == TransportEnd || _icon == TransportRange) {
+ if (icon == ArdourButton::TransportEnd || icon == ArdourButton::TransportRange) {
cairo_rectangle (cr,
- x + wh - ln, y - tri * 1.7,
- ln * 2, tri * 3.4);
+ x + wh - ln, y - tri * 1.7,
+ ln * 2, tri * 3.4);
VECTORICONSTROKEFILL(1.0);
}
- if (_icon == TransportStart) {
+ if (icon == ArdourButton::TransportStart) {
cairo_move_to (cr, x - wh, y);
cairo_line_to (cr, x + wh, y - tri);
cairo_line_to (cr, x + wh, y + tri);
@@ -543,9 +467,11 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_close_path (cr);
VECTORICONSTROKEFILL(1.0);
}
- else if ((_elements & VectorIcon) && _icon == TransportLoop) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ break;
+ case ArdourButton::TransportLoop:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double r = std::min(x, y);
cairo_arc (cr, x, y, r * .62, 0, 2 * M_PI);
@@ -568,17 +494,19 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
cairo_fill(cr);
#undef ARCARROW
}
- else if ((_elements & VectorIcon) && _icon == TransportMetronom) {
- const double x = get_width() * .5;
- const double y = get_height() * .5;
+ break;
+ case ArdourButton::TransportMetronom:
+ {
+ const double x = width * .5;
+ const double y = height * .5;
const double wh = std::min(x, y);
const double h = wh * .85;
const double w = wh * .55;
const double lw = w * .34;
cairo_rectangle (cr,
- x - w * .7, y + h * .25,
- w * 1.4, lw);
+ x - w * .7, y + h * .25,
+ w * 1.4, lw);
VECTORICONSTROKEFILL(1.0);
@@ -611,15 +539,137 @@ ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
VECTORICONSTROKEFILL(1.0);
cairo_rectangle (cr,
- x - w * .7, y + h * .25,
- w * 1.4, lw);
+ x - w * .7, y + h * .25,
+ w * 1.4, lw);
cairo_fill(cr);
}
- else if (_elements & VectorIcon) {
+ break;
+ default:
// missing icon
assert(0);
- }
+ } // end case(icon)
#undef VECTORICONSTROKEFILL
+}
+
+void
+ArdourButton::render (cairo_t* cr, cairo_rectangle_t *)
+{
+ uint32_t text_color;
+ uint32_t led_color;
+
+ const float corner_radius = std::max(2.f, _corner_radius * ARDOUR_UI::ui_scale);
+
+ if (_update_colors) {
+ set_colors ();
+ }
+ if (get_height() != _pattern_height) {
+ build_patterns ();
+ }
+
+ if ( active_state() == Gtkmm2ext::ExplicitActive ) {
+ text_color = text_active_color;
+ led_color = led_active_color;
+ } else {
+ text_color = text_inactive_color;
+ led_color = led_inactive_color;
+ }
+
+ if (use_custom_led_color) {
+ led_color = led_custom_color;
+ }
+
+ void (*rounded_function)(cairo_t*, double, double, double, double, double);
+
+ switch (_corner_mask) {
+ case 0x1: /* upper left only */
+ rounded_function = Gtkmm2ext::rounded_top_left_rectangle;
+ break;
+ case 0x2: /* upper right only */
+ rounded_function = Gtkmm2ext::rounded_top_right_rectangle;
+ break;
+ case 0x3: /* upper only */
+ rounded_function = Gtkmm2ext::rounded_top_rectangle;
+ break;
+ /* should really have functions for lower right, lower left,
+ lower only, but for now, we don't
+ */
+ default:
+ rounded_function = Gtkmm2ext::rounded_rectangle;
+ }
+
+ // draw edge (filling a rect underneath, rather than stroking a border on top, allows the corners to be lighter-weight.
+ if ((_elements & (Body|Edge)) == (Body|Edge)) {
+ rounded_function (cr, 0, 0, get_width(), get_height(), corner_radius + 1.5);
+ cairo_set_source_rgba (cr, 0, 0, 0, 1);
+ cairo_fill(cr);
+ }
+
+ // background fill
+ 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);
+ cairo_fill (cr);
+ } else if ( (active_state() == Gtkmm2ext::ExplicitActive) && !((_elements & Indicator)==Indicator) ) {
+ //background color
+ ArdourCanvas::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);
+ }
+ cairo_fill (cr);
+ }
+
+ // IMPLICIT ACTIVE: draw a border of the active color
+ if ((_elements & Body)==Body) {
+ 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);
+ cairo_stroke (cr);
+ }
+ }
+
+ //show the "convex" or "concave" gradient
+ if (!_flat_buttons) {
+ if ( active_state() == Gtkmm2ext::ExplicitActive && ( !((_elements & Indicator)==Indicator) || use_custom_led_color) ) {
+ //concave
+ cairo_set_source (cr, concave_pattern);
+ Gtkmm2ext::rounded_rectangle (cr, 1, 1, get_width() - 2, get_height() - 2, corner_radius);
+ cairo_fill (cr);
+ } else {
+ cairo_set_source (cr, convex_pattern);
+ Gtkmm2ext::rounded_rectangle (cr, 1, 1, get_width() - 2, get_height() - 2, corner_radius);
+ cairo_fill (cr);
+ }
+ }
+
+ //Pixbuf, if any
+ if (_pixbuf) {
+ double x = rint((get_width() - _pixbuf->get_width()) * .5);
+ const double y = rint((get_height() - _pixbuf->get_height()) * .5);
+#if 0 // DEBUG style (print on hover)
+ if (_hovering || (_elements & Inactive)) {
+ printf("%s: p:%dx%d (%dx%d)\n",
+ get_name().c_str(),
+ _pixbuf->get_width(), _pixbuf->get_height(),
+ get_width(), get_height());
+ }
+#endif
+ if (_elements & Menu) {
+ //if this is a DropDown with an icon, then we need to
+ //move the icon left slightly to accomomodate the arrow
+ x -= _diameter - 2;
+ }
+ cairo_rectangle (cr, x, y, _pixbuf->get_width(), _pixbuf->get_height());
+ gdk_cairo_set_source_pixbuf (cr, _pixbuf->gobj(), x, y);
+ cairo_fill (cr);
+ }
+ else /* VectorIcons are exclusive to Pixbuf Icons */
+ if (_elements & VectorIcon) {
+ render_vector_icon (cr, _icon, get_width(), get_height(), active_state(), text_color);
+ }
const int text_margin = char_pixel_width();
// Text, if any