ui/gtk/container.c

changeset 102
64ded9f6a6c6
parent 101
7b3a3130be44
--- a/ui/gtk/container.c	Mon Jan 06 22:22:55 2025 +0100
+++ b/ui/gtk/container.c	Tue Feb 25 21:11:00 2025 +0100
@@ -52,6 +52,17 @@
     return 1;
 }
 
+UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    UIWIDGET widget = create_widget(obj, args, userdata);
+    
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, widget, FALSE);
+    
+    return widget;
+}
+
 GtkWidget* ui_gtk_vbox_new(int spacing) {
 #if GTK_MAJOR_VERSION >= 3
     return gtk_box_new(GTK_ORIENTATION_VERTICAL, spacing);
@@ -96,7 +107,7 @@
         case UI_CONTAINER_GRID: {
             sub = ui_create_grid_widget(columnspacing, rowspacing);
             add = ui_box_set_margin(sub, margin);
-            newobj->container = ui_grid_container(newobj, sub);
+            newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
             newobj->widget = sub;
             break;
         }
@@ -156,11 +167,22 @@
     ct->current = widget;
 }
 
-UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid) {
+UiContainer* ui_grid_container(
+        UiObject *obj,
+        GtkWidget *grid,
+        UiBool def_hexpand,
+        UiBool def_vexpand,
+        UiBool def_hfill,
+        UiBool def_vfill)
+{
     UiGridContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiGridContainer));
+    ct->def_hexpand = def_hexpand;
+    ct->def_vexpand = def_vexpand;
+    ct->def_hfill = def_hfill;
+    ct->def_vfill = def_vfill;
     ct->container.widget = grid;
     ct->container.add = ui_grid_container_add;
     UI_GTK_V2(ct->width = 0);
@@ -182,15 +204,34 @@
     int vexpand = FALSE;
     int hfill = FALSE;
     int vfill = FALSE;
+    if(!ct->layout.override_defaults) {
+        if(grid->def_hexpand) {
+            hexpand = TRUE;
+            hfill = TRUE;
+        } else if(grid->def_hfill) {
+            hfill = TRUE;
+        }
+        if(grid->def_vexpand) {
+            vexpand = TRUE;
+            vfill = TRUE;
+        } else if(grid->def_vfill) {
+            vfill = TRUE;
+        }
+    }
+    
     if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
         fill = ui_lb2bool(ct->layout.fill);
     }
-    if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) {
-        hexpand = ct->layout.hexpand;
+    if(ct->layout.hexpand) {
+        hexpand = TRUE;
+        hfill = TRUE;
+    } else if(ct->layout.hfill) {
         hfill = TRUE;
     }
-    if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) {
-        vexpand = ct->layout.vexpand;
+    if(ct->layout.vexpand) {
+        vexpand = TRUE;
+        vfill = TRUE;
+    } else if(ct->layout.vfill) {
         vfill = TRUE;
     }
     if(fill) {
@@ -230,14 +271,57 @@
     
     int hexpand = FALSE;
     int vexpand = FALSE;
-    if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) {
-        hexpand = ct->layout.hexpand;
+    int hfill = FALSE;
+    int vfill = FALSE;
+    if(!ct->layout.override_defaults) {
+        if(grid->def_hexpand) {
+            hexpand = TRUE;
+            hfill = TRUE;
+        } else if(grid->def_hfill) {
+            hfill = TRUE;
+        }
+        if(grid->def_vexpand) {
+            vexpand = TRUE;
+            vfill = TRUE;
+        } else if(grid->def_vfill) {
+            vfill = TRUE;
+        }
+    }
+    
+    if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
+        fill = ui_lb2bool(ct->layout.fill);
+    }
+    if(ct->layout.hexpand) {
+        hexpand = TRUE;
+        hfill = TRUE;
+    } else if(ct->layout.hfill) {
+        hfill = TRUE;
     }
-    if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) {
-        vexpand = ct->layout.vexpand;
+    if(ct->layout.vexpand) {
+        vexpand = TRUE;
+        vfill = TRUE;
+    } else if(ct->layout.vfill) {
+        vfill = TRUE;
+    }
+    if(fill) {
+        hfill = TRUE;
+        vfill = TRUE;
     }
-    GtkAttachOptions xoptions = hexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL;
-    GtkAttachOptions yoptions = vexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL;
+    
+    GtkAttachOptions xoptions = 0;
+    GtkAttachOptions yoptions = 0;
+    if(hexpand) {
+        xoptions = GTK_EXPAND;
+    }
+    if(hfill) {
+        xoptions |= GTK_FILL;
+    }
+    if(vexpand) {
+        yoptions = GTK_EXPAND;
+    }
+    if(vfill) {
+        yoptions |= GTK_FILL;
+    }
     
     int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1;
     int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1;
@@ -396,7 +480,7 @@
     current->container->add(current->container, widget, TRUE);
     
     UiObject *newobj = uic_object_new(obj, grid);
-    newobj->container = ui_grid_container(obj, grid);
+    newobj->container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill);
     uic_obj_add(obj, newobj);
     
     return widget;
