add box/grid containers (Server)

Fri, 12 Dec 2025 11:38:47 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 12 Dec 2025 11:38:47 +0100
changeset 990
38a48b756d80
parent 989
cd1ccc0d3d05
child 991
ab3125bd8b5f

add box/grid containers (Server)

application/main.c file | annotate | diff | comparison | revisions
ui/server/args.h file | annotate | diff | comparison | revisions
ui/server/container.c file | annotate | diff | comparison | revisions
ui/server/container.h file | annotate | diff | comparison | revisions
ui/server/toolkit.h file | annotate | diff | comparison | revisions
ui/server/window.c file | annotate | diff | comparison | revisions
--- a/application/main.c	Thu Dec 11 21:05:40 2025 +0100
+++ b/application/main.c	Fri Dec 12 11:38:47 2025 +0100
@@ -1292,7 +1292,14 @@
 
 void application_startup(UiEvent *event, void *userdata) {
     UiObject *obj = ui_window("Test");
-    ui_button(obj, .label = "Button");
+    ui_vbox(obj, .margin = 10, .spacing = 10) {
+        ui_button(obj, .label = "Test");
+        ui_hbox(obj, .spacing = 10) {
+            ui_button(obj, .label = "Test 1");
+            ui_button(obj, .label = "Test 2");
+            ui_button(obj, .label = "Test 3");
+        }
+    }
     ui_show(obj);
 }
 
--- a/ui/server/args.h	Thu Dec 11 21:05:40 2025 +0100
+++ b/ui/server/args.h	Fri Dec 12 11:38:47 2025 +0100
@@ -61,6 +61,10 @@
     if(args->icon) ui_argstr_add_str(buf, "icon", args->icon); \
     if(args->tooltip) ui_argstr_add_str(buf, "tooltip", args->tooltip)
 
+#define UI_SPACING_ARGS(buf, args) \
+    if(args->spacing != 0) ui_argstr_add_int(buf, "spacing", args->spacing); \
+    if(args->columnspacing != 0) ui_argstr_add_int(buf, "columnspacing", args->columnspacing); \
+    if(args->rowspacing != 0) ui_argstr_add_int(buf, "rowspacing", args->rowspacing)
 
 #ifdef __cplusplus
 }
--- a/ui/server/container.c	Thu Dec 11 21:05:40 2025 +0100
+++ b/ui/server/container.c	Fri Dec 12 11:38:47 2025 +0100
@@ -26,10 +26,114 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <cx/linked_list.h>
+#include <cx/buffer.h>
+
 #include "container.h"
+#include "args.h"
+
+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;
+}
 
 UiContainerX* ui_widget_container(UiWidget *w) {
     UiContainerX *container = cxZalloc(w->obj->ctx->allocator, sizeof(UiContainerX));
     container->container = w;
     return container;
 }
