# HG changeset patch # User David Demelier # Date 1691690220 -7200 # Node ID ed1d3244ed5701668c283f2647ec01a2d40ed7dc # Parent 7e168493f0bd11e5d9c267c757a84bc8b3a970c1 ui: start re-working delegates diff -r 7e168493f0bd -r ed1d3244ed57 examples/example-font/example-font.c --- a/examples/example-font/example-font.c Thu Aug 10 21:16:05 2023 +0200 +++ b/examples/example-font/example-font.c Thu Aug 10 19:57:00 2023 +0200 @@ -97,7 +97,7 @@ { (void)st; - struct mlk_font *font = mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + struct mlk_font *font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; struct mlk_texture tex; mlk_painter_set_color(MLK_EXAMPLE_BG); diff -r 7e168493f0bd -r ed1d3244ed57 examples/example-label/example-label.c --- a/examples/example-label/example-label.c Thu Aug 10 21:16:05 2023 +0200 +++ b/examples/example-label/example-label.c Thu Aug 10 19:57:00 2023 +0200 @@ -31,29 +31,20 @@ #include #include +#include #include #include #include -static struct mlk_label_style style = { - .color = 0x005162ff -}; - -/* - * Add a glower effect to the main label in the middle. - */ -static void main_update(struct mlk_label_delegate *, struct mlk_label *, unsigned int); - -static struct mlk_glower main_glower = { +/* Custom delegate/style for glowing one. */ +static struct mlk_style style_glow; +static struct mlk_label_delegate delegate_glow; +static struct mlk_glower glower = { .start = 0xffce7fff, .end = 0xd58d6bff, .delay = 22 }; -static struct mlk_label_delegate main_delegate = { - .update = main_update -}; -static struct mlk_label_style main_style; static struct { enum mlk_align align; @@ -63,80 +54,89 @@ .align = MLK_ALIGN_CENTER, .label = { .text = "The world is Malikania.", - .style = &main_style, - .delegate = &main_delegate + .style = &style_glow, + .delegate = &delegate_glow } }, { .align = MLK_ALIGN_TOP_LEFT, .label = { .text = "Top left", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_TOP, .label = { .text = "Top", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_TOP_RIGHT, .label = { .text = "Top right", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_RIGHT, .label = { .text = "Right", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_BOTTOM_RIGHT, .label = { .text = "Bottom right", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_BOTTOM, .label = { .text = "Bottom", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_BOTTOM_LEFT, .label = { .text = "Bottom left", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } }, { .align = MLK_ALIGN_LEFT, .label = { .text = "Left", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate } } }; static struct mlk_label mouse_label = { .text = "This one follows your mouse and is not aligned.", - .style = &style + .style = &mlk_style, + .delegate = &mlk_label_delegate }; static void -main_update(struct mlk_label_delegate *delegate, struct mlk_label *label, unsigned int ticks) +delegate_glow_update(struct mlk_label_delegate *self, struct mlk_label *label, unsigned int ticks) { - (void)delegate; + (void)self; - mlk_glower_update(&main_glower, ticks); - label->style->color = main_glower.color; + mlk_glower_update(&glower, ticks); + label->style->text_color = glower.color; } static void @@ -154,7 +154,15 @@ mlk_align(table[i].align, &l->x, &l->y, w, h, 0, 0, mlk_window.w, mlk_window.h); } - mlk_glower_init(&main_glower); + mlk_glower_init(&glower); + + /* Change default style. */ + mlk_style.text_color = 0x005162ff; + + /* Copy default label delegate and style and adapt. */ + style_glow = mlk_style; + delegate_glow = mlk_label_delegate; + delegate_glow.update = delegate_glow_update; } static void diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-example/mlk/example/trace-hud.c --- a/libmlk-example/mlk/example/trace-hud.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-example/mlk/example/trace-hud.c Thu Aug 10 19:57:00 2023 +0200 @@ -90,7 +90,7 @@ struct mlk_font *font; unsigned fh; - font = mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; fh = mlk_font_height(font); for (int i = 0; i < LINES_MAX && data.lines[i][0]; ++i) { diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-rpg/mlk/rpg/message.c --- a/libmlk-rpg/mlk/rpg/message.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-rpg/mlk/rpg/message.c Thu Aug 10 19:57:00 2023 +0200 @@ -44,7 +44,7 @@ if (style->text_font) return style->text_font; - return mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + return &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; } static unsigned int diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/CMakeLists.txt --- a/libmlk-ui/CMakeLists.txt Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/CMakeLists.txt Thu Aug 10 19:57:00 2023 +0200 @@ -28,6 +28,7 @@ ${libmlk-ui_SOURCE_DIR}/mlk/ui/gridmenu.c ${libmlk-ui_SOURCE_DIR}/mlk/ui/label.c ${libmlk-ui_SOURCE_DIR}/mlk/ui/notify.c + ${libmlk-ui_SOURCE_DIR}/mlk/ui/style.c ${libmlk-ui_SOURCE_DIR}/mlk/ui/ui.c ${libmlk-ui_SOURCE_DIR}/mlk/ui/ui_p.h ) @@ -42,6 +43,7 @@ ${libmlk-ui_SOURCE_DIR}/mlk/ui/gridmenu.h ${libmlk-ui_SOURCE_DIR}/mlk/ui/label.h ${libmlk-ui_SOURCE_DIR}/mlk/ui/notify.h + ${libmlk-ui_SOURCE_DIR}/mlk/ui/style.h ${libmlk-ui_SOURCE_DIR}/mlk/ui/ui.h ) diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/button.c --- a/libmlk-ui/mlk/ui/button.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/button.c Thu Aug 10 19:57:00 2023 +0200 @@ -48,7 +48,7 @@ if (style->text_font) return style->text_font; - return mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + return &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; } static void diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/debug.c --- a/libmlk-ui/mlk/ui/debug.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/debug.c Thu Aug 10 19:57:00 2023 +0200 @@ -66,7 +66,7 @@ vsnprintf(line, sizeof (line), fmt, ap); // TODO: add style support. - font = mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; if (mlk_font_render(font, &tex, line, MLK_UI_COLOR_DEBUG) < 0) return; diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/gridmenu.c --- a/libmlk-ui/mlk/ui/gridmenu.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/gridmenu.c Thu Aug 10 19:57:00 2023 +0200 @@ -44,7 +44,7 @@ if (style && style->text_font) return style->text_font; - return mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + return &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; } static struct index diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/label.c --- a/libmlk-ui/mlk/ui/label.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/label.c Thu Aug 10 19:57:00 2023 +0200 @@ -17,56 +17,34 @@ */ #include -#include -#include #include -#include -#include #include "align.h" #include "label.h" +#include "style.h" #include "ui.h" -#include "ui_p.h" - -static inline struct mlk_font * -style_font(const struct mlk_label *label) -{ - const struct mlk_label_style *style = MLK__STYLE(label, mlk_label_style); - - if (style->font) - return style->font; - - return mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; -} static int -delegate_query(struct mlk_label_delegate *delegate, const struct mlk_label *label, unsigned int *w, unsigned *h) +query(struct mlk_label_delegate *self, + const struct mlk_label *label, + unsigned int *w, + unsigned int *h) { - (void)delegate; - - struct mlk_font *font; - int err; + (void)self; - font = style_font(label); - - if ((err = mlk_font_query(font, label->text, w, h)) < 0) - return err; - - return 0; + return mlk_font_query(label->style->text_font, label->text, w, h); } static void -delegate_draw(struct mlk_label_delegate *delegate, const struct mlk_label *label) +draw(struct mlk_label_delegate *self, const struct mlk_label *label) { - (void)delegate; - - const struct mlk_label_style *style = MLK__STYLE(label, mlk_label_style); + (void)self; mlk_ui_draw_text( MLK_ALIGN_NONE, - style_font(label), - style->color, + label->style->text_font, + label->style->text_color, label->text, label->x, label->y, @@ -75,27 +53,32 @@ ); } -struct mlk_label_style mlk_label_style = { - .color = MLK_UI_COLOR_TEXT +struct mlk_label_delegate mlk_label_delegate = { + .query = query, + .draw = draw }; -struct mlk_label_delegate mlk_label_delegate = { - .query = delegate_query, - .draw = delegate_draw -}; +void +mlk_label_init(struct mlk_label *lbl, + struct mlk_style *st, + struct mlk_label_delegate *dt) +{ + assert(lbl); -int -mlk_label_ok(const struct mlk_label *label) -{ - return label && label->text && strlen(label->text) > 0; + lbl->x = 0; + lbl->y = 0; + lbl->text = ""; + lbl->style = st ? st : &mlk_style; + lbl->delegate = dt ? dt : &mlk_label_delegate; } int -mlk_label_query(const struct mlk_label *label, unsigned int *w, unsigned int *h) +mlk_label_query(const struct mlk_label *lbl, unsigned int *w, unsigned int *h) { - assert(mlk_label_ok(label)); + assert(lbl); - MLK__DELEGATE_INVOKE_RET(label->delegate, mlk_label_delegate, query, label, w, h); + if (lbl->delegate->query) + return lbl->delegate->query(lbl->delegate, lbl, w, h); if (w) *w = 0; @@ -106,17 +89,28 @@ } void -mlk_label_update(struct mlk_label *label, unsigned int ticks) +mlk_label_update(struct mlk_label *lbl, unsigned int ticks) { - assert(mlk_label_ok(label)); + assert(lbl); - MLK__DELEGATE_INVOKE(label->delegate, mlk_label_delegate, update, label, ticks); + if (lbl->delegate->update) + lbl->delegate->update(lbl->delegate, lbl, ticks); } void -mlk_label_draw(const struct mlk_label *label) +mlk_label_draw(const struct mlk_label *lbl) { - assert(mlk_label_ok(label)); + assert(lbl); + + if (lbl->delegate->draw) + lbl->delegate->draw(lbl->delegate, lbl); +} - MLK__DELEGATE_INVOKE(label->delegate, mlk_label_delegate, draw, label); +void +mlk_label_finish(struct mlk_label *lbl) +{ + assert(lbl); + + if (lbl->delegate->finish) + lbl->delegate->finish(lbl->delegate, lbl); } diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/label.h --- a/libmlk-ui/mlk/ui/label.h Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/label.h Thu Aug 10 19:57:00 2023 +0200 @@ -19,46 +19,167 @@ #ifndef MLK_UI_LABEL_H #define MLK_UI_LABEL_H -struct mlk_font; +/** + * \file label.h + * \brief GUI label. + */ + struct mlk_label; +struct mlk_label_delegate; +struct mlk_style; -struct mlk_label_style { - unsigned long color; - struct mlk_font *font; -}; +/** + * \struct mlk_label + * \brief UI label text. + */ +struct mlk_label { + /** + * (read-write) + * + * Position in x. + */ + int x; -struct mlk_label_delegate { - void *data; - int (*query)(struct mlk_label_delegate *, const struct mlk_label *, unsigned int *, unsigned int *); - void (*update)(struct mlk_label_delegate *, struct mlk_label *, unsigned int); - void (*draw)(struct mlk_label_delegate *, const struct mlk_label *); -}; + /** + * (read-write) + * + * Position in y. + */ + int y; -struct mlk_label { - int x, y; + /** + * (read-write, borrowed) + * + * Text to show. + */ const char *text; - struct mlk_label_style *style; + + /** + * (read-write, borrowed) + * + * Label style. + */ + struct mlk_style *style; + + /** + * (read-write, borrowed) + * + * Label delegate. + */ struct mlk_label_delegate *delegate; }; -extern struct mlk_label_style mlk_label_style; +/** + * \struct mlk_label_delegate + * \brief Label delegate. + */ +struct mlk_label_delegate { + /* + * (read-write, borrowed, optional) + * + * Arbitrary user data. + */ + void *data; + + /** + * (read-write) + * + * Query required dimensions to draw this label. + * + * \param self this delegate + * \param lbl the label to query + * \param w the width destination (maybe NULL) + * \param h the height destination (maybe NULL) + * \return 0 on success or -1 on error + */ + int (*query)(struct mlk_label_delegate *self, + const struct mlk_label *lbl, + unsigned int *w, + unsigned int *h); + + /** + * (read-write, optional) + * + * Update the label. + * + * \param self this delegate + * \param lbl the label to update + * \param ticks number of ticks since last frame + */ + void (*update)(struct mlk_label_delegate *self, + struct mlk_label *lbl, + unsigned int ticks); + + /** + * (read-write, optional) + * + * Draw this label. + * + * \param self this delegate + * \param lbl the label to update + */ + void (*draw)(struct mlk_label_delegate *self, + const struct mlk_label *lbl); + + /** + * (read-write, optional) + * + * Cleanup this delegate associated with the label. + * + * \param self this delegate + * \param lbl the underlying label + */ + void (*finish)(struct mlk_label_delegate *self, + struct mlk_label *lbl); +}; + +/** + * \brief Default stateless delegate for label. + */ extern struct mlk_label_delegate mlk_label_delegate; #if defined(__cplusplus) extern "C" { #endif -int -mlk_label_ok(const struct mlk_label *); - -int -mlk_label_query(const struct mlk_label *, unsigned int *, unsigned int *); +/** + * Initialize the label with default values. + * + * This is not required if you use designated initializers. + * + * \pre lbl != NULL + * \param lbl the label 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_label_init(struct mlk_label *lbl, + struct mlk_style *st, + struct mlk_label_delegate *dt); +/** + * Invoke ::mlk_label_delegate::query. + */ +int +mlk_label_query(const struct mlk_label *lbl, unsigned int *w, unsigned int *h); + +/** + * Invoke ::mlk_label_delegate::update. + */ void -mlk_label_update(struct mlk_label *, unsigned int ticks); +mlk_label_update(struct mlk_label *lbl, unsigned int ticks); +/** + * Invoke ::mlk_label_delegate::draw. + */ void -mlk_label_draw(const struct mlk_label *); +mlk_label_draw(const struct mlk_label *lbl); + +/** + * Invoke ::mlk_label_delegate::finish. + */ +void +mlk_label_finish(struct mlk_label *lbl); #if defined(__cplusplus) } diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/notify.c --- a/libmlk-ui/mlk/ui/notify.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/notify.c Thu Aug 10 19:57:00 2023 +0200 @@ -35,7 +35,7 @@ #define WIDTH (mlk_window.w / 2.5) #define HEIGHT (mlk_window.h / 10) #define MAX (4) -#define FONT (mlk_notify_style.text_font ? mlk_notify_style.text_font : mlk_ui_fonts[MLK_UI_FONT_INTERFACE]) +#define FONT (mlk_notify_style.text_font ? mlk_notify_style.text_font : &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]) struct geo { const struct mlk_theme *theme; @@ -66,7 +66,7 @@ y = mlk_notify_style.padding * (index + 1); y += HEIGHT * index; - font = mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; /* Content frame. */ geo->frame_x = x; diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/style.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-ui/mlk/ui/style.c Thu Aug 10 19:57:00 2023 +0200 @@ -0,0 +1,25 @@ +#include +#include + +#include "style.h" +#include "ui.h" + +struct mlk_style mlk_style = { + .padding = MLK_STYLE_PADDING, + .bg_color = MLK_STYLE_BG_COLOR, + .fg_color = MLK_STYLE_FG_COLOR, + .border_color = MLK_STYLE_BORDER_COLOR, + .border_size = MLK_STYLE_BORDER_SIZE, + .text_color = MLK_STYLE_TEXT_COLOR, + .selected_color = MLK_STYLE_SELECTED_COLOR, + .animation = MLK_STYLE_ANIMATION, + .text_font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE] +}; + +void +mlk_style_init(struct mlk_style *style) +{ + assert(style); + + memset(style, 0, sizeof (*style)); +} diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/style.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmlk-ui/mlk/ui/style.h Thu Aug 10 19:57:00 2023 +0200 @@ -0,0 +1,34 @@ +#ifndef MLK_UI_STYLE_H +#define MLK_UI_STYLE_H + +/* https://lospec.com/palette-list/duel */ + +#define MLK_STYLE_PADDING (10) +#define MLK_STYLE_BG_COLOR (0xf5f7faff) +#define MLK_STYLE_FG_COLOR (0x000000ff) +#define MLK_STYLE_BORDER_COLOR (0xcdd2daff) +#define MLK_STYLE_BORDER_SIZE (2) +#define MLK_STYLE_TEXT_COLOR (0x222323ff) +#define MLK_STYLE_SELECTED_COLOR (0x55b67dff) +#define MLK_STYLE_ANIMATION (500) + +struct mlk_font; + +struct mlk_style { + unsigned int padding; + unsigned long bg_color; + unsigned long fg_color; + unsigned long border_color; + unsigned int border_size; + unsigned long text_color; + unsigned long selected_color; + unsigned int animation; + struct mlk_font *text_font; +}; + +extern struct mlk_style mlk_style; + +void +mlk_style_init(struct mlk_style *style); + +#endif /* MLK_UI_STYLE_H */ diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/ui.c --- a/libmlk-ui/mlk/ui/ui.c Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/ui.c Thu Aug 10 19:57:00 2023 +0200 @@ -43,36 +43,33 @@ .data = b, \ .datasz = sizeof (b), \ .size = s, \ - .fontaddr = &mlk_ui_fonts[i] \ + .font = &mlk_ui_fonts[i] \ } static struct font_def { const unsigned char *data; const size_t datasz; unsigned int size; - struct mlk_font **fontaddr; - struct mlk_font font; + struct mlk_font *font; } fonts[MLK_UI_FONT_LAST] = { FONT_DEF(assets_fonts_opensans_regular, 14, MLK_UI_FONT_INTERFACE) }; -struct mlk_font *mlk_ui_fonts[MLK_UI_FONT_LAST] = {0}; +struct mlk_font mlk_ui_fonts[MLK_UI_FONT_LAST] = {0}; int mlk_ui_init(void) { struct font_def *def; - int err; /* Open all fonts and set the appropriate pointer address. */ for (size_t i = 0; i < MLK_UTIL_SIZE(fonts); ++i) { def = &fonts[i]; - if ((err = mlk_font_openmem(&def->font, def->data, def->datasz, def->size)) < 0) - goto failed; - - /* Reference this font into the catalog. */ - *fonts[i].fontaddr = &fonts[i].font; + if (mlk_font_openmem(def->font, def->data, def->datasz, def->size) < 0) { + mlk_ui_finish(); + return -1; + } } #if defined(MLK_WITH_NLS) @@ -80,11 +77,6 @@ #endif return 0; - -failed: - mlk_ui_finish(); - - return err; } void diff -r 7e168493f0bd -r ed1d3244ed57 libmlk-ui/mlk/ui/ui.h --- a/libmlk-ui/mlk/ui/ui.h Thu Aug 10 21:16:05 2023 +0200 +++ b/libmlk-ui/mlk/ui/ui.h Thu Aug 10 19:57:00 2023 +0200 @@ -20,6 +20,7 @@ #define MLK_UI_UI_H #include +#include /* TODO: make this a global variable to allow modification of default theme. */ /* https://lospec.com/palette-list/duel */ @@ -34,14 +35,12 @@ enum mlk_align; -struct mlk_font; - enum mlk_ui_font { MLK_UI_FONT_INTERFACE, MLK_UI_FONT_LAST }; -extern struct mlk_font *mlk_ui_fonts[MLK_UI_FONT_LAST]; +extern struct mlk_font mlk_ui_fonts[MLK_UI_FONT_LAST]; #if defined(__cplusplus) extern "C" {