# HG changeset patch # User Olaf Wintermann # Date 1759409357 -7200 # Node ID b943e3d618f0444bf2af906fbc1d4fac95224a9f # Parent 2fded949593049f234cee74c3721c19eecc8c754 create new BoxContainer based on GridLayout diff -r 2fded9495930 -r b943e3d618f0 make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj --- 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 = ""; }; + ED18C9222E76CA5500B64EA5 /* entry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = entry.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/entry.m; sourceTree = ""; }; ED2F55AC2E34FAD800A84793 /* Toolbar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Toolbar.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Toolbar.h; sourceTree = ""; }; ED2F55AD2E34FAD800A84793 /* Toolbar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Toolbar.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Toolbar.m; sourceTree = ""; }; ED52BFAE2D86FC5D00FD8BE5 /* text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = text.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/text.h; sourceTree = ""; }; @@ -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 = ""; }; ED679B0B2E5B2FB0001D4F71 /* UiThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UiThread.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiThread.h; sourceTree = ""; }; ED679B0C2E5B2FB0001D4F71 /* UiThread.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UiThread.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiThread.m; sourceTree = ""; }; + ED83C2BD2E8EA49200054B22 /* BoxContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BoxContainer.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/BoxContainer.h; sourceTree = ""; }; + ED83C2BE2E8EA49200054B22 /* BoxContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BoxContainer.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/BoxContainer.m; sourceTree = ""; }; 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 = ""; }; @@ -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 */, ); diff -r 2fded9495930 -r b943e3d618f0 make/xcode/toolkit/toolkit/main.m --- 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); diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/BoxContainer.h --- /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 + diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/BoxContainer.m --- /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 diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/GridLayout.h --- 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; diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/GridLayout.m --- 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; diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/MainWindow.m --- 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 @@ -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)); diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/container.h --- 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 - -- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing; - -@end - - - UiContainerX* ui_create_container(UiObject *obj, id container); diff -r 2fded9495930 -r b943e3d618f0 ui/cocoa/container.m --- 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 --------------------- */