ui/cocoa/container.m

changeset 112
c3f2f16fa4b8
parent 110
c00e968d018b
child 113
dde28a806552
equal deleted inserted replaced
111:81c4f73236a4 112:c3f2f16fa4b8
27 */ 27 */
28 28
29 #import "Container.h" 29 #import "Container.h"
30 #import "GridLayout.h" 30 #import "GridLayout.h"
31 #import "BoxContainer.h" 31 #import "BoxContainer.h"
32 32 #import "TabView.h"
33 /* ------------------------- container classes ------------------------- */
34
35 /*
36 @implementation BoxContainer
37
38 @synthesize label=_label;
39 @synthesize uilayout=_uilayout;
40 @synthesize newline=_newline;
41
42 - (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing {
43 self = [super init];
44 _label = NULL;
45 _uilayout = (UiLayout){ 0 };
46 _newline = false;
47
48 self.distribution = NSStackViewDistributionFillProportionally;
49 self.spacing = spacing;
50
51 self.orientation = orientation;
52 if(orientation == NSUserInterfaceLayoutOrientationHorizontal) {
53 self.alignment = NSLayoutAttributeHeight;
54 } else {
55 self.alignment = NSLayoutAttributeWidth;
56 }
57
58
59 return self;
60 }
61
62 - (void) addView:(NSView*)view {
63 UiBool fill = _uilayout.fill;
64
65 [self addArrangedSubview:view];
66
67 if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) {
68 [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
69 if(!fill) {
70 NSSize isize = view.intrinsicContentSize;
71 [view.widthAnchor constraintEqualToConstant:isize.width].active = YES;
72 }
73 } else {
74 [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
75 if(!fill) {
76 NSSize isize = view.intrinsicContentSize;
77 NSRect frame = view.frame;
78 CGFloat height = isize.height > 0 ? isize.height : frame.size.height;
79 if(height == 0) {
80 printf("debug");
81 }
82 if(height > 0) {
83 [view.heightAnchor constraintEqualToConstant:height].active = YES;
84 }
85 }
86 }
87
88 // at the moment, only the fill layout option needs to be reset
89 _uilayout.fill = UI_DEFAULT;
90 }
91
92 @end
93 */
94
95 33
96 /* -------------------- public container functions --------------------- */ 34 /* -------------------- public container functions --------------------- */
97 35
98 static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, NSUserInterfaceLayoutOrientation orientation) { 36 static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, NSUserInterfaceLayoutOrientation orientation) {
99 BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args->spacing]; 37 BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args->spacing];
100 box.translatesAutoresizingMaskIntoConstraints = false; 38 box.translatesAutoresizingMaskIntoConstraints = false;
39 UiContainerX *container = ui_create_container(obj, box);
101 40
102 // add box to the parent 41 // add box to the parent
103 UiLayout layout = UI_INIT_LAYOUT(args); 42 UiLayout layout = UI_INIT_LAYOUT(args);
104 ui_container_add(obj, box, &layout); 43 ui_container_add(obj, box, &layout);
105 44
106 // add new box to the obj container chain 45 // add new box to the obj container chain
107 uic_object_push_container(obj, ui_create_container(obj, box)); 46 uic_object_push_container(obj, container);
108 47
109 return (__bridge void*)box; 48 return (__bridge void*)box;
110 } 49 }
111 50
112 UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { 51 UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
118 } 57 }
119 58
120 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { 59 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
121 GridLayout *grid = [[GridLayout alloc] init]; 60 GridLayout *grid = [[GridLayout alloc] init];
122 grid.translatesAutoresizingMaskIntoConstraints = false; 61 grid.translatesAutoresizingMaskIntoConstraints = false;
62 grid.columnspacing = args->columnspacing;
63 grid.rowspacing = args->rowspacing;
64 UiContainerX *container = ui_create_container(obj, grid);
65 grid.container = container;
123 66
124 // add box to the parent 67 // add box to the parent
125 UiLayout layout = UI_INIT_LAYOUT(args); 68 UiLayout layout = UI_INIT_LAYOUT(args);
126 ui_container_add(obj, grid, &layout); 69 ui_container_add(obj, grid, &layout);
127 70
128 // add new box to the obj container chain 71 // add new box to the obj container chain
129 uic_object_push_container(obj, ui_create_container(obj, grid)); 72 uic_object_push_container(obj, container);
130 73
131 return (__bridge void*)grid; 74 return (__bridge void*)grid;
132 } 75 }
76
77 UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
78 NSString *title = args->label ? [[NSString alloc]initWithUTF8String:args->label] : nil;
79 FrameContainer *frame = [[FrameContainer alloc] init:title];
80 UiLayout layout = UI_ARGS2LAYOUT(args);
81 ui_container_add(obj, frame, &layout);
82
83 // add container to the chain
84 UiContainerX *container;
85 UiLayout subLayout = {0};
86 switch(args->subcontainer) {
87 default: {
88 // UI_CONTAINER_NO_SUB
89 container = ui_create_container(obj, frame);
90 break;
91 }
92 case UI_CONTAINER_VBOX: {
93 BoxContainer *box = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationVertical spacing:args->spacing];
94 box.translatesAutoresizingMaskIntoConstraints = false;
95 [frame addView:box layout:&subLayout];
96 container = ui_create_container(obj, box);
97 break;
98 }
99 case UI_CONTAINER_HBOX: {
100 BoxContainer *box = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationHorizontal spacing:args->spacing];
101 box.translatesAutoresizingMaskIntoConstraints = false;
102 [frame addView:box layout:&subLayout];
103 container = ui_create_container(obj, box);
104 break;
105 }
106 case UI_CONTAINER_GRID: {
107 GridLayout *grid = [[GridLayout alloc] init];
108 grid.translatesAutoresizingMaskIntoConstraints = false;
109 grid.columnspacing = args->columnspacing;
110 grid.rowspacing = args->rowspacing;
111 [frame addView:grid layout:&subLayout];
112 container = ui_create_container(obj, grid);
113 break;
114 }
115 }
116
117 uic_object_push_container(obj, container);
118
119 return (__bridge void*)frame;
120 }
121
122 UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
123 return ui_frame_create(obj, args); // TODO
124 }
125
126 UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs *args) {
127 int colspacing = args->spacing;
128 int rowspacing = args->spacing;
129 if(args->subcontainer == UI_CONTAINER_GRID) {
130 colspacing = args->columnspacing;
131 rowspacing = args->rowspacing;
132 }
133 ScrollViewContainer *scrollview = [[ScrollViewContainer alloc]init:args->subcontainer columnSpacing:colspacing rowSpacing:rowspacing];
134 scrollview.hasVerticalScroller = YES;
135 scrollview.scrollerStyle = NSScrollerStyleOverlay;
136 scrollview.autohidesScrollers = YES;
137 UiLayout layout = UI_ARGS2LAYOUT(args);
138 ui_container_add(obj, scrollview, &layout);
139
140 UiContainerX *container = ui_create_container(obj, scrollview);
141 uic_object_push_container(obj, container);
142
143 return (__bridge void*)scrollview;
144 }
145
146 UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
147 NSView<TabView, Container> *tabview;
148 switch(args->tabview) {
149 default: tabview = [[UiTopTabView alloc]init:obj args:args]; break;
150 }
151
152 UiLayout layout = UI_ARGS2LAYOUT(args);
153 ui_container_add(obj, tabview, &layout);
154
155 UiContainerX *container = ui_create_container(obj, tabview);
156 uic_object_push_container(obj, container);
157
158 return (__bridge void*)tabview;
159 }
160
161 void ui_tab_create(UiObject *obj, const char* title) {
162 UiContainerX *ctn = obj->container_end;
163 id<TabView> tabview = (__bridge id<TabView>)ctn->container;
164 NSString *s = title ? [[NSString alloc]initWithUTF8String:title] : @"";
165 NSView<Container> *sub = [tabview createTab:-1 title:s];
166
167 UiContainerX *container = ui_create_container(obj, sub);
168 uic_object_push_container(obj, container);
169 }
170
171 void ui_tabview_select(UIWIDGET tabview, int tab) {
172 id<TabView> tabv = (__bridge id<TabView>)tabview;
173 [tabv selectTab:tab];
174 }
175
176 void ui_tabview_remove(UIWIDGET tabview, int tab) {
177 id<TabView> tabv = (__bridge id<TabView>)tabview;
178 [tabv removeTab:tab];
179 }
180
181 UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
182 id<TabView> tabv = (__bridge id<TabView>)tabview;
183 NSString *s = name ? [[NSString alloc]initWithUTF8String:name] : @"";
184 return [tabv addTab:tab_index title:s];
185 }
186
187
188
133 189
134 void ui_container_begin_close(UiObject *obj) { 190 void ui_container_begin_close(UiObject *obj) {
135 UiContainerX *ct = obj->container_end; 191 UiContainerX *ct = obj->container_end;
136 ct->close = 1; 192 ct->close = 1;
137 } 193 }
142 ui_end_new(obj); 198 ui_end_new(obj);
143 return 0; 199 return 0;
144 } 200 }
145 return 1; 201 return 1;
146 } 202 }
203
204 /* -------------------------- Frame Container -------------------------- */
205
206 @implementation FrameContainer
207
208 @synthesize container = _container;
209
210 - (id)init:(NSString*)title {
211 self = [super init];
212 self.title = title;
213 self.boxType = NSBoxPrimary;
214 if(title != nil) {
215 self.titlePosition = NSAtTop;
216 }
217 return self;
218 }
219
220 - (void) addView:(NSView*)view layout:(UiLayout*)layout {
221 [self.contentView addSubview:view];
222 view.translatesAutoresizingMaskIntoConstraints = NO;
223 [NSLayoutConstraint activateConstraints:@[
224 [view.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0],
225 [view.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:0],
226 [view.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-0],
227 [view.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-0]
228 ]];
229 }
230
231 @end
232
233
234 /* -------------------------- Expander Container -------------------------- */
235
236 // TODO
237
238
239 /* ------------------------ ScrollView Container ------------------------ */
240
241 @implementation ScrollViewContainer
242
243 @synthesize container = _container;
244
245 - (id)init:(UiSubContainerType)subContainer columnSpacing:(int)columnSpacing rowSpacing:(int)rowSpacing {
246 self = [super init];
247
248 if(subContainer != UI_CONTAINER_NO_SUB) {
249 GridLayout *child;
250 switch(subContainer) {
251 default:
252 case UI_CONTAINER_VBOX: {
253 child = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationVertical spacing:columnSpacing];
254 break;
255 }
256 case UI_CONTAINER_HBOX: {
257 child = [[BoxContainer alloc]init:NSUserInterfaceLayoutOrientationHorizontal spacing:columnSpacing];
258 break;
259 }
260 case UI_CONTAINER_GRID: {
261 child = [[GridLayout alloc]init];
262 child.columnspacing = columnSpacing;
263 child.rowspacing = rowSpacing;
264 break;
265 }
266 }
267 child.translatesAutoresizingMaskIntoConstraints = NO;
268
269 self.documentView = child;
270 [child.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor].active = YES;
271
272 _child = child;
273 }
274
275
276 return self;
277 }
278
279 - (void) addView:(NSView*)view layout:(UiLayout*)layout {
280 if(_child != nil) {
281 _child.container = self.container; // required, otherwise child has no container and can't access the newline property
282 view.translatesAutoresizingMaskIntoConstraints = NO;
283 [_child addView:view layout:layout];
284 } else {
285 self.documentView = view;
286 [view.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor].active = YES;
287 }
288 }
289
290 @end
147 291
148 /* ------------------------- private functions ------------------------- */ 292 /* ------------------------- private functions ------------------------- */
149 293
150 UiContainerX* ui_create_container(UiObject *obj, id<Container> container) { 294 UiContainerX* ui_create_container(UiObject *obj, id<Container> container) {
151 UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX)); 295 UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX));
152 ctn->container = (__bridge void*)container; 296 ctn->container = (__bridge void*)container;
153 ctn->close = 0; 297 ctn->close = 0;
154 ctn->prev = NULL; 298 ctn->prev = NULL;
155 ctn->next = NULL; 299 ctn->next = NULL;
300 container.container = ctn;
156 return ctn; 301 return ctn;
157 } 302 }
158 303
159 void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout) { 304 void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout) {
160 UiContainerX *ctn = obj->container_end; 305 UiContainerX *ctn = obj->container_end;
161 id<Container> container = (__bridge id<Container>)ctn->container; 306 id<Container> container = (__bridge id<Container>)ctn->container;
162 container.uilayout = *layout; 307 UiLayout adjustedLayout = *layout;
163 [container addView:view]; 308 if(adjustedLayout.margin > 0) {
164 } 309 adjustedLayout.margin_left = adjustedLayout.margin;
165 310 adjustedLayout.margin_right = adjustedLayout.margin;
166 /* ---------------------- public layout functions ----------------------- */ 311 adjustedLayout.margin_top = adjustedLayout.margin;
167 312 adjustedLayout.margin_bottom = adjustedLayout.margin;
168 void ui_newline(UiObject *obj) { 313 }
169 UiContainerX *ctn = obj->container_end; 314 [container addView:view layout:&adjustedLayout];
170 if(ctn) { 315 }
171 id<Container> container = (__bridge id<Container>)ctn->container; 316
172 container.newline = TRUE;
173 } else {
174 fprintf(stderr, "Error: obj has no container\n");
175 }
176 }

mercurial