changeset 606:35e58271d820

ui: do the same with checkbox
author David Demelier <markand@malikania.fr>
date Fri, 11 Aug 2023 12:58:02 +0200
parents a8094fad01a1
children 8444f83d48af
files examples/example-ui/example-ui.c libmlk-ui/mlk/ui/checkbox.c libmlk-ui/mlk/ui/checkbox.h
diffstat 3 files changed, 239 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-ui/example-ui.c	Fri Aug 11 19:22:00 2023 +0200
+++ b/examples/example-ui/example-ui.c	Fri Aug 11 12:58:02 2023 +0200
@@ -125,7 +125,9 @@
 	.autosave = {
 		.cb = {
 			.w = ELEMENT_HEIGHT,
-			.h = ELEMENT_HEIGHT
+			.h = ELEMENT_HEIGHT,
+			.delegate = &mlk_checkbox_delegate,
+			.style = &mlk_style
 		},
 		.label = {
 			.text = "Auto save game",
--- a/libmlk-ui/mlk/ui/checkbox.c	Fri Aug 11 19:22:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/checkbox.c	Fri Aug 11 12:58:02 2023 +0200
@@ -17,75 +17,28 @@
  */
 
 #include <assert.h>
-#include <string.h>
 
 #include <mlk/core/event.h>
 #include <mlk/core/maths.h>
 #include <mlk/core/painter.h>
 
 #include "checkbox.h"
-#include "ui.h"
-#include "ui_p.h"
+#include "style.h"
 
-static int
+static inline int
 is_boxed(const struct mlk_checkbox *cb, const struct mlk_event_click *click)
 {
-	assert(cb);
 	assert(click && click->type == MLK_EVENT_CLICKDOWN);
 
 	return mlk_maths_is_boxed(click->x, click->y, cb->x, cb->y, cb->w, cb->h);
 }
 
-static void
-draw(struct mlk_checkbox_delegate *delegate, const struct mlk_checkbox *cb)
+static int
+handle(struct mlk_checkbox_delegate *self,
+       struct mlk_checkbox *cb,
+       const union mlk_event *ev)
 {
-	(void)delegate;
-
-	const struct mlk_checkbox_style *style = MLK__STYLE(cb, mlk_checkbox_style);
-
-	if (!style->border_size) {
-		mlk_painter_set_color(style->bg_color);
-		mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h);
-	} else {
-		mlk_painter_set_color(style->border_color);
-		mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h);
-		mlk_painter_set_color(style->bg_color);
-		mlk_painter_draw_rectangle(
-			cb->x + style->border_size,
-			cb->y + style->border_size,
-			cb->w - (style->border_size * 2),
-			cb->h - (style->border_size * 2)
-		);
-	}
-
-	if (cb->checked) {
-		mlk_painter_set_color(style->check_color);
-		mlk_painter_draw_rectangle(cb->x + 5, cb->y + 5, cb->w - 10, cb->h - 10);
-	}
-}
-
-struct mlk_checkbox_style mlk_checkbox_style = {
-	.bg_color = MLK_UI_COLOR_BG,
-	.check_color = MLK_UI_COLOR_TEXT,
-	.border_color = MLK_UI_COLOR_BORDER,
-	.border_size = 1
-};
-
-struct mlk_checkbox_delegate mlk_checkbox_delegate = {
-	.draw = draw
-};
-
-int
-mlk_checkbox_ok(const struct mlk_checkbox *cb)
-{
-	return cb != NULL;
-}
-
-int
-mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev)
-{
-	assert(mlk_checkbox_ok(cb));
-	assert(ev);
+	(void)self;
 
 	switch (ev->type) {
 	case MLK_EVENT_CLICKDOWN:
@@ -99,18 +52,90 @@
 	return 0;
 }
 
+static void
+draw(struct mlk_checkbox_delegate *self, const struct mlk_checkbox *cb)
+{
+	(void)self;
+
+	const struct mlk_style_attr *attr = &cb->style->normal;
+
+	if (!attr->geo.border) {
+		mlk_painter_set_color(attr->color.bg);
+		mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h);
+	} else {
+		mlk_painter_set_color(attr->color.border);
+		mlk_painter_draw_rectangle(cb->x, cb->y, cb->w, cb->h);
+		mlk_painter_set_color(attr->color.bg);
+		mlk_painter_draw_rectangle(
+			cb->x + attr->geo.border,
+			cb->y + attr->geo.border,
+			cb->w - (attr->geo.border * 2),
+			cb->h - (attr->geo.border * 2)
+		);
+	}
+
+	if (cb->checked) {
+		mlk_painter_set_color(attr->color.fg);
+		mlk_painter_draw_rectangle(cb->x + 5, cb->y + 5, cb->w - 10, cb->h - 10);
+	}
+}
+
+struct mlk_checkbox_delegate mlk_checkbox_delegate = {
+	.handle = handle,
+	.draw = draw
+};
+
+void
+mlk_checkbox_init(struct mlk_checkbox *cb,
+                  struct mlk_checkbox_delegate *dt,
+                  struct mlk_style *st)
+{
+	assert(cb);
+
+	cb->x = 0;
+	cb->y = 0;
+	cb->w = 0;
+	cb->h = 0;
+	cb->checked = 0;
+	cb->delegate = dt ? dt : &mlk_checkbox_delegate;
+	cb->style = st ? st : &mlk_style;
+}
+
+int
+mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev)
+{
+	assert(cb);
+	assert(ev);
+
+	if (cb->delegate->handle)
+		return cb->delegate->handle(cb->delegate, cb, ev);
+
+	return 0;
+}
+
 void
 mlk_checkbox_update(struct mlk_checkbox *cb, unsigned int ticks)
 {
-	assert(mlk_checkbox_ok(cb));
+	assert(cb);
 
-	MLK__DELEGATE_INVOKE(cb->delegate, mlk_checkbox_delegate, update, cb, ticks);
+	if (cb->delegate->update)
+		cb->delegate->update(cb->delegate, cb, ticks);
 }
 
 void
 mlk_checkbox_draw(const struct mlk_checkbox *cb)
 {
-	assert(mlk_checkbox_ok(cb));
+	assert(cb);
+
+	if (cb->delegate->draw)
+		cb->delegate->draw(cb->delegate, cb);
+}
 
