Fri, 31 Oct 2025 10:12:27 +0100
implement frame container (Motif)
--- a/application/demo_bindings.c Thu Oct 30 21:29:18 2025 +0100 +++ b/application/demo_bindings.c Fri Oct 31 10:12:27 2025 +0100 @@ -104,7 +104,7 @@ ui_newline(obj); ui_frame(obj, .label = "Document", .colspan = 2, .fill = TRUE) { - ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10) { + ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10, .fill = TRUE) { ui_rlabel(obj, .label = "Name:", .vfill = TRUE); ui_textfield(obj, .varname = "input_name", .onchange = update_name); }
--- a/ui/common/object.c Thu Oct 30 21:29:18 2025 +0100 +++ b/ui/common/object.c Fri Oct 31 10:12:27 2025 +0100 @@ -144,4 +144,29 @@ } else { toplevel->container_begin = NULL; } + + // TODO: free container? } + +/* + * This might look like a weird function, but in case a container creates a + * sub-container, 2 container objects are added to the list, however we want + * only one container, otherwise ui_container_finish() would not work + */ +void uic_object_remove_second_last_container(UiObject *toplevel) { + if(toplevel->container_end && toplevel->container_end->prev) { + UiContainerX *end = toplevel->container_end; + UiContainerX *rm = toplevel->container_end->prev; + + end->prev = rm->prev; + if(rm->prev) { + rm->prev->next = end; + } else { + toplevel->container_begin = end; + } + + // TODO: free container? + } else { + fprintf(stderr, "Error: uic_object_remove_second_last_container expected at least 2 containers\n"); + } +}
--- a/ui/common/object.h Thu Oct 30 21:29:18 2025 +0100 +++ b/ui/common/object.h Fri Oct 31 10:12:27 2025 +0100 @@ -51,6 +51,7 @@ void uic_object_push_container(UiObject *toplevel, UiContainerX *newcontainer); void uic_object_pop_container(UiObject *toplevel); +void uic_object_remove_second_last_container(UiObject *toplevel);
--- a/ui/motif/container.c Thu Oct 30 21:29:18 2025 +0100 +++ b/ui/motif/container.c Fri Oct 31 10:12:27 2025 +0100 @@ -227,6 +227,82 @@ grid->container.container.newline = FALSE; } +/* -------------------------- Frame Container -------------------------- */ + +UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) { + Arg xargs[16]; + int n = 0; + + UiContainerPrivate *ctn = ui_obj_container(obj); + UiLayout layout = UI_ARGS2LAYOUT(args); + + Widget parent = ui_container_prepare(ctn, &layout, xargs, &n); + + char *name = args->name ? (char*)args->name : "frame"; + Widget frame = XmCreateFrame(parent, name, xargs, 6); + XtManageChild(frame); + ui_container_add(ctn, frame); + + if(args->label) { + XmString s = XmStringCreateLocalized((char*)args->label); + n = 0; + XtSetArg(xargs[n], XmNlabelString, s); n++; + XtSetArg(xargs[n], XmNchildType, XmFRAME_TITLE_CHILD); n++; + Widget label = XmCreateLabel(frame, "frame_label", xargs, n); + XtManageChild(label); + XmStringFree(s); + } + + UiContainerX *container = ui_frame_container(obj, frame); + uic_object_push_container(obj, container); + + UiContainerArgs sub_args = { + .spacing = args->spacing, + .columnspacing = args->columnspacing, + .rowspacing = args->rowspacing + }; + switch(args->subcontainer) { + default: break; + case UI_CONTAINER_VBOX: { + ui_vbox_create(obj, &sub_args); + uic_object_remove_second_last_container(obj); + break; + } + case UI_CONTAINER_HBOX: { + ui_hbox_create(obj, &sub_args); + uic_object_remove_second_last_container(obj); + break; + } + case UI_CONTAINER_GRID: { + ui_grid_create(obj, &sub_args); + uic_object_remove_second_last_container(obj); + break; + } + } + + + return frame; +} + +UiContainerX* ui_frame_container(UiObject *obj, Widget frame) { + UiContainerPrivate *ctn = ui_malloc(obj->ctx, sizeof(UiContainerPrivate)); + memset(ctn, 0, sizeof(UiContainerPrivate)); + ctn->prepare = ui_frame_container_prepare; + ctn->add = ui_frame_container_add; + ctn->widget = frame; + return (UiContainerX*)ctn; +} + +Widget ui_frame_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n) { + int a = *n; + XtSetArg(args[a], XmNchildType, XmFRAME_WORKAREA_CHILD); + *n = a+1; + return ctn->widget; +} + +void ui_frame_container_add(UiContainerPrivate *ctn, Widget widget) { + // NOOP +} /* -------------------------- TabView Container -------------------------- */
--- a/ui/motif/container.h Thu Oct 30 21:29:18 2025 +0100 +++ b/ui/motif/container.h Fri Oct 31 10:12:27 2025 +0100 @@ -156,6 +156,10 @@ Widget ui_grid_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n); void ui_grid_container_add(UiContainerPrivate *ctn, Widget widget); +UiContainerX* ui_frame_container(UiObject *obj, Widget frame); +Widget ui_frame_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n); +void ui_frame_container_add(UiContainerPrivate *ctn, Widget widget); + #ifdef __cplusplus } #endif