Mercurial > molko
changeset 174:6992085d47fd
ui: major theme overhaul, closes #2509 @1h
- The font does not contain a color anymore,
- Add a new color argument to font_render,
- Theme are stored `const` in UI elements to promise no modifications,
- Also make all <ui>_draw function to take a const widget too.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 22 Oct 2020 15:16:43 +0200 |
parents | cd69c8791dac |
children | ce789473567e |
files | examples/example-font.c examples/example-message.c libadventure/adventure/state/mainmenu.c libadventure/adventure/state/panic.c libadventure/adventure/state/splashscreen.c libcore/core/font.c libcore/core/font.h librpg/rpg/message.c librpg/rpg/message.h libui/ui/button.c libui/ui/button.h libui/ui/checkbox.c libui/ui/checkbox.h libui/ui/debug.c libui/ui/debug.h libui/ui/frame.c libui/ui/frame.h libui/ui/label.c libui/ui/label.h libui/ui/theme.c libui/ui/theme.h libui/ui/ui.h |
diffstat | 22 files changed, 135 insertions(+), 105 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-font.c Wed Oct 21 12:50:11 2020 +0200 +++ b/examples/example-font.c Thu Oct 22 15:16:43 2020 +0200 @@ -102,10 +102,9 @@ painter_set_color(0xffffffff); painter_clear(); - font->color = colors[ci]; font->style = style; - if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.")) + if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.", colors[ci])) panic(); texture_draw(&tex, 10, 10);
--- a/examples/example-message.c Wed Oct 21 12:50:11 2020 +0200 +++ b/examples/example-message.c Thu Oct 22 15:16:43 2020 +0200 @@ -97,7 +97,7 @@ } static void -my_draw_frame(struct theme *th, const struct frame *f) +my_draw_frame(const struct theme *th, const struct frame *f) { (void)th;
--- a/libadventure/adventure/state/mainmenu.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libadventure/adventure/state/mainmenu.c Thu Oct 22 15:16:43 2020 +0200 @@ -84,7 +84,7 @@ static void init_title(struct mainmenu *main, struct font *font) { - if (!font_render(font, &main->texts[3].tex, "Molko's Adventure")) + if (!font_render(font, &main->texts[3].tex, "Molko's Adventure", 0x000000ff)) panic(); /* Align header. */ @@ -97,9 +97,9 @@ static void init_items(struct mainmenu *main, struct font *font) { - if (!font_render(font, &main->texts[0].tex, "New") || - !font_render(font, &main->texts[1].tex, "Continue") || - !font_render(font, &main->texts[2].tex, "Quit")) + if (!font_render(font, &main->texts[0].tex, "New", 0x000000ff) || + !font_render(font, &main->texts[1].tex, "Continue", 0x000000ff) || + !font_render(font, &main->texts[2].tex, "Quit", 0x000000ff)) panic(); main->texts[0].x = (window.w / 2) - (main->texts[0].tex.w / 2); @@ -125,7 +125,6 @@ !font_openmem(&fonts[1], fonts_pirata_one, sizeof (fonts_pirata_one), 30)) panic(); - fonts[0].color = fonts[1].color = 0x000000ff; fonts[0].style = fonts[1].style = FONT_STYLE_ANTIALIASED; init_title(main, &fonts[0]);
--- a/libadventure/adventure/state/panic.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libadventure/adventure/state/panic.c Thu Oct 22 15:16:43 2020 +0200 @@ -94,20 +94,16 @@ { struct theme *theme; struct view *view; - struct font font; + struct font *font; theme = theme_default(); + font = theme->fonts[THEME_FONT_INTERFACE]; view = ecalloc(1, sizeof (*view)); - /* Generate the texts. */ - font_shallow(&font, theme->fonts[THEME_FONT_INTERFACE]); - font.style = FONT_STYLE_ANTIALIASED, - font.color = FOREGROUND; - - if (!font_render(&font, &view->texts[0].tex, "An unrecoverable error occured and the game cannot continue.") || - !font_render(&font, &view->texts[1].tex, "Please report the detailed error as provided below.") || - !font_render(&font, &view->texts[2].tex, "Press <s> to save information and generate a core dump.") || - !font_render(&font, &view->texts[3].tex, "Press <q> to quit without saving information.")) + if (!font_render(font, &view->texts[0].tex, "An unrecoverable error occured and the game cannot continue.", FOREGROUND) || + !font_render(font, &view->texts[1].tex, "Please report the detailed error as provided below.", FOREGROUND) || + !font_render(font, &view->texts[2].tex, "Press <s> to save information and generate a core dump.", FOREGROUND) || + !font_render(font, &view->texts[3].tex, "Press <q> to quit without saving information.", FOREGROUND)) die("%s", error()); /* All align x the same. */ @@ -173,7 +169,7 @@ struct theme *theme = theme_default(); struct view *view = state->data; struct texture tex; - struct font font; + struct font *font; int x, y; painter_set_color(BACKGROUND); @@ -183,11 +179,9 @@ texture_draw(&view->texts[i].tex, view->texts[i].x, view->texts[i].y); /* The error is only available here. */ - font_shallow(&font, theme->fonts[THEME_FONT_INTERFACE]); - font.color = FOREGROUND; - font.style = FONT_STYLE_ANTIALIASED; + font = theme->fonts[THEME_FONT_INTERFACE]; - if (!font_render(&font, &tex, error())) + if (!font_render(font, &tex, error(), FOREGROUND)) die("%s\n", error()); align(ALIGN_LEFT, &x, &y, tex.w, tex.h, 0, 0, window.w, window.h);
--- a/libadventure/adventure/state/splashscreen.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libadventure/adventure/state/splashscreen.c Thu Oct 22 15:16:43 2020 +0200 @@ -60,10 +60,9 @@ if (!font_openmem(&font, fonts_cubic, sizeof (fonts_cubic), 80)) panic(); - font.color = 0x19332dff; font.style = FONT_STYLE_ANTIALIASED; - if (!font_render(&font, &splash->tex, "malikania")) + if (!font_render(&font, &splash->tex, "malikania", 0x19332dff)) panic(); align(ALIGN_CENTER, &splash->x, &splash->y, splash->tex.w, splash->tex.h,
--- a/libcore/core/font.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libcore/core/font.c Thu Oct 22 15:16:43 2020 +0200 @@ -66,22 +66,20 @@ bool font_ok(const struct font *font) { - assert(font); - - return font->handle; + return font && font->handle; } bool -font_render(struct font *font, struct texture *tex, const char *text) +font_render(struct font *font, struct texture *tex, const char *text, unsigned int color) { assert(font_ok(font)); assert(text); SDL_Color fg = { - .r = COLOR_R(font->color), - .g = COLOR_G(font->color), - .b = COLOR_B(font->color), - .a = COLOR_A(font->color) + .r = COLOR_R(color), + .g = COLOR_G(color), + .b = COLOR_B(color), + .a = COLOR_A(color) }; SDL_Surface *surface; SDL_Surface *(*func)(TTF_Font *, const char *, SDL_Color);
--- a/libcore/core/font.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libcore/core/font.h Thu Oct 22 15:16:43 2020 +0200 @@ -28,6 +28,8 @@ #include <stdbool.h> #include <stddef.h> +#include <core/plat.h> + struct texture; /** @@ -43,7 +45,6 @@ */ struct font { enum font_style style; /*!< (+) Style for rendering. */ - unsigned long color; /*!< (+) Color for rendering. */ void *handle; /*!< (*) Native handle. */ }; @@ -58,7 +59,7 @@ * \return False on errors. */ bool -font_open(struct font *font, const char *path, unsigned int size); +font_open(struct font *font, const char *path, unsigned int size) PLAT_NODISCARD; /** * Open font from memory buffer. @@ -73,7 +74,7 @@ * \return False on errors. */ bool -font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size); +font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size) PLAT_NODISCARD; /** * Convenient shortcut to shallow copy src into dst. @@ -95,8 +96,7 @@ /** * Tells if the font was properly opened. * - * \pre font != NULL - * \param font the font to check + * \param font the font to check (may be NULL) * \return True if the native handle was opened. */ bool @@ -113,10 +113,11 @@ * \param font the font to use * \param tex the texture to generate * \param text the UTF-8 text + * \param color the foreground color * \return False on errors. */ bool -font_render(struct font *font, struct texture *tex, const char *text); +font_render(struct font *font, struct texture *tex, const char *text, unsigned int color) PLAT_NODISCARD; /** * Get the maximum height for all glyphs. @@ -140,7 +141,7 @@ * \return False in case of error and pointers to w and h are left unmodified. */ bool -font_query(const struct font *font, const char *text, unsigned int *w, unsigned int *h); +font_query(const struct font *font, const char *text, unsigned int *w, unsigned int *h) PLAT_NODISCARD; /** * Close the font.
--- a/librpg/rpg/message.c Wed Oct 21 12:50:11 2020 +0200 +++ b/librpg/rpg/message.c Thu Oct 22 15:16:43 2020 +0200 @@ -115,8 +115,11 @@ struct label label; unsigned int lw, lh; - /* Shallow copy theme to modify colors. */ - theme_shallow(&theme, msg->theme); + /* + * We need a copy of the current theme because we will alter the label + * color depending on the selection. + */ + theme_shallow(&theme, THEME(msg)); for (int i = 0; i < MESSAGE_LINES_MAX; ++i) { if (!msg->text[i]) @@ -261,7 +264,7 @@ } void -message_draw(struct message *msg) +message_draw(const struct message *msg) { assert(msg);
--- a/librpg/rpg/message.h Wed Oct 21 12:50:11 2020 +0200 +++ b/librpg/rpg/message.h Thu Oct 22 15:16:43 2020 +0200 @@ -134,7 +134,7 @@ unsigned int index; /*!< (+) Line selected */ enum message_flags flags; /*!< (+) Message flags */ enum message_state state; /*!< (-) Current state */ - struct theme *theme; /*!< (+&?) Theme to use. */ + const struct theme *theme; /*!< (+&?) Theme to use. */ unsigned int elapsed; /*!< (-) Time elapsed. */ double scale; /*!< (-) Current scale [0-1]. */ }; @@ -194,7 +194,7 @@ * \param msg the message */ void -message_draw(struct message *msg); +message_draw(const struct message *msg); /** * Start hiding the message.
--- a/libui/ui/button.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/button.c Thu Oct 22 15:16:43 2020 +0200 @@ -54,7 +54,7 @@ } void -button_draw_default(struct theme *t, const struct button *button) +button_draw_default(const struct theme *t, const struct button *button) { assert(t); assert(button); @@ -118,7 +118,7 @@ } void -button_draw(struct button *button) +button_draw(const struct button *button) { assert(button);
--- a/libui/ui/button.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/button.h Thu Oct 22 15:16:43 2020 +0200 @@ -49,7 +49,7 @@ unsigned int h; /*!< (+) Height. */ const char *text; /*!< (+&) Text to draw. */ enum button_state state; /*!< (+) Button state. */ - struct theme *theme; /*!< (+&?) Theme to use. */ + const struct theme *theme; /*!< (+&?) Theme to use. */ }; /** @@ -84,7 +84,7 @@ * \param button the button */ void -button_draw_default(struct theme *t, const struct button *button); +button_draw_default(const struct theme *t, const struct button *button); /** * Draw the button. @@ -93,7 +93,7 @@ * \param button the button */ void -button_draw(struct button *button); +button_draw(const struct button *button); /** * Convert the button into an action.
--- a/libui/ui/checkbox.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/checkbox.c Thu Oct 22 15:16:43 2020 +0200 @@ -50,7 +50,7 @@ } void -checkbox_draw_default(struct theme *t, const struct checkbox *cb) +checkbox_draw_default(const struct theme *t, const struct checkbox *cb) { assert(t); assert(cb);
--- a/libui/ui/checkbox.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/checkbox.h Thu Oct 22 15:16:43 2020 +0200 @@ -36,12 +36,12 @@ * \brief GUI checkbox. */ struct checkbox { - int x; /*!< (+) Position in x. */ - int y; /*!< (+) Position in y. */ - unsigned int w; /*!< (+) Width. */ - unsigned int h; /*!< (+) Height. */ - bool checked; /*!< (+) Is activated? */ - struct theme *theme; /*!< (+&?) Theme to use. */ + int x; /*!< (+) Position in x. */ + int y; /*!< (+) Position in y. */ + unsigned int w; /*!< (+) Width. */ + unsigned int h; /*!< (+) Height. */ + bool checked; /*!< (+) Is activated? */ + const struct theme *theme; /*!< (+&?) Theme to use. */ }; /** @@ -53,7 +53,7 @@ * \param cb the checkbox */ void -checkbox_draw_default(struct theme *t, const struct checkbox *cb); +checkbox_draw_default(const struct theme *t, const struct checkbox *cb); /** * Draw the checkbox.
--- a/libui/ui/debug.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/debug.c Thu Oct 22 15:16:43 2020 +0200 @@ -56,22 +56,17 @@ return; char line[DEBUG_LINE_MAX]; - struct theme *theme; - struct font font; + const struct theme *theme; + struct font *font; struct texture tex; int x, y; vsnprintf(line, sizeof (line), fmt, ap); - /* Get the font and modify its style. */ theme = report->theme ? report->theme : theme_default(); + font = theme->fonts[THEME_FONT_DEBUG]; - /* Update font style. */ - font_shallow(&font, theme->fonts[THEME_FONT_DEBUG]); - font.style = FONT_STYLE_ANTIALIASED; - font.color = theme->colors[THEME_COLOR_DEBUG]; - - if (!font_render(&font, &tex, line)) + if (!font_render(font, &tex, line, theme->colors[THEME_COLOR_DEBUG])) return; x = theme->padding;
--- a/libui/ui/debug.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/debug.h Thu Oct 22 15:16:43 2020 +0200 @@ -66,7 +66,7 @@ * Use this structure each time you need to print one or more messages. */ struct debug_report { - struct theme *theme; /*!< (+&?) Theme to use. */ + const struct theme *theme; /*!< (+&?) Theme to use. */ unsigned int count; /*!< (-) Number of messages already printed. */ };
--- a/libui/ui/frame.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/frame.c Thu Oct 22 15:16:43 2020 +0200 @@ -32,7 +32,7 @@ } void -frame_draw_default(struct theme *t, const struct frame *frame) +frame_draw_default(const struct theme *t, const struct frame *frame) { assert(t); assert(frame);
--- a/libui/ui/frame.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/frame.h Thu Oct 22 15:16:43 2020 +0200 @@ -40,12 +40,12 @@ * \brief GUI frame. */ struct frame { - int x; /*!< (+) Position in x. */ - int y; /*!< (+) Position in y. */ - unsigned int w; /*!< (+) Width. */ - unsigned int h; /*!< (+) Height. */ - enum frame_style style; /*!< (+) Frame style. */ - struct theme *theme; /*!< (+&?) Theme to use. */ + int x; /*!< (+) Position in x. */ + int y; /*!< (+) Position in y. */ + unsigned int w; /*!< (+) Width. */ + unsigned int h; /*!< (+) Height. */ + enum frame_style style; /*!< (+) Frame style. */ + const struct theme *theme; /*!< (+&?) Theme to use. */ }; /** @@ -57,7 +57,7 @@ * \param frame the frame */ void -frame_draw_default(struct theme *t, const struct frame *frame); +frame_draw_default(const struct theme *t, const struct frame *frame); /** * Draw the frame.
--- a/libui/ui/label.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/label.c Thu Oct 22 15:16:43 2020 +0200 @@ -34,7 +34,7 @@ } void -label_draw_default(struct theme *t, const struct label *label) +label_draw_default(const struct theme *t, const struct label *label) { assert(t); assert(label); @@ -46,9 +46,7 @@ /* Shadow text, only if enabled. */ if (label->flags & LABEL_FLAGS_SHADOW) { - font->color = t->colors[THEME_COLOR_SHADOW]; - - if (!font_render(font, &tex, label->text)) + if (!font_render(font, &tex, label->text, t->colors[THEME_COLOR_SHADOW])) panic(); texture_draw(&tex, label->x + 1, label->y + 1); @@ -56,22 +54,26 @@ } /* Normal text. */ - font->color = t->colors[THEME_COLOR_NORMAL]; - - if (!font_render(font, &tex, label->text)) + if (!font_render(font, &tex, label->text, t->colors[THEME_COLOR_NORMAL])) panic(); texture_draw(&tex, label->x, label->y); texture_finish(&tex); } +bool +label_ok(const struct label *label) +{ + return label && label->text && strlen(label->text) > 0; +} + void -label_query(struct label *label, unsigned int *w, unsigned int *h) +label_query(const struct label *label, unsigned int *w, unsigned int *h) { assert(label); assert(label->text); - struct theme *t = label->theme ? label->theme : theme_default(); + const struct theme *t = label->theme ? label->theme : theme_default(); if (!font_query(t->fonts[THEME_FONT_INTERFACE], label->text, w, h)) panic();
--- a/libui/ui/label.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/label.h Thu Oct 22 15:16:43 2020 +0200 @@ -44,7 +44,7 @@ int y; /*!< (+) Position in y. */ const char *text; /*!< (+&) Text to show. */ enum label_flags flags; /*!< (+) Optional flags. */ - struct theme *theme; /*!< (+&?) Theme to use. */ + const struct theme *theme; /*!< (+&?) Theme to use. */ }; /** @@ -56,7 +56,16 @@ * \param label the label */ void -label_draw_default(struct theme *t, const struct label *label); +label_draw_default(const struct theme *t, const struct label *label); + +/** + * Tells if the label is usable. + * + * \param label the label to check (may be NULL) + * \return False if label is null or as empty text. + */ +bool +label_ok(const struct label *label); /** * Update the `w` and `h` fields with the dimensions the text would needs with @@ -68,7 +77,7 @@ * \param h the pointer to height (may be NULL) */ void -label_query(struct label *label, unsigned int *w, unsigned int *h); +label_query(const struct label *label, unsigned int *w, unsigned int *h); /** * Draw the label.
--- a/libui/ui/theme.c Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/theme.c Thu Oct 22 15:16:43 2020 +0200 @@ -112,7 +112,7 @@ } void -theme_draw_frame(struct theme *t, const struct frame *frame) +theme_draw_frame(const struct theme *t, const struct frame *frame) { assert(frame); @@ -120,7 +120,7 @@ } void -theme_draw_label(struct theme *t, const struct label *label) +theme_draw_label(const struct theme *t, const struct label *label) { assert(label); @@ -128,7 +128,7 @@ } void -theme_draw_button(struct theme *t, const struct button *button) +theme_draw_button(const struct theme *t, const struct button *button) { assert(button); @@ -136,7 +136,7 @@ } void -theme_draw_checkbox(struct theme *t, const struct checkbox *cb) +theme_draw_checkbox(const struct theme *t, const struct checkbox *cb) { assert(cb);
--- a/libui/ui/theme.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/theme.h Thu Oct 22 15:16:43 2020 +0200 @@ -63,7 +63,7 @@ struct font *fonts[THEME_FONT_LAST]; /** - * (+) Miscellaneous colors. + * (+) User interface colors. */ unsigned long colors[THEME_COLOR_LAST]; @@ -80,28 +80,28 @@ * * \see \ref theme_draw_frame */ - void (*draw_frame)(struct theme *, const struct frame *); + void (*draw_frame)(const struct theme *, const struct frame *); /** * (+) Draw a label. * * \see \ref theme_draw_label */ - void (*draw_label)(struct theme *, const struct label *); + void (*draw_label)(const struct theme *, const struct label *); /** * (+) Draw a button. * * \see \ref theme_draw_button */ - void (*draw_button)(struct theme *, const struct button *); + void (*draw_button)(const struct theme *, const struct button *); /** * (+) Draw a checkbox. * * \see \ref theme_draw_button */ - void (*draw_checkbox)(struct theme *t, const struct checkbox *); + void (*draw_checkbox)(const struct theme *t, const struct checkbox *); }; /** @@ -118,7 +118,9 @@ /** * Get a reference to the default theme. * - * \return A non-owning pointer to a static storage for the default theme + * The returned theme may be modified to modify the whole UI. + * + * \return A non-owning pointer to a static storage for the default theme. */ struct theme * theme_default(void); @@ -129,13 +131,40 @@ * Use this function when you want your own local copy of a theme because you * want to modify some attributes. * + * You should not modify underlying objects within the new theme because they + * still point to the same region and you may erase the user settings. + * + * This code is incorrect: + * + * ```c + * struct theme th; + * + * theme_shallow(&th, theme_default()); + * th.fonts[THEME_FONT_INTERFACE].style = FONT_STYLE_NONE; + * + * // + * // Since th.fonts contain same pointers to theme_default, you'll erase + * // the default theme settings. + * // + * ``` + * + * Instead, if you really need to modify an underlying object, you have to copy + * it too. + * + * ```c + * struct font font; + * + * font_shallow(&font, theme_default()->fonts[THEME_FONT_INTERFACE]; + * font.style = FONT_STYLE_NONE; + * + * // No font_finish needed either, it is only a shallow copy. + * ``` + * * This is a shortcut to `memcpy(dst, src, sizeof (*src))`. * * \pre dst != NULL * \param dst the destination theme * \param src the source theme (may be NULL) - * \note Resources are not cloned, internal pointers will adress the same - * regions. */ void theme_shallow(struct theme *dst, const struct theme *src); @@ -148,7 +177,7 @@ * \param frame the frame */ void -theme_draw_frame(struct theme *t, const struct frame *frame); +theme_draw_frame(const struct theme *t, const struct frame *frame); /** * Draw a label. @@ -158,7 +187,7 @@ * \param label the label */ void -theme_draw_label(struct theme *t, const struct label *label); +theme_draw_label(const struct theme *t, const struct label *label); /** * Draw a button. @@ -168,7 +197,7 @@ * \param button the button */ void -theme_draw_button(struct theme *t, const struct button *button); +theme_draw_button(const struct theme *t, const struct button *button); /** * Draw a checkbox. @@ -177,7 +206,7 @@ * \param cb the checkbox */ void -theme_draw_checkbox(struct theme *t, const struct checkbox *cb); +theme_draw_checkbox(const struct theme *t, const struct checkbox *cb); /** * This function is automatically called from \ref ui_finish and thus not
--- a/libui/ui/ui.h Wed Oct 21 12:50:11 2020 +0200 +++ b/libui/ui/ui.h Thu Oct 22 15:16:43 2020 +0200 @@ -26,13 +26,15 @@ #include <stdbool.h> +#include <core/plat.h> + /** * Initialize the ui library. * * \return False on errors. */ bool -ui_init(void); +ui_init(void) PLAT_NODISCARD; /** * Close the ui library.