# HG changeset patch # User Olaf Wintermann # Date 1695549837 -7200 # Node ID 4a8b1a748f091b1987be597e31746bbff7a5f4c0 # Parent 8c9b4b28aaa90b6de147aa6fa653186cd02692c0 implement grid container (WinUI) diff -r 8c9b4b28aaa9 -r 4a8b1a748f09 make/vs/testapp/main.c --- a/make/vs/testapp/main.c Sat Sep 23 15:41:23 2023 +0200 +++ b/make/vs/testapp/main.c Sun Sep 24 12:03:57 2023 +0200 @@ -42,9 +42,27 @@ void application_startup(UiEvent* event, void* data) { UiObject* obj = ui_window("Test", NULL); + /* ui_button(obj, "Button1", action1, "action1"); ui_button(obj, "Button2", action1, "action2"); + ui_layout_fill(obj, TRUE); ui_button(obj, "Button3", action1, "action3"); + */ + + UI_GRID_SP(obj, 10, 5, 20) { + ui_button(obj, "Button1", action1, "action1"); + ui_button(obj, "Button2", action1, "action2"); + ui_layout_hexpand(obj, 1); + ui_button(obj, "Button3", action1, "action3"); + ui_newline(obj); + + ui_button(obj, "Button4", action1, "action4"); + ui_layout_gridwidth(obj, 2); + ui_button(obj, "Button5_", action1, "action5"); + ui_newline(obj); + + ui_button(obj, "Very Long Button Label Text ____________ Test", action1, "test"); + } ui_show(obj); } diff -r 8c9b4b28aaa9 -r 4a8b1a748f09 ui/winui/container.cpp --- a/ui/winui/container.cpp Sat Sep 23 15:41:23 2023 +0200 +++ b/ui/winui/container.cpp Sun Sep 24 12:03:57 2023 +0200 @@ -28,23 +28,55 @@ #include "container.h" +#include "../common/context.h" +#include "../common/object.h" + + +void ui_container_begin_close(UiObject* obj) { + UiContainer* ct = uic_get_current_container(obj); + ct->close = 1; +} + +int ui_container_finish(UiObject* obj) { + UiContainer* ct = uic_get_current_container(obj); + if (ct->close) { + ui_end(obj); + return 0; + } + return 1; +} + + +// --------------------- UiBoxContainer --------------------- UiBoxContainer::UiBoxContainer(Grid grid, enum UiBoxContainerType type) { this->grid = grid; this->type = type; + GridLength gl; + gl.Value = 1; + gl.GridUnitType = GridUnitType::Star; + // hbox needs one row def, vbox needs one col def // all other col/row defs are created when elements are added if (type == UI_CONTAINER_HBOX) { - RowDefinition rowdef = RowDefinition(); - grid.RowDefinitions().Append(rowdef); + boxRowDef = RowDefinition(); + boxRowDef.Height(gl); + grid.RowDefinitions().Append(boxRowDef); } else { - ColumnDefinition coldef = ColumnDefinition(); - grid.ColumnDefinitions().Append(coldef); + boxColDef = ColumnDefinition(); + boxColDef.Width(gl); + grid.ColumnDefinitions().Append(boxColDef); } + + ui_reset_layout(layout); } -void UiBoxContainer::Add(Control control, UiBool fill) { +void UiBoxContainer::Add(FrameworkElement control, UiBool fill) { + if (this->layout.fill != UI_LAYOUT_UNDEFINED) { + fill = ui_lb2bool(this->layout.fill); + } + GridLength gl; if (fill) { gl.Value = 1; @@ -55,18 +87,155 @@ gl.GridUnitType = GridUnitType::Auto; } + control.HorizontalAlignment(HorizontalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + if (type == UI_CONTAINER_HBOX) { ColumnDefinition coldef = ColumnDefinition(); coldef.Width(gl); grid.ColumnDefinitions().Append(coldef); grid.SetColumn(control, grid.Children().Size()); + grid.SetRow(control, 0); } else { RowDefinition rowdef = RowDefinition(); rowdef.Height(gl); grid.RowDefinitions().Append(rowdef); grid.SetRow(control, grid.Children().Size()); + grid.SetColumn(control, 0); } grid.Children().Append(control); + + ui_reset_layout(layout); +} + +// --------------------- UiBoxContainer --------------------- + +UIWIDGET ui_grid(UiObject* obj) { + return ui_grid_sp(obj, 0, 0, 0); +} + +UIWIDGET ui_grid_sp(UiObject* obj, int margin, int columnspacing, int rowspacing) { + UiContainer* ct = uic_get_current_container(obj); + + Grid grid = Grid(); + ct->Add(grid, true); + + UIElement elm = grid; + UiWidget* widget = new UiWidget(elm); + + UiObject* newobj = uic_object_new(obj, widget); + newobj->container = new UiGridContainer(grid, margin, columnspacing, rowspacing); + uic_obj_add(obj, newobj); + + return widget; +} + +UiGridContainer::UiGridContainer(Grid grid, int margin, int columnspacing, int rowspacing) { + this->grid = grid; + Thickness t = { (double)margin, (double)margin, (double)margin, (double)margin }; + grid.Margin(t); + grid.ColumnSpacing((double)columnspacing); + grid.RowSpacing((double)rowspacing); + ui_reset_layout(layout); } +void UiGridContainer::Add(FrameworkElement control, UiBool fill) { + GridLength gl; + + int hexpand = FALSE; + int vexpand = FALSE; + if (layout.hexpand != UI_LAYOUT_UNDEFINED) { + hexpand = layout.hexpand; + } + if (layout.vexpand != UI_LAYOUT_UNDEFINED) { + vexpand = layout.vexpand; + } + + // create new RowDefinition for the new line + if (layout.newline || y == -1) { + x = 0; + y++; + RowDefinition rowdef = RowDefinition(); + if (vexpand) { + gl.GridUnitType = GridUnitType::Star; + gl.Value = 1; + } + else { + gl.GridUnitType = GridUnitType::Auto; + gl.Value = 0; + } + rowdef.Height(gl); + grid.RowDefinitions().Append(rowdef); + } + + // create new columndefinition, if a new column is added + if (x == cols) { + if (hexpand) { + gl.GridUnitType = GridUnitType::Star; + gl.Value = 1; + } + else { + gl.GridUnitType = GridUnitType::Auto; + gl.Value = 0; + } + ColumnDefinition coldef = ColumnDefinition(); + coldef.Width(gl); + grid.ColumnDefinitions().Append(coldef); + cols++; + } + + // add control + control.HorizontalAlignment(HorizontalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + + if (layout.gridwidth > 0) { + grid.SetColumnSpan(control, layout.gridwidth); + } + + grid.SetRow(control, y); + grid.SetColumn(control, x); + grid.Children().Append(control); + + x++; + + ui_reset_layout(layout); +} + +/* + * -------------------- Layout Functions -------------------- + * + * functions for setting layout attributes for the current container + * + */ + +void ui_layout_fill(UiObject* obj, UiBool fill) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.fill = ui_bool2lb(fill); +} + +void ui_layout_hexpand(UiObject* obj, UiBool expand) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.hexpand = expand; +} + +void ui_layout_vexpand(UiObject* obj, UiBool expand) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.vexpand = expand; +} + +void ui_layout_width(UiObject* obj, int width) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.width = width; +} + +void ui_layout_gridwidth(UiObject* obj, int width) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.gridwidth = width; +} + +void ui_newline(UiObject* obj) { + UiContainer* ct = uic_get_current_container(obj); + ct->layout.newline = TRUE; +} + diff -r 8c9b4b28aaa9 -r 4a8b1a748f09 ui/winui/container.h --- a/ui/winui/container.h Sat Sep 23 15:41:23 2023 +0200 +++ b/ui/winui/container.h Sun Sep 24 12:03:57 2023 +0200 @@ -40,6 +40,11 @@ #include #include + +#define ui_reset_layout(layout) memset(&(layout), 0, sizeof(UiLayout)) +#define ui_lb2bool(b) ((b) == UI_LAYOUT_TRUE ? TRUE : FALSE) +#define ui_bool2lb(b) ((b) ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE) + typedef struct UiLayout UiLayout; typedef enum UiLayoutBool UiLayoutBool; @@ -68,9 +73,9 @@ struct UiContainer { UiLayout layout; - int close; + int close = 0; - virtual void Add(Control control, UiBool fill) = 0; + virtual void Add(FrameworkElement control, UiBool fill) = 0; }; enum UiBoxContainerType { @@ -81,8 +86,21 @@ struct UiBoxContainer : UiContainer { Grid grid; enum UiBoxContainerType type; + RowDefinition boxRowDef; + ColumnDefinition boxColDef; UiBoxContainer(Grid grid, enum UiBoxContainerType type); - void Add(Control control, UiBool fill); + void Add(FrameworkElement control, UiBool fill); }; + +struct UiGridContainer : UiContainer { + Grid grid; + int x = 0; + int y = -1; + int cols = 0; + + UiGridContainer(Grid grid, int margin, int columnspacing, int rowspacing); + + void Add(FrameworkElement control, UiBool fill); +};