diff options
-rw-r--r-- | apps/window.c | 10 | ||||
-rw-r--r-- | libgui/gui.c | 111 | ||||
-rw-r--r-- | libgui/inc/gfx.h | 2 | ||||
-rw-r--r-- | libgui/inc/gui.h | 36 |
4 files changed, 139 insertions, 20 deletions
diff --git a/apps/window.c b/apps/window.c index a69b6db..9342009 100644 --- a/apps/window.c +++ b/apps/window.c @@ -19,11 +19,13 @@ int main() struct element *root = gui_init("test", 600, 400); struct element *container = - gui_add_container(root, 100, 0, root->ctx->width / 2, root->ctx->height, COLOR_RED); - struct element_button *button = - gui_add_button(container, 10, 10, FONT_24, "Baum!", COLOR_WHITE, COLOR_BLACK)->data; + gui_add_container(root, 0, 0, root->ctx->width / 2, root->ctx->height, COLOR_RED); + struct element *button = + gui_add_button(container, 10, 10, FONT_24, "Button", COLOR_WHITE, COLOR_BLACK); + struct element *text_input = + gui_add_text_input(container, 10, 50, 200, FONT_24, COLOR_WHITE, COLOR_BLACK); - button->on_click = on_click; + button->event.on_click = on_click; gui_event_loop(root); diff --git a/libgui/gui.c b/libgui/gui.c index dcf8b1f..72de970 100644 --- a/libgui/gui.c +++ b/libgui/gui.c @@ -1,5 +1,6 @@ // MIT License, Copyright (c) 2020 Marvin Borner // Mostly GFX function wrappers +// TODO: Reduce code duplication #include <def.h> #include <gfx.h> @@ -105,6 +106,20 @@ void gui_sync_button(struct element *elem) gfx_write(elem->ctx, 0, 0, button->font_type, button->color_fg, button->text); } +void gui_sync_label(struct element *elem) +{ + struct element_label *label = elem->data; + gfx_fill(elem->ctx, label->color_bg); + gfx_write(elem->ctx, 0, 0, label->font_type, label->color_fg, label->text); +} + +void gui_sync_text_input(struct element *elem) +{ + struct element_text_input *text_input = elem->data; + gfx_fill(elem->ctx, text_input->color_bg); + gfx_write(elem->ctx, 0, 0, text_input->font_type, text_input->color_fg, text_input->text); +} + void gui_sync_container(struct element *elem) { struct element_container *container = elem->data; @@ -115,11 +130,9 @@ void gui_sync_container(struct element *elem) struct element *gui_add_button(struct element *container, int x, int y, enum font_type font_type, char *text, u32 color_bg, u32 color_fg) { - if (!container || !container->childs) + if (!container || !container->childs || !gfx_resolve_font(font_type)) return NULL; - gfx_resolve_font(font_type); - struct element *button = malloc(sizeof(*button)); button->type = GUI_TYPE_BUTTON; button->window_id = container->window_id; @@ -144,6 +157,65 @@ struct element *gui_add_button(struct element *container, int x, int y, enum fon return button; } +struct element *gui_add_label(struct element *container, int x, int y, enum font_type font_type, + char *text, u32 color_bg, u32 color_fg) +{ + if (!container || !container->childs || !gfx_resolve_font(font_type)) + return NULL; + + struct element *label = malloc(sizeof(*label)); + label->type = GUI_TYPE_LABEL; + label->window_id = container->window_id; + label->ctx = malloc(sizeof(*label->ctx)); + label->ctx->x = x; + label->ctx->y = y; + label->ctx->width = strlen(text) * gfx_font_width(font_type); + label->ctx->height = gfx_font_height(font_type); + label->ctx->flags = WF_RELATIVE; + label->childs = list_new(); + label->data = malloc(sizeof(struct element_label)); + ((struct element_label *)label->data)->text = text; + ((struct element_label *)label->data)->color_fg = color_fg; + ((struct element_label *)label->data)->color_bg = color_bg; + ((struct element_label *)label->data)->font_type = font_type; + + gfx_new_ctx(label->ctx); + list_add(container->childs, label); + gui_sync_label(label); + merge_elements(get_root(container->window_id)); + + return label; +} + +struct element *gui_add_text_input(struct element *container, int x, int y, u32 width, + enum font_type font_type, u32 color_bg, u32 color_fg) +{ + if (!container || !container->childs || !gfx_resolve_font(font_type)) + return NULL; + + struct element *text_input = malloc(sizeof(*text_input)); + text_input->type = GUI_TYPE_TEXT_INPUT; + text_input->window_id = container->window_id; + text_input->ctx = malloc(sizeof(*text_input->ctx)); + text_input->ctx->x = x; + text_input->ctx->y = y; + text_input->ctx->width = width; + text_input->ctx->height = gfx_font_height(font_type); + text_input->ctx->flags = WF_RELATIVE; + text_input->childs = list_new(); + text_input->data = malloc(sizeof(struct element_text_input)); + ((struct element_text_input *)text_input->data)->color_fg = color_fg; + ((struct element_text_input *)text_input->data)->color_bg = color_bg; + ((struct element_text_input *)text_input->data)->font_type = font_type; + + gfx_new_ctx(text_input->ctx); + list_add(container->childs, text_input); + gui_sync_text_input(text_input); + merge_elements(get_root(container->window_id)); + + return text_input; +} + struct element *gui_add_container(struct element *container, int x, int y, u32 width, u32 height, u32 color_bg) { @@ -172,12 +244,14 @@ struct element *gui_add_container(struct element *container, int x, int y, u32 w return new_container; } +// TODO: Split into small functions void gui_event_loop(struct element *container) { if (!container) return; struct message *msg; + struct element *focused = NULL; while (1) { if (!(msg = msg_receive())) { yield(); @@ -187,15 +261,30 @@ void gui_event_loop(struct element *container) switch (msg->type) { case GUI_MOUSE: { struct gui_event_mouse *event = msg->data; - struct element *elem = element_at(container, event->x, event->y); - if (!elem) - continue; - - if (elem->type == GUI_TYPE_BUTTON) { - struct element_button *button = elem->data; - if (event->but1 && button->on_click) - button->on_click(); + focused = element_at(container, event->x, event->y); + if (focused && focused->event.on_click && event->but1) + focused->event.on_click(event); + break; + } + case GUI_KEYBOARD: { + struct gui_event_keyboard *event = msg->data; + + if (focused && focused->type == GUI_TYPE_TEXT_INPUT && event->press && + event->ch) { + char *s = ((struct element_text_input *)focused->data)->text; + u32 l = strlen(s); + s[l] = event->ch; + s[l + 1] = '\0'; + gui_sync_text_input(focused); + merge_elements(get_root(focused->window_id)); + gfx_redraw(); } + + if (focused && focused->event.on_key && event->ch) { + focused->event.on_key(event); + } + + break; } } } diff --git a/libgui/inc/gfx.h b/libgui/inc/gfx.h index 5010650..c8e5a29 100644 --- a/libgui/inc/gfx.h +++ b/libgui/inc/gfx.h @@ -13,6 +13,8 @@ #define GET_GREEN(color) ((color >> 8) & 0x000000FF) #define GET_BLUE(color) ((color >> 0) & 0X000000FF) +#define COLOR_TRANSPARENT 0x00000000 +#define COLOR_INVISIBLE 0x00000000 #define COLOR_BLACK 0xff0f0f0f #define COLOR_RED 0xfff07f7f #define COLOR_GREEN 0xff7ff088 diff --git a/libgui/inc/gui.h b/libgui/inc/gui.h index b79db3a..3f74178 100644 --- a/libgui/inc/gui.h +++ b/libgui/inc/gui.h @@ -8,14 +8,28 @@ #include <gfx.h> #include <list.h> +// TODO: Remove limits #define MAX_CHILDS 100 +#define MAX_INPUT_LENGTH 100 // TODO: Improve event types (maybe as struct header) enum window_event_type { GUI_KEYBOARD = GFX_MAX + 1, GUI_MOUSE, GUI_MAX }; -enum element_type { GUI_TYPE_ROOT, GUI_TYPE_CONTAINER, GUI_TYPE_BUTTON, GUI_TYPE_TEXTBOX }; +enum element_type { + GUI_TYPE_ROOT, + GUI_TYPE_CONTAINER, + GUI_TYPE_BUTTON, + GUI_TYPE_LABEL, + GUI_TYPE_TEXT_INPUT +}; enum container_flags { SPLIT }; +struct element_event { + void (*on_click)(); + void (*on_key)(); + void (*on_submit)(); +}; + struct element_container { u32 color_bg; enum container_flags flags; @@ -26,12 +40,19 @@ struct element_button { u32 color_fg; u32 color_bg; enum font_type font_type; - void (*on_click)(); }; -struct element_textbox { - const char *text; - u32 color; +struct element_label { + char *text; + u32 color_fg; + u32 color_bg; + enum font_type font_type; +}; + +struct element_text_input { + char text[MAX_INPUT_LENGTH]; + u32 color_fg; + u32 color_bg; enum font_type font_type; }; @@ -39,6 +60,7 @@ struct element { enum element_type type; u32 window_id; struct context *ctx; // Coordinates are relative to container + struct element_event event; struct list *childs; void *data; // Who needs static types anyways :) }; @@ -68,6 +90,10 @@ struct element *gui_init(const char *title, u32 width, u32 height); void gui_event_loop(struct element *container); struct element *gui_add_button(struct element *container, int x, int y, enum font_type font_type, char *text, u32 color_bg, u32 color_fg); +struct element *gui_add_label(struct element *container, int x, int y, enum font_type font_type, + char *text, u32 color_bg, u32 color_fg); +struct element *gui_add_text_input(struct element *container, int x, int y, u32 width, + enum font_type font_type, u32 color_bg, u32 color_fg); struct element *gui_add_container(struct element *container, int x, int y, u32 width, u32 height, u32 color_bg); |