changeset 153:aa6e70e330a1

ui: make label less smart It should not contain alignment because it should be handled by the user tself.
author David Demelier <markand@malikania.fr>
date Thu, 15 Oct 2020 18:45:27 +0200
parents 1008a796a9e7
children 2252f9efac9a
files examples/example-drawable.c examples/example-label.c examples/example-sound.c examples/example-ui.c librpg/rpg/inventory_dialog.c librpg/rpg/message.c libui/ui/button.c libui/ui/label.c libui/ui/label.h
diffstat 9 files changed, 149 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-drawable.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/examples/example-drawable.c	Thu Oct 15 18:45:27 2020 +0200
@@ -41,30 +41,12 @@
 #define H 720
 
 static struct label help = {
-	.text = "Keys: <Esc> to reset. Click anywhere to spawn a drawable.",
 	.x = 10,
 	.y = 10,
-	.w = W,
-	.h = H,
-	.align = ALIGN_TOP_LEFT,
+	.text = "Keys: <Esc> to reset. Click anywhere to spawn a drawable.",
 	.flags = LABEL_FLAGS_SHADOW
 };
 
-#if 0
-// TODO: for the moment only animations are supported.
-static unsigned int which_selection;
-static char which_text[128];
-static struct label which = {
-	.text = buf,
-	.x = 10,
-	.y = 40,
-	.w = W,
-	.h = 32,
-	.flags = LABEL_NO_HCENTER,
-	.color = 0x4f8fbaff
-};
-#endif
-
 static struct drawable_stack stack;
 
 /*
--- a/examples/example-label.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/examples/example-label.c	Thu Oct 15 18:45:27 2020 +0200
@@ -24,12 +24,74 @@
 #include <core/util.h>
 #include <core/window.h>
 
+#include <ui/align.h>
 #include <ui/label.h>
 #include <ui/theme.h>
 
 #define W       (1280)
 #define H       (720)
 
+struct {
+	enum align align;
+	struct label label;
+} table[] = {
+	{
+		.align = ALIGN_TOP_LEFT,
+		.label = {
+			.text = "Top left"
+		}
+	},
+	{
+		.align = ALIGN_TOP,
+		.label = {
+			.text = "Top",
+		}
+	},
+	{
+		.align = ALIGN_TOP_RIGHT,
+		.label = {
+			.text = "Top right",
+		}
+	},
+	{
+		.align = ALIGN_RIGHT,
+		.label = {
+			.text = "Right",
+		}
+	},
+	{
+		.align = ALIGN_BOTTOM_RIGHT,
+		.label = {
+			.text = "Bottom right",
+		}
+	},
+	{
+		.align = ALIGN_BOTTOM,
+		.label = {
+			.text = "Bottom",
+		}
+	},
+	{
+		.align = ALIGN_BOTTOM_LEFT,
+		.label = {
+			.text = "Bottom left",
+		}
+	},
+	{
+		.align = ALIGN_LEFT,
+		.label = {
+			.text = "Left",
+		}
+	},
+	{
+		.align = ALIGN_CENTER,
+		.label = {
+			.text = "The world is Malikania.",
+			.flags = LABEL_FLAGS_SHADOW
+		}
+	}
+};
+
 static void
 init(void)
 {
@@ -37,6 +99,13 @@
 	    !window_init("Example - Label", W, H) ||
 	    !theme_init())
 		panic();
+
+	for (size_t i = 0; i < NELEM(table); ++i) {
+		struct label *l = &table[i].label;
+
+		label_query(l);
+		align(table[i].align, &l->x, &l->y, l->w, l->h, 0, 0, W, H);
+	}
 }
 
 static void
@@ -51,81 +120,6 @@
 run(void)
 {
 	struct clock clock = {0};
-	struct label labels[] = {
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Top left",
-			.align = ALIGN_TOP_LEFT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Top",
-			.align = ALIGN_TOP
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Top right",
-			.align = ALIGN_TOP_RIGHT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Right",
-			.align = ALIGN_RIGHT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Bottom right",
-			.align = ALIGN_BOTTOM_RIGHT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Bottom",
-			.align = ALIGN_BOTTOM
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Bottom left",
-			.align = ALIGN_BOTTOM_LEFT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "Left",
-			.align = ALIGN_LEFT
-		},
-		{
-			.x = 0,
-			.y = 0,
-			.w = W,
-			.h = H,
-			.text = "The world is Malikania.",
-			.flags = LABEL_FLAGS_SHADOW,
-			.align = ALIGN_CENTER
-		},
-	};
 	struct label mlabel = {
 		.text = "This one follows your mouse and is not aligned."
 	};
@@ -154,8 +148,8 @@
 		painter_set_color(0x4f8fbaff);
 		painter_clear();
 
-		for (size_t i = 0; i < NELEM(labels); ++i)
-			label_draw(&labels[i]);
+		for (size_t i = 0; i < NELEM(table); ++i)
+			label_draw(&table[i].label);
 
 		label_draw(&mlabel);
 		painter_present();
--- a/examples/example-sound.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/examples/example-sound.c	Thu Oct 15 18:45:27 2020 +0200
@@ -39,9 +39,6 @@
 	.text = "Keys: <s> start, <p> pause, <r> resume, <q> stop, <l> loop",
 	.x = 10,
 	.y = 10,
-	.w = W,
-	.h = H,
-	.align = ALIGN_TOP_LEFT,
 	.flags = LABEL_FLAGS_SHADOW
 };
 
--- a/examples/example-ui.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/examples/example-ui.c	Thu Oct 15 18:45:27 2020 +0200
@@ -26,6 +26,7 @@
 #include <core/util.h>
 #include <core/window.h>
 
+#include <ui/align.h>
 #include <ui/button.h>
 #include <ui/checkbox.h>
 #include <ui/frame.h>
@@ -101,10 +102,7 @@
 			.text = "Preferences",
 			.x = FRAME_ORIGIN_X,
 			.y = FRAME_ORIGIN_Y,
-			.w = FRAME_WIDTH,
-			.h = HEADER_HEIGHT,
 			.flags = LABEL_FLAGS_SHADOW,
-			.align = ALIGN_LEFT
 		}
 	},
 	.autosave = {
@@ -114,9 +112,7 @@
 		},
 		.label = {
 			.text = "Auto save game",
-			.align = ALIGN_LEFT,
 			.flags = LABEL_FLAGS_SHADOW,
-			.h = ELEMENT_HEIGHT
 		}
 	},
 	.quit = {
@@ -137,35 +133,57 @@
 }
 
 static void
-resize(void)
+resize_header(void)
 {
-	const unsigned int padding = theme_default()->padding;
+	struct frame *h = &ui.panel.frame;
+	struct label *l = &ui.header.label;
 
 	/* Header. */
