Mercurial > molko
changeset 606:35e58271d820
ui: do the same with checkbox
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 11 Aug 2023 12:58:02 +0200 |
parents | a8094fad01a1 |
children | 8444f83d48af |
files | examples/example-ui/example-ui.c libmlk-ui/mlk/ui/checkbox.c libmlk-ui/mlk/ui/checkbox.h |
diffstat | 3 files changed, 239 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-ui/example-ui.c Fri Aug 11 19:22:00 2023 +0200 +++ b/examples/example-ui/example-ui.c Fri Aug 11 12:58:02 2023 +0200 @@ -125,7 +125,9 @@ .autosave = { .cb = { .w = ELEMENT_HEIGHT, - .h = ELEMENT_HEIGHT + .h = ELEMENT_HEIGHT, + .delegate = &mlk_checkbox_delegate, + .style = &mlk_style }, .label = { .text = "Auto save game",
--- a/libmlk-ui/mlk/ui/checkbox.c Fri Aug 11 19:22:00 2023 +0200 +++ b/libmlk-ui/mlk/ui/checkbox.c Fri Aug 11 12:58:02 2023 +0200 @@ -17,75 +17,28 @@ */ #include <assert.h> -#include <string.h> #include <mlk/core/event.h> #include <mlk/core/maths.h> #include <mlk/core/painter.h> #include "checkbox.h" -#include "ui.h" -#include "ui_p.h" +#include "style.h" -static int +static inline int is_boxed(const struct mlk_checkbox *cb, const struct mlk_event_click *click) { - assert(cb); assert(click && click->type == MLK_EVENT_CLICKDOWN); return mlk_maths_is_boxed(click->x, click->y, cb->x, cb->y, cb->w, cb->h); } -static void -draw(struct mlk_checkbox_delegate *delegate, const struct mlk_checkbox *cb) +static int +handle(struct mlk_checkbox_delegate *self, + struct mlk_checkbox *cb, + const union mlk_event *ev) { - (void)delegate; - - const struct mlk_checkbox_style *style = MLK__STYLE(cb, mlk_checkbox_style); - - if (!style->border_size) { - mlk_painter_set_color(style->bg_color); - mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h); - } else { - mlk_painter_set_color(style->border_color); - mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h); - mlk_painter_set_color(style->bg_color); - mlk_painter_draw_rectangle( - cb->x + style->border_size, - cb->y + style->border_size, - cb->w - (style->border_size * 2), - cb->h - (style->border_size * 2) - ); - } - - if (cb->checked) { - mlk_painter_set_color(style->check_color); - mlk_painter_draw_rectangle(cb->x + 5, cb->y + 5, cb->w - 10, cb->h - 10); - } -} - -struct mlk_checkbox_style mlk_checkbox_style = { - .bg_color = MLK_UI_COLOR_BG, - .check_color = MLK_UI_COLOR_TEXT, - .border_color = MLK_UI_COLOR_BORDER, - .border_size = 1 -}; - -struct mlk_checkbox_delegate mlk_checkbox_delegate = { - .draw = draw -}; - -int -mlk_checkbox_ok(const struct mlk_checkbox *cb) -{ - return cb != NULL; -} - -int -mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev) -{ - assert(mlk_checkbox_ok(cb)); - assert(ev); + (void)self; switch (ev->type) { case MLK_EVENT_CLICKDOWN: @@ -99,18 +52,90 @@ return 0; } +static void +draw(struct mlk_checkbox_delegate *self, const struct mlk_checkbox *cb) +{ + (void)self; + + const struct mlk_style_attr *attr = &cb->style->normal; + + if (!attr->geo.border) { + mlk_painter_set_color(attr->color.bg); + mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h); + } else { + mlk_painter_set_color(attr->color.border); + mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h); + mlk_painter_set_color(attr->color.bg); + mlk_painter_draw_rectangle( + cb->x + attr->geo.border, + cb->y + attr->geo.border, + cb->w - (attr->geo.border * 2), + cb->h - (attr->geo.border * 2) + ); + } + + if (cb->checked) { + mlk_painter_set_color(attr->color.fg); + mlk_painter_draw_rectangle(cb->x + 5, cb->y + 5, cb->w - 10, cb->h - 10); + } +} + +struct mlk_checkbox_delegate mlk_checkbox_delegate = { + .handle = handle, + .draw = draw +}; + +void +mlk_checkbox_init(struct mlk_checkbox *cb, + struct mlk_checkbox_delegate *dt, + struct mlk_style *st) +{ + assert(cb); + + cb->x = 0; + cb->y = 0; + cb->w = 0; + cb->h = 0; + cb->checked = 0; + cb->delegate = dt ? dt : &mlk_checkbox_delegate; + cb->style = st ? st : &mlk_style; +} + +int +mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev) +{ + assert(cb); + assert(ev); + + if (cb->delegate->handle) + return cb->delegate->handle(cb->delegate, cb, ev); + + return 0; +} + void mlk_checkbox_update(struct mlk_checkbox *cb, unsigned int ticks) { - assert(mlk_checkbox_ok(cb)); + assert(cb); - MLK__DELEGATE_INVOKE(cb->delegate, mlk_checkbox_delegate, update, cb, ticks); + if (cb->delegate->update) + cb->delegate->update(cb->delegate, cb, ticks); } void mlk_checkbox_draw(const struct mlk_checkbox *cb) { - assert(mlk_checkbox_ok(cb)); + assert(cb); + + if (cb->delegate->draw) + cb->delegate->draw(cb->delegate, cb); +} - MLK__DELEGATE_INVOKE(cb->delegate, mlk_checkbox_delegate, draw, cb); +void +mlk_checkbox_finish(struct mlk_checkbox *cb) +{ + assert(cb); + + if (cb->delegate->finish) + cb->delegate->finish(cb->delegate, cb); }
--- a/libmlk-ui/mlk/ui/checkbox.h Fri Aug 11 19:22:00 2023 +0200 +++ b/libmlk-ui/mlk/ui/checkbox.h Fri Aug 11 12:58:02 2023 +0200 @@ -19,49 +19,181 @@ #ifndef MLK_UI_CHECKBOX_H #define MLK_UI_CHECKBOX_H -union mlk_event; +/** + * \file mlk/ui/checkbox.h + * \brief GUI checkbox. + */ struct mlk_checkbox; +struct mlk_checkbox_delegate; +struct mlk_style; -struct mlk_checkbox_style { - unsigned long bg_color; - unsigned long check_color; - unsigned long border_color; - unsigned int border_size; +union mlk_event; + +/** + * \struct mlk_checkbox + * \brief UI clickable checkbox. + */ +struct mlk_checkbox { + /** + * (read-write) + * + * Position in x. + */ + int x; + + /** + * (read-write) + * + * Position in y. + */ + int y; + + /** + * (read-write) + * + * Checkbox width. + */ + unsigned int w; + + /** + * (read-write) + * + * Checkbox height. + */ + unsigned int h; + + /** + * (read-write) + * + * Checkbox status, non-zero if activated. + */ + int checked; + + /** + * (read-write, borrowed) + * + * Checkbox delegate. + */ + struct mlk_checkbox_delegate *delegate; + + /** + * (read-write, borrowed) + * + * Checkbox style. + */ + struct mlk_style *style; }; +/** + * \struct mlk_checkbox_delegate + * \brief Checkbox delegate. + */ struct mlk_checkbox_delegate { + /* + * (read-write, borrowed, optional) + * + * Arbitrary user data. + */ void *data; - void (*update)(struct mlk_checkbox_delegate *, struct mlk_checkbox *, unsigned int); - void (*draw)(struct mlk_checkbox_delegate *, const struct mlk_checkbox *); + + /** + * (read-write, optional) + * + * Handle an event. + * + * \param self this delegate + * \param cb the checkbox + * \param ev the event + * \return the current checkbox status (1 or 0) + */ + int (*handle)(struct mlk_checkbox_delegate *self, + struct mlk_checkbox *cb, + const union mlk_event *ev); + + /** + * (read-write, optional) + * + * Update the checkbox. + * + * \param self this delegate + * \param cb the checkbox to update + * \param ticks number of ticks since last frame + */ + void (*update)(struct mlk_checkbox_delegate *self, + struct mlk_checkbox *cb, + unsigned int ticks); + + /** + * (read-write, optional) + * + * Draw this checkbox. + * + * \param self this delegate + * \param cb the checkbox to update + */ + void (*draw)(struct mlk_checkbox_delegate *self, + const struct mlk_checkbox *cb); + + /** + * (read-write, optional) + * + * Cleanup this delegate associated with the checkbox. + * + * \param self this delegate + * \param cb the underlying checkbox + */ + void (*finish)(struct mlk_checkbox_delegate *self, + struct mlk_checkbox *cb); }; -struct mlk_checkbox { - int x, y; - unsigned int w, h; - int checked; - struct mlk_checkbox_delegate *delegate; - struct mlk_checkbox_style *style; -}; - -extern struct mlk_checkbox_style mlk_checkbox_style; +/** + * \brief Default stateless delegate for checkbox. + */ extern struct mlk_checkbox_delegate mlk_checkbox_delegate; #if defined(__cplusplus) extern "C" { #endif -int -mlk_checkbox_ok(const struct mlk_checkbox *cb); +/** + * Initialize the checkbox with default values. + * + * This is not required if you use designated initializers. + * + * \pre cb != NULL + * \param cb the checkbox to default initialize + * \param st style to use (or NULL to use a default) + * \param dt delegate to use (or NULL to use a default) + */ +void +mlk_checkbox_init(struct mlk_checkbox *cb, + struct mlk_checkbox_delegate *dt, + struct mlk_style *st); +/** + * Invoke ::mlk_checkbox_delegate::update. + */ int -mlk_checkbox_handle(struct mlk_checkbox *, const union mlk_event *); +mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev); +/** + * Invoke ::mlk_checkbox_delegate::update. + */ void mlk_checkbox_update(struct mlk_checkbox *cb, unsigned int ticks); +/** + * Invoke ::mlk_checkbox_delegate::draw. + */ void -mlk_checkbox_draw(const struct mlk_checkbox *); +mlk_checkbox_draw(const struct mlk_checkbox *cb); + +/** + * Invoke ::mlk_checkbox_delegate::finish. + */ +void +mlk_checkbox_finish(struct mlk_checkbox *cb); #if defined(__cplusplus) }