From ff36b7225cd146b50cb8e4522ad58aa43c6bc153 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Fri, 06 Aug 2021 08:25:33 -0400 Subject: tk: Build focus tab index --- 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 #include +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) { -- cgit v0.9.1