-	MLK__DELEGATE_INVOKE(cb->delegate, mlk_checkbox_delegate, draw, cb);
+void
+mlk_checkbox_finish(struct mlk_checkbox *cb)
+{
+	assert(cb);
+
+	if (cb->delegate->finish)
+		cb->delegate->finish(cb->delegate, cb);
 }
--- a/libmlk-ui/mlk/ui/checkbox.h	Fri Aug 11 19:22:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/checkbox.h	Fri Aug 11 12:58:02 2023 +0200
@@ -19,49 +19,181 @@
 #ifndef MLK_UI_CHECKBOX_H
 #define MLK_UI_CHECKBOX_H
 
-union mlk_event;
+/**
+ * \file mlk/ui/checkbox.h
+ * \brief GUI checkbox.
+ */
 
 struct mlk_checkbox;
+struct mlk_checkbox_delegate;
+struct mlk_style;
 
-struct mlk_checkbox_style {
-	unsigned long bg_color;
-	unsigned long check_color;
-	unsigned long border_color;
-	unsigned int border_size;
+union mlk_event;
+
+/**
+ * \struct mlk_checkbox
+ * \brief UI clickable checkbox.
+ */
+struct mlk_checkbox {
+	/**
+	 * (read-write)
+	 *
+	 * Position in x.
+	 */
+	int x;
+
+	/**
+	 * (read-write)
+	 *
+	 * Position in y.
+	 */
+	int y;
+
+	/**
+	 * (read-write)
+	 *
+	 * Checkbox width.
+	 */
+	unsigned int w;
+
+	/**
+	 * (read-write)
+	 *
+	 * Checkbox height.
+	 */
+	unsigned int h;
+
+	/**
+	 * (read-write)
+	 *
+	 * Checkbox status, non-zero if activated.
+	 */
+	int checked;
+
+	/**
+	 * (read-write, borrowed)
+	 *
+	 * Checkbox delegate.
+	 */
+	struct mlk_checkbox_delegate *delegate;
+
+	/**
+	 * (read-write, borrowed)
+	 *
+	 * Checkbox style.
+	 */
+	struct mlk_style *style;
 };
 
+/**
+ * \struct mlk_checkbox_delegate
+ * \brief Checkbox delegate.
+ */
 struct mlk_checkbox_delegate {
+	/*
+	 * (read-write, borrowed, optional)
+	 *
+	 * Arbitrary user data.
+	 */
 	void *data;
-	void (*update)(struct mlk_checkbox_delegate *, struct mlk_checkbox *, unsigned int);
-	void (*draw)(struct mlk_checkbox_delegate *, const struct mlk_checkbox *);
+
+	/**
+	 * (read-write, optional)
+	 *
+	 * Handle an event.
+	 *
+	 * \param self this delegate
+	 * \param cb the checkbox
+	 * \param ev the event
+	 * \return the current checkbox status (1 or 0)
+	 */
+	int (*handle)(struct mlk_checkbox_delegate *self,
+	              struct mlk_checkbox *cb,
+	              const union mlk_event *ev);
+
+	/**
+	 * (read-write, optional)
+	 *
+	 * Update the checkbox.
+	 *
+	 * \param self this delegate
+	 * \param cb the checkbox to update
+	 * \param ticks number of ticks since last frame
+	 */
+	void (*update)(struct mlk_checkbox_delegate *self,
+	               struct mlk_checkbox *cb,
+	               unsigned int ticks);
+
+	/**
+	 * (read-write, optional)
+	 *
+	 * Draw this checkbox.
+	 *
+	 * \param self this delegate
+	 * \param cb the checkbox to update
+	 */
+	void (*draw)(struct mlk_checkbox_delegate *self,
+	             const struct mlk_checkbox *cb);
+
+	/**
+	 * (read-write, optional)
+	 *
+	 * Cleanup this delegate associated with the checkbox.
+	 *
+	 * \param self this delegate
+	 * \param cb the underlying checkbox
+	 */
+	void (*finish)(struct mlk_checkbox_delegate *self,
+	               struct mlk_checkbox *cb);
 };
 
-struct mlk_checkbox {
-	int x, y;
-	unsigned int w, h;
-	int checked;
-	struct mlk_checkbox_delegate *delegate;
-	struct mlk_checkbox_style *style;
-};
-
-extern struct mlk_checkbox_style mlk_checkbox_style;
+/**
+ * \brief Default stateless delegate for checkbox.
+ */
 extern struct mlk_checkbox_delegate mlk_checkbox_delegate;
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
-int
-mlk_checkbox_ok(const struct mlk_checkbox *cb);
+/**
+ * Initialize the checkbox with default values.
+ *
+ * This is not required if you use designated initializers.
+ *
+ * \pre cb != NULL
+ * \param cb the checkbox 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)
+ */
+void
+mlk_checkbox_init(struct mlk_checkbox *cb,
+                  struct mlk_checkbox_delegate *dt,
+                  struct mlk_style *st);
 
+/**
+ * Invoke ::mlk_checkbox_delegate::update.
+ */
 int
-mlk_checkbox_handle(struct mlk_checkbox *, const union mlk_event *);
+mlk_checkbox_handle(struct mlk_checkbox *cb, const union mlk_event *ev);
 
+/**
+ * Invoke ::mlk_checkbox_delegate::update.
+ */
 void
 mlk_checkbox_update(struct mlk_checkbox *cb, unsigned int ticks);
 
+/**
+ * Invoke ::mlk_checkbox_delegate::draw.
+ */
 void
-mlk_checkbox_draw(const struct mlk_checkbox *);
+mlk_checkbox_draw(const struct mlk_checkbox *cb);
+
+/**
+ * Invoke ::mlk_checkbox_delegate::finish.
+ */
+void
+mlk_checkbox_finish(struct mlk_checkbox *cb);
 
 #if defined(__cplusplus)
 }