# HG changeset patch # User David Demelier # Date 1692645870 -7200 # Node ID 509b395171f20d4d2844bd8cd5a384e1f2d3e8ab # Parent 19b195954ec39538ed9acac2627aa53a59501a9b ui: simplify button diff -r 19b195954ec3 -r 509b395171f2 examples/example-ui/button-glower.c --- a/examples/example-ui/button-glower.c Mon Aug 21 20:23:35 2023 +0200 +++ b/examples/example-ui/button-glower.c Mon Aug 21 21:24:30 2023 +0200 @@ -21,15 +21,14 @@ #include "button-glower.h" static void -update(struct mlk_button_delegate *delegate, struct mlk_button *button, unsigned int ticks) +update(struct mlk_button_style *self, struct mlk_button *button, unsigned int ticks) { - struct button_glower *glower = delegate->data; + struct button_glower *glower = self->data; /* Don't update if pressed. */ if (!button->pressed) { mlk_glower_update(&glower->glower, ticks); - glower->style.bg_color = glower->glower.color; - glower->style.pressed_bg_color = glower->glower.color; + glower->style.background = glower->glower.color; } } @@ -37,15 +36,13 @@ button_glower_init(struct button_glower *glower, struct mlk_button *button) { assert(glower); + assert(button); - glower->style.bg_color = glower->glower.start; - glower->style.pressed_bg_color = glower->glower.start; - glower->delegate.data = glower; - glower->delegate.update = update; + glower->style.background = glower->glower.start; + glower->style.data = glower; + glower->style.update = update; - /* Link this style and delegate to the button. */ button->style = &glower->style; - button->delegate = &glower->delegate; mlk_glower_init(&glower->glower); } diff -r 19b195954ec3 -r 509b395171f2 examples/example-ui/button-glower.h --- a/examples/example-ui/button-glower.h Mon Aug 21 20:23:35 2023 +0200 +++ b/examples/example-ui/button-glower.h Mon Aug 21 21:24:30 2023 +0200 @@ -30,7 +30,6 @@ struct button_glower { struct mlk_glower glower; struct mlk_button_style style; - struct mlk_button_delegate delegate; }; void diff -r 19b195954ec3 -r 509b395171f2 examples/example-ui/example-ui.c --- a/examples/example-ui/example-ui.c Mon Aug 21 20:23:35 2023 +0200 +++ b/examples/example-ui/example-ui.c Mon Aug 21 21:24:30 2023 +0200 @@ -135,10 +135,8 @@ .h = ELEMENT_HEIGHT }, .quit_style = { - .bg_color = 0x24aed6ff, - .pressed_bg_color = 0x328ca7ff, - .text_color = 0xffffffff, - .pressed_text_color = 0xffffffff + .background = 0x24aed6ff, + .color = 0xffffffff }, .quit = { .text = "Quit", @@ -152,10 +150,9 @@ .delay = BUTTON_STYLE_GLOW_DELAY }, .style = { - .text_color = 0xffffffff, - .pressed_text_color = 0xffffffff, - .border_color = BUTTON_STYLE_GLOW_COLOR_1, - .pressed_border_color = BUTTON_STYLE_GLOW_COLOR_1, + .color = 0xffffffff, + .border = BUTTON_STYLE_GLOW_COLOR_1, + .background = BUTTON_STYLE_GLOW_COLOR_1, .border_size = 2 } }, diff -r 19b195954ec3 -r 509b395171f2 libmlk-core/CMakeLists.txt --- a/libmlk-core/CMakeLists.txt Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-core/CMakeLists.txt Mon Aug 21 21:24:30 2023 +0200 @@ -26,7 +26,7 @@ ${libmlk-core_SOURCE_DIR}/mlk/core/alloc.c ${libmlk-core_SOURCE_DIR}/mlk/core/animation.c ${libmlk-core_SOURCE_DIR}/mlk/core/clock.c - ${libmlk-core_SOURCE_DIR}/mlk/core/core.c + ${libmlk-core_SOURCE_DIR}/mlk/core/color.c ${libmlk-core_SOURCE_DIR}/mlk/core/core.c ${libmlk-core_SOURCE_DIR}/mlk/core/core_p.h ${libmlk-core_SOURCE_DIR}/mlk/core/drawable-stack.c diff -r 19b195954ec3 -r 509b395171f2 libmlk-core/mlk/core/color.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-core/mlk/core/color.c Mon Aug 21 21:24:30 2023 +0200 @@ -0,0 +1,37 @@ +/* + * color.c -- basic color routines + * + * Copyright (c) 2020-2023 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "color.h" +#include "util.h" + +unsigned long +mlk_color_darken(unsigned long color, float perc) +{ + unsigned int r = MLK_COLOR_R(color) * perc; + unsigned int g = MLK_COLOR_G(color) * perc; + unsigned int b = MLK_COLOR_B(color) * perc; + unsigned int a = MLK_COLOR_A(color) * perc; + + return MLK_COLOR_HEX( + mlk_clampu(r, 0, 255), + mlk_clampu(g, 0, 255), + mlk_clampu(b, 0, 255), + mlk_clampu(a, 0, 255) + ); + +} diff -r 19b195954ec3 -r 509b395171f2 libmlk-core/mlk/core/color.h --- a/libmlk-core/mlk/core/color.h Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-core/mlk/core/color.h Mon Aug 21 21:24:30 2023 +0200 @@ -89,4 +89,7 @@ ((b << 8) & 0x0000ff00) | \ ((a) & 0x000000ff)) +unsigned long +mlk_color_darken(unsigned long color, float perc); + #endif /* !MLK_CORE_COLOR_H */ diff -r 19b195954ec3 -r 509b395171f2 libmlk-core/mlk/core/util.c --- a/libmlk-core/mlk/core/util.c Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-core/mlk/core/util.c Mon Aug 21 21:24:30 2023 +0200 @@ -52,3 +52,16 @@ return (rand() % (upper - lower)) + lower; } + +intmax_t +mlk_clampi(intmax_t v, intmax_t min, intmax_t max) +{ + return v < min ? min : v > max ? max : v; + +} + +uintmax_t +mlk_clampu(uintmax_t v, uintmax_t min, uintmax_t max) +{ + return v < min ? min : v > max ? max : v; +} diff -r 19b195954ec3 -r 509b395171f2 libmlk-core/mlk/core/util.h --- a/libmlk-core/mlk/core/util.h Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-core/mlk/core/util.h Mon Aug 21 21:24:30 2023 +0200 @@ -24,6 +24,8 @@ * \brief libmlk-core utilities */ +#include + /** * Compute the length of an fixed size array. * @@ -66,6 +68,12 @@ unsigned int mlk_util_nrand(unsigned int min, unsigned int max); +intmax_t +mlk_clampi(intmax_t v, intmax_t min, intmax_t max); + +uintmax_t +mlk_clampu(uintmax_t v, uintmax_t min, uintmax_t max); + #if defined(__cplusplus) } #endif diff -r 19b195954ec3 -r 509b395171f2 libmlk-ui/mlk/ui/button.c --- a/libmlk-ui/mlk/ui/button.c Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-ui/mlk/ui/button.c Mon Aug 21 21:24:30 2023 +0200 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -40,61 +41,35 @@ button->x, button->y, button->w, button->h); } -static inline struct mlk_font * -style_font(const struct mlk_button *button) +static void +draw_frame(struct mlk_button_style *self, struct mlk_button *button) { - const struct mlk_button_style *style = MLK__STYLE(button, mlk_button_style); - - if (style->text_font) - return style->text_font; - - return &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; -} - -static void -delegate_draw_frame(struct mlk_button_delegate *delegate, const struct mlk_button *button) -{ - (void)delegate; - - const struct mlk_button_style *style = MLK__STYLE(button, mlk_button_style); - unsigned long long border_color, bg_color; + unsigned long background = self->background; + unsigned long border = self->border; if (button->pressed) { - bg_color = style->pressed_bg_color; - border_color = style->pressed_border_color; - } else { - bg_color = style->bg_color; - border_color = style->border_color; + background = mlk_color_darken(background, 0.9); + border = mlk_color_darken(border, 0.9); } - mlk_painter_set_color(border_color); + mlk_painter_set_color(border); mlk_painter_draw_rectangle(button->x, button->y, button->w, button->h); - mlk_painter_set_color(bg_color); + mlk_painter_set_color(background); mlk_painter_draw_rectangle( - button->x + style->border_size, - button->y + style->border_size, - button->w - (style->border_size * 2), - button->h - (style->border_size * 2) + button->x + self->border_size, + button->y + self->border_size, + button->w - (self->border_size * 2), + button->h - (self->border_size * 2) ); } static void -delegate_draw_text(struct mlk_button_delegate *delegate, const struct mlk_button *button) +draw_text(struct mlk_button_style *style, struct mlk_button *button) { - (void)delegate; - - const struct mlk_button_style *style = MLK__STYLE(button, mlk_button_style); - unsigned long long text_color; - - if (button->pressed) - text_color = style->pressed_text_color; - else - text_color = style->text_color; - mlk_ui_draw_text( MLK_ALIGN_CENTER, - style_font(button), - text_color, + MLK__STYLE_FONT(style->font, MLK_UI_FONT_INTERFACE), + style->color, button->text, button->x, button->y, @@ -103,31 +78,25 @@ ); } -struct mlk_button_style mlk_button_style = { - .bg_color = MLK_UI_COLOR_BG, - .pressed_bg_color = 0xcdd2daff, - .border_color = MLK_UI_COLOR_BORDER, - .pressed_border_color = 0xa6aebaff, - .border_size = 1, - .text_color = MLK_UI_COLOR_TEXT, - .pressed_text_color = MLK_UI_COLOR_TEXT +struct mlk_button_style mlk_button_style_dark = { + .background = 0x222323ff, + .border = 0x141414ff, + .border_size = 2, + .color = 0xffffffff, + .draw_frame = draw_frame, + .draw_text = draw_text }; -struct mlk_button_delegate mlk_button_delegate = { - .draw_frame = delegate_draw_frame, - .draw_text = delegate_draw_text +struct mlk_button_style mlk_button_style_light = { + .background = 0xf5f7faff, + .border = 0xcdd2daff, + .border_size = 2, + .color = 0x000000ff, + .draw_frame = draw_frame, + .draw_text = draw_text }; -int -mlk_button_ok(const struct mlk_button *button) -{ - if (!button) - return 0; - if (button->text && strlen(button->text) == 0) - return 0; - - return 1; -} +struct mlk_button_style *mlk_button_style = &mlk_button_style_light; int mlk_button_handle(struct mlk_button *button, const union mlk_event *ev) @@ -165,16 +134,16 @@ { assert(button); - MLK__DELEGATE_INVOKE(button->delegate, mlk_button_delegate, update, button, ticks); + MLK__STYLE_CALL(button->style, mlk_button_style, update, button, ticks); } void -mlk_button_draw(const struct mlk_button *button) +mlk_button_draw(struct mlk_button *button) { assert(button); - MLK__DELEGATE_INVOKE(button->delegate, mlk_button_delegate, draw_frame, button); + MLK__STYLE_CALL(button->style, mlk_button_style, draw_frame, button); if (button->text) - MLK__DELEGATE_INVOKE(button->delegate, mlk_button_delegate, draw_text, button); + MLK__STYLE_CALL(button->style, mlk_button_style, draw_text, button); } diff -r 19b195954ec3 -r 509b395171f2 libmlk-ui/mlk/ui/button.h --- a/libmlk-ui/mlk/ui/button.h Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-ui/mlk/ui/button.h Mon Aug 21 21:24:30 2023 +0200 @@ -22,53 +22,176 @@ union mlk_event; struct mlk_button; +struct mlk_button_style; struct mlk_font; -struct mlk_button_style { - unsigned long bg_color; - unsigned long pressed_bg_color; - unsigned long border_color; - unsigned long pressed_border_color; - unsigned long border_size; - unsigned long text_color; - unsigned long pressed_text_color; - struct mlk_font *text_font; +struct mlk_button { + /** + * (read-write) + * + * Position in x. + */ + int x; + + /** + * (read-write) + * + * Position in y. + */ + int y; + + /** + * (read-write) + * + * Frame width. + */ + unsigned int w; + + /** + * (read-write) + * + * Frame height. + */ + unsigned int h; + + /** + * (read-write, borrowed, optional) + * + * Button text. + */ + const char *text; + + /** + * (read-only) + * + * Indicate if the button is pressed. + * + * This value goes non-zero when the user clicks the button even if the + * mouse is not released which is different than considered active. For + * example, if the user clicks the button but release the mouse outside + * of the button region it is no longer considered active and no action + * should be performed. + */ + int pressed; + + /** + * (read-write, borrowed, optional) + * + * Style to use for drawing this button. + */ + struct mlk_button_style *style; }; -struct mlk_button_delegate { +/** + * \struct mlk_label_button + * \brief Button style. + */ +struct mlk_button_style { + /** + * (read-write) + * + * Background color. + */ + unsigned long background; + + /** + * (read-write) + * + * Border color. + */ + unsigned long border; + + /** + * (read-write) + * + * Border size. + */ + unsigned int border_size; + + /** + * (read-write) + * + * Text color. + */ + unsigned long color; + + /** + * (read-write, borrowed, optional) + * + * Text font. + */ + struct mlk_font *font; + + /** + * (read-write, borrowed, optional) + * + * Arbitrary user data. + */ void *data; - void (*update)(struct mlk_button_delegate *delegate, struct mlk_button *button, unsigned int ticks); - void (*draw_frame)(struct mlk_button_delegate *delegate, const struct mlk_button *button); - void (*draw_text)(struct mlk_button_delegate *delegate, const struct mlk_button *button); + + /** + * (read-write, optional) + * + * Update this label. + * + * \param self this style + * \param button the button to update + * \param ticks frame ticks + */ + void (*update)(struct mlk_button_style *style, + struct mlk_button *button, + unsigned int ticks); + + /** + * (read-write, optional) + * + * Draw bounding frame owning the button. + * + * \param self this style + * \param button the button + */ + void (*draw_frame)(struct mlk_button_style *style, + struct mlk_button *button); + + /** + * (read-write, optional) + * + * Draw the butotn text. + * + * \param self this style + * \param button the button + */ + void (*draw_text)(struct mlk_button_style *style, + struct mlk_button *button); }; -struct mlk_button { - int x, y; - unsigned int w, h; - const char *text; - int pressed; - struct mlk_button_style *style; - struct mlk_button_delegate *delegate; -}; +/** + * \brief Dark default style for button. + */ +extern struct mlk_button_style mlk_button_style_dark; -extern struct mlk_button_style mlk_button_style; -extern struct mlk_button_delegate mlk_button_delegate; +/** + * \brief Light default style for button. + */ +extern struct mlk_button_style mlk_button_style_light; + +/** + * \brief Default style for all labels. + */ +extern struct mlk_button_style *mlk_button_style; #if defined(__cplusplus) extern "C" { #endif int -mlk_button_ok(const struct mlk_button *); - -int mlk_button_handle(struct mlk_button *, const union mlk_event *); void mlk_button_update(struct mlk_button *, unsigned int); void -mlk_button_draw(const struct mlk_button *); +mlk_button_draw(struct mlk_button *); #if defined(__cplusplus) } diff -r 19b195954ec3 -r 509b395171f2 libmlk-ui/mlk/ui/ui.c --- a/libmlk-ui/mlk/ui/ui.c Mon Aug 21 20:23:35 2023 +0200 +++ b/libmlk-ui/mlk/ui/ui.c Mon Aug 21 21:24:30 2023 +0200 @@ -37,6 +37,7 @@ #include #include "align.h" +#include "button.h" #include "frame.h" #include "label.h" #include "ui.h" @@ -96,11 +97,13 @@ mlk_ui_set_theme(enum mlk_window_theme theme) { if (theme == MLK_WINDOW_THEME_DARK) { + mlk_button_style = &mlk_button_style_dark; + mlk_frame_style = &mlk_frame_style_dark; mlk_label_style = &mlk_label_style_dark; - mlk_frame_style = &mlk_frame_style_dark; } else { + mlk_button_style = &mlk_button_style_light; + mlk_frame_style = &mlk_frame_style_light; mlk_label_style = &mlk_label_style_light; - mlk_frame_style = &mlk_frame_style_light; } }