+
+cxmutstr ui_container_args_to_string(UiContext *ctx, UiContainerArgs *args) {
+    CxBuffer buf;
+    cxBufferInit(&buf, NULL, 256, ctx->allocator, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+    
+    cxBufferPutString(&buf, "{");
+    
+    UI_STANDARD_ARGS(&buf, args);
+    UI_SPACING_ARGS(&buf, args);
+    if(args->def_hfill) cxBufferPutString(&buf, "\"def_hfill\":true,");
+    if(args->def_vfill) cxBufferPutString(&buf, "\"def_vfill\":true,");
+    if(args->def_hexpand) cxBufferPutString(&buf, "\"def_hexpand\":true,");
+    if(args->def_vexpand) cxBufferPutString(&buf, "\"def_vexpand\":true,");
+    
+    if(buf.size > 0 && buf.space[buf.size-1] == ',') {
+        buf.space[buf.size-1] = ' ';
+    }
+    cxBufferPutString(&buf, "}");
+    return cx_mutstrn(buf.space, buf.size);
+}
+
+static UIWIDGET container_create(UiObject *obj, const char *type, UiContainerArgs *args) {
+    const CxAllocator *a = obj->ctx->allocator;
+    UiWidget *widget = cxZalloc(a, sizeof(UiWidget));
+    widget->obj = obj->widget->obj;
+    widget->type = cx_str(type);
+    widget->args = ui_container_args_to_string(obj->ctx, args);
+    widget->children = cxLinkedListCreate(a, NULL, CX_STORE_POINTERS);
+    widget->serialize = ui_container_serialize;
+    uic_object_push_container(obj, ui_widget_container(widget));
+    ui_reg_widget((UiWidget*)widget);
+    
+    UiWidget *parent = obj->container_end->container;
+    cxListAdd(parent->children, widget); 
+    
+    return widget;
+}
+
+void ui_serialize_children(UiWidget *w, CxBuffer *buf) {
+    size_t numchildren = cxListSize(w->children);
+    if(numchildren > 0) {
+        cxBufferPutString(buf, ",\"children\":[");
+        CxIterator i = cxListIterator(w->children);
+        cx_foreach(UiWidget *, child, i) {
+            cxmutstr child_str = child->serialize(child);
+            cxBufferWrite(child_str.ptr, 1, child_str.length, buf);
+            if(i.index+1 < numchildren) {
+                cxBufferPut(buf, ',');
+            }
+        }
+        cxBufferPutString(buf, "]");
+    }
+}
+
+cxmutstr ui_container_serialize(UiWidget *w) {
+    CxBuffer buf;
+    cxBufferInit(&buf, NULL, 1024, NULL, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+    
+    cxBufferPutString(&buf, "{\"type\":\"");
+    cxBufferPutString(&buf, w->type.ptr);
+    cxBufferPutString(&buf, "\",\"args\":\"");
+    cxBufferPutString(&buf, w->args.ptr);
+    cxBufferPutString(&buf, "\",\"obj\":");
+    cxBufferPutString(&buf, w->obj->id.ptr);
+    cxBufferPutString(&buf, "\",\"id\":");
+    cxBufferPutString(&buf, w->id.ptr);
+    cxBufferPutString(&buf, "\"");
+    
+    ui_serialize_children(w, &buf);
+    
+    cxBufferPutString(&buf, "}\n");
+    
+    return cx_mutstrn(buf.space, buf.size);
+}
+
+UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
+    return container_create(obj, "vbox", args);
+}
+
+UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) {
+    return container_create(obj, "hbox", args);
+}
+
+UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
+    return container_create(obj, "grid", args);
+}
--- a/ui/server/container.h	Thu Dec 11 21:05:40 2025 +0100
+++ b/ui/server/container.h	Fri Dec 12 11:38:47 2025 +0100
@@ -32,12 +32,20 @@
 #include "toolkit.h"
 #include "../common/container.h"
 
+#include <cx/buffer.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 UiContainerX* ui_widget_container(UiWidget *w);
 
+cxmutstr ui_container_args_to_string(UiContext *ctx, UiContainerArgs *args);
+
+void ui_serialize_children(UiWidget *w, CxBuffer *buf);
+
+cxmutstr ui_container_serialize(UiWidget *w);
+
 #ifdef __cplusplus
 }
 #endif
--- a/ui/server/toolkit.h	Thu Dec 11 21:05:40 2025 +0100
+++ b/ui/server/toolkit.h	Fri Dec 12 11:38:47 2025 +0100
@@ -72,6 +72,7 @@
 struct UiWidget {
     UiSrvObj *obj;
     cxmutstr id;
+    cxstring type;
     UiVar *var;
     cxmutstr var_id;
     UiVarType var_type;
--- a/ui/server/window.c	Thu Dec 11 21:05:40 2025 +0100
+++ b/ui/server/window.c	Fri Dec 12 11:38:47 2025 +0100
@@ -97,19 +97,7 @@
         cxBufferPutString(&buf, "\"");
     }
     
-    size_t numchildren = cxListSize(w->widget.children);
-    if(numchildren > 0) {
-        cxBufferPutString(&buf, ",\"children\":[");
-        CxIterator i = cxListIterator(w->widget.children);
-        cx_foreach(UiWidget *, child, i) {
-            cxmutstr child_str = child->serialize(child);
-            cxBufferWrite(child_str.ptr, 1, child_str.length, &buf);
-            if(i.index+1 < numchildren) {
-                cxBufferPut(&buf, ',');
-            }
-        }
-        cxBufferPutString(&buf, "]");
-    }
+    ui_serialize_children(&w->widget, &buf);
     
     cxBufferPutString(&buf, "}\n");
     

mercurial