create new BoxContainer based on GridLayout

Thu, 02 Oct 2025 14:49:17 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 02 Oct 2025 14:49:17 +0200
changeset 785
b943e3d618f0
parent 784
2fded9495930
child 786
150a1180f7ec

create new BoxContainer based on GridLayout

make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/main.m file | annotate | diff | comparison | revisions
ui/cocoa/BoxContainer.h file | annotate | diff | comparison | revisions
ui/cocoa/BoxContainer.m file | annotate | diff | comparison | revisions
ui/cocoa/GridLayout.h file | annotate | diff | comparison | revisions
ui/cocoa/GridLayout.m file | annotate | diff | comparison | revisions
ui/cocoa/MainWindow.m file | annotate | diff | comparison | revisions
ui/cocoa/container.h file | annotate | diff | comparison | revisions
ui/cocoa/container.m file | annotate | diff | comparison | revisions
--- a/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj	Thu Oct 02 13:15:21 2025 +0200
+++ b/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj	Thu Oct 02 14:49:17 2025 +0200
@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		ED18C9232E76CA5500B64EA5 /* entry.m in Sources */ = {isa = PBXBuildFile; fileRef = ED18C9222E76CA5500B64EA5 /* entry.m */; };
 		ED2F55AE2E34FAD800A84793 /* Toolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = ED2F55AD2E34FAD800A84793 /* Toolbar.m */; };
 		ED52BFB02D86FC5D00FD8BE5 /* text.m in Sources */ = {isa = PBXBuildFile; fileRef = ED52BFAF2D86FC5D00FD8BE5 /* text.m */; };
 		ED6580EE2CFF19F900F5402F /* context.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580DD2CFF19F900F5402F /* context.c */; };
@@ -45,6 +46,7 @@
 		ED65815F2CFF4BF200F5402F /* WindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65815E2CFF4BF200F5402F /* WindowManager.m */; };
 		ED679B0A2E5B266C001D4F71 /* label.m in Sources */ = {isa = PBXBuildFile; fileRef = ED679B092E5B266C001D4F71 /* label.m */; };
 		ED679B0D2E5B2FB0001D4F71 /* UiThread.m in Sources */ = {isa = PBXBuildFile; fileRef = ED679B0C2E5B2FB0001D4F71 /* UiThread.m */; };
+		ED83C2BF2E8EA49200054B22 /* BoxContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = ED83C2BE2E8EA49200054B22 /* BoxContainer.m */; };
 		ED8687E52D999CF3002F3EC2 /* menu.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8687E42D999CF3002F3EC2 /* menu.m */; };
 		ED99F04A2E5CBD2E00A4CC97 /* widget.m in Sources */ = {isa = PBXBuildFile; fileRef = ED99F0492E5CBD2E00A4CC97 /* widget.m */; };
 		EDB452C32E302C65006FB12D /* image.m in Sources */ = {isa = PBXBuildFile; fileRef = EDB452C22E302C65006FB12D /* image.m */; };
