changeset 505:6100c643dba0

ui: finally ditch theme
author David Demelier <markand@malikania.fr>
date Wed, 01 Mar 2023 16:24:07 +0100
parents 52a305833381
children e205625015ba
files CMakeLists.txt examples/example-ui/button-style-glow.h examples/example-ui/example-ui.c libmlk-example/mlk/example/trace-hud.c libmlk-rpg/mlk/rpg/battle-bar-default.c libmlk-rpg/mlk/rpg/battle-entity.c libmlk-rpg/mlk/rpg/battle-indicator.c libmlk-rpg/mlk/rpg/battle-message.c libmlk-rpg/mlk/rpg/battle-state-selection.c libmlk-rpg/mlk/rpg/battle.c libmlk-rpg/mlk/rpg/message.c libmlk-ui/CMakeLists.txt libmlk-ui/mlk/ui/button.c libmlk-ui/mlk/ui/button.h libmlk-ui/mlk/ui/checkbox.c libmlk-ui/mlk/ui/debug.c libmlk-ui/mlk/ui/frame.c libmlk-ui/mlk/ui/frame.h libmlk-ui/mlk/ui/gridmenu.c libmlk-ui/mlk/ui/gridmenu.h libmlk-ui/mlk/ui/label.c libmlk-ui/mlk/ui/label.h libmlk-ui/mlk/ui/notify.c libmlk-ui/mlk/ui/theme.c libmlk-ui/mlk/ui/theme.h libmlk-ui/mlk/ui/ui.c libmlk-ui/mlk/ui/ui.h
diffstat 27 files changed, 221 insertions(+), 282 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Mar 01 14:07:10 2023 +0100
+++ b/CMakeLists.txt	Wed Mar 01 16:24:07 2023 +0100
@@ -21,7 +21,7 @@
 
 set_property(GLOBAL PROPERTY USE_FOLDERS On)
 
-set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD 23)
 set(CMAKE_C_STANDARD_REQUIRED On)
 set(CMAKE_C_EXTENSIONS On)
 set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
@@ -31,6 +31,8 @@
 
 	if (CMAKE_C_COMPILER_ID MATCHES "GNU")
 		set(CMAKE_C_FLAGS "-Wno-format-truncation ${CMAKE_C_FLAGS}")
+	else ()
+		set(CMAKE_C_FLAGS "-Wno-fixed-enum-extension ${CMAKE_C_FLAGS}")
 	endif ()
 elseif (CMAKE_C_COMPILER_ID MATCHES "MSVC")
 	set(CMAKE_C_FLAGS "/W3 /wd4090 /wd4244 /wd4267 /wd4996 /wd5105 /wd6031 /wd6001 /wd26451 ${CMAKE_C_FLAGS}")
--- a/examples/example-ui/button-style-glow.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/examples/example-ui/button-style-glow.h	Wed Mar 01 16:24:07 2023 +0100
@@ -21,8 +21,8 @@
 
 #include <mlk/ui/button.h>
 
-#define BUTTON_STYLE_GLOW_COLOR_1       0x235b7cff
-#define BUTTON_STYLE_GLOW_COLOR_2       0x2d80a6ff
+#define BUTTON_STYLE_GLOW_COLOR_1       0x7da42dff
+#define BUTTON_STYLE_GLOW_COLOR_2       0xa6cc34ff
 #define BUTTON_STYLE_GLOW_DELAY         20
 
 struct button_style_glow {
--- a/examples/example-ui/example-ui.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/examples/example-ui/example-ui.c	Wed Mar 01 16:24:07 2023 +0100
@@ -35,7 +35,6 @@
 #include <mlk/ui/frame.h>
 #include <mlk/ui/label.h>
 #include <mlk/ui/notify.h>
-#include <mlk/ui/theme.h>
 #include <mlk/ui/ui.h>
 
 #include <mlk/example/example.h>
@@ -52,6 +51,8 @@
 
 #define ELEMENT_HEIGHT  (20)
 
+#define PADDING         (10)
+
 /*
  * We design a basic UI like this.
  *
@@ -90,6 +91,7 @@
 		struct mlk_button hello;
 
 		/* [Quit] with custom style color. */
+		struct mlk_label_style quit_text_style;
 		struct mlk_button_style quit_style;
 		struct mlk_button quit;
 
@@ -112,8 +114,7 @@
 		.label = {
 			.text = "Preferences",
 			.x = FRAME_ORIGIN_X,
-			.y = FRAME_ORIGIN_Y,
-			.flags = MLK_LABEL_FLAGS_SHADOW,
+			.y = FRAME_ORIGIN_Y
 		}
 	},
 	.autosave = {
@@ -122,8 +123,7 @@
 			.h = ELEMENT_HEIGHT
 		},
 		.label = {
-			.text = "Auto save game",
-			.flags = MLK_LABEL_FLAGS_SHADOW,
+			.text = "Auto save game"
 		}
 	},
 	.buttons = {
@@ -132,25 +132,34 @@
 			.h = ELEMENT_HEIGHT
 		},
 		.quit_style = {
-			.bg_color = 0x235b7cff
+			.bg_color = 0x24aed6ff,
+			.border_color = 0x328ca7ff
+		},
+		.quit_text_style = {
+			.text_color = 0xf5f7faff
 		},
 		.quit = {
 			.text = "Quit",
 			.h = ELEMENT_HEIGHT,
-			.style = &ui.buttons.quit_style
+			.style = &ui.buttons.quit_style,
+			.text_style = &ui.buttons.quit_text_style
 		},
 		.download_glow = {
 			.colors = {
 				BUTTON_STYLE_GLOW_COLOR_1,
 				BUTTON_STYLE_GLOW_COLOR_2
 			},
+			.style = {
+				.border_color = BUTTON_STYLE_GLOW_COLOR_1
+			},
 			.delay = BUTTON_STYLE_GLOW_DELAY
 		},
 		.download = {
 			.w = 180,
 			.h = 32,
 			.text = "!! Download free RAM !!",
-			.style = &ui.buttons.download_glow.style
+			.style = &ui.buttons.download_glow.style,
+			.text_style = &ui.buttons.quit_text_style
 		}
 	}
 };
