diff -r b9767cb5b06b -r d2bd73d28ff1 ui/cocoa/container.m --- a/ui/cocoa/container.m Fri Nov 29 22:21:36 2024 +0100 +++ b/ui/cocoa/container.m Thu Dec 12 20:01:43 2024 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2014 Olaf Wintermann. All rights reserved. + * 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: @@ -26,81 +26,143 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#import -#import +#import "Container.h" +#import "GridLayout.h" + +/* ------------------------- container classes ------------------------- */ -#import "container.h" +@implementation BoxContainer +@synthesize label=_label; +@synthesize uilayout=_uilayout; +@synthesize newline=_newline; -UiContainer* ui_window_container(UiObject *obj, NSWindow *window) { - UiContainer *ct = ucx_mempool_malloc( - obj->ctx->mempool, - sizeof(UiContainer)); - ct->widget = [window contentView]; - ct->add = ui_container_add; - ct->getframe = ui_container_getframe; - return ct; +- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing { + self = [super init]; + _label = NULL; + _uilayout = (UiLayout){ 0 }; + _newline = false; + + self.distribution = NSStackViewDistributionFillProportionally; + self.spacing = spacing; + + self.orientation = orientation; + if(orientation == NSUserInterfaceLayoutOrientationHorizontal) { + self.alignment = NSLayoutAttributeHeight; + } else { + self.alignment = NSLayoutAttributeWidth; + } + + + return self; } -UIWIDGET ui_sidebar(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - NSRect frame = ct->getframe(ct); +- (void) addView:(NSView*)view fill:(BOOL)fill { + if(_uilayout.fill != UI_LAYOUT_UNDEFINED) { + fill = ui_lb2bool(_uilayout.fill); + } - // create and add views - NSSplitView *splitview = [[NSSplitView alloc] initWithFrame:frame]; - [splitview setVertical:YES]; - [splitview setDividerStyle:NSSplitViewDividerStyleThin]; - ct->add(ct, splitview); + [self addArrangedSubview:view]; - NSRect lframe; - lframe.origin.x = 0; - lframe.origin.y = 0; - lframe.size.width = 200; - lframe.size.height = frame.size.height; - - NSRect rframe; - rframe.origin.x = 0; - rframe.origin.y = 0; - rframe.size.width = frame.size.width - 201; - rframe.size.height = frame.size.height; - - NSView *sidebar = [[NSView alloc]initWithFrame:lframe]; - NSView *contentarea = [[NSView alloc]initWithFrame:rframe]; + if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) { + [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES; + if(!fill) { + [view.widthAnchor constraintEqualToConstant:view.intrinsicContentSize.width].active = YES; + } + } else { + [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; + if(!fill) { + [view.heightAnchor constraintEqualToConstant:view.intrinsicContentSize.height].active = YES; + } + } - [splitview addSubview:sidebar]; - [splitview addSubview:contentarea]; + // at the moment, only the fill layout option needs to be reset + _uilayout.fill = UI_DEFAULT; +} + +@end + + + +/* -------------------- public container functions --------------------- */ + +static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, NSUserInterfaceLayoutOrientation orientation) { + BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args.spacing]; + box.translatesAutoresizingMaskIntoConstraints = false; - // add ui objects for the sidebar and contentarea - // the sidebar is added last, so that new views are added first to it - UiObject *left = uic_object_new(obj, sidebar); - UiContainer *ct1 = ucx_mempool_malloc( - obj->ctx->mempool, - sizeof(UiContainer)); - ct1->widget = sidebar; - ct1->add = ui_container_add; - ct1->getframe = ui_container_getframe; - left->container = ct1; + // add box to the parent + UiLayout layout = UI_INIT_LAYOUT(args); + ui_container_add(obj, box, &layout, TRUE); + + // add new box to the obj container chain + uic_object_push_container(obj, ui_create_container(obj, box)); - UiObject *right = uic_object_new(obj, sidebar); - UiContainer *ct2 = ucx_mempool_malloc( - obj->ctx->mempool, - sizeof(UiContainer)); - ct2->widget = contentarea; - ct2->add = ui_container_add; - ct2->getframe = ui_container_getframe; - right->container = ct2; + return (__bridge void*)box; +} + +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { + return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationVertical); +} + +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { + return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationHorizontal); +} + +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { + GridLayout *grid = [[GridLayout alloc] init]; + grid.translatesAutoresizingMaskIntoConstraints = false; - uic_obj_add(obj, right); - uic_obj_add(obj, left); + // add box to the parent + UiLayout layout = UI_INIT_LAYOUT(args); + ui_container_add(obj, grid, &layout, TRUE); - return splitview; + // add new box to the obj container chain + uic_object_push_container(obj, ui_create_container(obj, grid)); + + return (__bridge void*)grid; } -NSRect ui_container_getframe(UiContainer *ct) { - return [ct->widget frame]; +void ui_container_begin_close(UiObject *obj) { + UiContainerX *ct = obj->container_end; + ct->close = 1; +} + +int ui_container_finish(UiObject *obj) { + UiContainerX *ct = obj->container_end; + if(ct->close) { + ui_end_new(obj); + return 0; + } + return 1; } -void ui_container_add(UiContainer *ct, NSView *view) { - [ct->widget addSubview: view]; +/* ------------------------- private functions ------------------------- */ + +UiContainerX* ui_create_container(UiObject *obj, id container) { + UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX)); + ctn->container = (__bridge void*)container; + ctn->close = 0; + ctn->prev = NULL; + ctn->next = NULL; + return ctn; } + +void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout, UiBool fill) { + UiContainerX *ctn = obj->container_end; + id container = (__bridge id)ctn->container; + container.uilayout = *layout; + [container addView:view fill:fill]; +} + +/* ---------------------- public layout functions ----------------------- */ + +void ui_newline(UiObject *obj) { + UiContainerX *ctn = obj->container_end; + if(ctn) { + id container = (__bridge id)ctn->container; + container.newline = TRUE; + } else { + fprintf(stderr, "Error: obj has no container\n"); + } +}