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.
Files changed (50) hide show
  1. package/core/System/Buffer.nm +32 -0
  2. package/core/System/ClassBuffer.nm +24 -0
  3. package/core/System/Controls/Alert.nm +326 -0
  4. package/core/System/Controls/App.nm +147 -0
  5. package/core/System/Controls/Button.nm +119 -1
  6. package/core/System/Controls/CheckBox.nm +24 -0
  7. package/core/System/Controls/ColorPicker.nm +307 -0
  8. package/core/System/Controls/ComboBox.nm +430 -0
  9. package/core/System/Controls/Container.nm +837 -9
  10. package/core/System/Controls/Control.nm +443 -0
  11. package/core/System/Controls/DatePicker.nm +288 -0
  12. package/core/System/Controls/Form.nm +70 -0
  13. package/core/System/Controls/GroupBox.nm +267 -0
  14. package/core/System/Controls/ImageView.nm +311 -0
  15. package/core/System/Controls/LevelIndicator.nm +305 -0
  16. package/core/System/Controls/ListView.nm +633 -0
  17. package/core/System/Controls/Menu.nm +428 -0
  18. package/core/System/Controls/NumberInput.nm +56 -0
  19. package/core/System/Controls/OtpInput.nm +50 -0
  20. package/core/System/Controls/OutlineView.nm +598 -0
  21. package/core/System/Controls/Pagination.nm +142 -0
  22. package/core/System/Controls/Popover.nm +296 -0
  23. package/core/System/Controls/Progress.nm +348 -0
  24. package/core/System/Controls/Radio.nm +292 -0
  25. package/core/System/Controls/Scrollable.nm +584 -0
  26. package/core/System/Controls/SearchField.nm +326 -0
  27. package/core/System/Controls/SecureField.nm +344 -0
  28. package/core/System/Controls/Segmented.nm +380 -0
  29. package/core/System/Controls/Select.nm +340 -0
  30. package/core/System/Controls/Separator.nm +198 -0
  31. package/core/System/Controls/Sheet.nm +329 -0
  32. package/core/System/Controls/Slider.nm +315 -0
  33. package/core/System/Controls/Spinner.nm +287 -0
  34. package/core/System/Controls/SplitView.nm +509 -0
  35. package/core/System/Controls/Stepper.nm +349 -0
  36. package/core/System/Controls/Switch.nm +259 -0
  37. package/core/System/Controls/Table.nm +833 -0
  38. package/core/System/Controls/Tabs.nm +500 -0
  39. package/core/System/Controls/Text.nm +108 -11
  40. package/core/System/Controls/TextBox.nm +112 -1
  41. package/core/System/Controls/TextView.nm +329 -0
  42. package/core/System/Controls/Toggle.nm +346 -0
  43. package/core/System/Controls/Toolbar.nm +501 -0
  44. package/core/System/Controls/Tooltip.nm +76 -0
  45. package/core/System/Controls/Window.nm +1549 -91
  46. package/core/System/List.nm +34 -0
  47. package/core/System/Map.nm +21 -4
  48. package/core/System/Set.nm +14 -0
  49. package/dist/index.mjs +2556 -656
  50. package/package.json +1 -1
