Mercurial > molko
changeset 620:91ef0df9f501
ui: simplify gridmenu
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 22 Aug 2023 19:23:00 +0200 |
parents | b8fd5c112538 |
children | eecdf5140245 |
files | examples/example-gridmenu/example-gridmenu.c libmlk-ui/CMakeLists.txt libmlk-ui/mlk/ui/checkbox.c libmlk-ui/mlk/ui/gridmenu.c libmlk-ui/mlk/ui/gridmenu.h |
diffstat | 5 files changed, 176 insertions(+), 247 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-gridmenu/example-gridmenu.c Mon Aug 21 21:42:17 2023 +0200 +++ b/examples/example-gridmenu/example-gridmenu.c Tue Aug 22 19:23:00 2023 +0200 @@ -59,15 +59,13 @@ "Double tour" }; -static struct mlk_style style; - static struct mlk_gridmenu menu = { + .w = 300, + .h = 100, .nrows = 3, .ncols = 2, .items = items, - .itemsz = MLK_UTIL_SIZE(items), - .delegate = &mlk_gridmenu_delegate, - .style = &style, + .itemsz = MLK_UTIL_SIZE(items) }; static struct mlk_glower menu_glower = { .start = 0x00bfa3ff, @@ -79,7 +77,7 @@ update_color(unsigned int ticks) { mlk_glower_update(&menu_glower, ticks); - style.selected.color.text = menu_glower.color; + mlk_gridmenu_style->color_selected = menu_glower.color; } static void @@ -89,7 +87,6 @@ mlk_panic(); /* Copy style. */ - style = mlk_style; mlk_glower_init(&menu_glower); } @@ -138,7 +135,7 @@ .draw = draw, }; - mlk_gridmenu_resize(&menu, 0, 0, 300, 100); + mlk_gridmenu_resize(&menu); mlk_align(MLK_ALIGN_CENTER, &menu.x, &menu.y, menu.w, menu.h, 0, 0, mlk_window.w, mlk_window.h); mlk_game_init();
--- a/libmlk-ui/CMakeLists.txt Mon Aug 21 21:42:17 2023 +0200 +++ b/libmlk-ui/CMakeLists.txt Tue Aug 22 19:23:00 2023 +0200 @@ -28,7 +28,6 @@ ${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 ) @@ -43,7 +42,6 @@ ${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 )
--- a/libmlk-ui/mlk/ui/checkbox.c Mon Aug 21 21:42:17 2023 +0200 +++ b/libmlk-ui/mlk/ui/checkbox.c Tue Aug 22 19:23:00 2023 +0200 @@ -24,7 +24,6 @@ #include <mlk/core/painter.h> #include "checkbox.h" -#include "style.h" #include "ui_p.h" static inline int
--- a/libmlk-ui/mlk/ui/gridmenu.c Mon Aug 21 21:42:17 2023 +0200 +++ b/libmlk-ui/mlk/ui/gridmenu.c Tue Aug 22 19:23:00 2023 +0200 @@ -27,10 +27,11 @@ #include <mlk/core/trace.h> #include <mlk/core/window.h> -#include "gridmenu.h" +#include "align.h" #include "frame.h" +#include "gridmenu.h" #include "label.h" -#include "style.h" +#include "ui.h" #include "ui_p.h" struct index { @@ -89,7 +90,6 @@ { assert(click->type == MLK_EVENT_CLICKDOWN); - const struct mlk_style_attr *attr = &menu->style->normal; size_t pagesz, pagenr, selected, c = 0, r = 0; int x, y; @@ -97,8 +97,8 @@ pagenr = menu->selected / pagesz; for (size_t i = 0; i < pagesz; ++i) { - x = (int)(menu->x + attr->geo.padding + (c * menu->eltw) + (c * menu->spacew)); - y = (int)(menu->y + attr->geo.padding + (r * menu->elth) + (r * menu->spaceh)); + x = (int)(menu->x + (c * menu->eltw) + (c * menu->spacew)); + y = (int)(menu->y + (r * menu->elth) + (r * menu->spaceh)); if (mlk_maths_is_boxed(click->x, click->y, x, y, menu->eltw, menu->elth)) { selected = c + r * menu->ncols; @@ -120,73 +120,7 @@ } static void -resize(struct mlk_gridmenu_delegate *self, struct mlk_gridmenu *menu) -{ - (void)self; - - const struct mlk_style_attr *attr = &menu->style->normal; - unsigned int reqw = 0, reqh = 0, lw, lh; - - /* Compute which item has the bigger width/height to create a spacing. */ - menu->eltw = menu->elth = 0; - menu->spacew = menu->spaceh = 0; - - for (size_t i = 0; i < menu->itemsz; ++i) { - if (!(menu->items[i])) - continue; - - mlk_font_query(attr->font, menu->items[i], &lw, &lh); - - menu->eltw = fmax(menu->eltw, lw); - menu->elth = fmax(menu->elth, lh); - } - - /* Total texture size required to draw items. */ - reqw = (attr->geo.padding * 3) + (menu->eltw * menu->ncols); - reqh = (attr->geo.padding * 3) + (menu->elth * menu->nrows); - - /* - * Compute spacing between elements. We remove the padding because it - * is outside of the elements. - */ - if (reqw > menu->w) { - mlk_tracef(_("gridmenu width is too small: %u < %u"), menu->w, reqw); - menu->spacew = 1; - } else if (menu->ncols > 1) { - reqw -= attr->geo.padding * 2; - menu->spacew = (menu->w - reqw) / menu->ncols; - } - - if (reqh > menu->h) { - mlk_tracef(_("gridmenu height is too small: %u < %u"), menu->h, reqh); - menu->spaceh = 1; - } else if (menu->nrows > 1) { - reqh -= attr->geo.padding * 2; - menu->spaceh = (menu->h - reqh) / menu->nrows; - } -} - -static int -handle(struct mlk_gridmenu_delegate *self, - struct mlk_gridmenu *menu, - const union mlk_event *ev) -{ - (void)self; - - switch (ev->type) { - case MLK_EVENT_KEYDOWN: - return handle_keydown(menu, &ev->key); - case MLK_EVENT_CLICKDOWN: - return handle_clickdown(menu, &ev->click); - default: - break; - } - - return 0; -} - -static void -draw_frame(struct mlk_gridmenu_delegate *self, const struct mlk_gridmenu *menu) +draw_frame(struct mlk_gridmenu_style *self, struct mlk_gridmenu *menu) { (void)self; @@ -201,75 +135,94 @@ } static void -draw_item(struct mlk_gridmenu_delegate *self, - const struct mlk_gridmenu *menu, +draw_text(struct mlk_gridmenu_style *self, + struct mlk_gridmenu *menu, const char *item, unsigned int row, unsigned int col, int selected) { - (void)self; - (void)selected; - - struct mlk_label label = {}; + unsigned long color = selected ? self->color_selected : self->color; - label.x = menu->x + menu->style->normal.geo.padding + (col * menu->eltw) + (col * menu->spacew); - label.y = menu->y + menu->style->normal.geo.padding + (row * menu->elth) + (row * menu->spaceh); - label.text = item; - - mlk_label_draw(&label); - - // TODO: use a different style if selected. + mlk_ui_draw_text( + MLK_ALIGN_CENTER, + MLK__STYLE_FONT(self->font, MLK_UI_FONT_INTERFACE), + color, + item, + menu->x + (col * menu->eltw) + (col * menu->spacew), + menu->y + (row * menu->elth) + (row * menu->spaceh), + menu->eltw, + menu->elth + ); } -struct mlk_gridmenu_delegate mlk_gridmenu_delegate = { - .resize = resize, - .handle = handle, +struct mlk_gridmenu_style mlk_gridmenu_style_dark = { + .background = 0x222323ff, + .border = 0x141414ff, + .border_size = 2, + .color = 0xffffffff, + .color_selected = 0x518822ff, .draw_frame = draw_frame, - .draw_item = draw_item + .draw_text = draw_text }; +struct mlk_gridmenu_style mlk_gridmenu_style_light = { + .background = 0x222323ff, + .border = 0x141414ff, + .border_size = 2, + .color = 0x000000ff, + .color_selected = 0x518822ff, + .draw_frame = draw_frame, + .draw_text = draw_text +}; + +struct mlk_gridmenu_style *mlk_gridmenu_style = &mlk_gridmenu_style_light; + void -mlk_gridmenu_init(struct mlk_gridmenu *menu, - struct mlk_gridmenu_delegate *dt, - struct mlk_style *st) +mlk_gridmenu_resize(struct mlk_gridmenu *menu) { - assert(menu); + unsigned int reqw = 0, reqh = 0, lw, lh; + struct mlk_font *font; + + /* Compute which item has the bigger width/height to create a spacing. */ + menu->eltw = menu->elth = 0; + menu->spacew = menu->spaceh = 0; - menu->x = 0; - menu->y = 0; - menu->w = 0; - menu->h = 0; - menu->items = NULL; - menu->itemsz = 0; - menu->nrows = 0; - menu->ncols = 0; - menu->delegate = dt ? dt : &mlk_gridmenu_delegate; - menu->style = st ? st : &mlk_style; + /* Get appropriate font. */ + if (menu->style) + font = MLK__STYLE_FONT(menu->style->font, MLK_UI_FONT_INTERFACE); + else + font = &mlk_ui_fonts[MLK_UI_FONT_INTERFACE]; + + for (size_t i = 0; i < menu->itemsz; ++i) { + if (!(menu->items[i])) + continue; + + mlk_font_query(font, menu->items[i], &lw, &lh); - /* Can't be computed yet. */ - menu->eltw = 0; - menu->elth = 0; - menu->spacew = 0; - menu->spaceh = 0; -} + menu->eltw = fmax(menu->eltw, lw); + menu->elth = fmax(menu->elth, lh); + } + + /* Total texture size required to draw items. */ + reqw = menu->eltw * menu->ncols; + reqh = menu->elth * menu->nrows; -void -mlk_gridmenu_resize(struct mlk_gridmenu *menu, - int x, - int y, - unsigned int w, - unsigned int h) -{ - assert(menu); + /* + * Compute spacing between elements. We remove the padding because it + * is outside of the elements. + */ + if (reqw > menu->w) { + mlk_tracef(_("gridmenu width is too small: %u < %u"), menu->w, reqw); + menu->spacew = 1; + } else if (menu->ncols > 1) + menu->spacew = (menu->w - reqw) / menu->ncols; - menu->x = x; - menu->y = y; - menu->w = w; - menu->h = h; - - if (menu->delegate->resize) - menu->delegate->resize(menu->delegate, menu); + if (reqh > menu->h) { + mlk_tracef(_("gridmenu height is too small: %u < %u"), menu->h, reqh); + menu->spaceh = 1; + } else if (menu->nrows > 1) + menu->spaceh = (menu->h - reqh) / menu->nrows; } int @@ -278,8 +231,14 @@ assert(menu); assert(ev); - if (menu->delegate->handle) - return menu->delegate->handle(menu->delegate, menu, ev); + switch (ev->type) { + case MLK_EVENT_KEYDOWN: + return handle_keydown(menu, &ev->key); + case MLK_EVENT_CLICKDOWN: + return handle_clickdown(menu, &ev->click); + default: + break; + } return 0; } @@ -289,12 +248,11 @@ { assert(menu); - if (menu->delegate->update) - menu->delegate->update(menu->delegate, menu, ticks); + MLK__STYLE_CALL(menu->style, mlk_gridmenu_style, update, menu, ticks); } void -mlk_gridmenu_draw(const struct mlk_gridmenu *menu) +mlk_gridmenu_draw(struct mlk_gridmenu *menu) { assert(menu); @@ -302,8 +260,7 @@ unsigned int row = 0, col = 0; int selected; - if (menu->delegate->draw_frame) - menu->delegate->draw_frame(menu->delegate, menu); + MLK__STYLE_CALL(menu->style, mlk_gridmenu_style, draw_frame, menu); /* * Select the first top-left column based on the current selection and @@ -320,15 +277,8 @@ selected = i == menu->selected % pagesz; - if (menu->delegate->draw_item) - menu->delegate->draw_item( - menu->delegate, - menu, - menu->items[item], - row, - col, - selected - ); + MLK__STYLE_CALL(menu->style, mlk_gridmenu_style, draw_text, + menu, menu->items[item], row, col, selected); if (++col >= menu->ncols) { ++row;
--- a/libmlk-ui/mlk/ui/gridmenu.h Mon Aug 21 21:42:17 2023 +0200 +++ b/libmlk-ui/mlk/ui/gridmenu.h Tue Aug 22 19:23:00 2023 +0200 @@ -21,9 +21,9 @@ #include <stddef.h> +struct mlk_font; struct mlk_gridmenu; -struct mlk_gridmenu_delegate; -struct mlk_style; +struct mlk_gridmenu_style; union mlk_event; @@ -94,16 +94,9 @@ /** * (read-write, borrowed) * - * Grid menu delegate. + * Style to use for drawing this menu. */ - struct mlk_gridmenu_delegate *delegate; - - /** - * (read-write, borrowed) - * - * Grid menu style. - */ - struct mlk_style *style; + struct mlk_gridmenu_style *style; /** \cond MLK_PRIVATE_DECLS */ unsigned int eltw; /* maximum entry label width */ @@ -114,10 +107,52 @@ }; /** - * \struct mlk_gridmenu_delegate - * \brief Grid menu delegate. + * \struct mlk_gridmenu_style + * \brief Grid menu style. */ -struct mlk_gridmenu_delegate { +struct mlk_gridmenu_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) + * + * Selected color. + */ + unsigned long color_selected; + + /** + * (read-write, borrowed, optional) + * + * Font for drawing text. + */ + struct mlk_font *font; + /* * (read-write, borrowed, optional) * @@ -128,38 +163,13 @@ /** * (read-write, optional) * - * Called after resizing the grid menu dimensions. - * - * \param self this delegate - * \param menu the grid menu - */ - void (*resize)(struct mlk_gridmenu_delegate *self, - struct mlk_gridmenu *menu); - - /** - * (read-write, optional) - * - * Handle an event. - * - * \param self this delegate - * \param menu the menu - * \param ev the event - * \return non-zero if an item has been selected - */ - int (*handle)(struct mlk_gridmenu_delegate *self, - struct mlk_gridmenu *menu, - const union mlk_event *ev); - - /** - * (read-write, optional) - * * Update the grid menu. * - * \param self this delegate + * \param self this style * \param menu the menu to update * \param ticks number of ticks since last frame */ - void (*update)(struct mlk_gridmenu_delegate *self, + void (*update)(struct mlk_gridmenu_style *self, struct mlk_gridmenu *menu, unsigned int ticks); @@ -168,93 +178,74 @@ * * Draw a frame box for this menu. * - * \param self this delegate + * \param self this style * \param menu the underlying menu */ - void (*draw_frame)(struct mlk_gridmenu_delegate *self, - const struct mlk_gridmenu *menu); + void (*draw_frame)(struct mlk_gridmenu_style *self, + struct mlk_gridmenu *menu); /** * (read-write, optional) * * Draw a specific item. * - * \param self this delegate + * \param self this style * \param menu the underlying menu * \param item the item content * \param row the row number (relative) * \param col the column number (relative) * \param selected non-zero if the item is currently selected */ - void (*draw_item)(struct mlk_gridmenu_delegate *self, - const struct mlk_gridmenu *menu, + void (*draw_text)(struct mlk_gridmenu_style *self, + struct mlk_gridmenu *menu, const char *item, unsigned int row, unsigned int col, int selected); - - /** - * (read-write, optional) - * - * Cleanup this delegate associated with the menu. - * - * \param self this delegate - * \param frame the underlying frame - */ - void (*finish)(struct mlk_gridmenu_delegate *self, - struct mlk_gridmenu *menu); - }; /** - * \brief Default stateless delegate for gridmenu. + * \brief Dark default style for gridmenu. + */ +extern struct mlk_gridmenu_style mlk_gridmenu_style_dark; + +/** + * \brief Light default style for gridmenu. */ -extern struct mlk_gridmenu_delegate mlk_gridmenu_delegate; +extern struct mlk_gridmenu_style mlk_gridmenu_style_light; + +/** + * \brief Default style for all gridmenus. + */ +extern struct mlk_gridmenu_style *mlk_gridmenu_style; #if defined(__cplusplus) extern "C" { #endif /** - * Initialize the menu with default values. - * - * This is not required if you use designated initializers. + * Resize the grid menu window. * * \pre menu != NULL - * \param menu the grid menu 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) + * \param menu the menu */ void -mlk_gridmenu_init(struct mlk_gridmenu *menu, - struct mlk_gridmenu_delegate *dt, - struct mlk_style *st); +mlk_gridmenu_resize(struct mlk_gridmenu *menu); /** - * Copy new dimensions and then invoke ::mlk_gridmenu_delegate::resize. + * Handle an event. * * \pre menu != NULL - * \param menu the menu to resize - * \param x new position in x - * \param y new position in y - * \param w new width - * \param h new height - */ -void -mlk_gridmenu_resize(struct mlk_gridmenu *menu, - int x, - int y, - unsigned int w, - unsigned int h); - -/** - * Invoke ::mlk_gridmenu_delegate::handle. + * \pre ev != NULL + * \param menu the menu + * \param ev the event + * \return non-zero if a new item is selected, 0 otherwise */ int mlk_gridmenu_handle(struct mlk_gridmenu *menu, const union mlk_event *ev); /** - * Invoke ::mlk_gridmenu_delegate::update. + * Invoke ::mlk_gridmenu_style::update. */ void mlk_gridmenu_update(struct mlk_gridmenu *menu, unsigned int ticks); @@ -262,17 +253,11 @@ /** * Invoke the functions: * - * - ::mlk_gridmenu_delegate::draw_frame, - * - ::mlk_gridmenu_delegate::draw_item. + * - ::mlk_gridmenu_style::draw_frame, + * - ::mlk_gridmenu_style::draw_item. */ void -mlk_gridmenu_draw(const struct mlk_gridmenu *menu); - -/** - * Invoke ::mlk_gridmenu_delegate::finish. - */ -void -mlk_gridmenu_finish(struct mlk_gridmenu *menu); +mlk_gridmenu_draw(struct mlk_gridmenu *menu); #if defined(__cplusplus) }