diff options
Diffstat (limited to 'src/blocks/slider.c')
| -rw-r--r-- | src/blocks/slider.c | 122 |
1 files changed, 87 insertions, 35 deletions
diff --git a/src/blocks/slider.c b/src/blocks/slider.c index f80c71b..98ce645 100644 --- a/src/blocks/slider.c +++ b/src/blocks/slider.c @@ -2,6 +2,7 @@ #include <stdio.h> #include <assert.h> #include <stdlib.h> +#include <math.h> #include "../block.h" #include "../format.h" @@ -9,13 +10,9 @@ typedef enum { KNOB_NONE, - KNOB_CIRCLE, - //KNOB_CAPSULE, + KNOB_CAPSULE, KNOB_TRIANGLE, - //KNOB_TRIANGLE_UP, - //KNOB_TRIANGLE_DOWN, - //KNOB_TRIANGLE_LEFT, - //KNOB_TRIANGLE_RIGHT, + KNOB_RECTANGLE, } block_slider_knob_t; typedef struct { @@ -30,11 +27,13 @@ typedef struct { bool seekable; block_slider_knob_t knob; unsigned int knob_height; + unsigned int knob_width; unsigned int knob_line_width; int knob_x_offset; int knob_y_offset; gradient_t knob_color; gradient_t knob_line_color; + double knob_rotation; } block_slider_t; static void block_slider_layout(block_t *block, layout_t *layout, layout_info_t info) @@ -66,7 +65,7 @@ static void block_slider_render(layout_t *layout, cairo_t *cr) pattern = slider->bar_color.pattern; if (pattern != NULL) { - int current = slider->width * (slider->value / 100.0); + int current = (slider->width * slider->value) / 100; render_capsule(cr, bar_x, bar_y, current, radius, radius); cairo_pattern_set_matrix(pattern, &matrix); @@ -85,48 +84,84 @@ static void block_slider_render(layout_t *layout, cairo_t *cr) cairo_stroke(cr); } - if (slider->knob == KNOB_NONE) return; + if (slider->knob == KNOB_NONE || slider->knob_width == 0 || slider->knob_height == 0) + return; - int knob_height = slider->knob_height != 0 ? slider->knob_height : slider->height; + int knob_height = slider->knob_height; + int knob_width = slider->knob_width; int knob_radius = knob_height / 2; - const double sqrt3 = 1.7320508075688772; - int knob_width = slider->knob == KNOB_TRIANGLE - ? (knob_height * sqrt3) / 2.0 - : knob_height; + int knob_rw = knob_width * cos(slider->knob_rotation) + knob_height * sin(slider->knob_rotation); + int current = (slider->value * (slider->width - knob_rw)) / 100; - // FIXME - int current = (slider->width - knob_width) * slider->value / 100.0; - - int knob_x = bar_x + slider->knob_x_offset + current; + int knob_x = bar_x + slider->line_width + slider->knob_x_offset + current - knob_rw / 2; int knob_y = bar_y + slider->knob_y_offset + radius - knob_radius; + int t_x = knob_x + knob_width / 2; + int t_y = knob_y + knob_height / 2; + pattern = slider->knob_color.pattern; if (pattern != NULL) { - - if (slider->knob == KNOB_TRIANGLE) - render_triangle(cr, knob_x, knob_y, knob_width, knob_height); - else if (slider->knob == KNOB_CIRCLE) - render_capsule(cr, knob_x, knob_y, knob_width, knob_radius, knob_radius); - cairo_pattern_set_matrix(pattern, &matrix); cairo_set_source(cr, pattern); + cairo_save(cr); + + cairo_translate(cr, t_x, t_y); + cairo_rotate(cr, slider->knob_rotation); + cairo_translate(cr, -t_x, -t_y); + + switch (slider->knob) { + case KNOB_CAPSULE: + render_capsule(cr, knob_x, knob_y, knob_width, knob_radius, knob_radius); + break; + + case KNOB_TRIANGLE: + render_triangle(cr, knob_x, knob_y, knob_width, knob_height); + break; + + case KNOB_RECTANGLE: + cairo_rectangle(cr, knob_x, knob_y, knob_width, knob_height); + break; + + default: + unreachable(); + } + + cairo_restore(cr); cairo_fill(cr); } pattern = slider->knob_line_color.pattern; if (pattern != NULL) { - int line_radius = knob_radius - slider->knob_line_width / 2; - - if (slider->knob == KNOB_TRIANGLE) - render_triangle(cr, knob_x, knob_y, knob_width, knob_height); - else if (slider->knob == KNOB_CIRCLE) - render_capsule(cr, knob_x, knob_y, knob_width, knob_radius, line_radius); - - cairo_pattern_set_matrix(pattern, &matrix); cairo_set_source(cr, pattern); cairo_set_line_width(cr, slider->knob_line_width); + cairo_save(cr); + + cairo_translate(cr, t_x, t_y); + cairo_rotate(cr, slider->knob_rotation); + cairo_translate(cr, -t_x, -t_y); + + switch (slider->knob) { + case KNOB_CAPSULE: { + int line_radius = knob_radius - slider->knob_line_width / 2; + render_capsule(cr, knob_x, knob_y, knob_width, knob_radius, line_radius); + break; + } + + case KNOB_TRIANGLE: + render_triangle(cr, knob_x, knob_y, knob_width, knob_height); + break; + + case KNOB_RECTANGLE: + cairo_rectangle(cr, knob_x, knob_y, knob_width, knob_height); + break; + + default: + unreachable(); + } + + cairo_restore(cr); cairo_stroke(cr); } } @@ -175,6 +210,8 @@ static void block_slider_clean(block_t *block) gradient_free(&slider->bar_color); gradient_free(&slider->line_color); gradient_free(&slider->bg_color); + gradient_free(&slider->knob_color); + gradient_free(&slider->knob_line_color); } static int block_slider_validate(block_t *block, const block_scheme_t *scheme) @@ -187,14 +224,27 @@ static int block_slider_validate(block_t *block, const block_scheme_t *scheme) errors++; } + if (slider->knob_width < slider->knob_height) { + log_error("Block '%s' requires '%s' greater than '%s'", block->label, "knob-width", "knob-height"); + errors++; + } + + if (fabs(slider->knob_rotation) > 360.0) { + log_error("Block '%s' requires '%s' to be at most 360", block->label, "knob-rotation"); + errors++; + } + + const double degree = M_PI / 180.0; + slider->knob_rotation *= degree; + return errors; } static config_enum_t knob_shape_enum[] = { - { "none", KNOB_NONE }, - { "circle", KNOB_CIRCLE }, - //{ "capsule", KNOB_CAPSULE }, - { "triangle", KNOB_TRIANGLE }, + { "none", KNOB_NONE }, + { "capsule", KNOB_CAPSULE }, + { "triangle", KNOB_TRIANGLE }, + { "rectangle", KNOB_RECTANGLE }, { 0 }, }; @@ -210,11 +260,13 @@ static const config_entry_t block_slider_entries[] = { { "seekable", CONFIG_BOOL, NULL, offsetof(block_slider_t, seekable) }, { "knob", CONFIG_ENUM, knob_shape_enum, offsetof(block_slider_t, knob) }, { "knob-height", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_height) }, + { "knob-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_width) }, { "knob-line-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_line_width) }, { "knob-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_color) }, { "knob-line-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_line_color) }, { "knob-x-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_x_offset) }, { "knob-y-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_y_offset) }, + { "knob-rotation", CONFIG_DOUBLE, NULL, offsetof(block_slider_t, knob_rotation) }, { 0 }, }; |
