changeset 504:52a305833381

ui: rework styles
author David Demelier <markand@malikania.fr>
date Wed, 01 Mar 2023 14:07:10 +0100
parents a55d0a29f466
children 6100c643dba0
files examples/example-battle/example-battle.c examples/example-font/example-font.c examples/example-message/example-message.c 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.h libmlk-rpg/mlk/rpg/message.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/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
diffstat 20 files changed, 180 insertions(+), 168 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-battle/example-battle.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/examples/example-battle/example-battle.c	Wed Mar 01 14:07:10 2023 +0100
@@ -135,7 +135,9 @@
 
 	/* Set cursor in default theme. */
 	mlk_registry_init();
+#if 0
 	mlk_theme_default()->sprites[MLK_THEME_SPRITE_CURSOR] = &mlk_registry_sprites[MLK_REGISTRY_TEXTURE_CURSOR];
+#endif
 }
 
 static struct mlk_state *states[2];
--- a/examples/example-font/example-font.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/examples/example-font/example-font.c	Wed Mar 01 14:07:10 2023 +0100
@@ -81,7 +81,9 @@
 			else
 				style = MLK_FONT_STYLE_ANTIALIASED;
 
+#if 0
 			mlk_theme_default()->fonts[MLK_THEME_FONT_INTERFACE]->style = style;
+#endif
 		default:
 			break;
 		}
@@ -99,7 +101,7 @@
 {
 	(void)st;
 
-	struct mlk_font *font = mlk_theme_default()->fonts[MLK_THEME_FONT_INTERFACE];
+	struct mlk_font *font = mlk_theme.fonts[MLK_THEME_FONT_INTERFACE];
 	struct mlk_texture tex;
 	int err;
 
--- a/examples/example-message/example-message.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/examples/example-message/example-message.c	Wed Mar 01 14:07:10 2023 +0100
@@ -99,6 +99,7 @@
 	mlk_game_loop();
 }
 
+#if 0
 static void
 my_draw_frame(const struct mlk_theme *th, const struct mlk_frame *f)
 {
@@ -107,6 +108,7 @@
 	mlk_painter_set_color(0xff0000ff);
 	mlk_painter_draw_rectangle(f->x, f->y, f->w, f->h);
 }
+#endif
 
 static void
 basic(void)
@@ -296,6 +298,7 @@
 static void
 custom(void)
 {
+#if 0
 	const char * const text[] = {
 		"This one will destroy your eyes.",
 		"Because it use a terrible custom theme."
@@ -312,11 +315,11 @@
 	};
 
 	/* Borrow default theme and change its frame drawing. */
-	mlk_theme_shallow(&theme, NULL);
 	theme.draw_frame = my_draw_frame;
 	theme.colors[MLK_THEME_COLOR_NORMAL] = 0x0000ffff;
 
 	run(&msg);
+#endif
 }
 
 static void
--- a/examples/example-ui/example-ui.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/examples/example-ui/example-ui.c	Wed Mar 01 14:07:10 2023 +0100
@@ -168,13 +168,13 @@
 	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_default()->padding;
