--- a/ui/gtk/container.c Sun Aug 24 15:24:16 2025 +0200 +++ b/ui/gtk/container.c Sat Oct 04 14:52:59 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); @@ -193,14 +196,14 @@ if(!ct->layout.override_defaults) { if(grid->def_hexpand) { hexpand = TRUE; - hfill = TRUE; - } else if(grid->def_hfill) { + } + if(grid->def_hfill) { hfill = TRUE; } if(grid->def_vexpand) { vexpand = TRUE; - vfill = TRUE; - } else if(grid->def_vfill) { + } + if(grid->def_vfill) { vfill = TRUE; } } @@ -208,19 +211,21 @@ UiBool fill = ct->layout.fill; if(ct->layout.hexpand) { hexpand = TRUE; - hfill = TRUE; - } else if(ct->layout.hfill) { + } + if(ct->layout.hfill) { hfill = TRUE; } if(ct->layout.vexpand) { vexpand = TRUE; - vfill = TRUE; - } else if(ct->layout.vfill) { + } + if(ct->layout.vfill) { vfill = TRUE; } if(fill) { hfill = TRUE; vfill = TRUE; + hexpand = TRUE; + vexpand = TRUE; } if(!hfill) { @@ -1048,6 +1053,35 @@ } #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_set_name_and_style(box, args->name, args->style_class); + 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) { @@ -1065,7 +1099,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); @@ -1077,12 +1117,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; } @@ -1138,6 +1206,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) {