@@ -168,28 +177,26 @@
 	mlk_label_query(l, &w, &h);
 	mlk_align(MLK_ALIGN_LEFT, &l->x, &l->y, w, h, f->x, f->y, f->w, HEADER_HEIGHT);
 
-	l->x += mlk_theme.padding;
+	l->x += PADDING;
 }
 
 static void
 resize_autosave(void)
 {
-	unsigned int padding = mlk_theme.padding;
 	struct mlk_frame *f = &ui.panel.frame;
 	struct mlk_checkbox *c = &ui.autosave.cb;
 	struct mlk_label *l = &ui.autosave.label;
 
-	c->x = f->x + padding;
-	c->y = f->y + HEADER_HEIGHT + padding;
+	c->x = f->x + PADDING;
+	c->y = f->y + HEADER_HEIGHT + PADDING;
 
-	l->x = c->x + c->w + padding;
+	l->x = c->x + c->w + PADDING;
 	l->y = c->y;
 }
 
 static void
 resize_button(void)
 {
-	unsigned int padding = mlk_theme.padding;
 	struct mlk_frame *f = &ui.panel.frame;
 	struct mlk_button *quit = &ui.buttons.quit;
 	struct mlk_button *hello = &ui.buttons.hello;
@@ -201,11 +208,11 @@
 	mlk_align(MLK_ALIGN_BOTTOM_RIGHT, &quit->x, &quit->y, quit->w, quit->h,
 	    f->x, f->y, f->w, f->h);
 
-	quit->x -= padding;
-	quit->y -= padding;
+	quit->x -= PADDING;
+	quit->y -= PADDING;
 
 	/* Hello is immediately left. */
-	hello->x = quit->x - quit->w - padding;
+	hello->x = quit->x - quit->w - PADDING;
 	hello->y = quit->y;
 
 	/* Download free ram is at the bottom center. */
@@ -302,7 +309,7 @@
 {
 	(void)st;
 
-	mlk_painter_set_color(0xffffffff);
+	mlk_painter_set_color(0x88d6ffff);
 	mlk_painter_clear();
 	mlk_frame_draw(&ui.panel.frame);
 	mlk_label_draw(&ui.header.label);
--- a/libmlk-example/mlk/example/trace-hud.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-example/mlk/example/trace-hud.c	Wed Mar 01 16:24:07 2023 +0100
@@ -25,7 +25,6 @@
 #include <mlk/core/window.h>
 
 #include <mlk/ui/label.h>
-#include <mlk/ui/theme.h>
 
 #include "trace-hud.h"
 
@@ -87,6 +86,7 @@
 void
 mlk_trace_hud_draw(void)
 {
+#if 0
 	struct mlk_theme *th;
 	int x, y;
 
@@ -105,6 +105,7 @@
 		y += mlk_font_height(th->fonts[MLK_THEME_FONT_INTERFACE]);
 		y += th->padding;
 	}
+#endif
 }
 
 void
--- a/libmlk-rpg/mlk/rpg/battle-bar-default.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-bar-default.c	Wed Mar 01 16:24:07 2023 +0100
@@ -30,7 +30,6 @@
 #include <mlk/core/window.h>
 
 #include <mlk/ui/align.h>
-#include <mlk/ui/theme.h>
 
 #include "battle-bar-default.h"
 #include "battle-bar.h"
@@ -141,6 +140,7 @@
 static void
 switch_selection_spell(struct battle_bar_default *bar, struct battle *bt)
 {
+#if 0
 	const struct character *ch = battle_current(bt)->ch;
 	const struct spell *sp = ch->spells[bar->grid.selected];
 	struct selection sel = {0};
@@ -157,11 +157,13 @@
 	/* A cursor should be present. */
 	if (!mlk_sprite_ok(BATTLE_THEME(bt)->sprites[MLK_THEME_SPRITE_CURSOR]))
 		mlk_tracef("battle: no cursor sprite in theme");
+#endif
 }
 
 static void
 switch_selection_item(struct battle *bt)
 {
+#if 0
 	const struct selection slt = {
 		.allowed_kinds = SELECTION_KIND_ONE,
 		.allowed_sides = SELECTION_SIDE_TEAM | SELECTION_SIDE_ENEMY,
@@ -170,6 +172,7 @@
 	};
 
 	battle_state_selection(bt, &slt);
+#endif
 }
 
 /*
@@ -180,15 +183,16 @@
 static void
 draw_help(const struct battle_bar_default *bar, const char *what)
 {
+#if 0
 	struct mlk_label label = {0};
 	unsigned int lw = 0, lh = 0;
 
-	label.flags = MLK_LABEL_FLAGS_SHADOW;
 	label.text = what;
 	mlk_label_query(&label, &lw, &lh);
 	label.x = bar->grid.x + (bar->grid.w / 2) - (lw / 2);
 	label.y = bar->grid.y - lh - THEME(bar)->padding;
 	mlk_label_draw(&label);
+#endif
 }
 
 static void
@@ -228,6 +232,7 @@
                             int y,
                             unsigned int h)
 {
+#if 0
 	const struct mlk_theme *theme = THEME(bar);
 	struct mlk_label label;
 	unsigned int spacing, lw, lh;
@@ -264,6 +269,7 @@
 
 	/* Status. */
 	/* TODO: list all status. */
+#endif
 }
 
 static void