+	l->x += mlk_theme.padding;
 }
 
 static void
 resize_autosave(void)
 {
-	unsigned int padding = mlk_theme_default()->padding;
+	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;
@@ -189,7 +189,7 @@
 static void
 resize_button(void)
 {
-	unsigned int padding = mlk_theme_default()->padding;
+	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;
--- a/libmlk-example/mlk/example/trace-hud.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-example/mlk/example/trace-hud.c	Wed Mar 01 14:07:10 2023 +0100
@@ -30,7 +30,7 @@
 #include "trace-hud.h"
 
 #define LINES_MAX       (4)
-#define THEME(t)        ((t) ? (t) : mlk_theme_default())
+#define THEME(t)        ((t) ? (t) : &mlk_theme)
 
 static struct {
 	char lines[LINES_MAX + 1][TRACE_LINE_MAX];
@@ -99,7 +99,6 @@
 			.x = x,
 			.y = y,
 			.text = data.lines[i],
-			.theme = th,
 			.flags = MLK_LABEL_FLAGS_SHADOW
 		});
 
--- a/libmlk-rpg/mlk/rpg/battle-bar-default.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-bar-default.c	Wed Mar 01 14:07:10 2023 +0100
@@ -42,7 +42,7 @@
 #include "item.h"
 #include "spell.h"
 
-#define THEME(bar) ((bar)->theme ? (bar)->theme : mlk_theme_default())
+#define THEME(bar) ((bar)->theme ? (bar)->theme : &mlk_theme)
 
 struct geo {
 	int x, y;
@@ -238,7 +238,6 @@
 	spacing /= 4;
 
 	/* Reuse the same label. */
-	label.theme = theme;
 	label.text = line;
 	label.flags = MLK_LABEL_FLAGS_SHADOW;
 
@@ -372,15 +371,15 @@
 	});
 
 	for (size_t i = 0; i < MLK_UTIL_SIZE(buttons); ++i) {
-		buttons[i].label.theme = theme;
-
 		mlk_label_query(&buttons[i].label, &buttons[i].w, &buttons[i].h);
 
 		/* Change theme if it's selected. */
+#if 0
 		if ((size_t)bar->menu == i)
 			buttons[i].label.flags |=  MLK_LABEL_FLAGS_SELECTED;
 		else
 			buttons[i].label.flags &= ~MLK_LABEL_FLAGS_SELECTED;
+#endif
 
 		mlk_align(buttons[i].align,
 		    &buttons[i].label.x, &buttons[i].label.y, buttons[i].w, buttons[i].h,
@@ -560,7 +559,7 @@
 		bar->items = mlk_alloc_new0(CHARACTER_SPELL_MAX, sizeof (*bar->items));
 	else
 		bar->items = mlk_alloc_renew0(bar->items, CHARACTER_SPELL_MAX);
-	
+
 	bar->itemsz = CHARACTER_SPELL_MAX;
 	bar->state = BATTLE_BAR_DEFAULT_STATE_GRID;
 
--- a/libmlk-rpg/mlk/rpg/battle-entity.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-entity.c	Wed Mar 01 14:07:10 2023 +0100
@@ -32,14 +32,20 @@
 static void
 draw_name(const struct battle_entity *et, const struct battle *bt)
 {
+	(void)bt;
+
 	struct mlk_label label = et->name;
 
+#if 0
 	label.theme = BATTLE_THEME(bt);
+#endif
 
+#if 0
 	if (et == battle_current(bt))
 		label.flags |=  MLK_LABEL_FLAGS_SELECTED;
 	else
 		label.flags &= ~MLK_LABEL_FLAGS_SELECTED;
+#endif
 
 	mlk_label_draw(&label);
 }
--- a/libmlk-rpg/mlk/rpg/battle-indicator.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-indicator.c	Wed Mar 01 14:07:10 2023 +0100
@@ -29,7 +29,7 @@
 
 #include "battle-indicator.h"
 
-#define THEME(bti)      ((bti)->theme ? (bti)->theme : mlk_theme_default())
+#define THEME(bti)      ((bti)->theme ? (bti)->theme : &mlk_theme)
 #define STEP            (2)
 #define DELAY           (5)
 
--- a/libmlk-rpg/mlk/rpg/battle-message.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle-message.c	Wed Mar 01 14:07:10 2023 +0100
@@ -50,7 +50,6 @@
 	/* Prepare message frame. */
 	f.w = mlk_window.w / 3;
 	f.h = mlk_window.h / 15;
-	f.theme = msg->theme;
 
 	/* Center on top. */
 	mlk_align(MLK_ALIGN_TOP, &f.x, &f.y, f.w, f.h, 0, 20, mlk_window.w, mlk_window.h);
@@ -58,7 +57,6 @@
 	/* Prepare message label box. */
 	l.text = msg->text;
 	l.flags = MLK_LABEL_FLAGS_SHADOW;
-	l.theme = msg->theme;
 	mlk_label_query(&l, &lw, &lh);
 
 	/* Align the text in the box. */
--- a/libmlk-rpg/mlk/rpg/battle.h	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/battle.h	Wed Mar 01 14:07:10 2023 +0100
@@ -49,7 +49,7 @@
 #define BATTLE_ENEMY_FOREACH(bt, iter) \
 	for (size_t i = 0; i < (bt)->enemiesz && ((iter) = (bt)->enemies[i]); ++i)
 
-#define BATTLE_THEME(bt) ((bt)->theme ? (bt)->theme : mlk_theme_default())
+#define BATTLE_THEME(bt) ((bt)->theme ? (bt)->theme : &mlk_theme)
 
 enum battle_status {
 	BATTLE_STATUS_NONE,
--- a/libmlk-rpg/mlk/rpg/message.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/message.c	Wed Mar 01 14:07:10 2023 +0100
@@ -36,7 +36,7 @@
 
 #include "message.h"
 
-#define THEME(msg)      (msg->theme ? msg->theme : mlk_theme_default())
+#define THEME(msg)      (msg->theme ? msg->theme : &mlk_theme)
 
 static void
 draw_frame(const struct message *msg)
@@ -45,8 +45,7 @@
 
 	struct mlk_frame frame = {
 		.w = msg->w,
-		.h = msg->h,
-		.theme = msg->theme
+		.h = msg->h
 	};
 
 	mlk_frame_draw(&frame);
@@ -97,7 +96,6 @@
 		if ((err = mlk_font_query(theme->fonts[MLK_THEME_FONT_INTERFACE], msg->lines[i], &lw, &lh)) < 0)
 			mlk_panic(err);
 
-		label.theme = theme;
 		label.x = theme->padding;
 		label.y = theme->padding + (i * (lh + msg->spacing));
 		label.text = msg->lines[i];
@@ -113,10 +111,12 @@
 		 * text and THEME_COLOR_SHADOW so if we have selected a line
 		 * we need to cheat the normal color.
 		 */
+#if 0
 		if ((msg->flags & MESSAGE_FLAGS_QUESTION) && msg->index == (unsigned int)i)
 			label.flags |= MLK_LABEL_FLAGS_SELECTED;
 		else
 			label.flags &= ~(MLK_LABEL_FLAGS_SELECTED);
+#endif
 
 		mlk_label_draw(&label);
 	}
--- a/libmlk-ui/mlk/ui/debug.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/debug.c	Wed Mar 01 14:07:10 2023 +0100
@@ -63,7 +63,7 @@
 
 	vsnprintf(line, sizeof (line), fmt, ap);
 
-	theme = report->theme ? report->theme : mlk_theme_default();
+	theme = &mlk_theme;
 	font = theme->fonts[MLK_THEME_FONT_DEBUG];
 
 	if (mlk_font_render(font, &tex, line, theme->colors[MLK_THEME_COLOR_DEBUG]) < 0)
--- a/libmlk-ui/mlk/ui/frame.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/frame.c	Wed Mar 01 14:07:10 2023 +0100
@@ -17,27 +17,37 @@
  */
 
 #include <assert.h>
-#include <string.h>
 
 #include <mlk/core/painter.h>
 
 #include "frame.h"
-#include "theme.h"
+
+#define STYLE_INVOKE(s, f, ...)                                                 \
+do {                                                                            \
+        if (s && s->f)                                                          \
+                s->f(s, __VA_ARGS__);                                           \
+        else if (mlk_frame_style.f)                                             \
+                mlk_frame_style.f(s ? s : &mlk_frame_style, __VA_ARGS__);       \
+} while (0)
+
+static void
+draw(struct mlk_frame_style *style, const struct mlk_frame *frame)
+{
+	mlk_painter_set_color(style->bg_color);
+	mlk_painter_draw_rectangle(frame->x, frame->y, frame->w, frame->h);
+}
+
+struct mlk_frame_style mlk_frame_style = {
+	.bg_color       = 0xad7757ff,
+	.draw           = draw
+};
 
 void
-mlk_frame_draw_default(const struct mlk_theme *t, const struct mlk_frame *frame)
+mlk_frame_init(struct mlk_frame *frame)
 {
-	assert(t);
 	assert(frame);
 
-	(void)t;
-
-	if (frame->style == MLK_FRAME_STYLE_BOX)
-		mlk_painter_set_color(0x7a4841ff);
-	else
-		mlk_painter_set_color(0xad7757ff);
-
-	mlk_painter_draw_rectangle(frame->x, frame->y, frame->w, frame->h);
+	STYLE_INVOKE(frame->style, init, frame);
 }
 
 void
@@ -45,5 +55,13 @@
 {
 	assert(frame);
 
-	mlk_theme_draw_frame(frame->theme, frame);
+	STYLE_INVOKE(frame->style, draw, frame);
 }
+
+void
+mlk_frame_finish(struct mlk_frame *frame)
+{
+	assert(frame);
+
+	STYLE_INVOKE(frame->style, finish, frame);
+}
--- a/libmlk-ui/mlk/ui/frame.h	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/frame.h	Wed Mar 01 14:07:10 2023 +0100
@@ -21,30 +21,35 @@
 
 #include <mlk/core/core.h>
 
-struct mlk_theme;
+struct mlk_frame;
 
-enum mlk_frame_style {
-	MLK_FRAME_STYLE_NORMAL,
-	MLK_FRAME_STYLE_BOX
+struct mlk_frame_style {
+	unsigned long bg_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 *);
+	void (*finish)(struct mlk_frame_style *, struct mlk_frame *);
 };
 
 struct mlk_frame {
-	int x;
-	int y;
-	unsigned int w;
-	unsigned int h;
-	enum mlk_frame_style style;
-	const struct mlk_theme *theme;
+	int x, y;
+	unsigned int w, h;
+	struct mlk_frame_style *style;
 };
 
+extern struct mlk_frame_style mlk_frame_style;
+
 MLK_CORE_BEGIN_DECLS
 
 void
-mlk_frame_draw_default(const struct mlk_theme *, const struct mlk_frame *);
+mlk_frame_init(struct mlk_frame *);
 
 void
 mlk_frame_draw(const struct mlk_frame *);
 
+void
+mlk_frame_finish(struct mlk_frame *);
+
 MLK_CORE_END_DECLS
 
 #endif /* !MLK_UI_FRAME_H */
--- a/libmlk-ui/mlk/ui/gridmenu.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/gridmenu.c	Wed Mar 01 14:07:10 2023 +0100
@@ -32,7 +32,7 @@
 #include "gridmenu.h"
 #include "theme.h"
 
-#define THEME(m) ((m)->theme ? (m)->theme : mlk_theme_default())
+#define THEME(m) ((m)->theme ? (m)->theme : &mlk_theme)
 
 struct index {
 	unsigned int row;
@@ -53,7 +53,6 @@
 {
 	const struct mlk_theme *theme = THEME(menu);
 	struct mlk_label label = {
-		.theme = theme,
 		.flags = MLK_LABEL_FLAGS_SHADOW
 	};
 	unsigned int reqw = 0, reqh = 0, lw, lh;
@@ -106,7 +105,6 @@
 		.y = menu->y,
 		.w = menu->w,
 		.h = menu->h,
-		.theme = menu->theme,
 	};
 
 	mlk_frame_draw(&f);
@@ -119,7 +117,6 @@
 	struct mlk_label label = {0};
 	const struct mlk_theme *theme = THEME(menu);
 
-	label.theme = theme;
 	label.flags = MLK_LABEL_FLAGS_SHADOW;
 
 	/*
@@ -139,10 +136,12 @@
 		label.x = menu->x + theme->padding + (c * menu->eltw) + (c * menu->spacew);
 		label.y = menu->y + theme->padding + (r * menu->elth) + (r * menu->spaceh);
 
+#if 0
 		if (i == menu->selected % pagesz)
 			label.flags |= MLK_LABEL_FLAGS_SELECTED;
 		else
 			label.flags &= ~(MLK_LABEL_FLAGS_SELECTED);
+#endif
 
 		mlk_label_draw(&label);
 
--- a/libmlk-ui/mlk/ui/label.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/label.c	Wed Mar 01 14:07:10 2023 +0100
@@ -26,27 +26,35 @@
 #include "label.h"
 #include "theme.h"
 
-void
-mlk_label_draw_default(const struct mlk_theme *t, const struct mlk_label *label)
+#define STYLE_INVOKE(s, f, ...)                                                 \
+do {                                                                            \
+        if (s && s->f)                                                          \
+                s->f(s, __VA_ARGS__);                                           \
+        else if (mlk_label_style.f)                                             \
+                mlk_label_style.f(s ? s : &mlk_label_style, __VA_ARGS__);       \
+} while (0)
+
+static inline struct mlk_font *
+style_font(struct mlk_label_style *style)
 {
-	assert(t);
-	assert(label);
+	if (style && style->text_font)
+		return style->text_font;
 
+	return mlk_theme.fonts[MLK_THEME_FONT_INTERFACE];
+}
+
+static void
+draw(struct mlk_label_style *style, const struct mlk_label *label)
+{
 	struct mlk_font *font;
 	struct mlk_texture tex;
-	unsigned long color;
 	int err;
 
-	font = label->flags & MLK_LABEL_FLAGS_IMPORTANT
-		? t->fonts[MLK_THEME_FONT_IMPORTANT]
-		: t->fonts[MLK_THEME_FONT_INTERFACE];
-	color = label->flags & MLK_LABEL_FLAGS_SELECTED
-		? t->colors[MLK_THEME_COLOR_SELECTED]
-	        : t->colors[MLK_THEME_COLOR_NORMAL];
+	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, t->colors[MLK_THEME_COLOR_SHADOW])) < 0)
+		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);
@@ -54,40 +62,53 @@
 	}
 
 	/* Normal text. */
-	if ((err = mlk_font_render(font, &tex, label->text, color)) < 0)
+	if ((err = mlk_font_render(font, &tex, label->text, style->text_color)) < 0)
 		mlk_panic(err);
 
 	mlk_texture_draw(&tex, label->x, label->y);
 	mlk_texture_finish(&tex);
 }
 
+struct mlk_label_style mlk_label_style = {
+	.shadow_color   = 0x000000ff,
+	.text_color     = 0xffffffff,
+	.draw           = draw
+};
+
 int
 mlk_label_ok(const struct mlk_label *label)
 {
 	return label && label->text && strlen(label->text) > 0;
 }
 
-void
+int
 mlk_label_query(const struct mlk_label *label, unsigned int *w, unsigned int *h)
 {
-	assert(label);
-	assert(label->text);
+	assert(mlk_label_ok(label));
 
-	const struct mlk_theme *t = label->theme ? label->theme : mlk_theme_default();
-	const struct mlk_font *f = label->flags & MLK_LABEL_FLAGS_IMPORTANT
-		? t->fonts[MLK_THEME_FONT_IMPORTANT]
-		: t->fonts[MLK_THEME_FONT_INTERFACE];
+	struct mlk_font *font;
 	int err;
 
-	if ((err = mlk_font_query(f, label->text, w, h)) < 0)
-		mlk_panic(err);
+	font = style_font(label->style);
+
+	if ((err = mlk_font_query(font, label->text, w, h)) < 0)
+		return err;
+
+	return err;
 }
 
 void
 mlk_label_draw(const struct mlk_label *label)
 {
-	assert(label);
-	assert(label->text);
+	assert(mlk_label_ok(label));
+
+	STYLE_INVOKE(label->style, draw, label);
+}
 
-	mlk_theme_draw_label(label->theme, label);
+void
+mlk_label_finish(struct mlk_label *label)
+{
+	assert(mlk_label_ok(label));
+
+	STYLE_INVOKE(label->style, finish, label);
 }
--- a/libmlk-ui/mlk/ui/label.h	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/label.h	Wed Mar 01 14:07:10 2023 +0100
@@ -21,37 +21,51 @@
 
 #include <mlk/core/core.h>
 
-struct mlk_theme;
+struct mlk_font;
+struct mlk_label;
 
 enum mlk_label_flags {
-	MLK_LABEL_FLAGS_NONE,
-	MLK_LABEL_FLAGS_SHADOW          = (1 << 0),
-	MLK_LABEL_FLAGS_IMPORTANT       = (1 << 1),
-	MLK_LABEL_FLAGS_SELECTED        = (1 << 2)
+	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 *);
+	void (*update)(struct mlk_label_style *, struct mlk_label *, unsigned int);
+	void (*draw)(struct mlk_label_style *, const struct mlk_label *);
+	void (*finish)(struct mlk_label_style *, struct mlk_label *);
 };
 
 struct mlk_label {
-	int x;
-	int y;
+	int x, y;
 	const char *text;
 	enum mlk_label_flags flags;
-	const struct mlk_theme *theme;
+	struct mlk_label_style *style;
 };
 
+extern struct mlk_label_style mlk_label_style;
+
 MLK_CORE_BEGIN_DECLS
 
 void
-mlk_label_draw_default(const struct mlk_theme *, const struct mlk_label *);
+mlk_label_init(struct mlk_label *);
 
 int
 mlk_label_ok(const struct mlk_label *);
 
-void
+int
 mlk_label_query(const struct mlk_label *, unsigned int *, unsigned int *);
 
 void
 mlk_label_draw(const struct mlk_label *);
 
+void
+mlk_label_finish(struct mlk_label *);
+
 MLK_CORE_END_DECLS
 
 #endif /* !MLK_UI_LABEL_H */
--- a/libmlk-ui/mlk/ui/notify.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/notify.c	Wed Mar 01 14:07:10 2023 +0100
@@ -63,7 +63,7 @@
 	int x, y;
 
 	/* Determine theme. */
-	geo->theme = system->theme ? system->theme : mlk_theme_default();
+	geo->theme = system->theme ? system->theme : &mlk_theme;
 
 	/* Determine notification position. */
 	x  = mlk_window.w - geo->theme->padding;
@@ -91,7 +91,7 @@
 	/* Align title to the right of the icon at the same y coordinate. */
 	geo->title_x  = geo->icon_x + n->icon->w + geo->theme->padding;
 	geo->title_y  = geo->icon_y;
-	geo->title_y -= mlk_font_height(geo->theme->fonts[MLK_THEME_FONT_IMPORTANT]) / 2;
+	geo->title_y -= mlk_font_height(geo->theme->fonts[MLK_THEME_FONT_INTERFACE]) / 2;
 
 	/* Align body so it ends at the end of the icon. */
 	geo->body_x  = geo->title_x;
@@ -118,8 +118,6 @@
 	mlk_texture_draw(n->icon, geo->icon_x, geo->icon_y);
 }
 
