UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2024 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #import "Container.h" 30 #import "GridLayout.h" 31 32 /* ------------------------- container classes ------------------------- */ 33 34 @implementation BoxContainer 35 36 @synthesize label=_label; 37 @synthesize uilayout=_uilayout; 38 @synthesize newline=_newline; 39 40 - (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing { 41 self = [super init]; 42 _label = NULL; 43 _uilayout = (UiLayout){ 0 }; 44 _newline = false; 45 46 self.distribution = NSStackViewDistributionFillProportionally; 47 self.spacing = spacing; 48 49 self.orientation = orientation; 50 if(orientation == NSUserInterfaceLayoutOrientationHorizontal) { 51 self.alignment = NSLayoutAttributeHeight; 52 } else { 53 self.alignment = NSLayoutAttributeWidth; 54 } 55 56 57 return self; 58 } 59 60 - (void) addView:(NSView*)view fill:(BOOL)fill { 61 if(_uilayout.fill != UI_LAYOUT_UNDEFINED) { 62 fill = ui_lb2bool(_uilayout.fill); 63 } 64 65 [self addArrangedSubview:view]; 66 67 if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) { 68 [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES; 69 if(!fill) { 70 [view.widthAnchor constraintEqualToConstant:view.intrinsicContentSize.width].active = YES; 71 } 72 } else { 73 [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; 74 if(!fill) { 75 [view.heightAnchor constraintEqualToConstant:view.intrinsicContentSize.height].active = YES; 76 } 77 } 78 79 // at the moment, only the fill layout option needs to be reset 80 _uilayout.fill = UI_DEFAULT; 81 } 82 83 @end 84 85 86 87 /* -------------------- public container functions --------------------- */ 88 89 static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, NSUserInterfaceLayoutOrientation orientation) { 90 BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args.spacing]; 91 box.translatesAutoresizingMaskIntoConstraints = false; 92 93 // add box to the parent 94 UiLayout layout = UI_INIT_LAYOUT(args); 95 ui_container_add(obj, box, &layout, TRUE); 96 97 // add new box to the obj container chain 98 uic_object_push_container(obj, ui_create_container(obj, box)); 99 100 return (__bridge void*)box; 101 } 102 103 UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { 104 return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationVertical); 105 } 106 107 UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { 108 return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationHorizontal); 109 } 110 111 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { 112 GridLayout *grid = [[GridLayout alloc] init]; 113 grid.translatesAutoresizingMaskIntoConstraints = false; 114 115 // add box to the parent 116 UiLayout layout = UI_INIT_LAYOUT(args); 117 ui_container_add(obj, grid, &layout, TRUE); 118 119 // add new box to the obj container chain 120 uic_object_push_container(obj, ui_create_container(obj, grid)); 121 122 return (__bridge void*)grid; 123 } 124 125 126 void ui_container_begin_close(UiObject *obj) { 127 UiContainerX *ct = obj->container_end; 128 ct->close = 1; 129 } 130 131 int ui_container_finish(UiObject *obj) { 132 UiContainerX *ct = obj->container_end; 133 if(ct->close) { 134 ui_end_new(obj); 135 return 0; 136 } 137 return 1; 138 } 139 140 /* ------------------------- private functions ------------------------- */ 141 142 UiContainerX* ui_create_container(UiObject *obj, id<Container> container) { 143 UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX)); 144 ctn->container = (__bridge void*)container; 145 ctn->close = 0; 146 ctn->prev = NULL; 147 ctn->next = NULL; 148 return ctn; 149 } 150 151 void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout, UiBool fill) { 152 UiContainerX *ctn = obj->container_end; 153 id<Container> container = (__bridge id<Container>)ctn->container; 154 container.uilayout = *layout; 155 [container addView:view fill:fill]; 156 } 157 158 /* ---------------------- public layout functions ----------------------- */ 159 160 void ui_newline(UiObject *obj) { 161 UiContainerX *ctn = obj->container_end; 162 if(ctn) { 163 id<Container> container = (__bridge id<Container>)ctn->container; 164 container.newline = TRUE; 165 } else { 166 fprintf(stderr, "Error: obj has no container\n"); 167 } 168 } 169