@@ -317,6 +323,7 @@
 static void
 draw_menu(const struct battle_bar_default *bar, const struct geo *geo)
 {
+#if 0
 	struct {
 		unsigned int w, h;
 		enum mlk_align align;
@@ -326,28 +333,24 @@
 			.align = MLK_ALIGN_TOP,
 			.label = {
 				.text = "Attack",
-				.flags = MLK_LABEL_FLAGS_SHADOW
 			}
 		},
 		{
 			.align = MLK_ALIGN_RIGHT,
 			.label = {
 				.text = "Magic",
-				.flags = MLK_LABEL_FLAGS_SHADOW
 			}
 		},
 		{
 			.align = MLK_ALIGN_BOTTOM,
 			.label = {
 				.text = "Objects",
-				.flags = MLK_LABEL_FLAGS_SHADOW
 			}
 		},
 		{
 			.align = MLK_ALIGN_LEFT,
 			.label = {
 				.text = "Special",
-				.flags = MLK_LABEL_FLAGS_SHADOW
 			}
 		}
 	};
@@ -386,6 +389,7 @@
 		    bx, by, bw, bh);
 		mlk_label_draw(&buttons[i].label);
 	}
+#endif
 }
 
 /*
@@ -528,6 +532,7 @@
 void
 battle_bar_default_init(struct battle_bar_default *bar)
 {
+#if 0
 	assert(bar);
 
 	struct geo geo[2];
@@ -544,6 +549,7 @@
 	mlk_gridmenu_init(&bar->grid, 2, 2, NULL, 0);
 	mlk_gridmenu_resize(&bar->grid, bar->x, geo[0].y, geo[1].w, bar->h);
 	bar->grid.theme = bar->theme;
+#endif
 }
 
 void
--- a/libmlk-rpg/mlk/rpg/battle-entity.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-entity.c	Wed Mar 01 16:24:07 2023 +0100
@@ -21,8 +21,6 @@
 #include <mlk/core/sprite.h>
 #include <mlk/core/texture.h>
 
-#include <mlk/ui/theme.h>
-
 #include "battle.h"
 #include "battle-entity.h"
 #include "battle-entity-state.h"
--- a/libmlk-rpg/mlk/rpg/battle-indicator.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-indicator.c	Wed Mar 01 16:24:07 2023 +0100
@@ -25,11 +25,8 @@
 #include <mlk/core/font.h>
 #include <mlk/core/panic.h>
 
-#include <mlk/ui/theme.h>
-
 #include "battle-indicator.h"
 
-#define THEME(bti)      ((bti)->theme ? (bti)->theme : &mlk_theme)
 #define STEP            (2)
 #define DELAY           (5)
 
@@ -54,7 +51,6 @@
 	assert(bti);
 
 	char buf[128];
-	const struct mlk_theme *theme = THEME(bti);
 	int err;
 
 	snprintf(buf, sizeof (buf), "%u", bti->amount);
@@ -63,9 +59,11 @@
 	bti->elapsed = 0;
 	bti->alpha = 250;
 
+#if 0
 	if ((err = mlk_font_render(theme->fonts[MLK_THEME_FONT_INTERFACE], &bti->tex[0], buf, bti->cur)) < 0 ||
 	    (err = mlk_font_render(theme->fonts[MLK_THEME_FONT_INTERFACE], &bti->tex[1], buf, 0x000000ff)) < 0)
 		mlk_panic(err);
+#endif
 }
 
 int
--- a/libmlk-rpg/mlk/rpg/battle-message.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-message.c	Wed Mar 01 16:24:07 2023 +0100
@@ -56,7 +56,6 @@
 
 	/* Prepare message label box. */
 	l.text = msg->text;
-	l.flags = MLK_LABEL_FLAGS_SHADOW;
 	mlk_label_query(&l, &lw, &lh);
 
 	/* Align the text in the box. */
--- a/libmlk-rpg/mlk/rpg/battle-state-selection.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-state-selection.c	Wed Mar 01 16:24:07 2023 +0100
@@ -26,8 +26,6 @@
 #include <mlk/core/sprite.h>
 #include <mlk/core/util.h>
 
-#include <mlk/ui/theme.h>
-
 #include "battle-bar.h"
 #include "battle-state-item.h"
 #include "battle-state-menu.h"
@@ -115,6 +113,7 @@
 static void
 draw_cursor(const struct battle *bt, const struct battle_entity *et)
 {
+#if 0
 	const struct mlk_theme *theme = BATTLE_THEME(bt);
 	const struct mlk_sprite *cursor = theme->sprites[MLK_THEME_SPRITE_CURSOR];
 	int x, y;
@@ -129,6 +128,7 @@
 	y = et->name.y + (((int)(lh) - (int)(cursor->cellh)) / 2);
 
 	mlk_sprite_draw(cursor, 1, 2, x, y);
+#endif
 }
 
 static void
--- a/libmlk-rpg/mlk/rpg/battle.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle.c	Wed Mar 01 16:24:07 2023 +0100
@@ -34,7 +34,6 @@
 #include <mlk/ui/align.h>
 #include <mlk/ui/frame.h>
 #include <mlk/ui/label.h>
-#include <mlk/ui/theme.h>
 
 #include "battle-bar.h"
 #include "battle-indicator.h"
