changeset 115:3bd0d3a39e30

core: implement checkbox, closes #2486
author David Demelier <markand@malikania.fr>
date Sun, 12 Jul 2020 09:44:27 +0200
parents bf7500aea454
children 0a6683615c73
files Makefile examples/example-sound.c src/adventure/main.c src/core/button.c src/core/checkbox.c src/core/checkbox.h src/core/theme.c src/core/theme.h
diffstat 8 files changed, 214 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Thu Jul 09 22:38:48 2020 +0200
+++ b/Makefile	Sun Jul 12 09:44:27 2020 +0200
@@ -52,6 +52,7 @@
 
 CORE_SRCS=      src/core/animation.c                    \
                 src/core/button.c                       \
+                src/core/checkbox.c                     \
                 src/core/clock.c                        \
                 src/core/debug.c                        \
                 src/core/error.c                        \
--- a/examples/example-sound.c	Thu Jul 09 22:38:48 2020 +0200
+++ b/examples/example-sound.c	Sun Jul 12 09:44:27 2020 +0200
@@ -38,7 +38,7 @@
 	.text = "Keys: <s> start, <p> pause, <r> resume, <q> stop, <l> loop",
 	.x = 10,
 	.y = 10,
-	.w = 1920,
+	.w = W,
 	.h = 32,
 	.flags = LABEL_NO_HCENTER
 };
--- a/src/adventure/main.c	Thu Jul 09 22:38:48 2020 +0200
+++ b/src/adventure/main.c	Sun Jul 12 09:44:27 2020 +0200
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include "button.h"
+#include "checkbox.h"
 #include "clock.h"
 #include "debug.h"
 #include "error.h"
@@ -83,12 +84,18 @@
 run(void)
 {
 	struct clock clock = { 0 };
-	struct button button = {
-		.text = "click me",
+	struct frame mainmenu = {
 		.x = 10,
-		.y = 40,
-		.w = 100,
-		.h = 30
+		.y = 10,
+		.w = 200,
+		.h = 64
+	};
+	struct checkbox cb = {
+		.label = "Play hard mode",
+		.x = 20,
+		.y = 20,
+		.w = 200,
+		.h = 16
 	};
 
 	for (;;) {
@@ -101,25 +108,16 @@
 			case EVENT_QUIT:
 				return;
 			default:
-				button_handle(&button, &ev);
-
-				if (button.state == BUTTON_STATE_ACTIVATED) {
-					puts("CLICKED!!!");
-					button_reset(&button);
-				}
-
+				checkbox_handle(&cb, &ev);
 				break;
 			}
 		}
 
-		printf("%d\n", button.state);
-
 		painter_set_color(0xffffffff);
 		painter_clear();
 
 		theme_draw_frame(NULL, &(const struct frame){ .x=10, .y=10, .w=500, .h=500 });
-		label_draw(&(const struct label){ .text = "Hello for this quest.", .x=20, .y=20, .w=100, .h=100 });
-		button_draw(&button);
+		checkbox_draw(&cb);
 
 		painter_present();
 
--- a/src/core/button.c	Thu Jul 09 22:38:48 2020 +0200
+++ b/src/core/button.c	Sun Jul 12 09:44:27 2020 +0200
@@ -40,7 +40,6 @@
 	assert(button);
 	assert(ev);
 
-
 	switch (ev->type) {
 	case EVENT_CLICKDOWN:
 		if (is_boxed(button, &ev->click))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/checkbox.c	Sun Jul 12 09:44:27 2020 +0200
@@ -0,0 +1,55 @@
+/*
+ * checkbox.c -- GUI checkbox
+ *
+ * Copyright (c) 2020 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 "checkbox.h"
+#include "theme.h"
+#include "event.h"
+#include "maths.h"
+
+static bool
+is_boxed(const struct checkbox *cb, const struct event_click *click)
+{
+	assert(cb);
+	assert(click && click->type == EVENT_CLICKDOWN);
+
+	return maths_is_boxed(cb->x, cb->y, cb->w, cb->h, click->x, click->y);
+}
+
+void
+checkbox_handle(struct checkbox *cb, const union event *ev)
+{
+	assert(cb);
+	assert(ev);
+
+	switch (ev->type) {
+	case EVENT_CLICKDOWN:
+		if (is_boxed(cb, &ev->click))
+			cb->checked = !cb->checked;
+		break;
+	default:
+		break;
+	}
+}
+
+void
+checkbox_draw(const struct checkbox *cb)
+{
+	theme_draw_checkbox(cb->theme, cb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/checkbox.h	Sun Jul 12 09:44:27 2020 +0200
@@ -0,0 +1,64 @@
+/*
+ * checkbox.h -- GUI checkbox
+ *
+ * Copyright (c) 2020 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 MOLKO_CHECKBOX_H
+#define MOLKO_CHECKBOX_H
+
+/**
+ * \file checkbox.h
+ * \brief GUI checkbox.
+ */
+
+#include <stdbool.h>
+
+union event;
+
+/**
+ * \brief GUI checkbox.
+ */
+struct checkbox {
+	int x;                  /*!< (RW) Position in x. */
+	int y;                  /*!< (RW) Position in y. */
+	unsigned int w;         /*!< (RW) Width. */
+	unsigned int h;         /*!< (RW) Height. */
+	const char *label;      /*!< (RW, ref) Text to show. */
+	bool checked;           /*!< (RW) Is activated? */
+	struct theme *theme;    /*!< (RW, ref, optional) Theme to use. */
+};
+
+/**
+ * Draw the checkbox.
+ *
+ * \pre cb != NULL
+ * \pre ev != NULL
+ * \param cb the checkbox
+ * \param ev the event
+ */
+void
+checkbox_handle(struct checkbox *cb, const union event *ev);
+
+/**
+ * Draw the checkbox.
+ *
+ * \pre cb != NULL
+ * \param cb the checkbox
+ */
+void
+checkbox_draw(const struct checkbox *cb);
+
+#endif /* !MOLKO_CHECKBOX_H */
--- a/src/core/theme.c	Thu Jul 09 22:38:48 2020 +0200
+++ b/src/core/theme.c	Sun Jul 12 09:44:27 2020 +0200
@@ -20,6 +20,7 @@
 #include <stddef.h>
 
 #include "button.h"
+#include "checkbox.h"
 #include "font.h"
 #include "frame.h"
 #include "label.h"
@@ -34,6 +35,10 @@
 
 #define THEME(t) (t ? t : &default_theme)
 
+#define CHECKBOX_W 16
+#define CHECKBOX_H 16
+#define CHECKBOX_RAD 6
+
 static struct font default_font;
 
 static void
@@ -48,6 +53,7 @@
 	painter_draw_line(x + w, y, x + w, y + h);
 }
 
+
 static void
 draw_frame(struct theme *t, const struct frame *frame)
 {
@@ -120,6 +126,31 @@
 	box(button->x, button->y, button->w, button->h);
 }
 
+static void
+draw_checkbox(struct theme *t, const struct checkbox *cb)
+{
+	box(cb->x, cb->y, CHECKBOX_W, CHECKBOX_H);
+
+	if (cb->checked)
+		painter_draw_rectangle(cb->x + 5, cb->y + 5, CHECKBOX_W - 9, CHECKBOX_H - 9);
+
+	if (cb->label) {
+		const unsigned int w = cb->w - (t->padding * 2) - CHECKBOX_W;
+		const int x = cb->x + (t->padding * 2) + CHECKBOX_W;
+
+		struct label label = {
+			.text = cb->label,
+			.flags = LABEL_NO_HCENTER,
+			.x = x,
+			.y = cb->y,
+			.w = w,
+			.h = cb->h
+		};
+
+		draw_label(t, &label);
+	}
+}
+
 /* Default theme. */
 static struct theme default_theme = {
 	.colors = {
@@ -127,9 +158,11 @@
 		[THEME_COLOR_SELECTED]  = 0x006554ff,
 		[THEME_COLOR_SHADOW]    = 0x000000ff
 	},
+	.padding = 10,
 	.draw_frame = draw_frame,
 	.draw_label = draw_label,
-	.draw_button = draw_button
+	.draw_button = draw_button,
+	.draw_checkbox = draw_checkbox
 };
 
 /* Default font catalog. */
@@ -174,6 +207,12 @@
 	return &default_theme;
 }
 
