diff options
-rw-r--r-- | apps/chess/main.c | 21 | ||||
-rw-r--r-- | apps/paint/main.c | 16 | ||||
-rw-r--r-- | apps/view/main.c | 9 | ||||
-rw-r--r-- | apps/wm/main.c | 2 | ||||
-rw-r--r-- | libs/libgui/gui.c | 129 | ||||
-rw-r--r-- | libs/libgui/gui.h | 18 | ||||
-rw-r--r-- | libs/libgui/widgets.c | 7 | ||||
-rw-r--r-- | libs/libgui/widgets.h | 2 |
8 files changed, 132 insertions, 72 deletions
diff --git a/apps/chess/main.c b/apps/chess/main.c index abfad59..d8c52c1 100644 --- a/apps/chess/main.c +++ b/apps/chess/main.c @@ -93,11 +93,11 @@ static void mouseclick(struct gui_event_mouse *event) gui_clear(win, selected_piece->widget, GUI_LAYER_FG); load_image(clicked_piece); - gui_redraw_window(win); + gui_window_redraw(win); selected = vec2(-1, -1); } else if (clicked_piece->piece) { - gui_redraw_widget(win, clicked_piece->widget); + gui_widget_redraw(win, clicked_piece->widget); selected = clicked; } } @@ -212,10 +212,15 @@ static void fen_parse(const char *fen) 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_widget(win), vec2(TILE * x, TILE * y), - vec2(TILE, TILE)); + gui_widget_margin(win, gui_widget_main(win), vec2(0, 0)); + gui_widget_layout(win, gui_widget_main(win), GUI_VLAYOUT); + + for (u8 y = 0; y < 8; y++) { + u8 row = gui_widget(win, gui_widget_main(win), vec2(TILE * 8, TILE)); + gui_widget_margin(win, row, vec2(0, 0)); + + for (u8 x = 0; x < 8; x++) { + u32 widget = gui_widget(win, row, vec2(TILE, TILE)); assert((signed)widget > 0); u8 colored = (x + y + 1) % 2 == 0; @@ -234,12 +239,12 @@ static void draw_board(void) } } - gui_redraw_window(win); + gui_window_redraw(win); } int main(void) { - win = gui_custom_window(APPNAME, vec2(0, 0), vec2(TILE * 8, TILE * 8)); + win = gui_window_custom(APPNAME, vec2(0, 0), vec2(TILE * 8, TILE * 8)); fen_parse(START_FEN); draw_board(); diff --git a/apps/paint/main.c b/apps/paint/main.c index 626d41d..0f0dd8c 100644 --- a/apps/paint/main.c +++ b/apps/paint/main.c @@ -20,7 +20,7 @@ static void mousemove(struct gui_event_mouse *event) if (event->but.left) { gui_draw_line(event->win, event->widget, GUI_LAYER_FG, last, event->pos, size, current_color); - gui_redraw_widget(event->win, event->widget); + gui_widget_redraw(event->win, event->widget); } last = event->pos; } @@ -37,27 +37,27 @@ int main(void) u32 win = gui_window(APPNAME); vec2 win_size = gui_window_size(win); - u32 toolbar = gui_widget(win, gui_main_widget(win), vec2(0, 0), + gui_widget_margin(win, gui_widget_main(win), vec2(0, 0)); + gui_widget_layout(win, gui_widget_main(win), GUI_VLAYOUT); + + u32 toolbar = gui_widget(win, gui_widget_main(win), 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)); + u32 color = gui_widget(win, toolbar, 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_widget(win), vec2(0, COLOR_SIZE + 2 * TOOLBAR_MARGIN), + u32 canvas = gui_widget(win, gui_widget_main(win), 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); - gui_redraw_window(win); + gui_window_redraw(win); gui_loop(); return 0; } diff --git a/apps/view/main.c b/apps/view/main.c index fc7e3bc..f3ccb3d 100644 --- a/apps/view/main.c +++ b/apps/view/main.c @@ -14,7 +14,7 @@ static void mousemove(struct gui_event_mouse *event) size = vec2_mul(size, event->scroll < 0 ? SCALING_FACTOR + 1 : 1 - SCALING_FACTOR); gui_fill(event->win, event->widget, GUI_LAYER_FG, COLOR_WHITE); gui_draw_image(event->win, event->widget, GUI_LAYER_FG, vec2(0, 0), size, path); - gui_redraw_widget(event->win, event->widget); + gui_widget_redraw(event->win, event->widget); } } @@ -25,12 +25,13 @@ int main(int argc, char *argv[]) path = "/res/test.png"; - u32 win = gui_custom_window(APPNAME, vec2(0, 0), size); - u32 canvas = gui_widget(win, gui_main_widget(win), vec2(0, 0), size); + u32 win = gui_window_custom(APPNAME, vec2(0, 0), size); + gui_widget_margin(win, gui_widget_main(win), vec2(0, 0)); + u32 canvas = gui_widget(win, gui_widget_main(win), size); gui_fill(win, canvas, GUI_LAYER_BG, COLOR_WHITE); gui_widget_listen(win, canvas, GUI_LISTEN_MOUSEMOVE, (u32)mousemove); - gui_redraw_window(win); + gui_window_redraw(win); gui_loop(); return 0; diff --git a/apps/wm/main.c b/apps/wm/main.c index 6a4b9bf..8c12b1a 100644 --- a/apps/wm/main.c +++ b/apps/wm/main.c @@ -754,7 +754,7 @@ int main(int argc, char **argv) assert(dev_control(DEV_BUS, DEVCTL_BUS_REGISTER, "wm") == EOK); - assert(exec("view", NULL) == EOK); + assert(exec("chess", NULL) == EOK); u8 msg[1024] = { 0 }; struct event_keyboard event_keyboard = { 0 }; diff --git a/libs/libgui/gui.c b/libs/libgui/gui.c index d011126..144ead8 100644 --- a/libs/libgui/gui.c +++ b/libs/libgui/gui.c @@ -15,8 +15,7 @@ struct gui_widget { struct gfx_context bg; struct list *children; - u32 margin; // Between sub-widgets - u32 offset; + vec2 margin; // Between sub-widgets enum gui_layout layout; struct { @@ -104,6 +103,33 @@ static void gui_connect_wm(void) } /** + * Layout stuff + */ + +static vec2 gui_layout_position(struct gui_widget *parent) +{ + enum gui_layout layout = parent->layout; + vec2 pos = parent->margin; + + struct node *iterator = parent->children->head; + while (iterator) { + struct gui_widget *widget = iterator->data; + + if (layout == GUI_HLAYOUT) { + pos.x += MAX(widget->bg.size.x, widget->fg.size.x) + parent->margin.x; + } else if (layout == GUI_VLAYOUT) { + pos.y += MAX(widget->bg.size.y, widget->fg.size.y) + parent->margin.y; + } else { + gui_error(EINVAL); + } + + iterator = iterator->next; + } + + return pos; +} + +/** * GFX wrappers */ @@ -221,7 +247,8 @@ void gui_draw_line(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos1, v * Widgets */ -static u8 gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf) +// TODO: Fix child location algorithm +static u8 gui_widget_child_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf) { if (!widget || !widget->children || !buf) gui_error(EFAULT); @@ -236,7 +263,7 @@ static u8 gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widg pos.y <= w->pos.y + w->bg.size.y) ret = w; - if (w->children->head && gui_sub_widget_at(w, pos, &sub)) + if (w->children->head && gui_widget_child_at(w, pos, &sub)) ret = ⊂ iterator = iterator->next; } @@ -260,7 +287,7 @@ static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget) struct gui_widget *ret = NULL; struct gui_widget sub = { 0 }; - if (gui_sub_widget_at(win->main_widget, pos, &sub)) + if (gui_widget_child_at(win->main_widget, pos, &sub)) ret = ⊂ if (!ret) @@ -270,7 +297,7 @@ static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget) return 1; } -static void gui_sync_sub_widgets(struct gui_widget *widget) +static void gui_widget_children_sync(struct gui_widget *widget) { if (!widget) gui_error(EFAULT); @@ -281,39 +308,39 @@ static void gui_sync_sub_widgets(struct gui_widget *widget) struct node *iterator = widget->children->head; while (iterator) { struct gui_widget *w = iterator->data; - gui_sync_sub_widgets(w); + gui_widget_children_sync(w); gfx_ctx_on_ctx(&widget->bg, &w->bg, w->pos, GFX_NON_ALPHA); gfx_ctx_on_ctx(&widget->fg, &w->fg, w->pos, GFX_NON_ALPHA); iterator = iterator->next; } } -static void gui_sync_widget(u32 win_id, u32 widget_id) +static void gui_widget_sync(u32 win_id, u32 widget_id) { struct gui_window *win = gui_window_by_id(win_id); struct gui_widget *widget = gui_widget_in_widget(win->main_widget, widget_id); if (!widget) gui_error(ENOENT); - gui_sync_sub_widgets(widget); + gui_widget_children_sync(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); } -static void gui_sync_widgets(u32 win_id) +static void gui_widget_sync_all(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); - gui_sync_sub_widgets(win->main_widget); + gui_widget_children_sync(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! -static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *child) +static vec2 gui_widget_offset(struct gui_widget *parent, struct gui_widget *child) { if (!parent || !parent->children || !child) return vec2(0, 0); @@ -330,7 +357,7 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil struct gui_widget *sub = gui_widget_in_widget(w, child->id); if (sub) { offset = vec2_add(offset, w->pos); - gui_offset_widget(w, child); + gui_widget_offset(w, child); break; } @@ -340,7 +367,7 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil return offset; } -static void gui_destroy_widget(u32 win_id, u32 widget_id) +static void gui_widget_destroy(u32 win_id, u32 widget_id) { struct gui_widget *widget = gui_widget_by_id(win_id, widget_id); if (!widget) @@ -349,7 +376,7 @@ static void gui_destroy_widget(u32 win_id, u32 widget_id) struct node *iterator = widget->children->head; while (iterator) { struct gui_widget *sub = iterator->data; - gui_destroy_widget(win_id, sub->id); + gui_widget_destroy(win_id, sub->id); iterator = iterator->next; } @@ -359,7 +386,7 @@ static void gui_destroy_widget(u32 win_id, u32 widget_id) free(widget); } -static struct gui_widget *gui_plain_widget(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp) +static struct gui_widget *gui_widget_plain(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp) { struct gui_widget *widget = zalloc(sizeof(*widget)); struct gfx_context bg; @@ -371,25 +398,26 @@ static struct gui_widget *gui_plain_widget(vec2 pos, vec2 size, enum gui_layout widget->bg = *gfx_new_ctx(&bg, size, bpp); widget->fg = *gfx_new_ctx(&fg, size, bpp); widget->children = list_new(); - widget->margin = 4; + widget->margin = vec2(4, 4); widget->layout = layout; return widget; } -u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size) +u32 gui_widget(u32 win_id, u32 widget_id, vec2 size) { struct gui_widget *parent = gui_widget_by_id(win_id, widget_id); if (!parent) gui_error(ENOENT); - struct gui_widget *child = gui_plain_widget(pos, size, GUI_HLAYOUT, parent->bg.bpp); + vec2 pos = gui_layout_position(parent); + struct gui_widget *child = gui_widget_plain(pos, size, GUI_HLAYOUT, parent->bg.bpp); list_add(parent->children, child); return child->id; } -u32 gui_main_widget(u32 win_id) +u32 gui_widget_main(u32 win_id) { struct gui_window *win = gui_window_by_id(win_id); if (!win) @@ -419,10 +447,10 @@ void gui_widget_listen(u32 win_id, u32 widget_id, enum gui_listener listener, u3 } } -void gui_redraw_widget(u32 win_id, u32 widget_id) +void gui_widget_redraw(u32 win_id, u32 widget_id) { - gui_sync_widget(win_id, widget_id); - gui_redraw_window_only(win_id); + gui_widget_sync(win_id, widget_id); + gui_window_redraw_plain(win_id); } /** @@ -436,15 +464,15 @@ void gui_popup(const char *text) { vec2 pos = vec2(200, 200); - u32 popup = gui_custom_window("Popup", pos, vec2(POPUP_WIDTH, POPUP_HEIGHT)); + u32 popup = gui_window_custom("Popup", pos, vec2(POPUP_WIDTH, POPUP_HEIGHT)); struct gui_window *win = gui_window_by_id(popup); gui_fill(popup, win->main_widget->id, GUI_LAYER_BG, COLOR_WHITE); - u32 widget = gui_widget(popup, win->main_widget->id, vec2(0, 0), vec2(POPUP_WIDTH, 32)); + u32 widget = gui_widget(popup, win->main_widget->id, 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); - gui_redraw_window(popup); + gui_window_redraw(popup); } /** @@ -460,10 +488,30 @@ vec2 gui_window_size(u32 win_id) } /** + * Window data setters + */ + +void gui_widget_margin(u32 win_id, u32 widget_id, vec2 margin) +{ + struct gui_widget *widget = gui_widget_by_id(win_id, widget_id); + if (!widget) + gui_error(ENOENT); + widget->margin = margin; +} + +void gui_widget_layout(u32 win_id, u32 widget_id, enum gui_layout layout) +{ + struct gui_widget *widget = gui_widget_by_id(win_id, widget_id); + if (!widget) + gui_error(ENOENT); + widget->layout = layout; +} + +/** * Window manager interfaces */ -u32 gui_custom_window(const char *name, vec2 pos, vec2 size) +u32 gui_window_custom(const char *name, vec2 pos, vec2 size) { if (!windows) windows = list_new(); @@ -501,7 +549,7 @@ u32 gui_custom_window(const char *name, vec2 pos, vec2 size) // Initialize GUI_MAIN widget win->main_widget = - gui_plain_widget(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, win->ctx.bpp); + gui_widget_plain(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, win->ctx.bpp); return win->id; } @@ -511,10 +559,10 @@ u32 gui_custom_window(const char *name, vec2 pos, vec2 size) u32 gui_window(const char *name) { - return gui_custom_window(name, vec2(0, 0), vec2(0, 0)); + return gui_window_custom(name, vec2(0, 0), vec2(0, 0)); } -void gui_redraw_window_only(u32 id) +void gui_window_redraw_plain(u32 id) { struct message_redraw_window msg = { .id = id }; gui_connect_wm(); @@ -524,16 +572,16 @@ void gui_redraw_window_only(u32 id) gui_error(EINVAL); } -void gui_redraw_window(u32 id) +void gui_window_redraw(u32 id) { - gui_sync_widgets(id); - gui_redraw_window_only(id); + gui_widget_sync_all(id); + gui_window_redraw_plain(id); } -static void gui_destroy_window(u32 id) +static void gui_window_destroy(u32 id) { struct gui_window *win = gui_window_by_id(id); - gui_destroy_widget(id, win->main_widget->id); + gui_widget_destroy(id, win->main_widget->id); u8 *fb = win->ctx.fb - (win->off.y * win->ctx.pitch); assert(sys_free(fb) == EOK); @@ -545,13 +593,13 @@ static void gui_destroy_window(u32 id) free(win); } -static void gui_destroy_windows(void) +static void gui_window_destroy_all(void) { struct node *iterator = windows->head; while (iterator) { struct gui_window *win = iterator->data; iterator = iterator->next; - gui_destroy_window(win->id); + gui_window_destroy(win->id); } list_destroy(windows); @@ -584,9 +632,10 @@ static void gui_handle_mouse(struct message_mouse *msg) struct gui_widget widget = { 0 }; gui_widget_at(msg->id, msg->pos, &widget); + printf("%d\n", widget.id); struct gui_window *win = gui_window_by_id(msg->id); - vec2 offset = gui_offset_widget(win->main_widget, &widget); + vec2 offset = gui_widget_offset(win->main_widget, &widget); vec2 pos = vec2_sub(msg->pos, offset); struct gui_event_mouse event = { @@ -608,7 +657,7 @@ static void gui_handle_mouse(struct message_mouse *msg) static void gui_handle_destroy_window(struct message_destroy_window *msg) { - gui_destroy_window(msg->id); + gui_window_destroy(msg->id); if (!windows || !windows->head || !windows->head->data) { log("No more windows, exiting\n"); exit(0); @@ -620,7 +669,7 @@ static void gui_handle_exit(void) if (!windows) return; - gui_destroy_windows(); + gui_window_destroy_all(); } /** diff --git a/libs/libgui/gui.h b/libs/libgui/gui.h index a2a44ed..00f49b8 100644 --- a/libs/libgui/gui.h +++ b/libs/libgui/gui.h @@ -42,10 +42,10 @@ struct gui_event_mouse { * Window operations */ -u32 gui_custom_window(const char *name, vec2 pos, vec2 size); u32 gui_window(const char *name); -void gui_redraw_window(u32 id); -void gui_redraw_window_only(u32 id); // Without widgets +u32 gui_window_custom(const char *name, vec2 pos, vec2 size); +void gui_window_redraw(u32 id); +void gui_window_redraw_plain(u32 id); // Without widgets /** * GFX wrappers @@ -69,14 +69,20 @@ void gui_draw_line(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos1, v * Widget operations */ -u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size); -u32 gui_main_widget(u32 win_id); +u32 gui_widget(u32 win_id, u32 widget_id, vec2 size); +u32 gui_widget_main(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); +void gui_widget_redraw(u32 win_id, u32 widget_id); void gui_popup(const char *text); +/** + * Getters/setters + */ + vec2 gui_window_size(u32 win_id); +void gui_widget_margin(u32 win_id, u32 widget_id, vec2 margin); +void gui_widget_layout(u32 win_id, u32 widget_id, enum gui_layout layout); void gui_loop(void); diff --git a/libs/libgui/widgets.c b/libs/libgui/widgets.c index d6e82cd..1881655 100644 --- a/libs/libgui/widgets.c +++ b/libs/libgui/widgets.c @@ -10,12 +10,12 @@ * Button */ -void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_type, u32 bg, u32 fg, +void gui_button_custom(u32 window, u32 widget, enum font_type font_type, u32 bg, u32 fg, void (*click)(struct gui_event_mouse *event), const char *text) { vec2 font_size = gfx_font_size(font_type); vec2 size = vec2(font_size.x * strlen(text) + TEXT_PAD * 2, font_size.y + TEXT_PAD * 2); - u32 button = gui_widget(window, widget, pos, size); + u32 button = gui_widget(window, widget, size); gui_fill(window, button, GUI_LAYER_BG, bg); gui_write(window, button, GUI_LAYER_FG, vec2(TEXT_PAD, TEXT_PAD), font_type, fg, text); gui_widget_listen(window, button, GUI_LISTEN_MOUSECLICK, (u32)click); @@ -24,6 +24,5 @@ void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_typ void gui_button(u32 window, u32 widget, void (*click)(struct gui_event_mouse *event), const char *text) { - gui_button_custom(window, widget, vec2(0, 0), FONT_16, COLOR_WHITE, COLOR_BLACK, click, - text); + gui_button_custom(window, widget, FONT_16, COLOR_WHITE, COLOR_BLACK, click, text); } diff --git a/libs/libgui/widgets.h b/libs/libgui/widgets.h index 64862f0..4028af6 100644 --- a/libs/libgui/widgets.h +++ b/libs/libgui/widgets.h @@ -6,7 +6,7 @@ #include <libgui/gfx.h> #include <libgui/gui.h> -void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_type, u32 bg, u32 fg, +void gui_button_custom(u32 window, u32 widget, enum font_type font_type, u32 bg, u32 fg, void (*click)(struct gui_event_mouse *event), const char *text); void gui_button(u32 window, u32 widget, void (*click)(struct gui_event_mouse *event), const char *text); |