aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-07-06 23:46:59 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-07-07 02:37:25 +0200
commitdc4a3a2db894e8e7bb0be620b90780d55c74accd (patch)
treee0d2de44fbdbb0883e0db21db7da0c99ae943a6c
parent3f793166bdbd73a61c3a858d95e700b42ead602d (diff)
downloadjancity-dc4a3a2db894e8e7bb0be620b90780d55c74accd.tar.gz
Allow multiple button types
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/inc/gui/button.h25
-rw-r--r--src/gui/privinc/gui_button_private.h22
-rw-r--r--src/gui/src/button.c136
-rw-r--r--src/gui/src/button_type1.c114
-rw-r--r--src/menu/src/menu.c37
6 files changed, 218 insertions, 117 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 1d7e686..b7fe2c1 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,6 +1,7 @@
add_library(gui
"src/bar.c"
"src/button.c"
+ "src/button_type1.c"
"src/container.c"
"src/gui.c"
"src/label.c"
diff --git a/src/gui/inc/gui/button.h b/src/gui/inc/gui/button.h
index acfc6c1..b712e29 100644
--- a/src/gui/inc/gui/button.h
+++ b/src/gui/inc/gui/button.h
@@ -15,8 +15,27 @@ extern "C"
struct gui_button
{
struct gui_common common;
- struct gui_label label;
- short w;
+
+ enum gui_button_type
+ {
+ GUI_BUTTON_TYPE_1,
+ GUI_BUTTON_TYPE_SPRITE
+ } type;
+
+ union
+ {
+ struct
+ {
+ short w;
+ struct gui_label label;
+ } type1;
+
+ struct
+ {
+ const struct sprite *s;
+ } sprite;
+ } u;
+
void *arg;
void (*on_pressed)(void *);
};
@@ -24,7 +43,7 @@ struct gui_button
UTIL_STATIC_ASSERT(!offsetof(struct gui_button, common),
"unexpected offset for struct gui_button");
-void gui_button_init(struct gui_button *b);
+void gui_button_init(struct gui_button *b, enum gui_button_type t);
enum
{
diff --git a/src/gui/privinc/gui_button_private.h b/src/gui/privinc/gui_button_private.h
new file mode 100644
index 0000000..7c2f897
--- /dev/null
+++ b/src/gui/privinc/gui_button_private.h
@@ -0,0 +1,22 @@
+#ifndef GUI_BUTTON_PRIVATE_H
+#define GUI_BUTTON_PRIVATE_H
+
+#include <gui/button.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void gui_button_init_type1(struct gui_button *b);
+void gui_button_init_sprite(struct gui_button *b);
+int gui_button_render_type1(const struct gui_button *b);
+int gui_button_render_sprite(const struct gui_button *b);
+void gui_button_get_dim_type1(const struct gui_button *b, short *w, short *h);
+void gui_button_get_dim_sprite(const struct gui_button *b, short *w, short *h);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GUI_BUTTON_PRIVATE_H */
diff --git a/src/gui/src/button.c b/src/gui/src/button.c
index e16db31..f4f94e0 100644
--- a/src/gui/src/button.c
+++ b/src/gui/src/button.c
@@ -1,5 +1,6 @@
#include <gui.h>
#include <gui/button.h>
+#include <gui_button_private.h>
#include <gui_private.h>
#include <camera.h>
#include <gfx.h>
@@ -7,98 +8,31 @@
#include <pad.h>
#include <peripheral.h>
-struct sprite gui_button_sprites[MAX_GUI_BUTTON_SPRITES];
-
-/* Alias for readability. */
-static const struct sprite *const refs = gui_button_sprites;
-
-static int render_left(const struct gui_button *const b,
- short *const x, const short y)
-{
- sprite_get_or_ret(s, -1);
-
- if (sprite_clone(&refs[GUI_BUTTON_LEFT], s))
- return -1;
-
- s->x = *x;
- s->y = y;
- sprite_sort(s);
- *x = s->x + s->w;
- return 0;
-}
-
-static int render_mid(const struct gui_button *const b,
- short *const x, const short y)
+static int render(const struct gui_common *const g)
{
- const short mid_w = refs[GUI_BUTTON_MID].w;
- const short lw = refs[GUI_BUTTON_LEFT].w;
- const short rw = refs[GUI_BUTTON_RIGHT].w;
- const short w = b->w - lw - rw;
-
- if (w > 0)
+ static int (*const f[])(const struct gui_button *) =
{
- const short rem_mid = w > 0 ? w % mid_w : 0;
- const short whole_mid = w / mid_w;
- const short n_mid = rem_mid ? whole_mid + 1 : whole_mid;
-
- for (struct
- {
- size_t i;
- short x;
- } a = {.x = lw};
- a.i < n_mid;
- a.i++, a.x += mid_w)
- {
- sprite_get_or_ret(m, -1);
-
- if (sprite_clone(&refs[GUI_BUTTON_MID], m))
- return -1;
-
- m->x = *x;
- m->y = y;
-
- if (rem_mid && a.i + 1 == n_mid)
- m->w = rem_mid;
- else
- m->w = mid_w;
+ [GUI_BUTTON_TYPE_1] = gui_button_render_type1,
+ /* [GUI_BUTTON_TYPE_SPRITE] = gui_button_render_sprite */
+ };
- sprite_sort(m);
- *x += m->w;
- }
- }
- else
- return -1;
+ const struct gui_button *const b = (const struct gui_button *)g;
- return 0;
+ return f[b->type](b);
}
-static int render_right(const struct gui_button *const b,
- const short x, const short y)
+static void get_dim(const struct gui_common *const g,
+ short *const w, short *const h)
{
- sprite_get_or_ret(s, -1);
-
- if (sprite_clone(&refs[GUI_BUTTON_RIGHT], s))
- return -1;
-
- s->x = x;
- s->y = y;
- sprite_sort(s);
- return 0;
-}
+ static void (*const f[])(const struct gui_button *, short *, short *) =
+ {
+ [GUI_BUTTON_TYPE_1] = gui_button_get_dim_type1,
+ /* [GUI_BUTTON_TYPE_SPRITE] = gui_button_get_dim_sprite */
+ };
-static int render(const struct gui_common *const g)
-{
const struct gui_button *const b = (const struct gui_button *)g;
- short x, y;
- gui_coords(&b->common, &x, &y);
-
- if (render_left(b, &x, y)
- || render_mid(b, &x, y)
- || render_right(b, x, y))
- return -1;
-
- return 0;
+ f[b->type](b, w, h);
}
static bool pressed(const struct gui_button *const b,
@@ -125,16 +59,12 @@ static bool pressed(const struct gui_button *const b,
if (check)
{
short x, y;
+ struct util_rect d;
gui_coords(&b->common, &x, &y);
-
- const struct util_rect d =
- {
- .x = x,
- .y = y,
- .w = b->w,
- .h = refs[GUI_BUTTON_LEFT].h
- };
+ get_dim(&b->common, &d.w, &d.h);
+ d.x = x;
+ d.y = y;
return cursor_collision(cam, &d);
}
@@ -153,16 +83,7 @@ static int update(struct gui_common *const g,
return 0;
}
-static void get_dim(const struct gui_common *const g,
- short *const w, short *const h)
-{
- const struct gui_button *const b = (const struct gui_button *)g;
-
- *w = b->w;
- *h = refs[GUI_BUTTON_MID].h;
-}
-
-void gui_button_init(struct gui_button *const b)
+void gui_button_init(struct gui_button *const b, const enum gui_button_type t)
{
static const struct gui_common_cb cb =
{
@@ -176,11 +97,16 @@ void gui_button_init(struct gui_button *const b)
.common =
{
.cb = &cb
- }
+ },
+
+ .type = t
+ };
+
+ static void (*const f[])(struct gui_button *) =
+ {
+ [GUI_BUTTON_TYPE_1] = gui_button_init_type1,
+ /* [GUI_BUTTON_TYPE_SPRITE] = gui_button_get_dim_sprite */
};
- gui_label_init(&b->label);
- b->label.common.hcentered = true;
- b->label.common.vcentered = true;
- gui_add_child(&b->common, &b->label.common);
+ f[b->type](b);
}
diff --git a/src/gui/src/button_type1.c b/src/gui/src/button_type1.c
new file mode 100644
index 0000000..16038b5
--- /dev/null
+++ b/src/gui/src/button_type1.c
@@ -0,0 +1,114 @@
+#include <gui.h>
+#include <gui/button.h>
+#include <gui_private.h>
+#include <gui_button_private.h>
+
+struct sprite gui_button_sprites[MAX_GUI_BUTTON_SPRITES];
+
+/* Alias for readability. */
+static const struct sprite *const refs = gui_button_sprites;
+
+static int render_left(const struct gui_button *const b,
+ short *const x, const short y)
+{
+ sprite_get_or_ret(s, -1);
+
+ if (sprite_clone(&refs[GUI_BUTTON_LEFT], s))
+ return -1;
+
+ s->x = *x;
+ s->y = y;
+ sprite_sort(s);
+ *x = s->x + s->w;
+ return 0;
+}
+
+static int render_mid(const struct gui_button *const b,
+ short *const x, const short y)
+{
+ const short mid_w = refs[GUI_BUTTON_MID].w,
+ lw = refs[GUI_BUTTON_LEFT].w,
+ rw = refs[GUI_BUTTON_RIGHT].w,
+ w = b->u.type1.w - lw - rw;
+
+ if (w > 0)
+ {
+ const short rem_mid = w > 0 ? w % mid_w : 0,
+ whole_mid = w / mid_w,
+ n_mid = rem_mid ? whole_mid + 1 : whole_mid;
+
+ for (struct
+ {
+ size_t i;
+ short x;
+ } a = {.x = lw};
+ a.i < n_mid;
+ a.i++, a.x += mid_w)
+ {
+ sprite_get_or_ret(m, -1);
+
+ if (sprite_clone(&refs[GUI_BUTTON_MID], m))
+ return -1;
+
+ m->x = *x;
+ m->y = y;
+
+ if (rem_mid && a.i + 1 == n_mid)
+ m->w = rem_mid;
+ else
+ m->w = mid_w;
+
+ sprite_sort(m);
+ *x += m->w;
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+static int render_right(const struct gui_button *const b,
+ const short x, const short y)
+{
+ sprite_get_or_ret(s, -1);
+
+ if (sprite_clone(&refs[GUI_BUTTON_RIGHT], s))
+ return -1;
+
+ s->x = x;
+ s->y = y;
+ sprite_sort(s);
+ return 0;
+}
+
+int gui_button_render_type1(const struct gui_button *const b)
+{
+ short x, y;
+
+ gui_coords(&b->common, &x, &y);
+
+ if (render_left(b, &x, y)
+ || render_mid(b, &x, y)
+ || render_right(b, x, y))
+ return -1;
+
+ return 0;
+}
+
+void gui_button_get_dim_type1(const struct gui_button *const b,
+ short *const w, short *const h)
+{
+ *w = b->u.type1.w;
+ *h = refs[GUI_BUTTON_MID].h;
+}
+
+void gui_button_init_type1(struct gui_button *const b)
+{
+ struct gui_label *const l = &b->u.type1.label;
+
+ gui_label_init(l);
+ l->common.hcentered = true;
+ l->common.vcentered = true;
+ gui_add_child(&b->common, &l->common);
+}
diff --git a/src/menu/src/menu.c b/src/menu/src/menu.c
index 38f8632..c2f1e96 100644
--- a/src/menu/src/menu.c
+++ b/src/menu/src/menu.c
@@ -29,18 +29,19 @@ int menu(void)
cnt.mode = GUI_CONTAINER_MODE_V;
cnt.common.hcentered = true;
cnt.common.vcentered = true;
- gui_button_init(&play);
- gui_button_init(&exit_btn);
+ cnt.spacing = 4;
+ gui_button_init(&play, GUI_BUTTON_TYPE_1);
+ gui_button_init(&exit_btn, GUI_BUTTON_TYPE_1);
play.on_pressed = on_pressed;
play.arg = &start;
- play.w = 140;
+ play.u.type1.w = 140;
play.common.hcentered = true;
- play.label.text = "Play";
+ play.u.type1.label.text = "Play";
exit_btn.arg = &exit;
- exit_btn.w = 140;
+ exit_btn.u.type1.w = 140;
exit_btn.common.hcentered = true;
- exit_btn.label.text = "Exit";
+ exit_btn.u.type1.label.text = "Exit";
exit_btn.on_pressed = on_pressed;
gui_add_child(&cnt.common, &play.common);
gui_add_child(&cnt.common, &exit_btn.common);
@@ -72,9 +73,27 @@ int menu(void)
if (p.common.exit || exit)
return 0;
- if (gui_render(&cnt.common)
- || cursor_render(&cam.cursor)
- || gfx_draw())
+ if (gui_render(&cnt.common))
+ return -1;
+
+ switch (p.common.type)
+ {
+ case PERIPHERAL_TYPE_PAD:
+ /* Fall through. */
+ case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
+ if (cursor_render(&cam.cursor))
+ return -1;
+
+ break;
+
+ case PERIPHERAL_TYPE_TOUCH:
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (gfx_draw())
return -1;
}