+unsigned int
+theme_padding(const struct theme *t)
+{
+	return THEME(t)->padding;
+}
+
 void
 theme_draw_frame(struct theme *t, const struct frame *frame)
 {
@@ -199,6 +238,14 @@
 }
 
 void
+theme_draw_checkbox(struct theme *t, const struct checkbox *cb)
+{
+	assert(cb);
+
+	THEME(t)->draw_checkbox(THEME(t), cb);
+}
+
+void
 theme_finish(void)
 {
 	for (size_t i = 0; i < NELEM(default_fonts); ++i) {
--- a/src/core/theme.h	Thu Jul 09 22:38:48 2020 +0200
+++ b/src/core/theme.h	Sun Jul 12 09:44:27 2020 +0200
@@ -26,6 +26,7 @@
 
 #include <stdbool.h>
 
+struct checkbox;
 struct button;
 struct font;
 struct frame;
@@ -64,6 +65,11 @@
 	unsigned long colors[THEME_COLOR_LAST];
 
 	/**
+	 * (RW) Padding between GUI elements.
+	 */
+	unsigned int padding;
+
+	/**
 	 * Draw a frame.
 	 *
 	 * This function is used to draw a box usually as a container where UI
@@ -86,6 +92,13 @@
 	 * \see \ref theme_draw_button
 	 */
 	void (*draw_button)(struct theme *, const struct button *);
+
+	/**
+	 * Draw a checkbox.
+	 *
+	 * \see \ref theme_draw_button
+	 */
+	void (*draw_checkbox)(struct theme *t, const struct checkbox *);
 };
 
 /**
@@ -106,6 +119,15 @@
 theme_default(void);
 
 /**
+ * Get the desired padding between GUI elements.
+ *
+ * \param t the theme to use (may be NULL)
+ * \return the padding in pixels
+ */
+unsigned int
+theme_padding(const struct theme *t);
+
+/**
  * Draw a frame.
  *
  * \pre frame != NULL
@@ -136,6 +158,15 @@
 theme_draw_button(struct theme *t, const struct button *button);
 
 /**
+ * Draw a checkbox.
+ *
+ * \param t the theme to use (may be NULL)
+ * \param cb the checkbox
+ */
+void
+theme_draw_checkbox(struct theme *t, const struct checkbox *cb);
+
+/**
  * Close associated resources.
  */
 void