Tue, 14 Oct 2025 09:45:44 +0200
add frame container (Cocoa)
/* * 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" #import "BoxContainer.h" /* -------------------- 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; UiContainerX *container = ui_create_container(obj, box); box.container = container; // add box to the parent UiLayout layout = UI_INIT_LAYOUT(args); ui_container_add(obj, box, &layout); // add new box to the obj container chain uic_object_push_container(obj, container); 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; grid.columnspacing = args->columnspacing; grid.rowspacing = args->rowspacing; UiContainerX *container = ui_create_container(obj, grid); grid.container = container; // add box to the parent UiLayout layout = UI_INIT_LAYOUT(args); ui_container_add(obj, grid, &layout); // add new box to the obj container chain uic_object_push_container(obj, container); return (__bridge void*)grid; } UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) { NSString *title = args->label ? [[NSString alloc]initWithUTF8String:args->label] : nil; FrameContainer *frame = [[FrameContainer alloc] init:title]; UiLayout layout = UI_ARGS2LAYOUT(args); ui_container_add(obj, frame, &layout); // add container to the chain UiContainerX *container; UiLayout subLayout = {0}; switch(args->subcontainer) { default: { // UI_CONTAINER_NO_SUB container = ui_create_container(obj, frame); break; } case UI_CONTAINER_VBOX: { BoxContainer *box = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationVertical spacing:args->spacing]; box.translatesAutoresizingMaskIntoConstraints = false; [frame addView:box layout:&subLayout]; container = ui_create_container(obj, box); break; } case UI_CONTAINER_HBOX: { BoxContainer *box = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationHorizontal spacing:args->spacing]; box.translatesAutoresizingMaskIntoConstraints = false; [frame addView:box layout:&subLayout]; container = ui_create_container(obj, box); break; } case UI_CONTAINER_GRID: { GridLayout *grid = [[GridLayout alloc] init]; grid.translatesAutoresizingMaskIntoConstraints = false; grid.columnspacing = args->columnspacing; grid.rowspacing = args->rowspacing; [frame addView:grid layout:&subLayout]; container = ui_create_container(obj, grid); break; } } uic_object_push_container(obj, container); return NULL; } 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; } /* -------------------------- Frame Container -------------------------- */ @implementation FrameContainer @synthesize container = _container; - (id)init:(NSString*)title { self = [super init]; self.title = title; self.boxType = NSBoxPrimary; if(title != nil) { self.titlePosition = NSAtTop; } return self; } - (void) addView:(NSView*)view layout:(UiLayout*)layout { [self.contentView addSubview:view]; view.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [view.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0], [view.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:0], [view.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-0], [view.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-0] ]]; } @end /* ------------------------- private functions ------------------------- */ UiContainerX* ui_create_container(UiObject *obj, id<Container> container) { UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX)); ctn->container = (__bridge void*)container; ctn->close = 0; ctn->prev = NULL; ctn->next = NULL; container.container = ctn; return ctn; } void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout) { UiContainerX *ctn = obj->container_end; id<Container> container = (__bridge id<Container>)ctn->container; UiLayout adjustedLayout = *layout; if(adjustedLayout.margin > 0) { adjustedLayout.margin_left = adjustedLayout.margin; adjustedLayout.margin_right = adjustedLayout.margin; adjustedLayout.margin_top = adjustedLayout.margin; adjustedLayout.margin_bottom = adjustedLayout.margin; } [container addView:view layout:layout]; }