-#include <stdio.h>
-
 static void
 draw_title(const struct geo *geo, const struct mlk_notify *n)
 {
@@ -127,7 +125,7 @@
 		.x = geo->title_x,
 		.y = geo->title_y,
 		.text = n->title,
-		.flags = MLK_LABEL_FLAGS_SHADOW | MLK_LABEL_FLAGS_IMPORTANT
+		.flags = MLK_LABEL_FLAGS_SHADOW
 	};
 
 	mlk_label_draw(&l);
--- a/libmlk-ui/mlk/ui/theme.c	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/theme.c	Wed Mar 01 14:07:10 2023 +0100
@@ -40,20 +40,7 @@
 
 /* Default font catalog. */
 #define FONT(bin, size, index)                                          \
-	{ bin, sizeof (bin), size, &default_theme.fonts[index], {0} }
-
-/* Default theme. */
-static struct mlk_theme default_theme = {
-	.colors = {
-		[MLK_THEME_COLOR_DEBUG]         = 0xff0000ff,
-		[MLK_THEME_COLOR_NORMAL]        = 0xffffffff,
-		[MLK_THEME_COLOR_SELECTED]      = 0x006554ff,
-		[MLK_THEME_COLOR_SHADOW]        = 0x000000ff
-	},
-	.padding = 10,
-	.draw_frame = mlk_frame_draw_default,
-	.draw_label = mlk_label_draw_default,
-};
+	{ bin, sizeof (bin), size, &mlk_theme.fonts[index], {0} }
 
 static struct font_catalog {
 	const unsigned char *data;
@@ -63,18 +50,31 @@
 	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),