@@ -132,6 +131,7 @@
 static void
 positionate_name(struct battle_entity *et, const struct battle *bt)
 {
+#if 0
 	unsigned int lw;
 	struct mlk_sprite *sprite;
 
@@ -139,10 +139,10 @@
 	sprite = et->ch->sprites[CHARACTER_SPRITE_NORMAL];
 
 	et->name.text = et->ch->name;
-	et->name.flags = MLK_LABEL_FLAGS_SHADOW;
 	mlk_label_query(&et->name, &lw, NULL);
 	et->name.y = et->y + sprite->cellh + BATTLE_THEME(bt)->padding;
 	et->name.x = et->x + (sprite->cellw / 2) - (lw / 2);
+#endif
 }
 
 static void
--- a/libmlk-rpg/mlk/rpg/message.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/message.c	Wed Mar 01 16:24:07 2023 +0100
@@ -32,12 +32,9 @@
 #include <mlk/ui/align.h>
 #include <mlk/ui/frame.h>
 #include <mlk/ui/label.h>
-#include <mlk/ui/theme.h>
 
 #include "message.h"
 
-#define THEME(msg)      (msg->theme ? msg->theme : &mlk_theme)
-
 static void
 draw_frame(const struct message *msg)
 {
@@ -54,6 +51,7 @@
 static inline unsigned int
 min_width(const struct message *msg)
 {
+#if 0
 	assert(msg);
 
 	unsigned int maxw = 0, w = 0;
@@ -69,6 +67,8 @@
 	}
 
 	return (THEME(msg)->padding * 2) + maxw;
+#endif
+	return 0;
 }
 
 static inline unsigned int
@@ -76,15 +76,19 @@
 {
 	assert(msg);
 
+#if 0
 	const struct mlk_theme *th = THEME(msg);
 	const unsigned int lh  = mlk_font_height(th->fonts[MLK_THEME_FONT_INTERFACE]);
 
 	return (th->padding * 2) + (msg->linesz * lh) + ((msg->linesz - 1) * msg->spacing);
+#endif
+	return 0;
 }
 
 static void
 draw_lines(const struct message *msg)
 {
+#if 0
 	const struct mlk_theme *theme = THEME(msg);
 	struct mlk_label label;
 	unsigned int lw, lh;
@@ -120,6 +124,7 @@
 
 		mlk_label_draw(&label);
 	}
+#endif
 }
 
 void
--- a/libmlk-ui/CMakeLists.txt	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/CMakeLists.txt	Wed Mar 01 16:24:07 2023 +0100
@@ -36,16 +36,12 @@
 	${libmlk-ui_SOURCE_DIR}/mlk/ui/label.h
 	${libmlk-ui_SOURCE_DIR}/mlk/ui/notify.c
 	${libmlk-ui_SOURCE_DIR}/mlk/ui/notify.h
-	${libmlk-ui_SOURCE_DIR}/mlk/ui/theme.c
-	${libmlk-ui_SOURCE_DIR}/mlk/ui/theme.h
 	${libmlk-ui_SOURCE_DIR}/mlk/ui/ui.c
 	${libmlk-ui_SOURCE_DIR}/mlk/ui/ui.h
 )
 
 set(
 	ASSETS
-	${libmlk-ui_SOURCE_DIR}/assets/fonts/opensans-light.ttf
-	${libmlk-ui_SOURCE_DIR}/assets/fonts/opensans-medium.ttf
 	${libmlk-ui_SOURCE_DIR}/assets/fonts/opensans-regular.ttf
 )
 
--- a/libmlk-ui/mlk/ui/button.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/button.c	Wed Mar 01 16:24:07 2023 +0100
@@ -27,7 +27,6 @@
 #include "align.h"
 #include "button.h"
 #include "label.h"
-#include "theme.h"
 
 #define STYLE_INVOKE(s, f, ...)                                                 \
 do {                                                                            \
@@ -42,10 +41,10 @@
 {
 	struct mlk_label label = {
 		.text = button->text,
+		.style = button->text_style
 	};
 	unsigned int lw, lh;
 
-	// TODO: once label has style, copy color.
 	mlk_label_query(&label, &lw, &lh);
 
 	if (lw > button->w)
@@ -56,9 +55,10 @@
 	mlk_align(MLK_ALIGN_CENTER, &label.x, &label.y, lw, lh,
 	    button->x, button->y, button->w, button->h);
 
-	mlk_painter_set_color(style->bg_color);
+	mlk_painter_set_color(style->border_color);
 	mlk_painter_draw_rectangle(button->x, button->y, button->w, button->h);
-
+	mlk_painter_set_color(style->bg_color);
+	mlk_painter_draw_rectangle(button->x + 1, button->y + 1, button->w - 2, button->h - 2);
 	mlk_label_draw(&label);
 }
 
@@ -74,9 +74,9 @@
 }
 
 struct mlk_button_style mlk_button_style = {
-	.bg_color = 0x577277ff,
-	.text_color = 0xffffffff,
-	.draw = draw
+	.bg_color       = 0xebf0f6ff,
+	.border_color   = 0xbac7dbff,
+	.draw           = draw
 };
 
 void
--- a/libmlk-ui/mlk/ui/button.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/button.h	Wed Mar 01 16:24:07 2023 +0100
@@ -23,13 +23,14 @@
 
 union mlk_event;
 
+struct mlk_button;
+struct mlk_label_style;
 struct mlk_theme;
