nomen-lang 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/System/Buffer.nm +32 -0
- package/core/System/ClassBuffer.nm +24 -0
- package/core/System/Controls/Alert.nm +326 -0
- package/core/System/Controls/App.nm +147 -0
- package/core/System/Controls/Button.nm +119 -1
- package/core/System/Controls/CheckBox.nm +24 -0
- package/core/System/Controls/ColorPicker.nm +307 -0
- package/core/System/Controls/ComboBox.nm +430 -0
- package/core/System/Controls/Container.nm +837 -9
- package/core/System/Controls/Control.nm +443 -0
- package/core/System/Controls/DatePicker.nm +288 -0
- package/core/System/Controls/Form.nm +70 -0
- package/core/System/Controls/GroupBox.nm +267 -0
- package/core/System/Controls/ImageView.nm +311 -0
- package/core/System/Controls/LevelIndicator.nm +305 -0
- package/core/System/Controls/ListView.nm +633 -0
- package/core/System/Controls/Menu.nm +428 -0
- package/core/System/Controls/NumberInput.nm +56 -0
- package/core/System/Controls/OtpInput.nm +50 -0
- package/core/System/Controls/OutlineView.nm +598 -0
- package/core/System/Controls/Pagination.nm +142 -0
- package/core/System/Controls/Popover.nm +296 -0
- package/core/System/Controls/Progress.nm +348 -0
- package/core/System/Controls/Radio.nm +292 -0
- package/core/System/Controls/Scrollable.nm +584 -0
- package/core/System/Controls/SearchField.nm +326 -0
- package/core/System/Controls/SecureField.nm +344 -0
- package/core/System/Controls/Segmented.nm +380 -0
- package/core/System/Controls/Select.nm +340 -0
- package/core/System/Controls/Separator.nm +198 -0
- package/core/System/Controls/Sheet.nm +329 -0
- package/core/System/Controls/Slider.nm +315 -0
- package/core/System/Controls/Spinner.nm +287 -0
- package/core/System/Controls/SplitView.nm +509 -0
- package/core/System/Controls/Stepper.nm +349 -0
- package/core/System/Controls/Switch.nm +259 -0
- package/core/System/Controls/Table.nm +833 -0
- package/core/System/Controls/Tabs.nm +500 -0
- package/core/System/Controls/Text.nm +108 -11
- package/core/System/Controls/TextBox.nm +112 -1
- package/core/System/Controls/TextView.nm +329 -0
- package/core/System/Controls/Toggle.nm +346 -0
- package/core/System/Controls/Toolbar.nm +501 -0
- package/core/System/Controls/Tooltip.nm +76 -0
- package/core/System/Controls/Window.nm +1549 -91
- package/core/System/List.nm +34 -0
- package/core/System/Map.nm +21 -4
- package/core/System/Set.nm +14 -0
- package/dist/index.mjs +2556 -656
- package/package.json +1 -1
|
@@ -94,32 +94,47 @@ func length_val = (LayoutLength len, out int) {
|
|
|
94
94
|
// methods below reference them (free functions aren't forward-inferred).
|
|
95
95
|
|
|
96
96
|
func is_visible = (uint64 handle, out bool) {
|
|
97
|
-
|
|
97
|
+
// The handle-0 guard lives INSIDE every arch block: a Nomen statement
|
|
98
|
+
// around `aarch64_use_c` blocks is rejected (the aarch64 backend replaces
|
|
99
|
+
// the whole body with the raw blocks and would silently drop it).
|
|
98
100
|
```
|
|
99
101
|
#arch: c
|
|
100
102
|
#platform: macos
|
|
103
|
+
if (handle == 0) return true;
|
|
101
104
|
BOOL hidden = ((BOOL(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("isHidden"));
|
|
102
105
|
return !hidden;
|
|
103
106
|
```
|
|
104
107
|
```
|
|
105
108
|
#arch: aarch64_use_c
|
|
106
109
|
#platform: macos
|
|
110
|
+
if (handle == 0) return true;
|
|
107
111
|
BOOL hidden = ((BOOL(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("isHidden"));
|
|
108
112
|
return !hidden;
|
|
109
113
|
```
|
|
110
114
|
```
|
|
111
115
|
#arch: c
|
|
112
116
|
#platform: ios
|
|
117
|
+
if (handle == 0) return true;
|
|
113
118
|
return true;
|
|
114
119
|
```
|
|
115
120
|
```
|
|
116
121
|
#arch: aarch64_use_c
|
|
117
122
|
#platform: ios
|
|
123
|
+
if (handle == 0) return true;
|
|
118
124
|
return true;
|
|
119
125
|
```
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
func apply_frame = (
|
|
128
|
+
func apply_frame = (
|
|
129
|
+
uint64 handle,
|
|
130
|
+
int x,
|
|
131
|
+
int y,
|
|
132
|
+
int w,
|
|
133
|
+
int h,
|
|
134
|
+
int content_w,
|
|
135
|
+
int content_h,
|
|
136
|
+
int flex
|
|
137
|
+
) {
|
|
123
138
|
```
|
|
124
139
|
#arch: c
|
|
125
140
|
#platform: macos
|
|
@@ -129,12 +144,18 @@ func apply_frame = (uint64 handle, int x, int y, int w, int h, int content_w, in
|
|
|
129
144
|
// vertical edge (top=NSViewMinYMargin 8 / bottom=NSViewMaxYMargin 32) to
|
|
130
145
|
// respect the top-left-origin layout instead of AppKit's default
|
|
131
146
|
// bottom-left pin, and let wide controls grow with the content width
|
|
132
|
-
// (NSViewWidthSizable 2).
|
|
133
|
-
//
|
|
147
|
+
// (NSViewWidthSizable 2). A GROW-driven leaf is the exception: it is the
|
|
148
|
+
// layout's flexible region, so it gets the matching sizable bit (see the
|
|
149
|
+
// `flex` argument) and resizes live with the window; every other control's
|
|
150
|
+
// height comes from the layout pass, not the window. AppKit's result
|
|
134
151
|
// matches what layout() computes, so the post-drag relayout only fixes up
|
|
135
152
|
// cells AppKit can't (column reflow for sub-full-width children).
|
|
136
153
|
unsigned long mask = (y * 2 < content_h) ? 8UL : 32UL;
|
|
137
154
|
if (w * 10 >= content_w * 8) mask |= 2UL;
|
|
155
|
+
// flex: 1 = width-flexible (HStack grow), 2 = height-flexible (VStack
|
|
156
|
+
// grow) — the region AppKit resizes live during a window drag.
|
|
157
|
+
if (flex == 1) mask |= 2UL;
|
|
158
|
+
if (flex == 2) mask |= 16UL;
|
|
138
159
|
((void(*)(id, SEL, unsigned long))objc_msgSend)((id)handle, sel_registerName("setAutoresizingMask:"), mask);
|
|
139
160
|
((void(*)(id, SEL, CGRect))objc_msgSend)(
|
|
140
161
|
(id)handle, sel_registerName("setFrame:"),
|
|
@@ -150,12 +171,18 @@ func apply_frame = (uint64 handle, int x, int y, int w, int h, int content_w, in
|
|
|
150
171
|
// vertical edge (top=NSViewMinYMargin 8 / bottom=NSViewMaxYMargin 32) to
|
|
151
172
|
// respect the top-left-origin layout instead of AppKit's default
|
|
152
173
|
// bottom-left pin, and let wide controls grow with the content width
|
|
153
|
-
// (NSViewWidthSizable 2).
|
|
154
|
-
//
|
|
174
|
+
// (NSViewWidthSizable 2). A GROW-driven leaf is the exception: it is the
|
|
175
|
+
// layout's flexible region, so it gets the matching sizable bit (see the
|
|
176
|
+
// `flex` argument) and resizes live with the window; every other control's
|
|
177
|
+
// height comes from the layout pass, not the window. AppKit's result
|
|
155
178
|
// matches what layout() computes, so the post-drag relayout only fixes up
|
|
156
179
|
// cells AppKit can't (column reflow for sub-full-width children).
|
|
157
180
|
unsigned long mask = (y * 2 < content_h) ? 8UL : 32UL;
|
|
158
181
|
if (w * 10 >= content_w * 8) mask |= 2UL;
|
|
182
|
+
// flex: 1 = width-flexible (HStack grow), 2 = height-flexible (VStack
|
|
183
|
+
// grow) — the region AppKit resizes live during a window drag.
|
|
184
|
+
if (flex == 1) mask |= 2UL;
|
|
185
|
+
if (flex == 2) mask |= 16UL;
|
|
159
186
|
((void(*)(id, SEL, unsigned long))objc_msgSend)((id)handle, sel_registerName("setAutoresizingMask:"), mask);
|
|
160
187
|
((void(*)(id, SEL, CGRect))objc_msgSend)(
|
|
161
188
|
(id)handle, sel_registerName("setFrame:"),
|
|
@@ -191,10 +218,18 @@ func apply_frame = (uint64 handle, int x, int y, int w, int h, int content_w, in
|
|
|
191
218
|
// conformance (`Button`/`CheckBox`/`TextBox`), so each leaf's `intrinsic_size`
|
|
192
219
|
// doesn't need its own raw-block FFI.
|
|
193
220
|
pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
194
|
-
|
|
221
|
+
// The handle-0 guard lives INSIDE every arch block: a Nomen statement
|
|
222
|
+
// around `aarch64_use_c` blocks is rejected (the aarch64 backend replaces
|
|
223
|
+
// the whole body with the raw blocks and would silently drop it).
|
|
195
224
|
```
|
|
196
225
|
#arch: c
|
|
197
226
|
#platform: macos
|
|
227
|
+
if (handle == 0) {
|
|
228
|
+
struct _Tuple_int_int r;
|
|
229
|
+
r._0 = 0;
|
|
230
|
+
r._1 = 0;
|
|
231
|
+
return r;
|
|
232
|
+
}
|
|
198
233
|
CGSize sz = ((CGSize(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("intrinsicContentSize"));
|
|
199
234
|
int w = (sz.width < 0 || sz.width > 100000) ? 0 : (int)sz.width;
|
|
200
235
|
int h = (sz.height < 0 || sz.height > 100000) ? 0 : (int)sz.height;
|
|
@@ -206,6 +241,12 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
|
206
241
|
```
|
|
207
242
|
#arch: aarch64_use_c
|
|
208
243
|
#platform: macos
|
|
244
|
+
if (handle == 0) {
|
|
245
|
+
struct _Tuple_int_int r;
|
|
246
|
+
r._0 = 0;
|
|
247
|
+
r._1 = 0;
|
|
248
|
+
return r;
|
|
249
|
+
}
|
|
209
250
|
CGSize sz = ((CGSize(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("intrinsicContentSize"));
|
|
210
251
|
int w = (sz.width < 0 || sz.width > 100000) ? 0 : (int)sz.width;
|
|
211
252
|
int h = (sz.height < 0 || sz.height > 100000) ? 0 : (int)sz.height;
|
|
@@ -217,6 +258,12 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
|
217
258
|
```
|
|
218
259
|
#arch: c
|
|
219
260
|
#platform: ios
|
|
261
|
+
if (handle == 0) {
|
|
262
|
+
struct _Tuple_int_int r;
|
|
263
|
+
r._0 = 0;
|
|
264
|
+
r._1 = 0;
|
|
265
|
+
return r;
|
|
266
|
+
}
|
|
220
267
|
CGSize sz = ((CGSize(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("intrinsicContentSize"));
|
|
221
268
|
int w = (sz.width < 0 || sz.width > 100000) ? 0 : (int)sz.width;
|
|
222
269
|
int h = (sz.height < 0 || sz.height > 100000) ? 0 : (int)sz.height;
|
|
@@ -228,6 +275,12 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
|
228
275
|
```
|
|
229
276
|
#arch: aarch64_use_c
|
|
230
277
|
#platform: ios
|
|
278
|
+
if (handle == 0) {
|
|
279
|
+
struct _Tuple_int_int r;
|
|
280
|
+
r._0 = 0;
|
|
281
|
+
r._1 = 0;
|
|
282
|
+
return r;
|
|
283
|
+
}
|
|
231
284
|
CGSize sz = ((CGSize(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("intrinsicContentSize"));
|
|
232
285
|
int w = (sz.width < 0 || sz.width > 100000) ? 0 : (int)sz.width;
|
|
233
286
|
int h = (sz.height < 0 || sz.height > 100000) ? 0 : (int)sz.height;
|
|
@@ -238,6 +291,60 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
|
238
291
|
```
|
|
239
292
|
}
|
|
240
293
|
|
|
294
|
+
// The NATIVE frame of a control handle as "x,y,w,h" (AppKit's answer, not the
|
|
295
|
+
// layout engine's intent — compare against `Container.fmt_frame` to verify the
|
|
296
|
+
// two agree). Returns "0,0,0,0" for handle 0.
|
|
297
|
+
pub func native_frame = (uint64 handle, out string) {
|
|
298
|
+
// The handle-0 guard lives INSIDE every arch block: a Nomen statement
|
|
299
|
+
// around `aarch64_use_c` blocks is rejected (the aarch64 backend replaces
|
|
300
|
+
// the whole body with the raw blocks and would silently drop it). The
|
|
301
|
+
// string RETURN builds the fat pair itself — the literal's length is 7.
|
|
302
|
+
```
|
|
303
|
+
#arch: c
|
|
304
|
+
#platform: macos
|
|
305
|
+
if (handle == 0) return (nomen_string){ (char*)"0,0,0,0", 7 };
|
|
306
|
+
CGRect r = ((CGRect(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("frame"));
|
|
307
|
+
char buf[96];
|
|
308
|
+
snprintf(buf, sizeof(buf), "%ld,%ld,%ld,%ld",
|
|
309
|
+
(long)r.origin.x, (long)r.origin.y, (long)r.size.width, (long)r.size.height);
|
|
310
|
+
char *dup = strdup(buf);
|
|
311
|
+
return (nomen_string){ dup, (long)strlen(dup) };
|
|
312
|
+
```
|
|
313
|
+
```
|
|
314
|
+
#arch: aarch64_use_c
|
|
315
|
+
#platform: macos
|
|
316
|
+
if (handle == 0) return (nomen_string){ (char*)"0,0,0,0", 7 };
|
|
317
|
+
CGRect r = ((CGRect(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("frame"));
|
|
318
|
+
char buf[96];
|
|
319
|
+
snprintf(buf, sizeof(buf), "%ld,%ld,%ld,%ld",
|
|
320
|
+
(long)r.origin.x, (long)r.origin.y, (long)r.size.width, (long)r.size.height);
|
|
321
|
+
char *dup = strdup(buf);
|
|
322
|
+
return (nomen_string){ dup, (long)strlen(dup) };
|
|
323
|
+
```
|
|
324
|
+
```
|
|
325
|
+
#arch: c
|
|
326
|
+
#platform: ios
|
|
327
|
+
if (handle == 0) return (nomen_string){ (char*)"0,0,0,0", 7 };
|
|
328
|
+
CGRect r = ((CGRect(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("frame"));
|
|
329
|
+
char buf[96];
|
|
330
|
+
snprintf(buf, sizeof(buf), "%ld,%ld,%ld,%ld",
|
|
331
|
+
(long)r.origin.x, (long)r.origin.y, (long)r.size.width, (long)r.size.height);
|
|
332
|
+
char *dup = strdup(buf);
|
|
333
|
+
return (nomen_string){ dup, (long)strlen(dup) };
|
|
334
|
+
```
|
|
335
|
+
```
|
|
336
|
+
#arch: aarch64_use_c
|
|
337
|
+
#platform: ios
|
|
338
|
+
if (handle == 0) return (nomen_string){ (char*)"0,0,0,0", 7 };
|
|
339
|
+
CGRect r = ((CGRect(*)(id, SEL))objc_msgSend)((id)handle, sel_registerName("frame"));
|
|
340
|
+
char buf[96];
|
|
341
|
+
snprintf(buf, sizeof(buf), "%ld,%ld,%ld,%ld",
|
|
342
|
+
(long)r.origin.x, (long)r.origin.y, (long)r.size.width, (long)r.size.height);
|
|
343
|
+
char *dup = strdup(buf);
|
|
344
|
+
return (nomen_string){ dup, (long)strlen(dup) };
|
|
345
|
+
```
|
|
346
|
+
}
|
|
347
|
+
|
|
241
348
|
/**
|
|
242
349
|
* A flexbox-style container that measures and arranges its child controls.
|
|
243
350
|
*
|
|
@@ -251,7 +358,7 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
|
|
|
251
358
|
* so a `Container` can also be driven polymorphically as a `Control` (passed to
|
|
252
359
|
* a `Control`-taking function, stored in a `ClassBuffer<Control>`, etc.).
|
|
253
360
|
**/
|
|
254
|
-
pub mv struct Container
|
|
361
|
+
pub mv struct Container: Control {
|
|
255
362
|
var kinds = Buffer<int>()
|
|
256
363
|
// Per-leaf requested size, stored as a (kind, value) pair per axis. The
|
|
257
364
|
// kind is one of LEN_* (auto/fixed/percent/fill); the value is the pixel
|
|
@@ -292,6 +399,13 @@ pub mv struct Container : Control {
|
|
|
292
399
|
var pry = Buffer<int>()
|
|
293
400
|
var prw = Buffer<int>()
|
|
294
401
|
var prh = Buffer<int>()
|
|
402
|
+
// The constraints each node's cached size was measured under (the
|
|
403
|
+
// measure_node cache gate). A clean node re-uses its cached size only
|
|
404
|
+
// when the constraints are unchanged — otherwise a standalone
|
|
405
|
+
// `measure(bc)` after an external resize answered with the PREVIOUS
|
|
406
|
+
// constraint's width (the page-scroll shrink-per-resize bug).
|
|
407
|
+
var mw = Buffer<int>()
|
|
408
|
+
var mh = Buffer<int>()
|
|
295
409
|
// Dirty-rect list: the node indices (leaves) whose frame changed in the
|
|
296
410
|
// most recent `compute`/`layout`, in the order discovered. `dirty_count`
|
|
297
411
|
// / `dirty_rect` expose it; `apply` repaints only these.
|
|
@@ -331,6 +445,8 @@ pub mv struct Container : Control {
|
|
|
331
445
|
self.pry.grow_int(cap)
|
|
332
446
|
self.prw.grow_int(cap)
|
|
333
447
|
self.prh.grow_int(cap)
|
|
448
|
+
self.mw.grow_int(cap)
|
|
449
|
+
self.mh.grow_int(cap)
|
|
334
450
|
self.dirty_idx.grow_int(cap)
|
|
335
451
|
}
|
|
336
452
|
|
|
@@ -355,6 +471,8 @@ pub mv struct Container : Control {
|
|
|
355
471
|
self.pry.store_int(0, -1)
|
|
356
472
|
self.prw.store_int(0, -1)
|
|
357
473
|
self.prh.store_int(0, -1)
|
|
474
|
+
self.mw.store_int(0, -1)
|
|
475
|
+
self.mh.store_int(0, -1)
|
|
358
476
|
self.root = 0
|
|
359
477
|
self.count = 1
|
|
360
478
|
}
|
|
@@ -432,6 +550,8 @@ pub mv struct Container : Control {
|
|
|
432
550
|
self.pry.store_int(idx, -1)
|
|
433
551
|
self.prw.store_int(idx, -1)
|
|
434
552
|
self.prh.store_int(idx, -1)
|
|
553
|
+
self.mw.store_int(idx, -1)
|
|
554
|
+
self.mh.store_int(idx, -1)
|
|
435
555
|
self.count = self.count + 1
|
|
436
556
|
return idx
|
|
437
557
|
}
|
|
@@ -676,6 +796,84 @@ pub mv struct Container : Control {
|
|
|
676
796
|
self.set_leaf_kind(idx, LEN_INTRINSIC, 0, LEN_INTRINSIC, 0)
|
|
677
797
|
}
|
|
678
798
|
|
|
799
|
+
// Remove the leaf whose native handle matches, deleting its node from the
|
|
800
|
+
// tree: every per-node array is backward-shifted over the slot and parent
|
|
801
|
+
// indices above it are fixed up, so the node vanishes from measure,
|
|
802
|
+
// arrange, hit-test, and apply entirely. Call this BEFORE freeing the
|
|
803
|
+
// control itself (its #destroy, whenever the owner's scope ends) — a
|
|
804
|
+
// freed handle left in the tree would still be measured, hit-tested, and
|
|
805
|
+
// re-framed. The whole tree is marked dirty afterwards so the next
|
|
806
|
+
// layout reflows the rows the removed child leaves behind. Returns true
|
|
807
|
+
// if a matching leaf was found and removed.
|
|
808
|
+
pub func remove_leaf = (ref self, uint64 handle, out bool) {
|
|
809
|
+
var int needle = handle as int
|
|
810
|
+
var removed = false
|
|
811
|
+
var idx = 1
|
|
812
|
+
while idx < self.count; idx += 1 {
|
|
813
|
+
if self.kinds.load_int(idx) == KIND_LEAF {
|
|
814
|
+
if self.handles.load_int(idx) == needle {
|
|
815
|
+
removed = true
|
|
816
|
+
break
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if !removed {
|
|
821
|
+
return false
|
|
822
|
+
}
|
|
823
|
+
// Backward-shift every per-node array over the removed slot. The
|
|
824
|
+
// cached frames (rx..prh) shift along with their nodes, so the tree
|
|
825
|
+
// stays internally consistent — only the structure changed. `idx`
|
|
826
|
+
// holds the removed slot here; remember it for the parent fix-up,
|
|
827
|
+
// then walk the shift destinations with it.
|
|
828
|
+
var int hole = idx
|
|
829
|
+
var int last = self.count - 1
|
|
830
|
+
while idx < last; idx += 1 {
|
|
831
|
+
self.kinds.store_int(idx, self.kinds.load_int(idx + 1))
|
|
832
|
+
self.w_kinds.store_int(idx, self.w_kinds.load_int(idx + 1))
|
|
833
|
+
self.w_vals.store_int(idx, self.w_vals.load_int(idx + 1))
|
|
834
|
+
self.h_kinds.store_int(idx, self.h_kinds.load_int(idx + 1))
|
|
835
|
+
self.h_vals.store_int(idx, self.h_vals.load_int(idx + 1))
|
|
836
|
+
self.gaps.store_int(idx, self.gaps.load_int(idx + 1))
|
|
837
|
+
self.pars.store_int(idx, self.pars.load_int(idx + 1))
|
|
838
|
+
self.spans.store_int(idx, self.spans.load_int(idx + 1))
|
|
839
|
+
self.cols.store_int(idx, self.cols.load_int(idx + 1))
|
|
840
|
+
self.handles.store_int(idx, self.handles.load_int(idx + 1))
|
|
841
|
+
self.pads.store_int(idx, self.pads.load_int(idx + 1))
|
|
842
|
+
self.grows.store_int(idx, self.grows.load_int(idx + 1))
|
|
843
|
+
self.shrinks.store_int(idx, self.shrinks.load_int(idx + 1))
|
|
844
|
+
self.aligns.store_int(idx, self.aligns.load_int(idx + 1))
|
|
845
|
+
self.dirty.store_int(idx, self.dirty.load_int(idx + 1))
|
|
846
|
+
self.measured_count.store_int(idx, self.measured_count.load_int(idx + 1))
|
|
847
|
+
self.rx.store_int(idx, self.rx.load_int(idx + 1))
|
|
848
|
+
self.ry.store_int(idx, self.ry.load_int(idx + 1))
|
|
849
|
+
self.rw.store_int(idx, self.rw.load_int(idx + 1))
|
|
850
|
+
self.rh.store_int(idx, self.rh.load_int(idx + 1))
|
|
851
|
+
self.prx.store_int(idx, self.prx.load_int(idx + 1))
|
|
852
|
+
self.pry.store_int(idx, self.pry.load_int(idx + 1))
|
|
853
|
+
self.prw.store_int(idx, self.prw.load_int(idx + 1))
|
|
854
|
+
self.prh.store_int(idx, self.prh.load_int(idx + 1))
|
|
855
|
+
self.mw.store_int(idx, self.mw.load_int(idx + 1))
|
|
856
|
+
self.mh.store_int(idx, self.mh.load_int(idx + 1))
|
|
857
|
+
}
|
|
858
|
+
self.count = last
|
|
859
|
+
// Fix parent indices that pointed above the removed slot. (A node
|
|
860
|
+
// parented AT the removed slot is impossible — leaves have no
|
|
861
|
+
// children.)
|
|
862
|
+
var k = 1
|
|
863
|
+
while k < self.count; k += 1 {
|
|
864
|
+
if self.pars.load_int(k) > hole + 1 {
|
|
865
|
+
self.pars.store_int(k, self.pars.load_int(k) - 1)
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
// The dirty-rect list holds node indices; the next layout's
|
|
869
|
+
// collect_dirty rebuilds it from scratch, so drop the stale entries.
|
|
870
|
+
self.dirty_n = 0
|
|
871
|
+
// The row structure changed: re-measure everything on the next
|
|
872
|
+
// compute/layout.
|
|
873
|
+
self.mark_dirty(self.root)
|
|
874
|
+
return true
|
|
875
|
+
}
|
|
876
|
+
|
|
679
877
|
// Translate the legacy int (w, h) into a (kind, value) pair: 0 → auto
|
|
680
878
|
// (no intrinsic; fills a bounded axis, stays 0 on an unbounded axis so
|
|
681
879
|
// `grow` decides), non-zero → fixed.
|
|
@@ -824,7 +1022,7 @@ pub mv struct Container : Control {
|
|
|
824
1022
|
// reuse its cached size instead of re-measuring the subtree. The cached
|
|
825
1023
|
// height is already in rh[idx] from the previous pass, so the caller's
|
|
826
1024
|
// `self.rh.load_int(ci)` picks it up without a re-measure.
|
|
827
|
-
if self.dirty.load_int(idx) == 0 {
|
|
1025
|
+
if self.dirty.load_int(idx) == 0 && self.mw.load_int(idx) == max_w && self.mh.load_int(idx) == max_h {
|
|
828
1026
|
var int cached = self.rw.load_int(idx)
|
|
829
1027
|
return cached
|
|
830
1028
|
}
|
|
@@ -879,6 +1077,8 @@ pub mv struct Container : Control {
|
|
|
879
1077
|
if h < min_h { h = min_h }
|
|
880
1078
|
self.rw.store_int(idx, w)
|
|
881
1079
|
self.rh.store_int(idx, h)
|
|
1080
|
+
self.mw.store_int(idx, max_w)
|
|
1081
|
+
self.mh.store_int(idx, max_h)
|
|
882
1082
|
self.dirty.store_int(idx, 0)
|
|
883
1083
|
return w
|
|
884
1084
|
}
|
|
@@ -905,6 +1105,8 @@ pub mv struct Container : Control {
|
|
|
905
1105
|
if max_child_w > max_w { max_child_w = max_w }
|
|
906
1106
|
self.rw.store_int(idx, max_child_w)
|
|
907
1107
|
self.rh.store_int(idx, total_h)
|
|
1108
|
+
self.mw.store_int(idx, max_w)
|
|
1109
|
+
self.mh.store_int(idx, max_h)
|
|
908
1110
|
self.dirty.store_int(idx, 0)
|
|
909
1111
|
return max_child_w
|
|
910
1112
|
}
|
|
@@ -931,6 +1133,8 @@ pub mv struct Container : Control {
|
|
|
931
1133
|
if max_child_h > max_h { max_child_h = max_h }
|
|
932
1134
|
self.rw.store_int(idx, total_w)
|
|
933
1135
|
self.rh.store_int(idx, max_child_h)
|
|
1136
|
+
self.mw.store_int(idx, max_w)
|
|
1137
|
+
self.mh.store_int(idx, max_h)
|
|
934
1138
|
self.dirty.store_int(idx, 0)
|
|
935
1139
|
return total_w
|
|
936
1140
|
}
|
|
@@ -955,6 +1159,8 @@ pub mv struct Container : Control {
|
|
|
955
1159
|
if best_h > max_h { best_h = max_h }
|
|
956
1160
|
self.rw.store_int(idx, best_w)
|
|
957
1161
|
self.rh.store_int(idx, best_h)
|
|
1162
|
+
self.mw.store_int(idx, max_w)
|
|
1163
|
+
self.mh.store_int(idx, max_h)
|
|
958
1164
|
self.dirty.store_int(idx, 0)
|
|
959
1165
|
return best_w
|
|
960
1166
|
}
|
|
@@ -988,6 +1194,8 @@ pub mv struct Container : Control {
|
|
|
988
1194
|
if total_h > max_h { total_h = max_h }
|
|
989
1195
|
self.rw.store_int(idx, total_w)
|
|
990
1196
|
self.rh.store_int(idx, total_h)
|
|
1197
|
+
self.mw.store_int(idx, max_w)
|
|
1198
|
+
self.mh.store_int(idx, max_h)
|
|
991
1199
|
self.dirty.store_int(idx, 0)
|
|
992
1200
|
return total_w
|
|
993
1201
|
}
|
|
@@ -1027,6 +1235,8 @@ pub mv struct Container : Control {
|
|
|
1027
1235
|
if total_h > max_h { total_h = max_h }
|
|
1028
1236
|
self.rw.store_int(idx, cols * col_w)
|
|
1029
1237
|
self.rh.store_int(idx, total_h)
|
|
1238
|
+
self.mw.store_int(idx, max_w)
|
|
1239
|
+
self.mh.store_int(idx, max_h)
|
|
1030
1240
|
self.dirty.store_int(idx, 0)
|
|
1031
1241
|
return cols * col_w
|
|
1032
1242
|
}
|
|
@@ -1330,6 +1540,26 @@ pub mv struct Container : Control {
|
|
|
1330
1540
|
var int i = self.dirty_idx.load_int(k)
|
|
1331
1541
|
var uint64 handle = self.handles.load_int(i) as uint64
|
|
1332
1542
|
if handle != 0 {
|
|
1543
|
+
// A grow-driven leaf IS the layout's flexible region: in a
|
|
1544
|
+
// VStack it absorbs a vertical window resize, in an HStack a
|
|
1545
|
+
// horizontal one. Expose that as the matching autoresizing
|
|
1546
|
+
// mask so AppKit resizes it LIVE during the drag (the engine's
|
|
1547
|
+
// relayout can't run mid-drag — heights otherwise only change
|
|
1548
|
+
// when the delegate fires or the drag ends, leaving the
|
|
1549
|
+
// flexible region sitting still under the pointer).
|
|
1550
|
+
var flex = 0
|
|
1551
|
+
if self.grows.load_int(i) > 0 {
|
|
1552
|
+
var int parent = self.pars.load_int(i) - 1
|
|
1553
|
+
if parent != -1 {
|
|
1554
|
+
var int pkind = self.kinds.load_int(parent)
|
|
1555
|
+
if pkind == KIND_VSTACK {
|
|
1556
|
+
flex = 2
|
|
1557
|
+
}
|
|
1558
|
+
if pkind == KIND_HSTACK {
|
|
1559
|
+
flex = 1
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1333
1563
|
apply_frame(
|
|
1334
1564
|
handle,
|
|
1335
1565
|
self.rx.load_int(i),
|
|
@@ -1338,6 +1568,7 @@ pub mv struct Container : Control {
|
|
|
1338
1568
|
self.rh.load_int(i),
|
|
1339
1569
|
content_w,
|
|
1340
1570
|
content_h,
|
|
1571
|
+
flex,
|
|
1341
1572
|
)
|
|
1342
1573
|
}
|
|
1343
1574
|
}
|
|
@@ -1469,6 +1700,20 @@ pub mv struct Container : Control {
|
|
|
1469
1700
|
g_resize_grid = grid;
|
|
1470
1701
|
g_resize_win = win;
|
|
1471
1702
|
}
|
|
1703
|
+
// Close interception (Window.run consults the app's
|
|
1704
|
+
// close_requested): the delegate REFUSES the native close and sets
|
|
1705
|
+
// the pending flag; the Nomen loop consumes it next frame — the app
|
|
1706
|
+
// declines (flag cleared, window stays) or accepts (close() forces
|
|
1707
|
+
// past this via nomen_close_forced). External linkage: Window's
|
|
1708
|
+
// close() and close_pending() extern both flags.
|
|
1709
|
+
int nomen_close_pending = 0;
|
|
1710
|
+
int nomen_close_forced = 0;
|
|
1711
|
+
BOOL nomen_window_should_close_imp(id self, SEL cmd, id notification) {
|
|
1712
|
+
(void)self; (void)cmd; (void)notification;
|
|
1713
|
+
if (nomen_close_forced) return YES;
|
|
1714
|
+
nomen_close_pending = 1;
|
|
1715
|
+
return NO;
|
|
1716
|
+
}
|
|
1472
1717
|
void nomen_window_did_resize(id self, SEL cmd, id notification) {
|
|
1473
1718
|
(void)self; (void)cmd; (void)notification;
|
|
1474
1719
|
if (g_resize_grid && g_resize_win) {
|
|
@@ -1497,6 +1742,20 @@ pub mv struct Container : Control {
|
|
|
1497
1742
|
g_resize_grid = grid;
|
|
1498
1743
|
g_resize_win = win;
|
|
1499
1744
|
}
|
|
1745
|
+
// Close interception (Window.run consults the app's
|
|
1746
|
+
// close_requested): the delegate REFUSES the native close and sets
|
|
1747
|
+
// the pending flag; the Nomen loop consumes it next frame — the app
|
|
1748
|
+
// declines (flag cleared, window stays) or accepts (close() forces
|
|
1749
|
+
// past this via nomen_close_forced). External linkage: Window's
|
|
1750
|
+
// close() and close_pending() extern both flags.
|
|
1751
|
+
int nomen_close_pending = 0;
|
|
1752
|
+
int nomen_close_forced = 0;
|
|
1753
|
+
BOOL nomen_window_should_close_imp(id self, SEL cmd, id notification) {
|
|
1754
|
+
(void)self; (void)cmd; (void)notification;
|
|
1755
|
+
if (nomen_close_forced) return YES;
|
|
1756
|
+
nomen_close_pending = 1;
|
|
1757
|
+
return NO;
|
|
1758
|
+
}
|
|
1500
1759
|
void nomen_window_did_resize(id self, SEL cmd, id notification) {
|
|
1501
1760
|
(void)self; (void)cmd; (void)notification;
|
|
1502
1761
|
if (g_resize_grid && g_resize_win) {
|
|
@@ -1513,6 +1772,9 @@ pub mv struct Container : Control {
|
|
|
1513
1772
|
Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
|
|
1514
1773
|
if (Dc) {
|
|
1515
1774
|
class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
|
|
1775
|
+
// Close interception: refuse the native close, set the
|
|
1776
|
+
// pending flag, let Window.run consult the app.
|
|
1777
|
+
class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
|
|
1516
1778
|
objc_registerClassPair(Dc);
|
|
1517
1779
|
}
|
|
1518
1780
|
}
|
|
@@ -1531,6 +1793,57 @@ pub mv struct Container : Control {
|
|
|
1531
1793
|
Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
|
|
1532
1794
|
if (Dc) {
|
|
1533
1795
|
class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
|
|
1796
|
+
// Close interception: refuse the native close, set the
|
|
1797
|
+
// pending flag, let Window.run consult the app.
|
|
1798
|
+
class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
|
|
1799
|
+
objc_registerClassPair(Dc);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
if (Dc) {
|
|
1803
|
+
id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
|
|
1804
|
+
delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
|
|
1805
|
+
((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
|
|
1806
|
+
}
|
|
1807
|
+
```
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
// Install the windowDidResize: delegate WITHOUT setting the target pair
|
|
1811
|
+
// (nomen_set_resize_target — call that first, e.g. from Window's
|
|
1812
|
+
// set_content). Window.run arms the delegate so the ROOT layout re-runs
|
|
1813
|
+
// live during AppKit's blocking resize drag; set_resize_callback is the
|
|
1814
|
+
// combined form for manual-loop apps.
|
|
1815
|
+
pub func arm_resize_delegate = (Window win) {
|
|
1816
|
+
```
|
|
1817
|
+
#arch: c
|
|
1818
|
+
#platform: macos
|
|
1819
|
+
Class Dc = objc_getClass("NomenResizeDelegate");
|
|
1820
|
+
if (!Dc) {
|
|
1821
|
+
Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
|
|
1822
|
+
if (Dc) {
|
|
1823
|
+
class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
|
|
1824
|
+
// Close interception: refuse the native close, set the
|
|
1825
|
+
// pending flag, let Window.run consult the app.
|
|
1826
|
+
class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
|
|
1827
|
+
objc_registerClassPair(Dc);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
if (Dc) {
|
|
1831
|
+
id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
|
|
1832
|
+
delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
|
|
1833
|
+
((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
|
|
1834
|
+
}
|
|
1835
|
+
```
|
|
1836
|
+
```
|
|
1837
|
+
#arch: aarch64_use_c
|
|
1838
|
+
#platform: macos
|
|
1839
|
+
Class Dc = objc_getClass("NomenResizeDelegate");
|
|
1840
|
+
if (!Dc) {
|
|
1841
|
+
Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
|
|
1842
|
+
if (Dc) {
|
|
1843
|
+
class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
|
|
1844
|
+
// Close interception: refuse the native close, set the
|
|
1845
|
+
// pending flag, let Window.run consult the app.
|
|
1846
|
+
class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
|
|
1534
1847
|
objc_registerClassPair(Dc);
|
|
1535
1848
|
}
|
|
1536
1849
|
}
|
|
@@ -1542,6 +1855,428 @@ pub mv struct Container : Control {
|
|
|
1542
1855
|
```
|
|
1543
1856
|
}
|
|
1544
1857
|
|
|
1858
|
+
// Register this grid as the document of a Scrollable, for Window.run's
|
|
1859
|
+
// relayout: on every content-rect change the framework re-runs the
|
|
1860
|
+
// document dance (measure unbounded → set_content_size → layout, plus a
|
|
1861
|
+
// one-time scroll_to_top) for every registered pair. `sv`/`doc` are the
|
|
1862
|
+
// scroll view's `handle`/`doc_handle()` — scalars, because a second
|
|
1863
|
+
// `ref` borrow of the same owner (self.page_grid AND self.page) would
|
|
1864
|
+
// trip the aliasing rule; see GUI.md ("The App run loop"). The grid (and
|
|
1865
|
+
// the Scrollable) must outlive the run — app fields. Call once, from
|
|
1866
|
+
// App.start.
|
|
1867
|
+
// Call once, from App.start. The file-scope registry lives HERE (in the
|
|
1868
|
+
// same file as this method and the thunk below): split builds emit only
|
|
1869
|
+
// referenced structs' methods, and every TU that emits set_document /
|
|
1870
|
+
// Window_relayout must also emit the registry + thunk they call —
|
|
1871
|
+
// putting them in Scrollable.nm broke aarch64 split links (undefined
|
|
1872
|
+
// symbols).
|
|
1873
|
+
pub func set_document = (ref self, uint64 sv, uint64 doc) {
|
|
1874
|
+
```
|
|
1875
|
+
#arch: c
|
|
1876
|
+
#platform: macos
|
|
1877
|
+
#scope: file
|
|
1878
|
+
// The registered (scroll view, document, content grid) triples —
|
|
1879
|
+
// walked by nomen_scroll_relayout_all on every window resize. Raw
|
|
1880
|
+
// addresses: the grid and the scroll live in the app struct, whose
|
|
1881
|
+
// storage is stable for the whole run (the app is moved into
|
|
1882
|
+
// Window.run once).
|
|
1883
|
+
static unsigned long long nomen_scroll_reg_sv[8];
|
|
1884
|
+
static unsigned long long nomen_scroll_reg_doc[8];
|
|
1885
|
+
static void *nomen_scroll_reg_grid[8];
|
|
1886
|
+
static int nomen_scroll_reg_n = 0;
|
|
1887
|
+
void nomen_scroll_register(unsigned long long sv, unsigned long long doc, void *grid) {
|
|
1888
|
+
if (nomen_scroll_reg_n >= 8) return;
|
|
1889
|
+
nomen_scroll_reg_sv[nomen_scroll_reg_n] = sv;
|
|
1890
|
+
nomen_scroll_reg_doc[nomen_scroll_reg_n] = doc;
|
|
1891
|
+
nomen_scroll_reg_grid[nomen_scroll_reg_n] = grid;
|
|
1892
|
+
nomen_scroll_reg_n++;
|
|
1893
|
+
}
|
|
1894
|
+
// The dance trampoline — a free function defined at the bottom of
|
|
1895
|
+
// this file; prototyped so the walker can call it regardless of
|
|
1896
|
+
// emission order (file-scope blocks hoist above function bodies).
|
|
1897
|
+
extern void nomen_scroll_thunk(struct Container *, unsigned long long, unsigned long long, struct Window *, long);
|
|
1898
|
+
void nomen_scroll_relayout_all(void *win, long first) {
|
|
1899
|
+
for (int i = 0; i < nomen_scroll_reg_n; i++) {
|
|
1900
|
+
nomen_scroll_thunk(
|
|
1901
|
+
(struct Container *)nomen_scroll_reg_grid[i],
|
|
1902
|
+
nomen_scroll_reg_sv[i], nomen_scroll_reg_doc[i],
|
|
1903
|
+
(struct Window *)win, first);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
```
|
|
1907
|
+
```
|
|
1908
|
+
#arch: aarch64_use_c
|
|
1909
|
+
#platform: macos
|
|
1910
|
+
#scope: file
|
|
1911
|
+
static unsigned long long nomen_scroll_reg_sv[8];
|
|
1912
|
+
static unsigned long long nomen_scroll_reg_doc[8];
|
|
1913
|
+
static void *nomen_scroll_reg_grid[8];
|
|
1914
|
+
static int nomen_scroll_reg_n = 0;
|
|
1915
|
+
void nomen_scroll_register(unsigned long long sv, unsigned long long doc, void *grid) {
|
|
1916
|
+
if (nomen_scroll_reg_n >= 8) return;
|
|
1917
|
+
nomen_scroll_reg_sv[nomen_scroll_reg_n] = sv;
|
|
1918
|
+
nomen_scroll_reg_doc[nomen_scroll_reg_n] = doc;
|
|
1919
|
+
nomen_scroll_reg_grid[nomen_scroll_reg_n] = grid;
|
|
1920
|
+
nomen_scroll_reg_n++;
|
|
1921
|
+
}
|
|
1922
|
+
// The companion-emitted thunk (a free function, defined at the
|
|
1923
|
+
// bottom of this file) carries the asm label that maps its symbol
|
|
1924
|
+
// for the asm side; the label goes on this FIRST declaration too —
|
|
1925
|
+
// clang rejects an asm label applied after first use.
|
|
1926
|
+
extern void nomen_scroll_thunk(nm_Container *, unsigned long long, unsigned long long, nm_Window *, long) __asm__("nomen_scroll_thunk");
|
|
1927
|
+
void nomen_scroll_relayout_all(void *win, long first) {
|
|
1928
|
+
for (int i = 0; i < nomen_scroll_reg_n; i++) {
|
|
1929
|
+
nomen_scroll_thunk(
|
|
1930
|
+
(nm_Container *)nomen_scroll_reg_grid[i],
|
|
1931
|
+
nomen_scroll_reg_sv[i], nomen_scroll_reg_doc[i],
|
|
1932
|
+
(nm_Window *)win, first);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
```
|
|
1936
|
+
```
|
|
1937
|
+
#arch: c
|
|
1938
|
+
#platform: macos
|
|
1939
|
+
nomen_scroll_register(sv, doc, (void *)self);
|
|
1940
|
+
```
|
|
1941
|
+
```
|
|
1942
|
+
#arch: aarch64_use_c
|
|
1943
|
+
#platform: macos
|
|
1944
|
+
nomen_scroll_register(sv, doc, (void *)self);
|
|
1945
|
+
```
|
|
1946
|
+
```
|
|
1947
|
+
#arch: c
|
|
1948
|
+
#platform: ios
|
|
1949
|
+
/* TODO: iOS (see #init) */
|
|
1950
|
+
```
|
|
1951
|
+
```
|
|
1952
|
+
#arch: aarch64_use_c
|
|
1953
|
+
#platform: ios
|
|
1954
|
+
/* TODO: iOS (see #init) */
|
|
1955
|
+
```
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
// Register this grid as a PANE root: after every framework relayout pass
|
|
1959
|
+
// (first post-show + every resize — Window.relayout), the grid is re-laid
|
|
1960
|
+
// into its companion window (`pane_handle`). Pane hosts re-frame on their
|
|
1961
|
+
// own schedule — a Tabs page after the tab view is framed, a SplitView
|
|
1962
|
+
// pane after the split is re-framed — so the app cannot know the right
|
|
1963
|
+
// moment; registration hands the timing to the run loop (the same trade
|
|
1964
|
+
// set_document makes for Scrollable documents). `pane_handle` is the
|
|
1965
|
+
// companion window's `handle` — a scalar, because a second `ref` borrow
|
|
1966
|
+
// of the same owner (self.pane_grid AND self.pane_window) would trip the
|
|
1967
|
+
// aliasing rule (see set_document). The grid (and the pane window) must
|
|
1968
|
+
// outlive the run — app fields. Call once, from App.start. The file-scope
|
|
1969
|
+
// registry lives HERE (same file as the layout thunk the walker calls),
|
|
1970
|
+
// for the same split-link reason set_document records.
|
|
1971
|
+
pub func set_pane = (ref self, uint64 pane_handle) {
|
|
1972
|
+
```
|
|
1973
|
+
#arch: c
|
|
1974
|
+
#platform: macos
|
|
1975
|
+
#scope: file
|
|
1976
|
+
// The registered (pane grid, pane window handle) pairs — walked by
|
|
1977
|
+
// nomen_pane_relayout_all after every relayout pass. Raw grid
|
|
1978
|
+
// addresses: the grid lives in the app struct, whose storage is
|
|
1979
|
+
// stable for the whole run. The window is stored as its handle and
|
|
1980
|
+
// re-wrapped per walk (the same stack Window the scroll thunk builds
|
|
1981
|
+
// over the doc handle) — a by-value Window param would point at
|
|
1982
|
+
// set_pane's own frame once the call returns.
|
|
1983
|
+
static void *nomen_pane_reg_grid[8];
|
|
1984
|
+
static unsigned long long nomen_pane_reg_win[8];
|
|
1985
|
+
static int nomen_pane_reg_n = 0;
|
|
1986
|
+
void nomen_pane_register(void *grid, unsigned long long handle) {
|
|
1987
|
+
if (nomen_pane_reg_n >= 8) return;
|
|
1988
|
+
nomen_pane_reg_grid[nomen_pane_reg_n] = grid;
|
|
1989
|
+
nomen_pane_reg_win[nomen_pane_reg_n] = handle;
|
|
1990
|
+
nomen_pane_reg_n++;
|
|
1991
|
+
}
|
|
1992
|
+
void nomen_pane_relayout_all(void) {
|
|
1993
|
+
for (int i = 0; i < nomen_pane_reg_n; i++) {
|
|
1994
|
+
extern void *_Window_traits[];
|
|
1995
|
+
extern void nomen_layout_thunk(struct Container *, struct Window *);
|
|
1996
|
+
struct Window pane_win;
|
|
1997
|
+
pane_win._vt = (void *)&_Window_traits;
|
|
1998
|
+
pane_win.handle = nomen_pane_reg_win[i];
|
|
1999
|
+
nomen_layout_thunk((struct Container *)nomen_pane_reg_grid[i], &pane_win);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
```
|
|
2003
|
+
```
|
|
2004
|
+
#arch: aarch64_use_c
|
|
2005
|
+
#platform: macos
|
|
2006
|
+
#scope: file
|
|
2007
|
+
static void *nomen_pane_reg_grid[8];
|
|
2008
|
+
static unsigned long long nomen_pane_reg_win[8];
|
|
2009
|
+
static int nomen_pane_reg_n = 0;
|
|
2010
|
+
void nomen_pane_register(void *grid, unsigned long long handle) {
|
|
2011
|
+
if (nomen_pane_reg_n >= 8) return;
|
|
2012
|
+
nomen_pane_reg_grid[nomen_pane_reg_n] = grid;
|
|
2013
|
+
nomen_pane_reg_win[nomen_pane_reg_n] = handle;
|
|
2014
|
+
nomen_pane_reg_n++;
|
|
2015
|
+
}
|
|
2016
|
+
void nomen_pane_relayout_all(void) {
|
|
2017
|
+
for (int i = 0; i < nomen_pane_reg_n; i++) {
|
|
2018
|
+
extern void *Window_traits;
|
|
2019
|
+
extern void nomen_layout_thunk(struct Container *, struct Window *);
|
|
2020
|
+
nm_Window pane_win;
|
|
2021
|
+
pane_win._vt = (void *)&Window_traits;
|
|
2022
|
+
pane_win.handle = nomen_pane_reg_win[i];
|
|
2023
|
+
nomen_layout_thunk((struct Container *)nomen_pane_reg_grid[i], (struct Window *)&pane_win);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
```
|
|
2027
|
+
```
|
|
2028
|
+
#arch: c
|
|
2029
|
+
#platform: macos
|
|
2030
|
+
nomen_pane_register((void *)self, pane_handle);
|
|
2031
|
+
```
|
|
2032
|
+
```
|
|
2033
|
+
#arch: aarch64_use_c
|
|
2034
|
+
#platform: macos
|
|
2035
|
+
nomen_pane_register((void *)self, pane_handle);
|
|
2036
|
+
```
|
|
2037
|
+
```
|
|
2038
|
+
#arch: c
|
|
2039
|
+
#platform: ios
|
|
2040
|
+
/* TODO: iOS (see #init) */
|
|
2041
|
+
```
|
|
2042
|
+
```
|
|
2043
|
+
#arch: aarch64_use_c
|
|
2044
|
+
#platform: ios
|
|
2045
|
+
/* TODO: iOS (see #init) */
|
|
2046
|
+
```
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
// The on_right_click desugar's drain (docs/HANDLERS.md): the synthesized
|
|
2050
|
+
// pump arm polls this per frame. The record is WINDOW-level — the same
|
|
2051
|
+
// edge FrameEvents.click reports as 2, stamped by every process_events
|
|
2052
|
+
// pump and stale the moment the next pump runs — so registration reads
|
|
2053
|
+
// "tell me when a right-click happens": every registered arm sees the
|
|
2054
|
+
// edge (broadcast — no consumption, so arms never starve each other),
|
|
2055
|
+
// and the HANDLER disambiguates: read the click through the dispatch
|
|
2056
|
+
// window (win.click_x()/click_y()), translate for scrollables
|
|
2057
|
+
// (content_click), hit-test children (contains). `self` is the routing
|
|
2058
|
+
// receiver only — the event is not container-scoped.
|
|
2059
|
+
pub func take_right_click = (self, out bool) {
|
|
2060
|
+
```
|
|
2061
|
+
#arch: c
|
|
2062
|
+
#platform: macos
|
|
2063
|
+
extern unsigned char nomen_window_had_right_click(void);
|
|
2064
|
+
return nomen_window_had_right_click();
|
|
2065
|
+
```
|
|
2066
|
+
```
|
|
2067
|
+
#arch: aarch64_use_c
|
|
2068
|
+
#platform: macos
|
|
2069
|
+
extern unsigned char nomen_window_had_right_click(void) __asm__("nomen_window_had_right_click");
|
|
2070
|
+
return nomen_window_had_right_click();
|
|
2071
|
+
```
|
|
2072
|
+
```
|
|
2073
|
+
#arch: c
|
|
2074
|
+
#platform: ios
|
|
2075
|
+
return 0;
|
|
2076
|
+
```
|
|
2077
|
+
```
|
|
2078
|
+
#arch: aarch64_use_c
|
|
2079
|
+
#platform: ios
|
|
2080
|
+
return 0;
|
|
2081
|
+
```
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
// The on_mouse_down desugar's drain (docs/HANDLERS.md): the synthesized
|
|
2085
|
+
// pump arm polls this per frame. The exhaustive window-level edge —
|
|
2086
|
+
// EVERY mouse-down (left, right, middle, mouse 4+), not just the two
|
|
2087
|
+
// named buttons. Like take_right_click, the record is window-level and
|
|
2088
|
+
// broadcast (one edge per pump, every registered arm sees it); the
|
|
2089
|
+
// HANDLER filters and disambiguates: `win.mouse_button()` (1-based —
|
|
2090
|
+
// 1 left, 2 right, 3 middle, 4+ extras), `mouse_click_count()`
|
|
2091
|
+
// (double/triple), `mouse_modifiers()` (cmd/option/ctrl/shift bits),
|
|
2092
|
+
// `click_x()`/`click_y()` for the position. `on_right_click` is the
|
|
2093
|
+
// sugar for button 2.
|
|
2094
|
+
pub func take_mouse_down = (self, out bool) {
|
|
2095
|
+
```
|
|
2096
|
+
#arch: c
|
|
2097
|
+
#platform: macos
|
|
2098
|
+
extern int nomen_last_click_button;
|
|
2099
|
+
return nomen_last_click_button != 0;
|
|
2100
|
+
```
|
|
2101
|
+
```
|
|
2102
|
+
#arch: aarch64_use_c
|
|
2103
|
+
#platform: macos
|
|
2104
|
+
extern int nomen_last_click_button;
|
|
2105
|
+
return nomen_last_click_button != 0;
|
|
2106
|
+
```
|
|
2107
|
+
```
|
|
2108
|
+
#arch: c
|
|
2109
|
+
#platform: ios
|
|
2110
|
+
return 0;
|
|
2111
|
+
```
|
|
2112
|
+
```
|
|
2113
|
+
#arch: aarch64_use_c
|
|
2114
|
+
#platform: ios
|
|
2115
|
+
return 0;
|
|
2116
|
+
```
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
// The on_double_click desugar's drain (docs/HANDLERS.md tier 2): the
|
|
2120
|
+
// sugar over the mouse-down record — left button (1) with a click count
|
|
2121
|
+
// of 2, the list-row "open" gesture. Window-level and broadcast, like
|
|
2122
|
+
// the rest of the family: every registered arm sees the edge, and the
|
|
2123
|
+
// HANDLER disambiguates — position via win.click_x()/click_y() for
|
|
2124
|
+
// hit-testing (a row-targeted refinement can come later through the
|
|
2125
|
+
// table family's native doubleAction). `on_mouse_down` remains the raw
|
|
2126
|
+
// tier (it sees the same double-click with the full record).
|
|
2127
|
+
pub func take_double_click = (self, out bool) {
|
|
2128
|
+
```
|
|
2129
|
+
#arch: c
|
|
2130
|
+
#platform: macos
|
|
2131
|
+
extern int nomen_last_click_button;
|
|
2132
|
+
extern int nomen_last_click_count;
|
|
2133
|
+
return nomen_last_click_button == 1 && nomen_last_click_count == 2;
|
|
2134
|
+
```
|
|
2135
|
+
```
|
|
2136
|
+
#arch: aarch64_use_c
|
|
2137
|
+
#platform: macos
|
|
2138
|
+
extern int nomen_last_click_button;
|
|
2139
|
+
extern int nomen_last_click_count;
|
|
2140
|
+
return nomen_last_click_button == 1 && nomen_last_click_count == 2;
|
|
2141
|
+
```
|
|
2142
|
+
```
|
|
2143
|
+
#arch: c
|
|
2144
|
+
#platform: ios
|
|
2145
|
+
return 0;
|
|
2146
|
+
```
|
|
2147
|
+
```
|
|
2148
|
+
#arch: aarch64_use_c
|
|
2149
|
+
#platform: ios
|
|
2150
|
+
return 0;
|
|
2151
|
+
```
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
// The on_key_down / on_key_up desugars' drains (docs/HANDLERS.md): the
|
|
2155
|
+
// synthesized pump arm polls these per frame. The keyboard record is
|
|
2156
|
+
// window-level and broadcast (like the mouse records): every registered
|
|
2157
|
+
// arm sees every key, and the HANDLER filters — `win.key_code()`
|
|
2158
|
+
// (hardware keycode: Space = 49, Return = 36, arrows = 123–126, letters
|
|
2159
|
+
// a…z = 0–25), `win.key_modifiers()` (Command = 1048576, Option =
|
|
2160
|
+
// 524288, Control = 262144, Shift = 131072), `win.key_repeat()` (a held
|
|
2161
|
+
// key auto-repeating — filter for first-press-only shortcuts),
|
|
2162
|
+
// `win.key_up_code()`. These are SHORTCUT and raw-key events: text
|
|
2163
|
+
// entry does not flow here — a TextBox's typing arrives through
|
|
2164
|
+
// `on_input` (the field editor), which is the right event for editors.
|
|
2165
|
+
pub func take_key_down = (self, out bool) {
|
|
2166
|
+
```
|
|
2167
|
+
#arch: c
|
|
2168
|
+
#platform: macos
|
|
2169
|
+
extern int nomen_last_key_code;
|
|
2170
|
+
return nomen_last_key_code != -1;
|
|
2171
|
+
```
|
|
2172
|
+
```
|
|
2173
|
+
#arch: aarch64_use_c
|
|
2174
|
+
#platform: macos
|
|
2175
|
+
extern int nomen_last_key_code;
|
|
2176
|
+
return nomen_last_key_code != -1;
|
|
2177
|
+
```
|
|
2178
|
+
```
|
|
2179
|
+
#arch: c
|
|
2180
|
+
#platform: ios
|
|
2181
|
+
return 0;
|
|
2182
|
+
```
|
|
2183
|
+
```
|
|
2184
|
+
#arch: aarch64_use_c
|
|
2185
|
+
#platform: ios
|
|
2186
|
+
return 0;
|
|
2187
|
+
```
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
pub func take_key_up = (self, out bool) {
|
|
2191
|
+
```
|
|
2192
|
+
#arch: c
|
|
2193
|
+
#platform: macos
|
|
2194
|
+
extern int nomen_last_key_up_code;
|
|
2195
|
+
return nomen_last_key_up_code != -1;
|
|
2196
|
+
```
|
|
2197
|
+
```
|
|
2198
|
+
#arch: aarch64_use_c
|
|
2199
|
+
#platform: macos
|
|
2200
|
+
extern int nomen_last_key_up_code;
|
|
2201
|
+
return nomen_last_key_up_code != -1;
|
|
2202
|
+
```
|
|
2203
|
+
```
|
|
2204
|
+
#arch: c
|
|
2205
|
+
#platform: ios
|
|
2206
|
+
return 0;
|
|
2207
|
+
```
|
|
2208
|
+
```
|
|
2209
|
+
#arch: aarch64_use_c
|
|
2210
|
+
#platform: ios
|
|
2211
|
+
return 0;
|
|
2212
|
+
```
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
// The on_mouse_move desugar's drain (docs/HANDLERS.md): the synthesized
|
|
2216
|
+
// pump arm polls this per frame. True on any frame whose pump saw a
|
|
2217
|
+
// pointer move or drag; the position rides the dispatch window —
|
|
2218
|
+
// `win.mouse_x()` / `win.mouse_y()` (-1 on a frame with no movement).
|
|
2219
|
+
// Window-level and broadcast, like every record in the family. Hover,
|
|
2220
|
+
// cursors, and tooltips hit-test this against contains(); per-control
|
|
2221
|
+
// entered/exited is sugar over the same record.
|
|
2222
|
+
pub func take_mouse_move = (self, out bool) {
|
|
2223
|
+
```
|
|
2224
|
+
#arch: c
|
|
2225
|
+
#platform: macos
|
|
2226
|
+
extern int nomen_last_mouse_move_x;
|
|
2227
|
+
return nomen_last_mouse_move_x != -1;
|
|
2228
|
+
```
|
|
2229
|
+
```
|
|
2230
|
+
#arch: aarch64_use_c
|
|
2231
|
+
#platform: macos
|
|
2232
|
+
extern int nomen_last_mouse_move_x;
|
|
2233
|
+
return nomen_last_mouse_move_x != -1;
|
|
2234
|
+
```
|
|
2235
|
+
```
|
|
2236
|
+
#arch: c
|
|
2237
|
+
#platform: ios
|
|
2238
|
+
return 0;
|
|
2239
|
+
```
|
|
2240
|
+
```
|
|
2241
|
+
#arch: aarch64_use_c
|
|
2242
|
+
#platform: ios
|
|
2243
|
+
return 0;
|
|
2244
|
+
```
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
// The on_resize desugar's drain (docs/HANDLERS.md): fires on the frame
|
|
2248
|
+
// whose content rect changed. The framework has ALREADY re-laid-out the
|
|
2249
|
+
// registered roots — the handler re-lays-out app-owned panes (tab
|
|
2250
|
+
// pages, split panes). The new size rides the dispatch window via
|
|
2251
|
+
// `win.resize_width()` / `win.resize_height()`; FrameEvents.resized /
|
|
2252
|
+
// width / height carry the same record for `frame`. The record is
|
|
2253
|
+
// stamped by Window.run's resize detection (same edge the frame form
|
|
2254
|
+
// reports) — window-level, broadcast like the rest of the family.
|
|
2255
|
+
pub func take_resize = (self, out bool) {
|
|
2256
|
+
```
|
|
2257
|
+
#arch: c
|
|
2258
|
+
#platform: macos
|
|
2259
|
+
extern int nomen_last_resized;
|
|
2260
|
+
return nomen_last_resized != 0;
|
|
2261
|
+
```
|
|
2262
|
+
```
|
|
2263
|
+
#arch: aarch64_use_c
|
|
2264
|
+
#platform: macos
|
|
2265
|
+
extern int nomen_last_resized;
|
|
2266
|
+
return nomen_last_resized != 0;
|
|
2267
|
+
```
|
|
2268
|
+
```
|
|
2269
|
+
#arch: c
|
|
2270
|
+
#platform: ios
|
|
2271
|
+
return 0;
|
|
2272
|
+
```
|
|
2273
|
+
```
|
|
2274
|
+
#arch: aarch64_use_c
|
|
2275
|
+
#platform: ios
|
|
2276
|
+
return 0;
|
|
2277
|
+
```
|
|
2278
|
+
}
|
|
2279
|
+
|
|
1545
2280
|
// Hit test: is point (cx, cy) (top-left origin, as returned by click_x/
|
|
1546
2281
|
// click_y) inside the leaf with the given handle?
|
|
1547
2282
|
pub func contains = (self, uint64 handle, int cx, int cy, out bool) {
|
|
@@ -1638,6 +2373,99 @@ pub func nomen_layout_thunk = (ref Container grid, Window win) {
|
|
|
1638
2373
|
grid.layout(win)
|
|
1639
2374
|
}
|
|
1640
2375
|
|
|
2376
|
+
// The grid-side measure for the document dance, as a C-linkage free
|
|
2377
|
+
// function (pure Nomen — asm-emitted on aarch64) so the thunk's raw bodies
|
|
2378
|
+
// can call it: constraints are the window's content width minus the grid's
|
|
2379
|
+
// own padding (the `layout_page` formula), height unbounded.
|
|
2380
|
+
pub func nomen_scroll_measure = (ref Container grid, int max_w, out [int, int]) {
|
|
2381
|
+
var bc = BoxConstraints()
|
|
2382
|
+
bc.max_width = max_w
|
|
2383
|
+
const Size cs = grid.measure(bc)
|
|
2384
|
+
return [cs.width, cs.height]
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
// The per-pair document dance, called from nomen_scroll_relayout_all (the
|
|
2388
|
+
// registration's C walker — see set_document above): measure the grid
|
|
2389
|
+
// unbounded-height at the window's content width, size the document view,
|
|
2390
|
+
// lay the grid out into the document, and — once, on the framework's first
|
|
2391
|
+
// post-show pass — scroll to the top. Pointer/handle params: free functions
|
|
2392
|
+
// are exported for C linkage on both backends, and the walker holds raw
|
|
2393
|
+
// addresses + the scroll's handles (scalars). FULLY RAW bodies: an
|
|
2394
|
+
// aarch64_use_c function routes to the C companion using only its raw
|
|
2395
|
+
// blocks, so any Nomen statement here would be silently dropped
|
|
2396
|
+
// (FOLLOWUP.md) — the measure goes through nomen_scroll_measure instead.
|
|
2397
|
+
pub func nomen_scroll_thunk = (ref Container grid, uint64 sv, uint64 doc, ref Window win, int first) {
|
|
2398
|
+
```
|
|
2399
|
+
#arch: c
|
|
2400
|
+
#platform: macos
|
|
2401
|
+
extern struct _Tuple_int_int nomen_scroll_measure(struct Container *, long);
|
|
2402
|
+
id ssv = (id)sv;
|
|
2403
|
+
id sdoc = (id)doc;
|
|
2404
|
+
id win_cv = ((id(*)(id, SEL))objc_msgSend)((id)win->handle, sel_registerName("contentView"));
|
|
2405
|
+
CGRect win_frame = ((CGRect(*)(id, SEL))objc_msgSend)(win_cv, sel_registerName("frame"));
|
|
2406
|
+
struct _Tuple_int_int cs = nomen_scroll_measure(grid, (long)win_frame.size.width - grid->padding * 2);
|
|
2407
|
+
id clip = ((id(*)(id, SEL))objc_msgSend)(ssv, sel_registerName("contentView"));
|
|
2408
|
+
CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
|
|
2409
|
+
double frame_h = (double)cs._1;
|
|
2410
|
+
if (frame_h < clip_bounds.size.height) frame_h = clip_bounds.size.height;
|
|
2411
|
+
((void(*)(id, SEL, CGSize))objc_msgSend)(sdoc, sel_registerName("setFrameSize:"),
|
|
2412
|
+
((CGSize(*)(double, double))CGSizeMake)((double)cs._0, frame_h));
|
|
2413
|
+
if (first == 1) {
|
|
2414
|
+
// The document view is unflipped and starts showing its bottom-left
|
|
2415
|
+
// corner — the one-time scroll_to_top (the clip's bounds origin sits
|
|
2416
|
+
// `doc_h - clip_h` up from the bottom).
|
|
2417
|
+
CGPoint origin = ((CGPoint(*)(double, double))CGPointMake)(0, frame_h - clip_bounds.size.height);
|
|
2418
|
+
((void(*)(id, SEL, CGPoint))objc_msgSend)(clip, sel_registerName("setBoundsOrigin:"), origin);
|
|
2419
|
+
((void(*)(id, SEL, id))objc_msgSend)(ssv, sel_registerName("reflectScrolledClipView:"), clip);
|
|
2420
|
+
}
|
|
2421
|
+
// Lay the grid out into the document view: a stack Window value over the
|
|
2422
|
+
// doc handle (layout only reads it — no retain needed).
|
|
2423
|
+
extern void *_Window_traits[];
|
|
2424
|
+
extern void nomen_layout_thunk(struct Container *, struct Window *);
|
|
2425
|
+
struct Window doc_win;
|
|
2426
|
+
doc_win._vt = (void *)&_Window_traits;
|
|
2427
|
+
doc_win.handle = doc;
|
|
2428
|
+
nomen_layout_thunk((struct Container *)grid, &doc_win);
|
|
2429
|
+
```
|
|
2430
|
+
```
|
|
2431
|
+
#arch: aarch64_use_c
|
|
2432
|
+
#platform: macos
|
|
2433
|
+
extern nm__Tuple_int_int nomen_scroll_measure(struct Container *, long);
|
|
2434
|
+
id ssv = (id)sv;
|
|
2435
|
+
id sdoc = (id)doc;
|
|
2436
|
+
id win_cv = ((id(*)(id, SEL))objc_msgSend)((id)win->handle, sel_registerName("contentView"));
|
|
2437
|
+
CGRect win_frame = ((CGRect(*)(id, SEL))objc_msgSend)(win_cv, sel_registerName("frame"));
|
|
2438
|
+
nm__Tuple_int_int cs = nomen_scroll_measure(grid, (long)win_frame.size.width - grid->padding * 2);
|
|
2439
|
+
id clip = ((id(*)(id, SEL))objc_msgSend)(ssv, sel_registerName("contentView"));
|
|
2440
|
+
CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
|
|
2441
|
+
double frame_h = (double)cs._1;
|
|
2442
|
+
if (frame_h < clip_bounds.size.height) frame_h = clip_bounds.size.height;
|
|
2443
|
+
((void(*)(id, SEL, CGSize))objc_msgSend)(sdoc, sel_registerName("setFrameSize:"),
|
|
2444
|
+
((CGSize(*)(double, double))CGSizeMake)((double)cs._0, frame_h));
|
|
2445
|
+
if (first == 1) {
|
|
2446
|
+
CGPoint origin = ((CGPoint(*)(double, double))CGPointMake)(0, frame_h - clip_bounds.size.height);
|
|
2447
|
+
((void(*)(id, SEL, CGPoint))objc_msgSend)(clip, sel_registerName("setBoundsOrigin:"), origin);
|
|
2448
|
+
((void(*)(id, SEL, id))objc_msgSend)(ssv, sel_registerName("reflectScrolledClipView:"), clip);
|
|
2449
|
+
}
|
|
2450
|
+
extern void *Window_traits;
|
|
2451
|
+
extern void nomen_layout_thunk(struct Container *, struct Window *);
|
|
2452
|
+
nm_Window doc_win;
|
|
2453
|
+
doc_win._vt = (void *)&Window_traits;
|
|
2454
|
+
doc_win.handle = doc;
|
|
2455
|
+
nomen_layout_thunk((struct Container *)grid, (struct Window *)&doc_win);
|
|
2456
|
+
```
|
|
2457
|
+
```
|
|
2458
|
+
#arch: c
|
|
2459
|
+
#platform: ios
|
|
2460
|
+
/* TODO: iOS (see #init) */
|
|
2461
|
+
```
|
|
2462
|
+
```
|
|
2463
|
+
#arch: aarch64_use_c
|
|
2464
|
+
#platform: ios
|
|
2465
|
+
/* TODO: iOS (see #init) */
|
|
2466
|
+
```
|
|
2467
|
+
}
|
|
2468
|
+
|
|
1641
2469
|
/**
|
|
1642
2470
|
* Creates a vertical stack container with the given spacing
|
|
1643
2471
|
**/
|