@@ -0,0 +1,584 @@
1
+ /**
2
+ * A scrolling viewport hosting arbitrary controls on a document view
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * fields are platform handles, so the value is movable and its `#destroy`
6
+ * releases what they name. The constructor's `self` is the inline instance
7
+ * (the `.` accessor); methods keep the pointer form.
8
+ *
9
+ * The scroll view is framed like any control (it sits in a Grid cell), but
10
+ * its children live on a DOCUMENT VIEW: `content_window` hands back a
11
+ * Window-shaped value whose `contentView` is the document view itself (the
12
+ * NomenDocumentView NSView subclass answers `-contentView` with `self`), so
13
+ * control constructors and `Container.layout` work unchanged. The document
14
+ * view stays unflipped, so the engine's y-flip against `content_height()`
15
+ * (the document height) is the existing math — see the Scrollable design
16
+ * note in GUI.md. Per relayout pass: measure the content grid unbounded,
17
+ * `set_content_size`, then `content_grid.layout(content)`. `content_click`
18
+ * translates window-space clicks into document coordinates so content
19
+ * children can be hit-tested while scrolled. iOS defers to UIScrollView
20
+ * (TODO stubs; see GUI_PLAN Tier 2).
21
+ **/
22
+ pub mv struct Scrollable: Control {
23
+ var uint64 handle = 0
24
+ var uint64 doc = 0
25
+
26
+ // File-scope helper: the document view class. It answers `-contentView`
27
+ // with `self` so Window-expecting constructors add their controls to the
28
+ // document view (registered once, like NomenResizeDelegate).
29
+ pub func #init = (self, Window window) {
30
+ ```
31
+ #arch: c
32
+ #platform: macos
33
+ #scope: file
34
+ static id nomen_doc_content_view(id self, SEL cmd) {
35
+ (void)cmd;
36
+ return self;
37
+ }
38
+ static id nomen_document_view_class(void) {
39
+ Class Dv = objc_getClass("NomenDocumentView");
40
+ if (!Dv) {
41
+ Dv = objc_allocateClassPair(objc_getClass("NSView"), "NomenDocumentView", 0);
42
+ if (Dv) {
43
+ class_addMethod(Dv, sel_registerName("contentView"), (IMP)nomen_doc_content_view, "@@:");
44
+ objc_registerClassPair(Dv);
45
+ }
46
+ }
47
+ return Dv;
48
+ }
49
+ ```
50
+ ```
51
+ #arch: aarch64_use_c
52
+ #platform: macos
53
+ #scope: file
54
+ static id nomen_doc_content_view(id self, SEL cmd) {
55
+ (void)cmd;
56
+ return self;
57
+ }
58
+ static id nomen_document_view_class(void) {
59
+ Class Dv = objc_getClass("NomenDocumentView");
60
+ if (!Dv) {
61
+ Dv = objc_allocateClassPair(objc_getClass("NSView"), "NomenDocumentView", 0);
62
+ if (Dv) {
63
+ class_addMethod(Dv, sel_registerName("contentView"), (IMP)nomen_doc_content_view, "@@:");
64
+ objc_registerClassPair(Dv);
65
+ }
66
+ }
67
+ return Dv;
68
+ }
69
+ ```
70
+ ```
71
+ #arch: c
72
+ #platform: macos
73
+ id sv = ((id(*)(id, SEL, CGRect))objc_msgSend)(
74
+ ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSScrollView"), sel_registerName("alloc")),
75
+ sel_registerName("initWithFrame:"),
76
+ ((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, 240, 160));
77
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(sv, sel_registerName("setHasVerticalScroller:"), 1);
78
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(sv, sel_registerName("setDrawsBackground:"), 0);
79
+ id doc = ((id(*)(id, SEL, CGRect))objc_msgSend)(
80
+ ((id(*)(id, SEL))objc_msgSend)(nomen_document_view_class(), sel_registerName("alloc")),
81
+ sel_registerName("initWithFrame:"),
82
+ ((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, 0, 0));
83
+ ((void(*)(id, SEL, id))objc_msgSend)(sv, sel_registerName("setDocumentView:"), doc);
84
+ ((void(*)(id, SEL))objc_msgSend)(doc, sel_registerName("release"));
85
+ id contentView = ((id(*)(id, SEL))objc_msgSend)(
86
+ (id)window->handle, sel_registerName("contentView"));
87
+ ((void(*)(id, SEL, id))objc_msgSend)(
88
+ contentView, sel_registerName("addSubview:"), sv);
89
+ self.handle = (uint64_t)sv;
90
+ self.doc = (uint64_t)((id(*)(id, SEL))objc_msgSend)(sv, sel_registerName("documentView"));
91
+ ```
92
+ ```
93
+ #arch: aarch64_use_c
94
+ #platform: macos
95
+ id sv = ((id(*)(id, SEL, CGRect))objc_msgSend)(
96
+ ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSScrollView"), sel_registerName("alloc")),
97
+ sel_registerName("initWithFrame:"),
98
+ ((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, 240, 160));
99
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(sv, sel_registerName("setHasVerticalScroller:"), 1);
100
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(sv, sel_registerName("setDrawsBackground:"), 0);
101
+ id doc = ((id(*)(id, SEL, CGRect))objc_msgSend)(
102
+ ((id(*)(id, SEL))objc_msgSend)(nomen_document_view_class(), sel_registerName("alloc")),
103
+ sel_registerName("initWithFrame:"),
104
+ ((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, 0, 0));
105
+ ((void(*)(id, SEL, id))objc_msgSend)(sv, sel_registerName("setDocumentView:"), doc);
106
+ ((void(*)(id, SEL))objc_msgSend)(doc, sel_registerName("release"));
107
+ id contentView = ((id(*)(id, SEL))objc_msgSend)(
108
+ (id)window->handle, sel_registerName("contentView"));
109
+ ((void(*)(id, SEL, id))objc_msgSend)(
110
+ contentView, sel_registerName("addSubview:"), sv);
111
+ self->handle = (uint64_t)sv;
112
+ self->doc = (uint64_t)((id(*)(id, SEL))objc_msgSend)(sv, sel_registerName("documentView"));
113
+ ```
114
+ ```
115
+ #arch: c
116
+ #platform: ios
117
+ /* TODO: iOS — UIScrollView + a UIView document view; the constructors'
118
+ * rootViewController.view path expects a UIWindow, so content_window
119
+ * needs the same `-contentView` trick on a UIView subclass (see
120
+ * GUI_PLAN Tier 2; defer with the other iOS stubs). */
121
+ ```
122
+ ```
123
+ #arch: aarch64_use_c
124
+ #platform: ios
125
+ /* TODO: iOS (see #init) */
126
+ ```
127
+ }
128
+
129
+ // A Window-shaped handle to the document view: pass it to control
130
+ // constructors and `Container.layout` to host controls in the scroll
131
+ // view. The value retains the document view (+1), so its scope-exit
132
+ // `#destroy` releases its OWN reference and the Scrollable's stays
133
+ // balanced — keep the Scrollable alive at least as long as the returned
134
+ // value.
135
+ pub func content_window = (self, out Window) {
136
+ ```
137
+ #arch: c
138
+ #platform: macos
139
+ extern void *_Window_traits[];
140
+ struct Window w;
141
+ w._vt = (void *)&_Window_traits;
142
+ w.handle = self->doc;
143
+ ((id(*)(id, SEL))objc_msgSend)((id)self->doc, sel_registerName("retain"));
144
+ return w;
145
+ ```
146
+ ```
147
+ #arch: aarch64_use_c
148
+ #platform: macos
149
+ extern void *Window_traits;
150
+ struct Window w;
151
+ w._vt = (void *)&Window_traits;
152
+ w.handle = self->doc;
153
+ ((id(*)(id, SEL))objc_msgSend)((id)self->doc, sel_registerName("retain"));
154
+ return w;
155
+ ```
156
+ ```
157
+ #arch: c
158
+ #platform: ios
159
+ /* TODO: iOS (see #init) */
160
+ {
161
+ extern void *_Window_traits[];
162
+ struct Window w;
163
+ w._vt = (void *)&_Window_traits;
164
+ w.handle = 0;
165
+ return w;
166
+ }
167
+ ```
168
+ ```
169
+ #arch: aarch64_use_c
170
+ #platform: ios
171
+ /* TODO: iOS (see #init) */
172
+ {
173
+ extern void *Window_traits;
174
+ struct Window w;
175
+ w._vt = (void *)&Window_traits;
176
+ w.handle = 0;
177
+ return w;
178
+ }
179
+ ```
180
+ }
181
+
182
+ // The document view's native handle — pair with `handle` to register
183
+ // this scroll view's document via `Container.set_document` (the
184
+ // Window.run relayout registry). Scalars, so the registration call
185
+ // never holds two borrows of the same owner.
186
+ pub func doc_handle = (self, out uint64) {
187
+ return self.doc
188
+ }
189
+
190
+ // Size the document view to the laid-out content. Call between the
191
+ // content grid's unbounded `measure` and its `layout(content)` — the
192
+ // flip needs the document height to equal the content height before
193
+ // frames are applied (see the Scrollable design note in GUI.md). The
194
+ // height is clamped UP to the viewport: an unflipped document shorter
195
+ // than its clip view sits at the clip's BOTTOM, so a short list would
196
+ // render bunched at the bottom of the scroll region — filling the
197
+ // viewport keeps the content top-anchored (and drops the scrollbar).
198
+ pub func set_content_size = (self, int width, int height) {
199
+ ```
200
+ #arch: c
201
+ #platform: macos
202
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
203
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
204
+ double frame_h = (double)height;
205
+ if (frame_h < clip_bounds.size.height) frame_h = clip_bounds.size.height;
206
+ ((void(*)(id, SEL, CGSize))objc_msgSend)(
207
+ (id)self->doc, sel_registerName("setFrameSize:"),
208
+ ((CGSize(*)(double, double))CGSizeMake)((double)width, frame_h));
209
+ ```
210
+ ```
211
+ #arch: aarch64_use_c
212
+ #platform: macos
213
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
214
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
215
+ double frame_h = (double)height;
216
+ if (frame_h < clip_bounds.size.height) frame_h = clip_bounds.size.height;
217
+ ((void(*)(id, SEL, CGSize))objc_msgSend)(
218
+ (id)self->doc, sel_registerName("setFrameSize:"),
219
+ ((CGSize(*)(double, double))CGSizeMake)((double)width, frame_h));
220
+ ```
221
+ ```
222
+ #arch: c
223
+ #platform: ios
224
+ /* TODO: iOS (see #init) */
225
+ ```
226
+ ```
227
+ #arch: aarch64_use_c
228
+ #platform: ios
229
+ /* TODO: iOS (see #init) */
230
+ ```
231
+ }
232
+
233
+ // Scroll so the top of the document is visible. The document view is
234
+ // unflipped (the engine's flip math owns the coordinates), and NSScrollView
235
+ // initially shows an unflipped document's bottom-left corner — call once
236
+ // after the first layout.
237
+ pub func scroll_to_top = (self) {
238
+ ```
239
+ #arch: c
240
+ #platform: macos
241
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
242
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("documentView"));
243
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
244
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
245
+ // Set the clip's bounds origin directly — the one primitive the live
246
+ // scroll machinery can't constrain short of the edge. The unflipped
247
+ // document's top edge is at doc height; the visible origin sits
248
+ // `doc_h - clip_h` up from the bottom.
249
+ CGPoint origin = ((CGPoint(*)(double, double))CGPointMake)(
250
+ 0, doc_frame.size.height - clip_bounds.size.height);
251
+ ((void(*)(id, SEL, CGPoint))objc_msgSend)(clip, sel_registerName("setBoundsOrigin:"), origin);
252
+ ((void(*)(id, SEL, id))objc_msgSend)((id)self->handle, sel_registerName("reflectScrolledClipView:"), clip);
253
+ ```
254
+ ```
255
+ #arch: aarch64_use_c
256
+ #platform: macos
257
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
258
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("documentView"));
259
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
260
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
261
+ // Set the clip's bounds origin directly — the one primitive the live
262
+ // scroll machinery can't constrain short of the edge. The unflipped
263
+ // document's top edge is at doc height; the visible origin sits
264
+ // `doc_h - clip_h` up from the bottom.
265
+ CGPoint origin = ((CGPoint(*)(double, double))CGPointMake)(
266
+ 0, doc_frame.size.height - clip_bounds.size.height);
267
+ ((void(*)(id, SEL, CGPoint))objc_msgSend)(clip, sel_registerName("setBoundsOrigin:"), origin);
268
+ ((void(*)(id, SEL, id))objc_msgSend)((id)self->handle, sel_registerName("reflectScrolledClipView:"), clip);
269
+ ```
270
+ ```
271
+ #arch: c
272
+ #platform: ios
273
+ /* TODO: iOS (see #init) */
274
+ ```
275
+ ```
276
+ #arch: aarch64_use_c
277
+ #platform: ios
278
+ /* TODO: iOS (see #init) */
279
+ ```
280
+ }
281
+
282
+ // How far the document is scrolled from its top, in document pixels
283
+ // (0 = top). Add this to a window-space click y (minus the scroll view's
284
+ // own origin) before hit-testing content children — see the Scrollable
285
+ // design note in GUI.md.
286
+ pub func scroll_offset_y = (self, out int) {
287
+ ```
288
+ #arch: c
289
+ #platform: macos
290
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
291
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("documentView"));
292
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
293
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
294
+ int offset = (int)(doc_frame.size.height - clip_bounds.size.height - clip_bounds.origin.y);
295
+ return offset < 0 ? 0 : offset; // content shorter than the viewport can't scroll
296
+ ```
297
+ ```
298
+ #arch: aarch64_use_c
299
+ #platform: macos
300
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
301
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("documentView"));
302
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
303
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
304
+ int offset = (int)(doc_frame.size.height - clip_bounds.size.height - clip_bounds.origin.y);
305
+ return offset < 0 ? 0 : offset; // content shorter than the viewport can't scroll
306
+ ```
307
+ ```
308
+ #arch: c
309
+ #platform: ios
310
+ /* TODO: iOS (see #init) */
311
+ return 0;
312
+ ```
313
+ ```
314
+ #arch: aarch64_use_c
315
+ #platform: ios
316
+ /* TODO: iOS (see #init) */
317
+ return 0;
318
+ ```
319
+ }
320
+
321
+ // Scroll so the BOTTOM of the document is visible (the unflipped document
322
+ // shows its bottom by default, so this restores the initial view after a
323
+ // `scroll_to_top`).
324
+ pub func scroll_to_bottom = (self) {
325
+ ```
326
+ #arch: c
327
+ #platform: macos
328
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
329
+ // Set the clip's bounds origin directly — the one primitive the live
330
+ // scroll machinery can't constrain short of the edge. (0, 0) is the
331
+ // unflipped document's bottom-left corner.
332
+ ((void(*)(id, SEL, CGPoint))objc_msgSend)(
333
+ clip, sel_registerName("setBoundsOrigin:"),
334
+ ((CGPoint(*)(double, double))CGPointMake)(0, 0));
335
+ ((void(*)(id, SEL, id))objc_msgSend)((id)self->handle, sel_registerName("reflectScrolledClipView:"), clip);
336
+ ```
337
+ ```
338
+ #arch: aarch64_use_c
339
+ #platform: macos
340
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
341
+ // Set the clip's bounds origin directly — the one primitive the live
342
+ // scroll machinery can't constrain short of the edge. (0, 0) is the
343
+ // unflipped document's bottom-left corner.
344
+ ((void(*)(id, SEL, CGPoint))objc_msgSend)(
345
+ clip, sel_registerName("setBoundsOrigin:"),
346
+ ((CGPoint(*)(double, double))CGPointMake)(0, 0));
347
+ ((void(*)(id, SEL, id))objc_msgSend)((id)self->handle, sel_registerName("reflectScrolledClipView:"), clip);
348
+ ```
349
+ ```
350
+ #arch: c
351
+ #platform: ios
352
+ /* TODO: iOS (see #init) */
353
+ ```
354
+ ```
355
+ #arch: aarch64_use_c
356
+ #platform: ios
357
+ /* TODO: iOS (see #init) */
358
+ ```
359
+ }
360
+
361
+ pub func set_hidden = (self, bool hidden) {
362
+ ```
363
+ #arch: c
364
+ #platform: macos
365
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(
366
+ (id)self->handle, sel_registerName("setHidden:"), hidden ? 1 : 0);
367
+ ```
368
+ ```
369
+ #arch: aarch64_use_c
370
+ #platform: macos
371
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(
372
+ (id)self->handle, sel_registerName("setHidden:"), hidden ? 1 : 0);
373
+ ```
374
+ ```
375
+ #arch: c
376
+ #platform: ios
377
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(
378
+ (id)self->handle, sel_registerName("setHidden:"), hidden ? 1 : 0);
379
+ ```
380
+ ```
381
+ #arch: aarch64_use_c
382
+ #platform: ios
383
+ ((void(*)(id, SEL, BOOL))objc_msgSend)(
384
+ (id)self->handle, sel_registerName("setHidden:"), hidden ? 1 : 0);
385
+ ```
386
+ }
387
+
388
+ // ── Control trait conformance ──
389
+ pub func set_frame = (ref self, int x, int y, int width, int height) {
390
+ ```
391
+ #arch: c
392
+ #platform: macos
393
+ ((void(*)(id, SEL, CGRect))objc_msgSend)(
394
+ (id)self->handle, sel_registerName("setFrame:"),
395
+ ((CGRect(*)(double, double, double, double))CGRectMake)((double)x, (double)y, (double)width, (double)height));
396
+ ```
397
+ ```
398
+ #arch: aarch64_use_c
399
+ #platform: macos
400
+ ((void(*)(id, SEL, CGRect))objc_msgSend)(
401
+ (id)self->handle, sel_registerName("setFrame:"),
402
+ ((CGRect(*)(double, double, double, double))CGRectMake)((double)x, (double)y, (double)width, (double)height));
403
+ ```
404
+ ```
405
+ #arch: c
406
+ #platform: ios
407
+ /* TODO: iOS (see #init) */
408
+ ```
409
+ ```
410
+ #arch: aarch64_use_c
411
+ #platform: ios
412
+ /* TODO: iOS (see #init) */
413
+ ```
414
+ }
415
+
416
+ pub func intrinsic_size = (self, out Size) {
417
+ var [w, h] = native_intrinsic(self.handle)
418
+ var s = Size()
419
+ s.width = w
420
+ s.height = h
421
+ return s
422
+ }
423
+
424
+ pub func measure = (self, BoxConstraints constraints, out Size) {
425
+ var Size s = self.intrinsic_size()
426
+ if s.width > constraints.max_width {
427
+ s.width = constraints.max_width
428
+ }
429
+ if s.width < constraints.min_width {
430
+ s.width = constraints.min_width
431
+ }
432
+ if s.height > constraints.max_height {
433
+ s.height = constraints.max_height
434
+ }
435
+ if s.height < constraints.min_height {
436
+ s.height = constraints.min_height
437
+ }
438
+ return s
439
+ }
440
+
441
+ func #destroy = () {
442
+ ```
443
+ #arch: c
444
+ #platform: macos
445
+ if (self->handle) {
446
+ ((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("removeFromSuperview"));
447
+ ((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
448
+ self->handle = 0;
449
+ }
450
+ self->doc = 0;
451
+ ```
452
+ ```
453
+ #arch: aarch64_use_c
454
+ #platform: macos
455
+ if (self->handle) {
456
+ ((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("removeFromSuperview"));
457
+ ((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
458
+ self->handle = 0;
459
+ }
460
+ self->doc = 0;
461
+ ```
462
+ ```
463
+ #arch: c
464
+ #platform: ios
465
+ /* TODO: iOS (see #init) */
466
+ ```
467
+ ```
468
+ #arch: aarch64_use_c
469
+ #platform: ios
470
+ /* TODO: iOS (see #init) */
471
+ ```
472
+ }
473
+
474
+ // The on_scroll desugar's drain (docs/HANDLERS.md): the synthesized
475
+ // pump arm polls this per frame. True on any frame whose pump saw
476
+ // scroll-wheel events; the deltas ride the dispatch window —
477
+ // `win.scroll_dx()` / `win.scroll_dy()` (dy positive scrolling up/away,
478
+ // dx positive right; a trackpad frame sums every small event). Scroll
479
+ // is continuous input, not a click: the edge means "this frame
480
+ // scrolled", and the magnitudes are the payload. The record is
481
+ // window-level (broadcast, like the mouse-down record) — handlers that
482
+ // care about WHICH scrollable route by hit-testing or by reading
483
+ // `self.scroll_offset_y()` deltas.
484
+ pub func take_scroll = (self, out bool) {
485
+ ```
486
+ #arch: c
487
+ #platform: macos
488
+ extern double nomen_scroll_dx_acc;
489
+ extern double nomen_scroll_dy_acc;
490
+ return (nomen_scroll_dx_acc != 0.0) || (nomen_scroll_dy_acc != 0.0);
491
+ ```
492
+ ```
493
+ #arch: aarch64_use_c
494
+ #platform: macos
495
+ extern double nomen_scroll_dx_acc;
496
+ extern double nomen_scroll_dy_acc;
497
+ return (nomen_scroll_dx_acc != 0.0) || (nomen_scroll_dy_acc != 0.0);
498
+ ```
499
+ ```
500
+ #arch: c
501
+ #platform: ios
502
+ return 0;
503
+ ```
504
+ ```
505
+ #arch: aarch64_use_c
506
+ #platform: ios
507
+ return 0;
508
+ ```
509
+ }
510
+ }
511
+
512
+ // Translate a WINDOW-space click (top-left origin, as click_x/click_y
513
+ // return) into the scroll view's DOCUMENT coordinates, so content children
514
+ // can be hit-tested with the content grid's `contains` while scrolled. The
515
+ // visible top-left of the document moves with the scroll position (and the
516
+ // clip view's own origin), so a raw click is off by both. A free function
517
+ // (not a method): a raw-block-backed method returning a tuple fails the
518
+ // checker's destructuring — native_intrinsic's free-function shape works.
519
+ pub func content_click = (Scrollable scroll, int cx, int cy, out [int, int]) {
520
+ ```
521
+ #arch: c
522
+ #platform: macos
523
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("contentView"));
524
+ id win = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("window"));
525
+ id cv = ((id(*)(id, SEL))objc_msgSend)(win, sel_registerName("contentView"));
526
+ CGRect cv_frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
527
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
528
+ // The visible rect in the window's content view (bottom-left origin).
529
+ CGRect visible = ((CGRect(*)(id, SEL, CGRect, id))objc_msgSend)(
530
+ clip, sel_registerName("convertRect:toView:"), clip_bounds, cv);
531
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("documentView"));
532
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
533
+ int visible_top = (int)(cv_frame.size.height - (visible.origin.y + visible.size.height));
534
+ int offset = (int)(doc_frame.size.height - clip_bounds.size.height - clip_bounds.origin.y);
535
+ if (offset < 0) offset = 0;
536
+ struct _Tuple_int_int r;
537
+ r._0 = cx - (int)visible.origin.x + (int)clip_bounds.origin.x;
538
+ r._1 = cy - visible_top + offset;
539
+ return r;
540
+ ```
541
+ ```
542
+ #arch: aarch64_use_c
543
+ #platform: macos
544
+ id clip = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("contentView"));
545
+ id win = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("window"));
546
+ id cv = ((id(*)(id, SEL))objc_msgSend)(win, sel_registerName("contentView"));
547
+ CGRect cv_frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
548
+ CGRect clip_bounds = ((CGRect(*)(id, SEL))objc_msgSend)(clip, sel_registerName("bounds"));
549
+ // The visible rect in the window's content view (bottom-left origin).
550
+ CGRect visible = ((CGRect(*)(id, SEL, CGRect, id))objc_msgSend)(
551
+ clip, sel_registerName("convertRect:toView:"), clip_bounds, cv);
552
+ id doc = ((id(*)(id, SEL))objc_msgSend)((id)scroll->handle, sel_registerName("documentView"));
553
+ CGRect doc_frame = ((CGRect(*)(id, SEL))objc_msgSend)(doc, sel_registerName("frame"));
554
+ int visible_top = (int)(cv_frame.size.height - (visible.origin.y + visible.size.height));
555
+ int offset = (int)(doc_frame.size.height - clip_bounds.size.height - clip_bounds.origin.y);
556
+ if (offset < 0) offset = 0;
557
+ struct _Tuple_int_int r;
558
+ r._0 = cx - (int)visible.origin.x + (int)clip_bounds.origin.x;
559
+ r._1 = cy - visible_top + offset;
560
+ return r;
561
+ ```
562
+ ```
563
+ #arch: c
564
+ #platform: ios
565
+ /* TODO: iOS (see #init) */
566
+ {
567
+ struct _Tuple_int_int r;
568
+ r._0 = 0;
569
+ r._1 = 0;
570
+ return r;
571
+ }
572
+ ```
573
+ ```
574
+ #arch: aarch64_use_c
575
+ #platform: ios
576
+ /* TODO: iOS (see #init) */
577
+ {
578
+ struct _Tuple_int_int r;
579
+ r._0 = 0;
580
+ r._1 = 0;
581
+ return r;
582
+ }
583
+ ```
584
+ }