summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tk/box.c10
-rw-r--r--src/tk/button.c2
-rw-r--r--src/tk/check.c2
-rw-r--r--src/tk/grid.c13
-rw-r--r--src/tk/radio.c2
-rw-r--r--src/tk/text.c2
-rw-r--r--src/tk/widget.c11
-rw-r--r--src/tk/widget.h64
-rw-r--r--src/tk/window.c23
9 files changed, 114 insertions, 15 deletions
diff --git a/src/tk/box.c b/src/tk/box.c
index 10a4ec3..d13982d 100644
--- a/src/tk/box.c
+++ b/src/tk/box.c
@@ -51,6 +51,14 @@ _mftk_box_layout(struct mftk_widget *w)
b->child_y = (b->container_h - w->h) / 2 + b->padding;
}
+static void
+_mftk_box_index(struct mftk_widget *w, struct mftk_window *win)
+{
+ struct mftk_box *b = (struct mftk_box *) w;
+
+ mftk_window_index(win, b->child);
+}
+
static int
_mftk_box_event(struct mftk_widget *w, SDL_Event *e, int x, int y)
{
@@ -122,7 +130,7 @@ mftk_box_new(int container_w, int container_h, int own_w, int own_h,
struct mftk_widget *w;
struct mftk_box *b;
- mftk_widget_init(w, b, box);
+ mftk_widget_init_container(w, b, box);
b->container_w = container_w;
b->container_h = container_h;
diff --git a/src/tk/button.c b/src/tk/button.c
index 57e505a..a236dd4 100644
--- a/src/tk/button.c
+++ b/src/tk/button.c
@@ -108,7 +108,7 @@ mftk_button_new(TTF_Font *font, const char *text, SDL_Color *text_color,
struct mftk_widget *w;
struct mftk_button *b;
- mftk_widget_init(w, b, button);
+ mftk_widget_init_focusable(w, b, button);
b->label = mftk_label_new(font, text, text_color, renderer);
if (b->label == NULL) {
diff --git a/src/tk/check.c b/src/tk/check.c
index 5c73554..a2eadd0 100644
--- a/src/tk/check.c
+++ b/src/tk/check.c
@@ -223,7 +223,7 @@ mftk_check_new(int butn_width, int butn_padding, SDL_Color *butn_color,
struct mftk_widget *w;
struct mftk_check *c;
- mftk_widget_init(w, c, check);
+ mftk_widget_init_focusable(w, c, check);
if (font != NULL && text != NULL && text_color != NULL) {
c->label = mftk_label_new(font, text, text_color, renderer);
diff --git a/src/tk/grid.c b/src/tk/grid.c
index 9d12b3c..e34223d 100644
--- a/src/tk/grid.c
+++ b/src/tk/grid.c
@@ -79,6 +79,17 @@ _mftk_grid_layout(struct mftk_widget *w)
}
}
+static void
+_mftk_grid_index(struct mftk_widget *w, struct mftk_window *win)
+{
+ struct mftk_grid *g = (struct mftk_grid *) w;
+ int i;
+
+ for (i = 0; i < g->rows * g->cols; ++i) {
+ mftk_window_index(win, g->children[i]);
+ }
+}
+
static int
_mftk_grid_event(struct mftk_widget *w, SDL_Event *e, int x, int y)
{
@@ -231,7 +242,7 @@ mftk_grid_new_a(int rows, int cols, int row_spacing, int col_spacing,
struct mftk_grid *g;
int i;
- mftk_widget_init(w, g, grid);
+ mftk_widget_init_container(w, g, grid);
g->rows_h = calloc(rows, sizeof(*g->rows_h));
if (g->rows_h == NULL) {
diff --git a/src/tk/radio.c b/src/tk/radio.c
index 27f7d37..11acbae 100644
--- a/src/tk/radio.c
+++ b/src/tk/radio.c
@@ -107,7 +107,7 @@ mftk_radio_new(int butn_width, int butn_padding, SDL_Color *butn_color,
va_list ap;
int i;
- mftk_widget_init(w, r, radio);
+ mftk_widget_init_focusable(w, r, radio);
r->children = calloc(options, sizeof(*r->children));
if (r->children == NULL) {
diff --git a/src/tk/text.c b/src/tk/text.c
index 205c8e3..6bac6e7 100644
--- a/src/tk/text.c
+++ b/src/tk/text.c
@@ -171,7 +171,7 @@ mftk_text_new(char min_char, char max_char, size_t len, const char *val,
int advance;
char ch;
- mftk_widget_init(w, t, text);
+ mftk_widget_init_focusable(w, t, text);
t->min_char = min_char;
t->max_char = max_char;
diff --git a/src/tk/widget.c b/src/tk/widget.c
index ea4835e..5c4ae17 100644
--- a/src/tk/widget.c
+++ b/src/tk/widget.c
@@ -60,6 +60,17 @@ mftk_widget_layout(struct mftk_widget *w)
w->layout(w);
}
+void
+mftk_widget_index(struct mftk_widget *w, struct mftk_window *win)
+{
+ if (w->role == MFTK_WIDGET_ROLE_CONTAINER) {
+ w->index(w, win);
+ } else if (w->role == MFTK_WIDGET_ROLE_FOCUSABLE) {
+ mftk_window_index(win, w);
+ w->window = win;
+ }
+}
+
int
mftk_widget_event(struct mftk_widget *w, SDL_Event *e, int x, int y)
{
diff --git a/src/tk/widget.h b/src/tk/widget.h
index 64b8b58..83abe0b 100644
--- a/src/tk/widget.h
+++ b/src/tk/widget.h
@@ -23,18 +23,33 @@
#include <SDL.h>
#include <stdarg.h>
+void
+mftk_window_index(struct mftk_window *win, struct mftk_widget *wid);
+
+enum mftk_widget_role {
+ MFTK_WIDGET_ROLE_NONE,
+ MFTK_WIDGET_ROLE_FOCUSABLE,
+ MFTK_WIDGET_ROLE_CONTAINER
+};
+
struct mftk_widget {
- int w;
- int h;
- struct mftk_widget *container;
- int vis;
- int can_focus;
- void (*layout)(struct mftk_widget *);
- int (*event)(struct mftk_widget *, SDL_Event *,
+ int w;
+ int h;
+ struct mftk_widget *container;
+ int vis;
+ void (*layout)(struct mftk_widget *);
+ void (*index)(struct mftk_widget *,
+ struct mftk_window *);
+ int (*event)(struct mftk_widget *, SDL_Event *,
int, int);
- int (*render)(struct mftk_widget *, SDL_Renderer *,
+ int (*render)(struct mftk_widget *, SDL_Renderer *,
int, int);
- void (*destroy)(struct mftk_widget *);
+ void (*destroy)(struct mftk_widget *);
+ enum mftk_widget_role role;
+ struct mftk_widget *prev;
+ struct mftk_widget *next;
+ struct mftk_window *window;
+ int focused;
};
struct mftk_widget *
@@ -50,6 +65,34 @@ mftk_widget_new(size_t size);
w->event = &_mftk_##name##_event; \
w->render = &_mftk_##name##_render; \
w->destroy = &_mftk_##name##_destroy; \
+ w->role = MFTK_WIDGET_ROLE_NONE; \
+ t_w = (struct mftk_##name *) w; \
+ } while (0)
+#define mftk_widget_init_focusable(w, t_w, name) \
+ do { \
+ w = mftk_widget_new(sizeof(struct mftk_##name)); \
+ if (w == NULL) { \
+ return NULL; \
+ }; \
+ w->layout = &_mftk_##name##_layout; \
+ w->event = &_mftk_##name##_event; \
+ w->render = &_mftk_##name##_render; \
+ w->destroy = &_mftk_##name##_destroy; \
+ w->role = MFTK_WIDGET_ROLE_FOCUSABLE; \
+ t_w = (struct mftk_##name *) w; \
+ } while (0)
+#define mftk_widget_init_container(w, t_w, name) \
+ do { \
+ w = mftk_widget_new(sizeof(struct mftk_##name)); \
+ if (w == NULL) { \
+ return NULL; \
+ }; \
+ w->layout = &_mftk_##name##_layout; \
+ w->index = &_mftk_##name##_index; \
+ w->event = &_mftk_##name##_event; \
+ w->render = &_mftk_##name##_render; \
+ w->destroy = &_mftk_##name##_destroy; \
+ w->role = MFTK_WIDGET_ROLE_CONTAINER; \
t_w = (struct mftk_##name *) w; \
} while (0)
@@ -63,6 +106,9 @@ mftk_widget_get_visible(struct mftk_widget *w)
void
mftk_widget_layout(struct mftk_widget *w);
+void
+mftk_widget_index(struct mftk_widget *w, struct mftk_window *win);
+
int
mftk_widget_event(struct mftk_widget *w, SDL_Event *e, int x, int y);
diff --git a/src/tk/window.c b/src/tk/window.c
index 532a2e4..b87e7c0 100644
--- a/src/tk/window.c
+++ b/src/tk/window.c
@@ -26,6 +26,8 @@
struct mftk_window {
struct mftk_widget *root;
+ struct mftk_widget *first;
+ struct mftk_widget *focus;
};
struct mftk_window *
@@ -44,10 +46,31 @@ mftk_window_new(struct mftk_widget *root)
w->root = root;
mftk_widget_layout(w->root);
+ mftk_widget_index(w->root, w);
+ w->focus = w->first;
return w;
}
+void
+mftk_window_index(struct mftk_window *win, struct mftk_widget *wid)
+{
+ if (win->first == NULL) {
+ win->first = wid;
+ wid->prev = wid;
+ wid->next = wid;
+ return;
+ }
+ /*
+ * Head: win->first
+ * Tail: win->first->prev
+ */
+ wid->prev = win->first->prev;
+ wid->next = win->first;
+ win->first->prev->next = wid;
+ win->first->prev = wid;
+}
+
int
mftk_window_event(struct mftk_window *w, SDL_Event *e)
{