-struct mlk_button;
 
 struct mlk_button_style {
 	void *data;
 	unsigned long bg_color;
-	unsigned long text_color;
+	unsigned long border_color;
 	void (*init)(struct mlk_button_style *, struct mlk_button *);
 	void (*update)(struct mlk_button_style *, struct mlk_button *, unsigned int);
 	void (*draw)(struct mlk_button_style *, const struct mlk_button *);
@@ -41,6 +42,7 @@
 	unsigned int w, h;
 	const char *text;
 	struct mlk_button_style *style;
+	struct mlk_label_style *text_style;
 	int pressed;
 };
 
--- a/libmlk-ui/mlk/ui/checkbox.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/checkbox.c	Wed Mar 01 16:24:07 2023 +0100
@@ -46,9 +46,9 @@
 static void
 draw(struct mlk_checkbox_style *style, const struct mlk_checkbox *cb)
 {
-	mlk_painter_set_color(style->bg_color);
+	mlk_painter_set_color(style->border_color);
 	mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h);
-	mlk_painter_set_color(style->border_color);
+	mlk_painter_set_color(style->bg_color);
 	mlk_painter_draw_rectangle(cb->x + 1, cb->y + 1, cb->w - 2, cb->h - 2);
 
 	if (cb->checked) {
@@ -58,9 +58,9 @@
 }
 
 struct mlk_checkbox_style mlk_checkbox_style = {
-	.bg_color       = 0x151d28ff,
-	.border_color   = 0xd7b594ff,
-	.check_color    = 0x341c27ff,
+	.bg_color       = 0xebf0f6ff,
+	.border_color   = 0xbac7dbff,
+	.check_color    = 0x848795ff,
 	.draw           = draw
 };
 
--- a/libmlk-ui/mlk/ui/debug.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/debug.c	Wed Mar 01 16:24:07 2023 +0100
@@ -22,7 +22,6 @@
 #include <mlk/core/texture.h>
 
 #include "debug.h"