-	ui.header.label.x = ui.panel.frame.x;
-	ui.header.label.y = ui.panel.frame.y;
+	label_query(l);
+	align(ALIGN_LEFT, &l->x, &l->y, l->w, l->h, h->x, h->y, h->w, HEADER_HEIGHT);
+
+	l->x += theme_default()->padding;
+}
+
+static void
+resize_autosave(void)
+{
+	unsigned int padding = theme_default()->padding;
+	struct frame *f = &ui.panel.frame;
+	struct checkbox *c = &ui.autosave.cb;
+	struct label *l = &ui.autosave.label;
 
-	/* Auto save. */
-	ui.autosave.cb.x = ui.panel.frame.x + padding;
-	ui.autosave.cb.y = ui.panel.frame.y + HEADER_HEIGHT + padding;
-	ui.autosave.label.w = ui.panel.frame.w - ui.autosave.cb.w - padding;
-	ui.autosave.label.x = ui.autosave.cb.x + ui.autosave.cb.w;
-	ui.autosave.label.y = ui.autosave.cb.y;
+	c->x = f->x + padding;
+	c->y = f->y + HEADER_HEIGHT + padding;
+
+	l->w = f->w - c->w - padding;
+	l->x = c->x + c->w + padding;
+	l->y = c->y;
+}
+
+static void
+resize_button(void)
+{
+	unsigned int padding = theme_default()->padding;
+	struct frame *f = &ui.panel.frame;
+	struct button *b = &ui.quit.button;
 
 	/* Button. */
-	ui.quit.button.w = ui.panel.frame.w / 4;
+	b->w = f->w / 4;
+
+	align(ALIGN_BOTTOM_RIGHT, &b->x, &b->y, b->w, b->h,
+	    f->x, f->y, f->w, f->h);
 
-	align(
-	    ALIGN_BOTTOM_RIGHT,
-	    &ui.quit.button.x,
-	    &ui.quit.button.y,
-	    ui.quit.button.w,
-	    ui.quit.button.h,
-	    ui.panel.frame.x + padding,
-	    ui.panel.frame.y + padding,
-	    ui.panel.frame.w - padding * 2,
-	    ui.panel.frame.h - padding * 2
-	);
+	b->x -= padding;
+	b->y -= padding;
+}
+
+static void
+resize(void)
+{
+	resize_header();
+	resize_autosave();
+	resize_button();
 }
 
 static void
--- a/librpg/rpg/inventory_dialog.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/librpg/rpg/inventory_dialog.c	Thu Oct 15 18:45:27 2020 +0200
@@ -195,7 +195,6 @@
 	dlg->fname.x = dlg->lname.x = dlg->x;
 	dlg->fname.y = dlg->lname.y = dlg->y + GRID_HEIGHT;
 	dlg->lname.x += ITEM_PADDING;
-	dlg->lname.align = ALIGN_LEFT;
 
 	/* Description label. */
 	dlg->fdesc.w = dlg->ldesc.w = LABEL_WIDTH;
@@ -203,7 +202,6 @@
 	dlg->fdesc.x = dlg->ldesc.x = dlg->y;
 	dlg->fdesc.y = dlg->ldesc.y = dlg->y + GRID_HEIGHT + (LABEL_HEIGHT / 2);
 	dlg->ldesc.x += ITEM_PADDING;
