--- a/ui/win32/container.c Sat Oct 04 14:54:25 2025 +0200 +++ b/ui/win32/container.c Sun Oct 19 21:20:08 2025 +0200 @@ -27,6 +27,48 @@ */ #include "container.h" +#include "grid.h" + +#include "../common/context.h" +#include "../common/container.h" +#include "../motif/container.h" + + +static W32WidgetClass grid_layout_widget_class = { + .eventproc = NULL, + .enable = NULL, + .show = w32_widget_default_show, + .get_preferred_size = ui_grid_layout_get_preferred_size, + .destroy = w32_widget_default_destroy +}; + +UiContainerPrivate* ui_obj_container(UiObject *obj) { + return (UiContainerPrivate*)obj->container_end; +} + +HWND ui_container_get_parent(UiContainerPrivate *ctn) { + return ctn->parent ? ctn->parent(ctn) : ctn->hwnd; +} + +void ui_container_add(UiContainerPrivate *ctn, W32Widget *widget, UiLayout *layout) { + UiLayout layout2 = *layout; + if (layout2.margin > 0) { + layout2.margin_left = layout2.margin; + layout2.margin_right = layout2.margin; + layout2.margin_top = layout2.margin; + layout2.margin_bottom = layout2.margin; + } + ctn->add(ctn, widget, &layout2); + ctn->container.newline = FALSE; +} + +W32Size ui_grid_layout_get_preferred_size(W32Widget *widget) { + UiGridLayout *grid = widget->layoutmanager; + W32Size size; + size.width = grid->preferred_width; + size.height = grid->preferred_height; + return size; +} /* ---------------------------- Box Container ---------------------------- */ @@ -45,4 +87,118 @@ return box_create(obj, args, UI_BOX_HORIZONTAL); } +UiContainerX* ui_box_container_create(UiObject *obj, HWND hwnd, UiBoxOrientation orientation, short spacing, GridEdgeInsets padding) { + UiBoxContainer *container = cxZalloc(obj->ctx->allocator, sizeof(UiBoxContainer)); + container->container.hwnd = hwnd; + container->container.add = ui_box_container_add; + container->layout = ui_grid_layout_create(obj->ctx->allocator, spacing, spacing); + container->layout->padding = padding; + container->orientation = orientation; + return (UiContainerX*)container; +} +void ui_box_container_add(UiContainerPrivate *ctn, W32Widget *widget, UiLayout *layout) { + UiBoxContainer *box = (UiBoxContainer*)ctn; + GridLayoutInfo gridLayout = (GridLayoutInfo) { + .margin = (GridEdgeInsets) { layout->margin_top, layout->margin_bottom, layout->margin_left, layout->margin_right }, + }; + if (box->orientation == UI_BOX_HORIZONTAL) { + gridLayout.vexpand = TRUE; + gridLayout.vfill = TRUE; + gridLayout.hexpand = layout->fill; + gridLayout.hfill = layout->fill; + } else { + gridLayout.hexpand = TRUE; + gridLayout.hfill = TRUE; + gridLayout.vexpand = layout->fill; + gridLayout.vfill = layout->fill; + } + ui_grid_add_widget(box->layout, box->x, box->y, widget, &gridLayout); + if (box->orientation == UI_BOX_HORIZONTAL) { + box->x++; + } else { + box->y++; + } +} + +/* ---------------------------- Grid Container ---------------------------- */ + +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { + HINSTANCE hInstance = GetModuleHandle(NULL); + UiContainerPrivate *container = ui_obj_container(obj); + HWND parent = ui_container_get_parent(container); + UiLayout layout = UI_ARGS2LAYOUT(args); + + HWND hwnd = CreateWindowEx( + 0, + TEXT("STATIC"), + NULL, + WS_CHILD | WS_VISIBLE, + 0, 0, 100, 100, + parent, + NULL, + hInstance, + NULL); + + W32Widget *widget = w32_widget_new(&grid_layout_widget_class, hwnd); + ui_container_add(container, widget, &layout); + + UiContainerX *gridContainer = ui_grid_container_create(obj, hwnd, args->columnspacing, args->rowspacing, INSETS_ZERO); + uic_object_push_container(obj, gridContainer); + + UiGridLayoutContainer *grid = (UiGridLayoutContainer*)gridContainer; + widget->layout = (W32LayoutFunc)ui_grid_layout; + widget->layoutmanager = grid->layout; + grid->layout->preferred_width = 200; + grid->layout->preferred_height = 200; + + return widget; +} + +UiContainerX* ui_grid_container_create(UiObject *obj, HWND hwnd, short columnspacing, short rowspacing, GridEdgeInsets padding) { + UiGridLayoutContainer *container = cxZalloc(obj->ctx->allocator, sizeof(UiGridLayoutContainer)); + container->container.hwnd = hwnd; + container->container.add = ui_grid_container_add; + container->layout = ui_grid_layout_create(obj->ctx->allocator, columnspacing, rowspacing); + container->layout->padding = padding; + return (UiContainerX*)container; +} + +void ui_grid_container_add(UiContainerPrivate *ctn, W32Widget *widget, UiLayout *layout) { + UiGridLayoutContainer *grid = (UiGridLayoutContainer*)ctn; + if (ctn->container.newline) { + grid->y++; + grid->x = 0; + } + + uic_layout_setup_expand_fill(layout, grid->def_hexpand, grid->def_vexpand, grid->def_hfill, grid->def_vfill); + GridLayoutInfo gridLayout = (GridLayoutInfo) { + .margin = (GridEdgeInsets) { layout->margin_top, layout->margin_bottom, layout->margin_left, layout->margin_right }, + .colspan = layout->colspan, + .rowspan = layout->rowspan, + .hexpand = layout->hexpand, + .vexpand = layout->vexpand, + .hfill = layout->hfill, + .vfill = layout->vfill, + }; + ui_grid_add_widget(grid->layout, grid->x, grid->y, widget, &gridLayout); + + grid->x++; +} + + +/* ---------------------------- Container Helper ---------------------------- */ + +void ui_container_begin_close(UiObject *obj) { + UiContainerX *ct = obj->container_end; + ct->close = 1; +} + +int ui_container_finish(UiObject *obj) { + UiContainerX *ct = obj->container_end; + if(ct->close) { + ui_end_new(obj); + return 0; + } + return 1; +} \ No newline at end of file