-	FONT(assets_fonts_opensans_medium, 14, MLK_THEME_FONT_IMPORTANT)
+	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) {
-		struct font_catalog *fc = &default_fonts[i];
+		fc = &default_fonts[i];
 
-		if (mlk_font_openmem(&fc->font, fc->data, fc->datasz, fc->size) < 0)
+		if ((err = mlk_font_openmem(&fc->font, fc->data, fc->datasz, fc->size)) < 0)
 			goto failed;
 
 		/* Reference this font into the catalog. */
@@ -86,43 +86,7 @@
 failed:
 	mlk_theme_finish();
 
-	return -1;
-}
-
-struct mlk_theme *
-mlk_theme_default(void)
-{
-	return &default_theme;
-}
-
-unsigned int
-theme_padding(const struct mlk_theme *t)
-{
-	return THEME(t)->padding;
-}
-
-void
-mlk_theme_shallow(struct mlk_theme *dst, const struct mlk_theme *src)
-{
-	assert(dst);
-
-	memcpy(dst, src ? src : &default_theme, sizeof (*src));
-}
-
-void
-mlk_theme_draw_frame(const struct mlk_theme *t, const struct mlk_frame *frame)
-{
-	assert(frame);
-
-	THEME(t)->draw_frame(THEME(t), frame);
-}
-
-void
-mlk_theme_draw_label(const struct mlk_theme *t, const struct mlk_label *label)
-{
-	assert(label);
-
-	THEME(t)->draw_label(THEME(t), label);
+	return err;
 }
 
 void
