ui/server/container.c

changeset 990
38a48b756d80
parent 985
93f07ccfd997
child 991
ab3125bd8b5f
--- 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);
+}

mercurial