diff options
-rw-r--r-- | apps/chess/main.c | 4 | ||||
-rw-r--r-- | apps/paint/main.c | 15 | ||||
-rw-r--r-- | apps/view/main.c | 6 | ||||
-rw-r--r-- | libs/libgui/gui.c | 142 | ||||
-rw-r--r-- | libs/libgui/gui.h | 6 |
5 files changed, 55 insertions, 118 deletions
diff --git a/apps/chess/main.c b/apps/chess/main.c index fbb00e8..abfad59 100644 --- a/apps/chess/main.c +++ b/apps/chess/main.c @@ -214,8 +214,8 @@ static void draw_board(void) { for (u8 x = 0; x < 8; x++) { for (u8 y = 0; y < 8; y++) { - u32 widget = gui_widget(win, GUI_MAIN, vec2(TILE * x, TILE * y), - vec2(TILE, TILE)); + u32 widget = gui_widget(win, gui_main_widget(win), vec2(TILE * x, TILE * y), + vec2(TILE, TILE)); assert((signed)widget > 0); u8 colored = (x + y + 1) % 2 == 0; diff --git a/apps/paint/main.c b/apps/paint/main.c index 0e90ee8..626d41d 100644 --- a/apps/paint/main.c +++ b/apps/paint/main.c @@ -37,24 +37,23 @@ int main(void) u32 win = gui_window(APPNAME); vec2 win_size = gui_window_size(win); - u32 toolbar = gui_widget(win, GUI_MAIN, vec2(0, 0), - vec2(win_size.x, COLOR_SIZE + 2 * TOOLBAR_MARGIN)); + u32 toolbar = gui_widget(win, gui_main_widget(win), vec2(0, 0), + vec2(win_size.x, COLOR_SIZE + 2 * TOOLBAR_MARGIN)); gui_fill(win, toolbar, GUI_LAYER_BG, COLOR_WHITE); u32 color_count = COUNT(colors); for (u32 i = 0; i < color_count; i++) { u32 color = gui_widget(win, toolbar, - vec2(TOOLBAR_MARGIN + i * (COLOR_SIZE + TOOLBAR_MARGIN), - TOOLBAR_MARGIN), - vec2(COLOR_SIZE, COLOR_SIZE)); + vec2(TOOLBAR_MARGIN + i * (COLOR_SIZE + TOOLBAR_MARGIN), + TOOLBAR_MARGIN), + vec2(COLOR_SIZE, COLOR_SIZE)); gui_fill(win, color, GUI_LAYER_FG, colors[i]); gui_draw_border(win, color, GUI_LAYER_FG, 2, COLOR_BLACK); gui_widget_listen(win, color, GUI_LISTEN_MOUSECLICK, (u32)color_click); } - u32 canvas = - gui_widget(win, GUI_MAIN, vec2(0, COLOR_SIZE + 2 * TOOLBAR_MARGIN), - vec2(win_size.x, win_size.y - (COLOR_SIZE + 2 * TOOLBAR_MARGIN))); + u32 canvas = gui_widget(win, gui_main_widget(win), vec2(0, COLOR_SIZE + 2 * TOOLBAR_MARGIN), + vec2(win_size.x, win_size.y - (COLOR_SIZE + 2 * TOOLBAR_MARGIN))); gui_fill(win, canvas, GUI_LAYER_BG, COLOR_WHITE); gui_widget_listen(win, canvas, GUI_LISTEN_MOUSEMOVE, (u32)mousemove); diff --git a/apps/view/main.c b/apps/view/main.c index 20661a7..fc7e3bc 100644 --- a/apps/view/main.c +++ b/apps/view/main.c @@ -25,10 +25,10 @@ int main(int argc, char *argv[]) path = "/res/test.png"; - u32 win = gui_new_custom_window(APPNAME, vec2(0, 0), size); - u32 canvas = gui_new_widget(win, GUI_MAIN, vec2(0, 0), size); + u32 win = gui_custom_window(APPNAME, vec2(0, 0), size); + u32 canvas = gui_widget(win, gui_main_widget(win), vec2(0, 0), size); gui_fill(win, canvas, GUI_LAYER_BG, COLOR_WHITE); - gui_listen_widget(win, canvas, GUI_LISTEN_MOUSEMOVE, (u32)mousemove); + gui_widget_listen(win, canvas, GUI_LISTEN_MOUSEMOVE, (u32)mousemove); gui_redraw_window(win); gui_loop(); diff --git a/libs/libgui/gui.c b/libs/libgui/gui.c index d5538aa..d011126 100644 --- a/libs/libgui/gui.c +++ b/libs/libgui/gui.c @@ -16,6 +16,7 @@ struct gui_widget { struct list *children; u32 margin; // Between sub-widgets + u32 offset; enum gui_layout layout; struct { @@ -29,7 +30,7 @@ struct gui_window { vec2 off; // fb offset vec2 pos; struct gfx_context ctx; - struct list *widgets; + struct gui_widget *main_widget; }; struct list *windows = NULL; @@ -82,31 +83,10 @@ static struct gui_widget *gui_widget_in_widget(struct gui_widget *parent, u32 wi return NULL; } -static struct gui_widget *gui_widget_in_win(struct gui_window *win, u32 widget_id) -{ - if (!win || !win->widgets) - return NULL; - - struct node *iterator = win->widgets->head; - while (iterator) { - struct gui_widget *widget = iterator->data; - if (widget->id == widget_id) - return iterator->data; - - struct gui_widget *sub = gui_widget_in_widget(widget, widget_id); - if (sub && sub->id == widget_id) - return sub; - - iterator = iterator->next; - } - - return NULL; -} - static struct gui_widget *gui_widget_by_id(u32 win_id, u32 widget_id) { struct gui_window *win = gui_window_by_id(win_id); - return gui_widget_in_win(win, widget_id); + return gui_widget_in_widget(win->main_widget, widget_id); } /** @@ -277,23 +257,11 @@ static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget) if (!win) gui_error(ENOENT); - if (!win->widgets) - return 1; - struct gui_widget *ret = NULL; struct gui_widget sub = { 0 }; - struct node *iterator = win->widgets->head; - while (iterator) { - struct gui_widget *w = iterator->data; - if (pos.x >= w->pos.x && pos.x <= w->pos.x + w->bg.size.x && pos.y >= w->pos.y && - pos.y <= w->pos.y + w->bg.size.y) - ret = w; - - if (w->children->head && gui_sub_widget_at(w, pos, &sub)) - ret = ⊂ - iterator = iterator->next; - } + if (gui_sub_widget_at(win->main_widget, pos, &sub)) + ret = ⊂ if (!ret) return 0; @@ -323,7 +291,7 @@ static void gui_sync_sub_widgets(struct gui_widget *widget) static void gui_sync_widget(u32 win_id, u32 widget_id) { struct gui_window *win = gui_window_by_id(win_id); - struct gui_widget *widget = gui_widget_in_win(win, widget_id); + struct gui_widget *widget = gui_widget_in_widget(win->main_widget, widget_id); if (!widget) gui_error(ENOENT); @@ -335,32 +303,13 @@ static void gui_sync_widget(u32 win_id, u32 widget_id) static void gui_sync_widgets(u32 win_id) { struct gui_window *win = gui_window_by_id(win_id); + struct gui_widget *widget = win->main_widget; if (!win) gui_error(ENOENT); - if (!win->widgets) - return; - - struct node *iterator = win->widgets->head; - while (iterator) { - struct gui_widget *widget = iterator->data; - gui_sync_sub_widgets(widget); - gfx_ctx_on_ctx(&win->ctx, &widget->bg, widget->pos, GFX_ALPHA); - gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA); - iterator = iterator->next; - } -} - -static struct gui_widget *gui_main_widget(struct gui_window *win) -{ - assert(win && win->widgets && win->widgets->head); - return win->widgets->head->data; -} - -static u32 gui_main_widget_id(struct gui_window *win) -{ - assert(win && win->widgets && win->widgets->head); - return ((struct gui_widget *)win->widgets->head->data)->id; + gui_sync_sub_widgets(win->main_widget); + gfx_ctx_on_ctx(&win->ctx, &widget->bg, widget->pos, GFX_ALPHA); + gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA); } // TODO: This is very recursive and inefficient -> improve! @@ -391,7 +340,26 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil return offset; } -static struct gui_widget *gui_new_plain_widget(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp) +static void gui_destroy_widget(u32 win_id, u32 widget_id) +{ + struct gui_widget *widget = gui_widget_by_id(win_id, widget_id); + if (!widget) + return; + + struct node *iterator = widget->children->head; + while (iterator) { + struct gui_widget *sub = iterator->data; + gui_destroy_widget(win_id, sub->id); + iterator = iterator->next; + } + + list_destroy(widget->children); + free(widget->bg.fb); + free(widget->fg.fb); + free(widget); +} + +static struct gui_widget *gui_plain_widget(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp) { struct gui_widget *widget = zalloc(sizeof(*widget)); struct gfx_context bg; @@ -415,45 +383,19 @@ u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size) if (!parent) gui_error(ENOENT); - struct gui_widget *child = gui_new_plain_widget(pos, size, GUI_HLAYOUT, parent->bg.bpp); + struct gui_widget *child = gui_plain_widget(pos, size, GUI_HLAYOUT, parent->bg.bpp); list_add(parent->children, child); return child->id; } -static void gui_destroy_widget(u32 win_id, u32 widget_id) -{ - struct gui_widget *widget = gui_widget_by_id(win_id, widget_id); - if (!widget) - return; - - struct node *iterator = widget->children->head; - while (iterator) { - struct gui_widget *sub = iterator->data; - gui_destroy_widget(win_id, sub->id); - iterator = iterator->next; - } - - list_destroy(widget->children); - free(widget->bg.fb); - free(widget->fg.fb); - free(widget); -} - -static void gui_destroy_widgets(u32 win_id) +u32 gui_main_widget(u32 win_id) { struct gui_window *win = gui_window_by_id(win_id); + if (!win) + gui_error(ENOENT); - if (!win->widgets) - return; - - struct node *iterator = win->widgets->head; - while (iterator) { - struct gui_widget *widget = iterator->data; - gui_destroy_widget(win_id, widget->id); - iterator = iterator->next; - } - list_destroy(win->widgets); + return win->main_widget->id; } void gui_widget_listen(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func) @@ -496,9 +438,9 @@ void gui_popup(const char *text) u32 popup = gui_custom_window("Popup", pos, vec2(POPUP_WIDTH, POPUP_HEIGHT)); struct gui_window *win = gui_window_by_id(popup); - gui_fill(popup, gui_main_widget_id(win), GUI_LAYER_BG, COLOR_WHITE); + gui_fill(popup, win->main_widget->id, GUI_LAYER_BG, COLOR_WHITE); - u32 widget = gui_widget(popup, GUI_MAIN, vec2(0, 0), vec2(POPUP_WIDTH, 32)); + u32 widget = gui_widget(popup, win->main_widget->id, vec2(0, 0), vec2(POPUP_WIDTH, 32)); gui_fill(popup, widget, GUI_LAYER_BG, COLOR_WHITE); gui_write(popup, widget, GUI_LAYER_FG, vec2(0, 0), FONT_32, COLOR_BLACK, text); @@ -556,11 +498,10 @@ u32 gui_custom_window(const char *name, vec2 pos, vec2 size) win->ctx.fb += msg.off.y * msg.ctx.pitch; list_add(windows, win); - win->widgets = list_new(); // Initialize GUI_MAIN widget - list_add(win->widgets, gui_new_plain_widget(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, - win->ctx.bpp)); + win->main_widget = + gui_plain_widget(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, win->ctx.bpp); return win->id; } @@ -591,9 +532,8 @@ void gui_redraw_window(u32 id) static void gui_destroy_window(u32 id) { - gui_destroy_widgets(id); - struct gui_window *win = gui_window_by_id(id); + gui_destroy_widget(id, win->main_widget->id); u8 *fb = win->ctx.fb - (win->off.y * win->ctx.pitch); assert(sys_free(fb) == EOK); @@ -646,7 +586,7 @@ static void gui_handle_mouse(struct message_mouse *msg) gui_widget_at(msg->id, msg->pos, &widget); struct gui_window *win = gui_window_by_id(msg->id); - vec2 offset = gui_offset_widget(gui_main_widget(win), &widget); + vec2 offset = gui_offset_widget(win->main_widget, &widget); vec2 pos = vec2_sub(msg->pos, offset); struct gui_event_mouse event = { diff --git a/libs/libgui/gui.h b/libs/libgui/gui.h index 37626cf..a2a44ed 100644 --- a/libs/libgui/gui.h +++ b/libs/libgui/gui.h @@ -8,8 +8,6 @@ #include <libgui/gfx.h> #include <vec.h> -#define GUI_MAIN 0 // First widget is the main widget - enum gui_listener { GUI_LISTEN_MOUSEMOVE, GUI_LISTEN_MOUSECLICK, @@ -21,9 +19,8 @@ enum gui_layer { }; enum gui_layout { - GUI_NO_LAYOUT, - GUI_VLAYOUT, // New widgets get positioned under previous widget GUI_HLAYOUT, // New widgets get positioned right of previous widget + GUI_VLAYOUT, // New widgets get positioned under previous widget }; struct gui_event_mouse { @@ -73,6 +70,7 @@ void gui_draw_line(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos1, v */ u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size); +u32 gui_main_widget(u32 win_id); void gui_widget_listen(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func); void gui_redraw_widget(u32 win_id, u32 widget_id); |