@@ -755,7 +839,7 @@
         }
         case UI_CONTAINER_GRID: {
             sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
-            newobj->container = ui_grid_container(newobj, sub);
+            newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
             break;
         }
     }
@@ -946,6 +1030,68 @@
 
 
 
+static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    GtkWidget *pane0 = create_paned(orientation);
+    
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, pane0, TRUE);
+    
+    int max = args.max_panes == 0 ? 2 : args.max_panes;
+    
+    UiObject *newobj = uic_object_new(obj, pane0);
+    newobj->container = ui_splitpane_container(obj, pane0, orientation, max);
+    uic_obj_add(obj, newobj);
+    
+    return pane0;
+}
+
+UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+    return splitpane_create(obj, UI_HORIZONTAL, args);
+}
+
+UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+    return splitpane_create(obj, UI_VERTICAL, args);
+}
+
+UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max) {
+    UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer));
+    ct->container.widget = pane;
+    ct->container.add = ui_splitpane_container_add;
+    ct->current_pane = pane;
+    ct->orientation = orientation;
+    ct->max = max;
+    return (UiContainer*)ct;
+}
+
+void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+    UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct;
+    
+    if(s->nchildren >= s->max) {
+        fprintf(stderr, "splitpane: maximum number of children reached\n");
+        return;
+    }
+    
+    if(s->pos == 0) {
+        gtk_paned_set_start_child(GTK_PANED(s->current_pane), widget);
+        s->pos++;
+        s->nchildren++;
+    } else {
+        if(s->nchildren+1 == s->max) {
+            gtk_paned_set_end_child(GTK_PANED(s->current_pane), widget);
+        } else {
+            GtkWidget *pane = create_paned(s->orientation);
+            gtk_paned_set_start_child(GTK_PANED(pane), widget);
+            gtk_paned_set_end_child(GTK_PANED(s->current_pane), pane);
+            s->current_pane = pane;
+        }
+        
+        s->pos = 0;
+        s->nchildren++;
+    }
+}
+
 /* -------------------- ItemList Container -------------------- */
 
 static void remove_item(void *data, void *item) {
@@ -997,7 +1143,7 @@
             ui_box_container_add(ct->container, item_obj->widget, FALSE);
         } else {
             // create new widget and object for this list element
-            CxMempool *mp = cxBasicMempoolCreate(256);
+            CxMempool *mp = cxMempoolCreateSimple(256);
             const CxAllocator *a = mp->allocator;
             UiObject *obj = cxCalloc(a, 1, sizeof(UiObject));
             obj->ctx = uic_context(obj, mp);
@@ -1102,6 +1248,11 @@
     ct->layout.vfill = fill;
 }
 
+UIEXPORT void ui_layout_override_defaults(UiObject *obj, UiBool d) {
+    UiContainer *ct = uic_get_current_container(obj);
+    ct->layout.override_defaults = d;
+}
+
 void ui_layout_colspan(UiObject* obj, int cols) {
     UiContainer* ct = uic_get_current_container(obj);
     ct->layout.colspan = cols;

mercurial