--- a/ui/gtk/container.c Thu Oct 02 14:49:17 2025 +0200 +++ b/ui/gtk/container.c Thu Oct 02 14:49:27 2025 +0200 @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <limits.h> #include "container.h" @@ -37,6 +38,8 @@ #include "../common/context.h" #include "../common/object.h" +#include "../ui/properties.h" + void ui_container_begin_close(UiObject *obj) { UiContainer *ct = uic_get_current_container(obj); @@ -1050,6 +1053,34 @@ } #endif +/* ------------------------ Split Window Panels ------------------------ */ + +static UIWIDGET splitwindow_panel(UiObject *obj, GtkWidget *pbox, UiSidebarArgs *args) { + if(!pbox) { + fprintf(stderr, "Error: window is not a splitview window\n"); + return NULL; + } + + GtkWidget *box = ui_gtk_vbox_new(args->spacing); + ui_box_set_margin(box, args->margin); + BOX_ADD_EXPAND(pbox, box); + + UiObject *newobj = uic_object_new(obj, box); + newobj->container = ui_box_container(obj, box, UI_CONTAINER_VBOX); + uic_obj_add(obj, newobj); + + return box; +} + +UIWIDGET ui_left_panel_create(UiObject *obj, UiSidebarArgs *args) { + return splitwindow_panel(obj, g_object_get_data(G_OBJECT(obj->widget), "ui_left_panel"), args); +} + +UIWIDGET ui_right_panel_create(UiObject *obj, UiSidebarArgs *args) { + return splitwindow_panel(obj, g_object_get_data(G_OBJECT(obj->widget), "ui_right_panel"), args); +} + + /* -------------------- Splitpane -------------------- */ static GtkWidget* create_paned(UiOrientation orientation) { @@ -1067,7 +1098,13 @@ return NULL; } - +static void save_pane_pos(GtkWidget *widget, char *property_name) { + int pos = gtk_paned_get_position(GTK_PANED(widget)); + char buf[32]; + snprintf(buf, 32, "%d", pos); + ui_set_property(property_name, buf); + free(property_name); +} static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs *args) { UiObject* current = uic_current_obj(obj); @@ -1079,12 +1116,40 @@ int max = args->max_panes == 0 ? 2 : args->max_panes; + if(args->position_property) { + const char *pos_str = ui_get_property(args->position_property); + if(pos_str) { + char *end; + long pos = strtol(pos_str, &end, 10); + if(*end == '\0') { + args->initial_position = (int)pos; + } + } + + g_signal_connect( + pane0, + "destroy", + G_CALLBACK(save_pane_pos), + strdup(args->position_property)); + } + UiObject *newobj = uic_object_new(obj, pane0); newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args->initial_position); uic_obj_add(obj, newobj); g_object_set_data(G_OBJECT(pane0), "ui_splitpane", newobj->container); + UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); + if(var) { + UiSplitPaneContainer *s = (UiSplitPaneContainer*)newobj->container; + UiInteger *i = var->value; + s->initial_position = i->value; + + i->obj = s; + i->get = ui_splitpane_get; + i->set = ui_splitpane_set; + } + return pane0; } @@ -1140,6 +1205,18 @@ } } +int64_t ui_splitpane_get(UiInteger *i) { + UiSplitPaneContainer *s = i->obj; + i->value = gtk_paned_get_position(GTK_PANED(s->container.widget)); + return i->value; +} + +void ui_splitpane_set(UiInteger *i, int64_t value) { + UiSplitPaneContainer *s = i->obj; + i->value = value; + gtk_paned_set_position(GTK_PANED(s->container.widget), (int)value); +} + UIEXPORT void ui_splitpane_set_visible(UIWIDGET splitpane, int child_index, UiBool visible) { UiSplitPaneContainer *ct = g_object_get_data(G_OBJECT(splitpane), "ui_splitpane"); if(!ct) {