--- a/libmlk-ui/mlk/ui/theme.h	Wed Mar 01 10:51:25 2023 +0100
+++ b/libmlk-ui/mlk/ui/theme.h	Wed Mar 01 14:07:10 2023 +0100
@@ -22,15 +22,12 @@
 #include <mlk/core/core.h>
 
 struct mlk_font;
-struct mlk_frame;
-struct mlk_label;
 struct mlk_sprite;
 
 enum mlk_theme_font {
 	MLK_THEME_FONT_DEBUG,
 	MLK_THEME_FONT_INTERFACE,
-	MLK_THEME_FONT_IMPORTANT,
-	MLK_THEME_FONT_NUM
+	MLK_THEME_FONT_LAST
 };
 
 enum mlk_theme_color {
@@ -38,41 +35,28 @@
 	MLK_THEME_COLOR_NORMAL,
 	MLK_THEME_COLOR_SELECTED,
 	MLK_THEME_COLOR_SHADOW,
-	MLK_THEME_COLOR_NUM
+	MLK_THEME_COLOR_LAST
 };
 
 enum mlk_theme_sprite {
 	MLK_THEME_SPRITE_CURSOR,
-	MLK_THEME_SPRITE_NUM
+	MLK_THEME_SPRITE_LAST
 };
 
 struct mlk_theme {
-	struct mlk_font *fonts[MLK_THEME_FONT_NUM];
-	const struct mlk_sprite *sprites[MLK_THEME_SPRITE_NUM];
-	unsigned long colors[MLK_THEME_COLOR_NUM];
+	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;
+};
 
-	void (*draw_frame)(const struct mlk_theme *, const struct mlk_frame *);
-	void (*draw_label)(const struct mlk_theme *, const struct mlk_label *);
-};
+extern struct mlk_theme mlk_theme;
 
 MLK_CORE_BEGIN_DECLS
 
 int
 mlk_theme_init(void);
 
-struct mlk_theme *
-mlk_theme_default(void);
-
-void
-mlk_theme_shallow(struct mlk_theme *, const struct mlk_theme *);
-
-void
-mlk_theme_draw_frame(const struct mlk_theme *, const struct mlk_frame *);
-
-void
-mlk_theme_draw_label(const struct mlk_theme *, const struct mlk_label *);
-
 void
 mlk_theme_finish(void);