-#include "theme.h"
 
 struct mlk_debug_options mlk_debug_options = {
 #if !defined(NDEBUG)
@@ -49,6 +48,7 @@
 void
 mlk_debugva(struct mlk_debug_report *report, const char *fmt, va_list ap)
 {
+#if 0
 	assert(report);
 	assert(fmt);
 
@@ -66,7 +66,7 @@
 	theme = &mlk_theme;
 	font = theme->fonts[MLK_THEME_FONT_DEBUG];
 
-	if (mlk_font_render(font, &tex, line, theme->colors[MLK_THEME_COLOR_DEBUG]) < 0)
+	if (mlk_font_render(font, &tex, line, MLK_THEME_COLOR_DEBUG) < 0)
 		return;
 
 	x = theme->padding;
@@ -75,4 +75,5 @@
 
 	mlk_texture_draw(&tex, x, y);
 	mlk_texture_finish(&tex);
+#endif
 }
--- a/libmlk-ui/mlk/ui/frame.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/frame.c	Wed Mar 01 16:24:07 2023 +0100
@@ -33,12 +33,15 @@
 static void
 draw(struct mlk_frame_style *style, const struct mlk_frame *frame)
 {
+	mlk_painter_set_color(style->border_color);
+	mlk_painter_draw_rectangle(frame->x, frame->y, frame->w, frame->h);
 	mlk_painter_set_color(style->bg_color);
-	mlk_painter_draw_rectangle(frame->x, frame->y, frame->w, frame->h);
+	mlk_painter_draw_rectangle(frame->x + 1, frame->y + 1, frame->w - 2, frame->h - 2);
 }
 
 struct mlk_frame_style mlk_frame_style = {
-	.bg_color       = 0xad7757ff,
+	.bg_color       = 0xf5f7faff,
+	.border_color   = 0xcdd2daff,
 	.draw           = draw
 };
 
--- a/libmlk-ui/mlk/ui/frame.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/frame.h	Wed Mar 01 16:24:07 2023 +0100
@@ -25,6 +25,7 @@
 
 struct mlk_frame_style {
 	unsigned long bg_color;
+	unsigned long border_color;
 	void (*init)(struct mlk_frame_style *, struct mlk_frame *);
 	void (*update)(struct mlk_frame_style *, struct mlk_frame *, unsigned int);
 	void (*draw)(struct mlk_frame_style *, const struct mlk_frame *);
--- a/libmlk-ui/mlk/ui/gridmenu.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/gridmenu.c	Wed Mar 01 16:24:07 2023 +0100
@@ -30,9 +30,16 @@
 #include "frame.h"
 #include "label.h"
 #include "gridmenu.h"
-#include "theme.h"
 
-#define THEME(m) ((m)->theme ? (m)->theme : &mlk_theme)
+#define STYLE_INVOKE(s, f, ...)                                                 \
+do {                                                                            \
+        if (s && s->f)                                                          \
+                s->f(s, __VA_ARGS__);                                           \
+        else if (mlk_gridmenu_style.f)                                          \
+                mlk_gridmenu_style.f(s ? s : &mlk_gridmenu_style, __VA_ARGS__); \
+} while (0)
+
+#define STYLE_GET(s, p) (s ? s->p : mlk_gridmenu_style.p)
 
 struct index {
 	unsigned int row;
@@ -51,9 +58,8 @@
 static void
 geometry(struct mlk_gridmenu *menu)
 {
-	const struct mlk_theme *theme = THEME(menu);
 	struct mlk_label label = {
-		.flags = MLK_LABEL_FLAGS_SHADOW
+		.style = menu->text_style
 	};
 	unsigned int reqw = 0, reqh = 0, lw, lh;
 
@@ -65,7 +71,6 @@
 		if (!(label.text = menu->items[i]))
 			continue;
 
-
 		mlk_label_query(&label, &lw, &lh);
 
 		menu->eltw = fmax(menu->eltw, lw);
@@ -73,8 +78,8 @@
 	}
 
 	/* Total texture size required to draw items. */
-	reqw = (theme->padding * 2) + (menu->eltw * menu->ncols);
-	reqh = (theme->padding * 2) + (menu->elth * menu->nrows);
+	reqw = (STYLE_GET(menu->style, padding) * 2) + (menu->eltw * menu->ncols);
+	reqh = (STYLE_GET(menu->style, padding) * 2) + (menu->elth * menu->nrows);
 
 	/*
 	 * Compute spacing between elements. We remove the padding because it
@@ -84,7 +89,7 @@
 		mlk_tracef("gridmenu width is too small: %u < %u", menu->w, reqw);
 		menu->spacew = 1;
 	} else if (menu->ncols > 1) {
-		reqw -= theme->padding * 2;
+		reqw -= STYLE_GET(menu->style, padding) * 2;
 		menu->spacew = (menu->w - reqw) / menu->ncols;
 	}
 
@@ -92,7 +97,7 @@
 		mlk_tracef("gridmenu height is too small: %u < %u", menu->h, reqh);
 		menu->spaceh = 1;
 	} else if (menu->nrows > 1) {
-		reqh -= theme->padding * 2;
+		reqh -= STYLE_GET(menu->style, padding) * 2;
 		menu->spaceh = (menu->h - reqh) / menu->nrows;
 	}
 }
@@ -115,9 +120,6 @@
 {
 	size_t pagesz, pagenr, item, c = 0, r = 0;
 	struct mlk_label label = {0};
-	const struct mlk_theme *theme = THEME(menu);
-
-	label.flags = MLK_LABEL_FLAGS_SHADOW;
 
 	/*
 	 * Select the first top-left column based on the current selection and
@@ -133,15 +135,15 @@
 			continue;
 
 		label.text = menu->items[item];
-		label.x = menu->x + theme->padding + (c * menu->eltw) + (c * menu->spacew);
-		label.y = menu->y + theme->padding + (r * menu->elth) + (r * menu->spaceh);
+		label.x = menu->x + STYLE_GET(menu->style, padding) + (c * menu->eltw) + (c * menu->spacew);
+		label.y = menu->y + STYLE_GET(menu->style, padding) + (r * menu->elth) + (r * menu->spaceh);
 
-#if 0
 		if (i == menu->selected % pagesz)
-			label.flags |= MLK_LABEL_FLAGS_SELECTED;
+			label.style = menu->text_selected_style
+			     ? menu->text_selected_style
+			     : &mlk_label_style_selected;
 		else
-			label.flags &= ~(MLK_LABEL_FLAGS_SELECTED);
-#endif
+			label.style = menu->text_style;
 
 		mlk_label_draw(&label);
 
@@ -194,7 +196,6 @@
 {
 	assert(click->type == MLK_EVENT_CLICKDOWN);
 
-	const struct mlk_theme *theme = THEME(menu);
 	size_t pagesz, pagenr, selected, c = 0, r = 0;
 	int x, y;
 
@@ -202,8 +203,8 @@
 	pagenr = menu->selected / pagesz;
 
 	for (size_t i = 0; i < pagesz; ++i) {
-		x = menu->x + theme->padding + (c * menu->eltw) + (c * menu->spacew);
-		y = menu->y + theme->padding + (r * menu->elth) + (r * menu->spaceh);
+		x = menu->x + STYLE_GET(menu->style, padding) + (c * menu->eltw) + (c * menu->spacew);
+		y = menu->y + STYLE_GET(menu->style, padding) + (r * menu->elth) + (r * menu->spaceh);
 
 		if (mlk_maths_is_boxed(x, y, menu->eltw, menu->elth, click->x, click->y)) {
 			selected  = c + r * menu->ncols;
@@ -284,3 +285,12 @@
 	draw_frame(menu);
 	draw_labels(menu);
 }
+
+void
+mlk_gridmenu_finish(struct mlk_gridmenu *menu)
+{
+	assert(menu);
+
+	
+
+}
--- a/libmlk-ui/mlk/ui/gridmenu.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/gridmenu.h	Wed Mar 01 16:24:07 2023 +0100
@@ -25,23 +25,37 @@
 
 #include "label.h"
 
-struct mlk_theme;
+union mlk_event;
+
+struct mlk_gridmenu;
 
-union mlk_event;
+struct mlk_gridmenu_style {
+	void *data;
+	unsigned long bg_color;
+	unsigned long border_color;
+	unsigned int padding;
+	void (*init)(struct mlk_gridmenu_style *, struct mlk_gridmenu *);
+	void (*update)(struct mlk_gridmenu_style *, struct mlk_gridmenu *, unsigned int);
+	void (*draw)(struct mlk_gridmenu_style *, const struct mlk_gridmenu *);
+	void (*finish)(struct mlk_gridmenu_style *, struct mlk_gridmenu *);
+};
 
 struct mlk_gridmenu {
 	/* public */
-	int x;
-	int y;
-	unsigned int w;
-	unsigned int h;
-	size_t selected;
-	const struct mlk_theme *theme;
+	int x, y;
+	unsigned int w, h;
+
 	const char * const *items;
 	size_t itemsz;
+	size_t selected;
+
 	unsigned int nrows;
 	unsigned int ncols;
 
+	struct mlk_gridmenu_style *style;
+	struct mlk_label_style *text_style;
+	struct mlk_label_style *text_selected_style;
+
 	/* private */
 	unsigned int eltw;      /* maximum entry label width */
 	unsigned int elth;      /* maximum entry label height */
@@ -49,6 +63,8 @@
 	unsigned int spaceh;    /* and vertically */
 };
 
+extern struct mlk_gridmenu_style mlk_gridmenu_style;
+
 MLK_CORE_BEGIN_DECLS
 
 void
@@ -63,6 +79,9 @@
 void
 mlk_gridmenu_draw(const struct mlk_gridmenu *);
 
+void
+mlk_gridmenu_finish(struct mlk_gridmenu *);
+
 MLK_CORE_END_DECLS
 
 #endif /* !MLK_UI_GRIDMENU_H */
--- a/libmlk-ui/mlk/ui/label.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/label.c	Wed Mar 01 16:24:07 2023 +0100
@@ -24,7 +24,7 @@
 #include <mlk/core/texture.h>
 
 #include "label.h"
-#include "theme.h"
+#include "ui.h"
 
 #define STYLE_INVOKE(s, f, ...)                                                 \
 do {                                                                            \
@@ -40,7 +40,7 @@
 	if (style && style->text_font)
 		return style->text_font;
 
-	return mlk_theme.fonts[MLK_THEME_FONT_INTERFACE];
+	return mlk_ui_fonts[MLK_UI_FONT_INTERFACE];
 }
 
 static void
@@ -52,16 +52,6 @@
 
 	font = style_font(style);
 
-	/* Shadow text, only if enabled. */
-	if (label->flags & MLK_LABEL_FLAGS_SHADOW) {
-		if ((err = mlk_font_render(font, &tex, label->text, style->shadow_color)) < 0)
-			mlk_panic(err);
-
-		mlk_texture_draw(&tex, label->x + 1, label->y + 1);
-		mlk_texture_finish(&tex);
-	}
-
-	/* Normal text. */
 	if ((err = mlk_font_render(font, &tex, label->text, style->text_color)) < 0)
 		mlk_panic(err);
 
@@ -70,11 +60,23 @@
 }
 
 struct mlk_label_style mlk_label_style = {
-	.shadow_color   = 0x000000ff,
-	.text_color     = 0xffffffff,
+	.text_color     = 0x000000ff,
+	.draw           = draw
+};
+
+struct mlk_label_style mlk_label_style_selected = {
+	.text_color     = 0x7da42dff,
 	.draw           = draw
 };
 
+void
+mlk_label_init(struct mlk_label *label)
+{
+	assert(mlk_label_ok(label));
+
+	STYLE_INVOKE(label->style, init, label);
+}
+
 int
 mlk_label_ok(const struct mlk_label *label)
 {
--- a/libmlk-ui/mlk/ui/label.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/label.h	Wed Mar 01 16:24:07 2023 +0100
@@ -24,14 +24,8 @@
 struct mlk_font;
 struct mlk_label;
 
-enum mlk_label_flags {
-	MLK_LABEL_FLAGS_NONE	= 0,
-	MLK_LABEL_FLAGS_SHADOW  = (1 << 0)
-};
-
 struct mlk_label_style {
 	void *data;
-	unsigned long shadow_color;
 	unsigned long text_color;
 	struct mlk_font *text_font;
 	void (*init)(struct mlk_label_style *, struct mlk_label *);
@@ -43,11 +37,11 @@
 struct mlk_label {
 	int x, y;
 	const char *text;
-	enum mlk_label_flags flags;
 	struct mlk_label_style *style;
 };
 
 extern struct mlk_label_style mlk_label_style;
+extern struct mlk_label_style mlk_label_style_selected;
 
 MLK_CORE_BEGIN_DECLS
 
--- a/libmlk-ui/mlk/ui/notify.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/notify.c	Wed Mar 01 16:24:07 2023 +0100
@@ -29,7 +29,6 @@
 #include "frame.h"
 #include "label.h"
 #include "notify.h"
-#include "theme.h"
 
 #define WIDTH   (mlk_window.w / 3)
 #define HEIGHT  (mlk_window.h / 10)
@@ -60,6 +59,7 @@
 static void
 geometry(struct geo *geo, const struct mlk_notify *n, size_t index)
 {
+#if 0
 	int x, y;
 
 	/* Determine theme. */
@@ -97,6 +97,7 @@
 	geo->body_x  = geo->title_x;
 	geo->body_y  = geo->icon_y + n->icon->h;
 	geo->body_y -= mlk_font_height(geo->theme->fonts[MLK_THEME_FONT_INTERFACE]) / 2;
+#endif
 }
 
 static void
@@ -121,6 +122,7 @@
 static void
 draw_title(const struct geo *geo, const struct mlk_notify *n)
 {
+#if 0
 	const struct mlk_label l = {
 		.x = geo->title_x,
 		.y = geo->title_y,
@@ -129,11 +131,13 @@
 	};
 
 	mlk_label_draw(&l);
+#endif
 }
 
 static void
 draw_body(const struct geo *geo, const struct mlk_notify *n)
 {
+#if 0
 	const struct mlk_label l = {
 		.x = geo->body_x,
 		.y = geo->body_y,
@@ -142,6 +146,7 @@
 	};
 
 	mlk_label_draw(&l);
+#endif
 }
 
 static void
--- a/libmlk-ui/mlk/ui/theme.c	Wed Mar 01 14:07:10 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * theme.c -- abstract theming
- *
- * Copyright (c) 2020-2023 David Demelier <markand@malikania.fr>
- *
- * 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 <assert.h>
-#include <stddef.h>
-#include <string.h>
-
-#include <mlk/core/font.h>
-#include <mlk/core/maths.h>
-#include <mlk/core/painter.h>
-#include <mlk/core/panic.h>
-#include <mlk/core/texture.h>
-#include <mlk/core/util.h>
-
-#include <assets/fonts/opensans-light.h>
-#include <assets/fonts/opensans-medium.h>
-#include <assets/fonts/opensans-regular.h>
-
-#include "align.h"
-#include "frame.h"
-#include "label.h"
-#include "theme.h"
-
-#define THEME(t) (t ? t : &default_theme)
-
-/* Default font catalog. */
-#define FONT(bin, size, index)                                          \
-	{ bin, sizeof (bin), size, &mlk_theme.fonts[index], {0} }
-
-static struct font_catalog {
-	const unsigned char *data;
-	const size_t datasz;
-	unsigned int size;
-	struct mlk_font **dest;
-	struct mlk_font font;
-} default_fonts[] = {
-	FONT(assets_fonts_opensans_light, 12, MLK_THEME_FONT_DEBUG),
-	FONT(assets_fonts_opensans_regular, 14, MLK_THEME_FONT_INTERFACE)
-};
-
-/* Default theme. */
-struct mlk_theme mlk_theme = {
-	.colors = {
-		[MLK_THEME_COLOR_DEBUG]         = 0xff0000ff,
-		[MLK_THEME_COLOR_NORMAL]        = 0xffffffff,
-		[MLK_THEME_COLOR_SELECTED]      = 0x006554ff,
-		[MLK_THEME_COLOR_SHADOW]        = 0x000000ff
-	},
-	.padding = 10,
-};
-
-int
-mlk_theme_init(void)
-{
-	struct font_catalog *fc;
-	int err;
-
-	/* Open all fonts. */
-	for (size_t i = 0; i < MLK_UTIL_SIZE(default_fonts); ++i) {
-		fc = &default_fonts[i];
-
-		if ((err = mlk_font_openmem(&fc->font, fc->data, fc->datasz, fc->size)) < 0)
-			goto failed;
-
-		/* Reference this font into the catalog. */
-		*default_fonts[i].dest = &default_fonts[i].font;
-	}
-
-	return 0;
-
-failed:
-	mlk_theme_finish();
-
-	return err;
-}
-
-void
-mlk_theme_finish(void)
-{
-	for (size_t i = 0; i < MLK_UTIL_SIZE(default_fonts); ++i) {
-		mlk_font_finish(&default_fonts[i].font);
-		*default_fonts[i].dest = NULL;
-	}
-}
--- a/libmlk-ui/mlk/ui/theme.h	Wed Mar 01 14:07:10 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * theme.h -- abstract theming
- *
- * Copyright (c) 2020-2023 David Demelier <markand@malikania.fr>
- *
- * 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.
- */
-
-#ifndef MLK_UI_THEME_H
-#define MLK_UI_THEME_H
-
-#include <mlk/core/core.h>
-
-struct mlk_font;
-struct mlk_sprite;
-
-enum mlk_theme_font {
-	MLK_THEME_FONT_DEBUG,
-	MLK_THEME_FONT_INTERFACE,
-	MLK_THEME_FONT_LAST
-};
-
-enum mlk_theme_color {
-	MLK_THEME_COLOR_DEBUG,
-	MLK_THEME_COLOR_NORMAL,
-	MLK_THEME_COLOR_SELECTED,
-	MLK_THEME_COLOR_SHADOW,
-	MLK_THEME_COLOR_LAST
-};
-
-enum mlk_theme_sprite {
-	MLK_THEME_SPRITE_CURSOR,
-	MLK_THEME_SPRITE_LAST
-};
-
-struct mlk_theme {
-	struct mlk_font *fonts[MLK_THEME_FONT_LAST];
-	const struct mlk_sprite *sprites[MLK_THEME_SPRITE_LAST];
-	unsigned long colors[MLK_THEME_COLOR_LAST];
-	unsigned int padding;
-};
-
-extern struct mlk_theme mlk_theme;
-
-MLK_CORE_BEGIN_DECLS
-
-int
-mlk_theme_init(void);
-
-void
-mlk_theme_finish(void);
-
-MLK_CORE_END_DECLS
-
-#endif /* !MLK_UI_THEME_H */
--- a/libmlk-ui/mlk/ui/ui.c	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/ui.c	Wed Mar 01 16:24:07 2023 +0100
@@ -16,17 +16,62 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "theme.h"
+#include <stddef.h>
+
+#include <mlk/core/font.h>
+#include <mlk/core/util.h>
+
+#include <assets/fonts/opensans-regular.h>
+
 #include "ui.h"
 
+/* Default font catalog. */
+#define FONT_DEF(b, s, i)                                               \
+{                                                                       \
+        .data = b,                                                      \
+        .datasz = sizeof (b),                                           \
+        .size = s,                                                      \
+        .fontaddr = &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;
+} 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};
+
 int
 mlk_ui_init(void)
 {
-	return mlk_theme_init();
+	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;
+	}
+
+	return 0;
+
+failed:
+	mlk_ui_finish();
+
+	return err;
 }
 
 void
 mlk_ui_finish(void)
 {
-	mlk_theme_finish();
 }
--- a/libmlk-ui/mlk/ui/ui.h	Wed Mar 01 14:07:10 2023 +0100
+++ b/libmlk-ui/mlk/ui/ui.h	Wed Mar 01 16:24:07 2023 +0100
@@ -23,6 +23,15 @@
 
 MLK_CORE_BEGIN_DECLS
 
+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];
+
 int
 mlk_ui_init(void);