-	dlg->ldesc.align = ALIGN_LEFT;
 
 	/* Button sort. */
 	dlg->bsort.x = dlg->x;
--- a/librpg/rpg/message.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/librpg/rpg/message.c	Thu Oct 15 18:45:27 2020 +0200
@@ -100,7 +100,6 @@
 			.h = msg->h,
 			.theme = &theme,
 			.text = msg->text[i],
-			.align = ALIGN_TOP_LEFT,
 			.flags = LABEL_FLAGS_SHADOW
 		};
 
--- a/libui/ui/button.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/libui/ui/button.c	Thu Oct 15 18:45:27 2020 +0200
@@ -60,15 +60,14 @@
 
 	(void)t;
 
-	const struct label label = {
+	struct label label = {
 		.text = button->text,
-		.x = button->x,
-		.y = button->y,
-		.w = button->w,
-		.h = button->h,
-		.align = ALIGN_CENTER
 	};
 
+	label_query(&label);
+	align(ALIGN_CENTER, &label.x, &label.y, label.w, label.h,
+	    button->x, button->y, button->w, button->h);
+
 	painter_set_color(0x577277ff);
 	painter_draw_rectangle(button->x, button->y, button->w, button->h);
 
--- a/libui/ui/label.c	Thu Oct 15 18:09:45 2020 +0200
+++ b/libui/ui/label.c	Thu Oct 15 18:45:27 2020 +0200
@@ -41,28 +41,9 @@
 
 	struct font *font;
 	struct texture tex;
-	int x, y, bx, by;
-	unsigned int tw, th, bw, bh;
 
-	/* Compute real box size according to padding. */
-	bx = label->x + t->padding;
-	by = label->y + t->padding;
-	bw = label->w - (t->padding * 2);
-	bh = label->h - (t->padding * 2);
-
-	/* Make a shallow copy of the interface font. */
 	font = t->fonts[THEME_FONT_INTERFACE];
 
-	/* Compute text size. */
-	if (!font_box(font, label->text, &tw, &th))
-		panic();
-
-	/* Align if needed. */
-	x = label->x;
-	y = label->y;
-
-	align(label->align, &x, &y, tw, th, bx, by, bw, bh);
-
 	/* Shadow text, only if enabled. */
 	if (label->flags & LABEL_FLAGS_SHADOW) {
 		font->color = t->colors[THEME_COLOR_SHADOW];
@@ -70,7 +51,7 @@
 		if (!font_render(font, &tex, label->text))
 			panic();
 
-		texture_draw(&tex, x + 1, y + 1);
+		texture_draw(&tex, label->x + 1, label->y + 1);
 		texture_finish(&tex);
 	}
 
@@ -80,11 +61,23 @@
 	if (!font_render(font, &tex, label->text))
 		panic();
 
-	texture_draw(&tex, x, y);
+	texture_draw(&tex, label->x, label->y);
 	texture_finish(&tex);
 }
 
 void
+label_query(struct label *label)
+{
+	assert(label);
+	assert(label->text);
+
+	struct theme *t = label->theme ? label->theme : theme_default();
+
+	if (!font_box(t->fonts[THEME_FONT_INTERFACE], label->text, &label->w, &label->h))
+		panic();
+}
+
+void
 label_draw(const struct label *label)
 {
 	assert(label);
--- a/libui/ui/label.h	Thu Oct 15 18:09:45 2020 +0200
+++ b/libui/ui/label.h	Thu Oct 15 18:45:27 2020 +0200
@@ -25,8 +25,6 @@
  * \ingroup ui
  */
 
-#include "align.h"
-
 struct action;
 struct theme;
 
@@ -41,9 +39,9 @@
 /**
  * \brief GUI label.
  *
- * A label can be conveniently positioned using a bounding box and an alignment
- * in that case the fields `w`, `h` and `align` must be specified, otherwise
- * the label is drawn immediately at `x` and `y` field.
+ * A label has a position and a size. The size is only provided to the user as
+ * information and is not used during rendering. It should be computed using the
+ * \ref label_query command each time you change the theme or text.
  */
 struct label {
 	int x;                          /*!< (+) Position in x. */
@@ -52,7 +50,6 @@
 	unsigned int h;                 /*!< (+?) Height. */
 	const char *text;               /*!< (+&) Text to show. */
 	enum label_flags flags;         /*!< (+) Optional flags. */
-	enum align align;               /*!< (+) How to positionate label. */
 	struct theme *theme;            /*!< (+&?) Theme to use. */
 };
 
@@ -68,6 +65,16 @@
 label_draw_default(struct theme *t, const struct label *label);
 
 /**
+ * Update the `w` and `h` fields with the dimensions the text would needs with
+ * the current theme.
+ *
+ * \pre label != NULL
+ * \param label the label
+ */
+void
+label_query(struct label *label);
+
+/**
  * Draw the label.
  *
  * \pre label != NULL