@@ -54,6 +56,8 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		ED18C9212E76CA5500B64EA5 /* entry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = entry.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/entry.h; sourceTree = "<absolute>"; };
+		ED18C9222E76CA5500B64EA5 /* entry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = entry.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/entry.m; sourceTree = "<absolute>"; };
 		ED2F55AC2E34FAD800A84793 /* Toolbar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Toolbar.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Toolbar.h; sourceTree = "<absolute>"; };
 		ED2F55AD2E34FAD800A84793 /* Toolbar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Toolbar.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Toolbar.m; sourceTree = "<absolute>"; };
 		ED52BFAE2D86FC5D00FD8BE5 /* text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = text.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/text.h; sourceTree = "<absolute>"; };
@@ -152,6 +156,8 @@
 		ED679B092E5B266C001D4F71 /* label.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = label.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/label.m; sourceTree = "<absolute>"; };
 		ED679B0B2E5B2FB0001D4F71 /* UiThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UiThread.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiThread.h; sourceTree = "<absolute>"; };
 		ED679B0C2E5B2FB0001D4F71 /* UiThread.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UiThread.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiThread.m; sourceTree = "<absolute>"; };
+		ED83C2BD2E8EA49200054B22 /* BoxContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BoxContainer.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/BoxContainer.h; sourceTree = "<absolute>"; };
+		ED83C2BE2E8EA49200054B22 /* BoxContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BoxContainer.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/BoxContainer.m; sourceTree = "<absolute>"; };
 		ED8687E32D999CF3002F3EC2 /* menu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = menu.h; path = ../../../ui/cocoa/menu.h; sourceTree = SOURCE_ROOT; };
 		ED8687E42D999CF3002F3EC2 /* menu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = menu.m; path = ../../../ui/cocoa/menu.m; sourceTree = SOURCE_ROOT; };
 		ED99F0482E5CBD2E00A4CC97 /* widget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = widget.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/widget.h; sourceTree = "<absolute>"; };
@@ -286,6 +292,10 @@
 		ED65812E2CFF1A7200F5402F /* cocoa */ = {
 			isa = PBXGroup;
 			children = (
+				ED83C2BD2E8EA49200054B22 /* BoxContainer.h */,
+				ED83C2BE2E8EA49200054B22 /* BoxContainer.m */,
+				ED18C9212E76CA5500B64EA5 /* entry.h */,
+				ED18C9222E76CA5500B64EA5 /* entry.m */,
 				ED99F0482E5CBD2E00A4CC97 /* widget.h */,
 				ED99F0492E5CBD2E00A4CC97 /* widget.m */,
 				ED679B0B2E5B2FB0001D4F71 /* UiThread.h */,
@@ -447,6 +457,7 @@
 				ED6581222CFF1A3000F5402F /* hash_map.c in Sources */,
 				ED6581232CFF1A3000F5402F /* array_list.c in Sources */,
 				ED6581242CFF1A3000F5402F /* list.c in Sources */,
+				ED18C9232E76CA5500B64EA5 /* entry.m in Sources */,
 				ED65815C2CFF3EE900F5402F /* MainWindow.m in Sources */,
 				ED99F04A2E5CBD2E00A4CC97 /* widget.m in Sources */,
 				ED6581252CFF1A3000F5402F /* compare.c in Sources */,
@@ -470,6 +481,7 @@
 				ED6580F52CFF19F900F5402F /* types.c in Sources */,
 				ED8687E52D999CF3002F3EC2 /* menu.m in Sources */,
 				ED6580F62CFF19F900F5402F /* properties.c in Sources */,
+				ED83C2BF2E8EA49200054B22 /* BoxContainer.m in Sources */,
 				EDCD22382E5A160A000612AF /* ListDelegate.m in Sources */,
 				ED6580F72CFF19F900F5402F /* ucx_properties.c in Sources */,
 			);
--- a/make/xcode/toolkit/toolkit/main.m	Thu Oct 02 13:15:21 2025 +0200
+++ b/make/xcode/toolkit/toolkit/main.m	Thu Oct 02 14:49:17 2025 +0200
@@ -93,23 +93,105 @@
 }
 
 void application_startup(UiEvent *event, void *data) {
-    UiObject *obj = ui_sidebar_window("My Window", NULL);
+    UiObject *obj = ui_window("My Window", NULL);
     //WindowData *wdata = ui_malloc(obj->ctx, sizeof(WindowData));
     //wdata->tbtoggle = ui_int_new(obj->ctx, "tbtoggle");
     //obj->window = wdata;
     MyDocument *doc = create_doc();
     ui_attach_document(obj->ctx, doc);
     
+    /*
     ui_sidebar(obj) {
         ui_button(obj, .label = "Sidebar Button");
         ui_textarea(obj, .varname = "todo: fix layout", .fill = TRUE);
     }
+    */
+    //ui_button(obj, .label = "Button 1");
+    //ui_button(obj, .label = "Button 2");
+    
+    /*
+    ui_grid(obj, .spacing = 0) {
+        ui_button(obj, .label = "HBox Button 1", .hfill = TRUE);
+        ui_button(obj, .label = "HBox Button 2", .hexpand = TRUE, .hfill = TRUE);
+        ui_button(obj, .label = "HBox Button 3", .hfill = TRUE);
+        ui_newline(obj);
+        ui_grid(obj, .spacing = 0, .colspan = 3) {
+            ui_button(obj, .label = "V1 Button 1");
+            ui_newline(obj);
+            ui_textarea(obj, .varname = "text1", .vexpand = TRUE, .vfill = TRUE);
+            ui_newline(obj);
+            ui_button(obj, .label = "V1 Button 3");
+        }
+        ui_newline(obj);
+        ui_button(obj, .label = "HBox 2 Button 1", .hfill = TRUE);
+        ui_button(obj, .label = "HBox 2 Button 2", .hfill = TRUE);
+        ui_button(obj, .label = "HBox 2 Button 3");
+    }
+    //*/
+    
+    ui_button(obj, .label = "HBox Button 1");
+    ui_button(obj, .label = "HBox Button 2");
+    ui_grid(obj, .fill = TRUE) {
+        ui_hbox(obj, .spacing = 0, .colspan = 2) {
+            ui_button(obj, .label = "HBox Button 1");
+            ui_button(obj, .label = "HBox Button 2");
+            ui_button(obj, .label = "HBox Button 3");
+        }
+        ui_newline(obj);
+        
+        ui_vbox(obj, .spacing = 0) {
+            ui_button(obj, .label = "VBox Button 1");
+            ui_button(obj, .label = "VBox Button 2");
+            ui_button(obj, .label = "VBox Button 3");
+        }
+        ui_textarea(obj, .fill = TRUE);
+    }
+    ui_button(obj, .label = "HBox Button 3");
+    
+    /*
+    ui_grid(obj, .spacing = 0, .fill = TRUE) {
+        ui_button(obj, .label = "HBox Button 1", .hfill = TRUE);
+        ui_button(obj, .label = "HBox Button 2", .hexpand = TRUE, .hfill = TRUE);
+        ui_button(obj, .label = "HBox Button 3", .hfill = TRUE);
+        ui_newline(obj);
+        ui_grid(obj, .spacing = 0, .fill = TRUE, .colspan = 3) {
+            ui_button(obj, .label = "V1 Button 1");
+            ui_newline(obj);
+            ui_textarea(obj, .varname = "text2", .hfill = TRUE, .vfill = TRUE, .hexpand = TRUE, .vexpand = TRUE);
+        }
+    }
+    */
+    
+    //ui_button(obj, .label = "Button 3");
+    /*
+    ui_button(obj, .label = "Button 1", .hexpand = TRUE,  .hfill = TRUE);
+    ui_newline(obj);
+    
+    ui_grid(obj, .margin = 10, .hexpand = TRUE, .hfill = TRUE) {
+        ui_button(obj, .label = "H1");
+        ui_button(obj, .label = "H2 Ext", .hexpand = TRUE, .hfill = TRUE);
+        ui_button(obj, .label = "H3");
+    }
+    ui_newline(obj);
+    
+    ui_grid(obj, .fill = TRUE) {
+        ui_button(obj, .label = "B1");
+        ui_newline(obj);
+        
+    }
+    ui_newline(obj);
+    
+    ui_button(obj, .label = "Button 2", .hexpand = TRUE, .hfill = TRUE);
+    ui_newline(obj);
+    */
+    
     
     UiModel *model = ui_model(obj->ctx, UI_STRING, "Column 0", UI_STRING, "Column 1", UI_STRING, "Column 2", -1);
     model->columnsize[1] = -1;
-    ui_grid(obj, .columnspacing = 10, .rowspacing = 10) {
-        ui_table(obj, .fill = UI_ON, .varname = "list1", .model = model, .getvalue = table_getvalue, .onactivate = action_list_activate, .onselection = action_list_selection, .multiselection = TRUE);
-    }
+    //ui_grid(obj, .columnspacing = 10, .rowspacing = 10) {
+        //ui_table(obj, .fill = UI_ON, .varname = "list1", .model = model, .getvalue = table_getvalue, .onactivate = action_list_activate, .onselection = action_list_selection, .multiselection = TRUE);
+        
+    //}
     
     /*
     UiModel *model = ui_model(obj->ctx, UI_STRING, "Column 0", UI_STRING, "Column 1", UI_STRING, "Column 2", -1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/BoxContainer.h	Thu Oct 02 14:49:17 2025 +0200
@@ -0,0 +1,39 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "Container.h"
+#import "GridLayout.h"
+
+@interface BoxContainer : GridLayout
+
+@property NSUserInterfaceLayoutOrientation orientation;
+
+- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing;
+
+@end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/BoxContainer.m	Thu Oct 02 14:49:17 2025 +0200
@@ -0,0 +1,33 @@
+
+
+#import "BoxContainer.h"
+
+@implementation BoxContainer
+
+- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing {
+    self = [super init];
+    _orientation = orientation;
+    self.columnspacing = spacing;
+    self.rowspacing = spacing;
+    
+    return self;
+}
+
+- (void) addView:(NSView*)view {
+    UiLayout layout = self.uilayout;
+    if(_orientation == NSUserInterfaceLayoutOrientationVertical) {
+        layout.hexpand = TRUE;
+        layout.hfill = TRUE;
+    } else {
+        layout.vexpand = TRUE;
+        layout.vfill = TRUE;
+        self.newline = FALSE;
+    }
+    self.uilayout = layout;
+    [super addView:view];
+    if(_orientation == NSUserInterfaceLayoutOrientationVertical) {
+        self.newline = TRUE;
+    }
+}
+
+@end
--- a/ui/cocoa/GridLayout.h	Thu Oct 02 13:15:21 2025 +0200
+++ b/ui/cocoa/GridLayout.h	Thu Oct 02 14:49:17 2025 +0200
@@ -61,8 +61,6 @@
 @property CxList *children;
 @property NSSize preferredSize;
 
-@property NSButton *test;
-
 @property int x;
 @property int y;
 @property int cols;
--- a/ui/cocoa/GridLayout.m	Thu Oct 02 13:15:21 2025 +0200
+++ b/ui/cocoa/GridLayout.m	Thu Oct 02 14:49:17 2025 +0200
@@ -41,6 +41,8 @@
     _columnspacing = 0;
     _rowspacing = 0;
     _children = cxArrayListCreateSimple(sizeof(GridElm), 32);
+    _preferredSize.width = -1;
+    _preferredSize.height = -1;
     
     return self;
 }
@@ -80,12 +82,6 @@
             
             NSSize size = elm->view.intrinsicContentSize;
             NSSize size2 = elm->view.fittingSize;
-            NSEdgeInsets alignment = elm->view.alignmentRectInsets;
-            // TODO: remove alignment
-            alignment.left = 0;
-            alignment.right = 0;
-            alignment.top = 0;
-            alignment.bottom = 0;
             if(size.width == NSViewNoIntrinsicMetric) {
                 size.width = size2.width;
             }
@@ -93,14 +89,14 @@
                 size.height = size2.height;
             }
             if(size.width != NSViewNoIntrinsicMetric) {
-                CGFloat width = size.width + alignment.left + alignment.right;
+                CGFloat width = size.width;
                 if(width > cols[elm->x].preferred_size && elm->colspan <= 1 && span_max == 1) {
                     cols[elm->x].preferred_size = width;
                 }
                 elm->preferred_width = width;
             }
             if(size.height != NSViewNoIntrinsicMetric) {
-                CGFloat height = size.height + alignment.top + alignment.right;
+                CGFloat height = size.height;
                 //CGFloat height = size.height;
                 if(height > rows[elm->y].preferred_size && elm->rowspan <= 1 && span_max == 1) {
                     rows[elm->y].preferred_size = height;
@@ -290,10 +286,16 @@
  
 
 - (NSSize)intrinsicContentSize {
+    if(_preferredSize.width == -1) {
+        [self layout];
+    }
     return self.preferredSize;
 }
 
 - (void) addView:(NSView*)view {
+    _preferredSize.width = -1;
+    _preferredSize.height = -1;
+    
     if(_newline) {
         _y++;
         _x = 0;
--- a/ui/cocoa/MainWindow.m	Thu Oct 02 13:15:21 2025 +0200
+++ b/ui/cocoa/MainWindow.m	Thu Oct 02 14:49:17 2025 +0200
@@ -29,6 +29,7 @@
 #import "MainWindow.h"
 #import "Container.h"
 #import "GridLayout.h"
+#import "BoxContainer.h"
 #import "../common/object.h"
 #import <objc/runtime.h>
 
@@ -93,7 +94,7 @@
         [vbox.topAnchor constraintEqualToAnchor:content.topAnchor constant:top],
         [vbox.leadingAnchor constraintEqualToAnchor:content.leadingAnchor],
         [vbox.trailingAnchor constraintEqualToAnchor:content.trailingAnchor],
-        [vbox.bottomAnchor constraintEqualToAnchor:content.bottomAnchor]
+        [vbox.bottomAnchor constraintEqualToAnchor:content.bottomAnchor],
     ]];
     uic_object_push_container(obj, ui_create_container(obj, vbox));
     
--- a/ui/cocoa/container.h	Thu Oct 02 13:15:21 2025 +0200
+++ b/ui/cocoa/container.h	Thu Oct 02 14:49:17 2025 +0200
@@ -75,14 +75,6 @@
 
 @end
 
-@interface BoxContainer : NSStackView<Container>
-
-- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing;
-
-@end
-
-
-
 
 
 UiContainerX* ui_create_container(UiObject *obj, id<Container> container);
--- a/ui/cocoa/container.m	Thu Oct 02 13:15:21 2025 +0200
+++ b/ui/cocoa/container.m	Thu Oct 02 14:49:17 2025 +0200
@@ -28,9 +28,11 @@
 
 #import "Container.h"
 #import "GridLayout.h"
+#import "BoxContainer.h"
 
 /* ------------------------- container classes ------------------------- */
 
+/*
 @implementation BoxContainer
 
 @synthesize label=_label;
@@ -88,7 +90,7 @@
 }
 
 @end
-
+*/
 
 
 /* -------------------- public container functions --------------------- */

mercurial