nomen-lang 0.7.0 → 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 +3425 -710
- package/package.json +1 -1
package/core/System/Buffer.nm
CHANGED
|
@@ -220,6 +220,14 @@ pub struct Buffer<T> {
|
|
|
220
220
|
// reaching here is always a value type (primitive or struct).
|
|
221
221
|
|
|
222
222
|
func alloc = (ref self, int size, out int: out >= size) {
|
|
223
|
+
// Reclaim the old slab before the fresh calloc (the raw body runs
|
|
224
|
+
// for scalar / trivially-destructible elements — plain bytes, so a
|
|
225
|
+
// straight free is sound; mv element types take the specialized
|
|
226
|
+
// body, which per-element destroys first). The exact-cap contract
|
|
227
|
+
// is preserved: the fresh slab is calloc'd at exactly `size`.
|
|
228
|
+
if self.data != 0 {
|
|
229
|
+
free(self.data)
|
|
230
|
+
}
|
|
223
231
|
self.cap = size
|
|
224
232
|
self.data = calloc(size, T_SIZE)
|
|
225
233
|
return self.cap
|
|
@@ -550,6 +558,30 @@ pub struct Buffer<T> {
|
|
|
550
558
|
self.replace(i, value)
|
|
551
559
|
}
|
|
552
560
|
|
|
561
|
+
// Address of slot `i` (library-only): the ELEMENT BORROW primitive —
|
|
562
|
+
// `ref T x = list.at(i)` (docs/HANDLERS.md Stage 4, the dynamic-tree
|
|
563
|
+
// dispatch) lowers to this, binding the alias to the slot itself rather
|
|
564
|
+
// than to a bitwise copy. The pointer is valid while the buffer is
|
|
565
|
+
// exclusively borrowed and not resized; a `ref self` call on the buffer
|
|
566
|
+
// (push/pop/set/…) invalidates the borrow through the ordinary
|
|
567
|
+
// borrow-invalidation rules. Library-internal: the caller (the `List`
|
|
568
|
+
// wrapper, or trusted internals) bounds-checks; the body is raw-only so
|
|
569
|
+
// the missing-return net does not apply to the raw return.
|
|
570
|
+
pub func slot_ptr = (ref self, int i, out ptr T) {
|
|
571
|
+
```
|
|
572
|
+
#arch: c
|
|
573
|
+
return (T*)(unsigned long long)self->data + i;
|
|
574
|
+
```
|
|
575
|
+
```
|
|
576
|
+
#arch: aarch64
|
|
577
|
+
// x19 = self, x1 = i — the slot address (the load primitive's
|
|
578
|
+
// address-of: data + i * T_SIZE), returned in x0.
|
|
579
|
+
ldr x8, [x19, #8]
|
|
580
|
+
mov x9, #T_SIZE
|
|
581
|
+
madd x0, x1, x9, x8
|
|
582
|
+
```
|
|
583
|
+
}
|
|
584
|
+
|
|
553
585
|
// Move slot src into slot dst: overwrite dst with src's bytes and zero
|
|
554
586
|
// src, so exactly ONE slot owns the value afterwards. The
|
|
555
587
|
// ownership-transferring primitive behind backward-shift deletion
|
|
@@ -58,6 +58,30 @@ pub struct ClassBuffer<T> {
|
|
|
58
58
|
```
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Address of slot `i` (library-only): the ELEMENT BORROW primitive for
|
|
62
|
+
// trait/class elements — `ref T x = list.at(i)` (docs/HANDLERS.md Stage
|
|
63
|
+
// 4) reaches here through the List wrapper when the element is a trait
|
|
64
|
+
// (the items buffer is a ClassBuffer). ClassBuffer slots are 8-byte
|
|
65
|
+
// handles, so the slot's CONTENT is the instance pointer: return the
|
|
66
|
+
// stored word, not the slot's address. Library-internal: bounds are the
|
|
67
|
+
// caller's obligation (the List wrapper constrains them).
|
|
68
|
+
pub func slot_ptr = (ref self, int i, out ptr T) {
|
|
69
|
+
```
|
|
70
|
+
#arch: c
|
|
71
|
+
// The slot's address: through the alias, reads and writes hit the
|
|
72
|
+
// stored handle word. void* converts to the caller's `T*` spelling.
|
|
73
|
+
return (void *)&((unsigned long long *)self->data)[i];
|
|
74
|
+
```
|
|
75
|
+
```
|
|
76
|
+
#arch: aarch64
|
|
77
|
+
// 8-byte slots: the address of slot i — loading through it yields
|
|
78
|
+
// the stored handle.
|
|
79
|
+
ldr x8, [x19, #8]
|
|
80
|
+
lsl x9, x1, #3
|
|
81
|
+
add x0, x9, x8
|
|
82
|
+
```
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
// Generic (T-typed) counterparts of the _int primitives. ClassBuffer only
|
|
62
86
|
// ever holds 8-byte class pointers (T_SIZE is 8), so these are
|
|
63
87
|
// behaviorally identical to their _int counterparts — they exist so
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A system alert dialog (NSAlert)
|
|
3
|
+
*
|
|
4
|
+
* An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
|
|
5
|
+
* single field is a platform handle, so the value is movable and its
|
|
6
|
+
* `#destroy` releases what the handle names. The constructor's `self` is
|
|
7
|
+
* the inline instance (the `.` accessor); methods keep the pointer form.
|
|
8
|
+
*
|
|
9
|
+
* Window-coordinated: `run` enters NSAlert's own modal loop (it blocks the
|
|
10
|
+
* caller and pumps its own events, so it works with the manual loop), and
|
|
11
|
+
* returns the clicked button's index (first button = 0). iOS defers —
|
|
12
|
+
* UIAlertController needs a presenting view controller (TODO stubs; see
|
|
13
|
+
* GUI_PLAN Tier 1 #19).
|
|
14
|
+
**/
|
|
15
|
+
pub mv struct Alert : Control {
|
|
16
|
+
var uint64 handle = 0
|
|
17
|
+
|
|
18
|
+
// The `#handle` hook synthesizes `NameHandle` — a copyable, non-owning
|
|
19
|
+
// twin (same public bare-self methods, no destroy) so closures can
|
|
20
|
+
// capture this control without moving it. See GUI.md, "Handles".
|
|
21
|
+
#handle = () {}
|
|
22
|
+
|
|
23
|
+
pub func #init = (self) {
|
|
24
|
+
```
|
|
25
|
+
#arch: c
|
|
26
|
+
#platform: macos
|
|
27
|
+
id alert = ((id(*)(id, SEL))objc_msgSend)(
|
|
28
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSAlert"), sel_registerName("alloc")),
|
|
29
|
+
sel_registerName("init"));
|
|
30
|
+
self.handle = (uint64_t)alert;
|
|
31
|
+
```
|
|
32
|
+
```
|
|
33
|
+
#arch: aarch64_use_c
|
|
34
|
+
#platform: macos
|
|
35
|
+
id alert = ((id(*)(id, SEL))objc_msgSend)(
|
|
36
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSAlert"), sel_registerName("alloc")),
|
|
37
|
+
sel_registerName("init"));
|
|
38
|
+
self->handle = (uint64_t)alert;
|
|
39
|
+
```
|
|
40
|
+
```
|
|
41
|
+
#arch: c
|
|
42
|
+
#platform: ios
|
|
43
|
+
/* TODO: iOS — UIAlertController needs a presenting view controller
|
|
44
|
+
* (see GUI_PLAN Tier 1 #19; defer the iOS block). */
|
|
45
|
+
```
|
|
46
|
+
```
|
|
47
|
+
#arch: aarch64_use_c
|
|
48
|
+
#platform: ios
|
|
49
|
+
/* TODO: iOS — UIAlertController needs a presenting view controller
|
|
50
|
+
* (see GUI_PLAN Tier 1 #19; defer the iOS block). */
|
|
51
|
+
```
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// The alert's headline (bold first line).
|
|
55
|
+
pub func set_title = (self, string title) {
|
|
56
|
+
```
|
|
57
|
+
#arch: c
|
|
58
|
+
#platform: macos
|
|
59
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
60
|
+
(id)self->handle, sel_registerName("setMessageText:"),
|
|
61
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
62
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
63
|
+
```
|
|
64
|
+
```
|
|
65
|
+
#arch: aarch64_use_c
|
|
66
|
+
#platform: macos
|
|
67
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
68
|
+
(id)self->handle, sel_registerName("setMessageText:"),
|
|
69
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
70
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
71
|
+
```
|
|
72
|
+
```
|
|
73
|
+
#arch: c
|
|
74
|
+
#platform: ios
|
|
75
|
+
/* TODO: iOS (see #init) */
|
|
76
|
+
```
|
|
77
|
+
```
|
|
78
|
+
#arch: aarch64_use_c
|
|
79
|
+
#platform: ios
|
|
80
|
+
/* TODO: iOS (see #init) */
|
|
81
|
+
```
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
pub func title = (self, out string) {
|
|
85
|
+
```
|
|
86
|
+
#arch: c
|
|
87
|
+
#platform: macos
|
|
88
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
89
|
+
(id)self->handle, sel_registerName("messageText"));
|
|
90
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
91
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
92
|
+
str, sel_registerName("UTF8String"));
|
|
93
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
94
|
+
```
|
|
95
|
+
```
|
|
96
|
+
#arch: aarch64_use_c
|
|
97
|
+
#platform: macos
|
|
98
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
99
|
+
(id)self->handle, sel_registerName("messageText"));
|
|
100
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
101
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
102
|
+
str, sel_registerName("UTF8String"));
|
|
103
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
104
|
+
```
|
|
105
|
+
```
|
|
106
|
+
#arch: c
|
|
107
|
+
#platform: ios
|
|
108
|
+
/* TODO: iOS (see #init) */
|
|
109
|
+
return (nomen_string){ strdup(""), 0 };
|
|
110
|
+
```
|
|
111
|
+
```
|
|
112
|
+
#arch: aarch64_use_c
|
|
113
|
+
#platform: ios
|
|
114
|
+
/* TODO: iOS (see #init) */
|
|
115
|
+
return (nomen_string){ strdup(""), 0 };
|
|
116
|
+
```
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// The explanatory second line.
|
|
120
|
+
pub func set_message = (self, string message) {
|
|
121
|
+
```
|
|
122
|
+
#arch: c
|
|
123
|
+
#platform: macos
|
|
124
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
125
|
+
(id)self->handle, sel_registerName("setInformativeText:"),
|
|
126
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
127
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), message.ptr));
|
|
128
|
+
```
|
|
129
|
+
```
|
|
130
|
+
#arch: aarch64_use_c
|
|
131
|
+
#platform: macos
|
|
132
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
133
|
+
(id)self->handle, sel_registerName("setInformativeText:"),
|
|
134
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
135
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), message.ptr));
|
|
136
|
+
```
|
|
137
|
+
```
|
|
138
|
+
#arch: c
|
|
139
|
+
#platform: ios
|
|
140
|
+
/* TODO: iOS (see #init) */
|
|
141
|
+
```
|
|
142
|
+
```
|
|
143
|
+
#arch: aarch64_use_c
|
|
144
|
+
#platform: ios
|
|
145
|
+
/* TODO: iOS (see #init) */
|
|
146
|
+
```
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
pub func message = (self, out string) {
|
|
150
|
+
```
|
|
151
|
+
#arch: c
|
|
152
|
+
#platform: macos
|
|
153
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
154
|
+
(id)self->handle, sel_registerName("informativeText"));
|
|
155
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
156
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
157
|
+
str, sel_registerName("UTF8String"));
|
|
158
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
159
|
+
```
|
|
160
|
+
```
|
|
161
|
+
#arch: aarch64_use_c
|
|
162
|
+
#platform: macos
|
|
163
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
164
|
+
(id)self->handle, sel_registerName("informativeText"));
|
|
165
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
166
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
167
|
+
str, sel_registerName("UTF8String"));
|
|
168
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
169
|
+
```
|
|
170
|
+
```
|
|
171
|
+
#arch: c
|
|
172
|
+
#platform: ios
|
|
173
|
+
/* TODO: iOS (see #init) */
|
|
174
|
+
return (nomen_string){ strdup(""), 0 };
|
|
175
|
+
```
|
|
176
|
+
```
|
|
177
|
+
#arch: aarch64_use_c
|
|
178
|
+
#platform: ios
|
|
179
|
+
/* TODO: iOS (see #init) */
|
|
180
|
+
return (nomen_string){ strdup(""), 0 };
|
|
181
|
+
```
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Append a button (left to right). The FIRST button is the default
|
|
185
|
+
// (Return); the clicked one's index is what `run` returns. A fresh
|
|
186
|
+
// NSAlert carries one default button ("OK") — the first
|
|
187
|
+
// `add_button` REPLACES it, so the count stays what the app adds.
|
|
188
|
+
pub func add_button = (self, string title) {
|
|
189
|
+
```
|
|
190
|
+
#arch: c
|
|
191
|
+
#platform: macos
|
|
192
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
193
|
+
(id)self->handle, sel_registerName("addButtonWithTitle:"),
|
|
194
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
195
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
196
|
+
```
|
|
197
|
+
```
|
|
198
|
+
#arch: aarch64_use_c
|
|
199
|
+
#platform: macos
|
|
200
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
201
|
+
(id)self->handle, sel_registerName("addButtonWithTitle:"),
|
|
202
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
203
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
204
|
+
```
|
|
205
|
+
```
|
|
206
|
+
#arch: c
|
|
207
|
+
#platform: ios
|
|
208
|
+
/* TODO: iOS (see #init) */
|
|
209
|
+
```
|
|
210
|
+
```
|
|
211
|
+
#arch: aarch64_use_c
|
|
212
|
+
#platform: ios
|
|
213
|
+
/* TODO: iOS (see #init) */
|
|
214
|
+
```
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// How many buttons the alert carries.
|
|
218
|
+
pub func button_count = (self, out int) {
|
|
219
|
+
```
|
|
220
|
+
#arch: c
|
|
221
|
+
#platform: macos
|
|
222
|
+
id buttons = ((id(*)(id, SEL))objc_msgSend)(
|
|
223
|
+
(id)self->handle, sel_registerName("buttons"));
|
|
224
|
+
return (int)((long(*)(id, SEL))objc_msgSend)(buttons, sel_registerName("count"));
|
|
225
|
+
```
|
|
226
|
+
```
|
|
227
|
+
#arch: aarch64_use_c
|
|
228
|
+
#platform: macos
|
|
229
|
+
id buttons = ((id(*)(id, SEL))objc_msgSend)(
|
|
230
|
+
(id)self->handle, sel_registerName("buttons"));
|
|
231
|
+
return (int)((long(*)(id, SEL))objc_msgSend)(buttons, sel_registerName("count"));
|
|
232
|
+
```
|
|
233
|
+
```
|
|
234
|
+
#arch: c
|
|
235
|
+
#platform: ios
|
|
236
|
+
/* TODO: iOS (see #init) */
|
|
237
|
+
return 0;
|
|
238
|
+
```
|
|
239
|
+
```
|
|
240
|
+
#arch: aarch64_use_c
|
|
241
|
+
#platform: ios
|
|
242
|
+
/* TODO: iOS (see #init) */
|
|
243
|
+
return 0;
|
|
244
|
+
```
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Show the alert modally and return the clicked button's index (0 =
|
|
248
|
+
// first button). BLOCKS in NSAlert's own modal loop until dismissed —
|
|
249
|
+
// call it from the event thread when the manual loop can afford to
|
|
250
|
+
// pause (NSAlert pumps its own events, so the UI stays live).
|
|
251
|
+
pub func run = (self, out int) {
|
|
252
|
+
```
|
|
253
|
+
#arch: c
|
|
254
|
+
#platform: macos
|
|
255
|
+
long code = ((long(*)(id, SEL))objc_msgSend)(
|
|
256
|
+
(id)self->handle, sel_registerName("runModal"));
|
|
257
|
+
return (int)(code - 1000); // NSModalResponseOK = 1000 + button index
|
|
258
|
+
```
|
|
259
|
+
```
|
|
260
|
+
#arch: aarch64_use_c
|
|
261
|
+
#platform: macos
|
|
262
|
+
long code = ((long(*)(id, SEL))objc_msgSend)(
|
|
263
|
+
(id)self->handle, sel_registerName("runModal"));
|
|
264
|
+
return (int)(code - 1000); // NSModalResponseOK = 1000 + button index
|
|
265
|
+
```
|
|
266
|
+
```
|
|
267
|
+
#arch: c
|
|
268
|
+
#platform: ios
|
|
269
|
+
/* TODO: iOS (see #init) */
|
|
270
|
+
return 0;
|
|
271
|
+
```
|
|
272
|
+
```
|
|
273
|
+
#arch: aarch64_use_c
|
|
274
|
+
#platform: ios
|
|
275
|
+
/* TODO: iOS (see #init) */
|
|
276
|
+
return 0;
|
|
277
|
+
```
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ── Control trait conformance ──
|
|
281
|
+
// An alert is a modal, not an in-window view: it measures to nothing and
|
|
282
|
+
// the layout engine never frames it. The conformance exists so an Alert
|
|
283
|
+
// can sit in a Control-typed slot without special-casing.
|
|
284
|
+
pub func set_frame = (ref self, int x, int y, int width, int height) {
|
|
285
|
+
// No-op: modals are positioned by the window server.
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
pub func intrinsic_size = (self, out Size) {
|
|
289
|
+
var s = Size()
|
|
290
|
+
return s
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
pub func measure = (self, BoxConstraints constraints, out Size) {
|
|
294
|
+
var s = Size()
|
|
295
|
+
return s
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
func #destroy = () {
|
|
299
|
+
```
|
|
300
|
+
#arch: c
|
|
301
|
+
#platform: macos
|
|
302
|
+
if (self->handle) {
|
|
303
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
304
|
+
self->handle = 0;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
```
|
|
308
|
+
#arch: aarch64_use_c
|
|
309
|
+
#platform: macos
|
|
310
|
+
if (self->handle) {
|
|
311
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
312
|
+
self->handle = 0;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
```
|
|
316
|
+
#arch: c
|
|
317
|
+
#platform: ios
|
|
318
|
+
/* TODO: iOS (see #init) */
|
|
319
|
+
```
|
|
320
|
+
```
|
|
321
|
+
#arch: aarch64_use_c
|
|
322
|
+
#platform: ios
|
|
323
|
+
/* TODO: iOS (see #init) */
|
|
324
|
+
```
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The App contract: the object Window.run drives
|
|
3
|
+
*
|
|
4
|
+
* The WinForms/Swift shape for a manual-loop toolkit: instead of pumping
|
|
5
|
+
* `Window.process_events` and re-checking sizes in a `while` loop, the app
|
|
6
|
+
* declares a struct conforming to `App`, moves it into `win.run(mv app)`,
|
|
7
|
+
* and the WINDOW owns everything else — the event pump, the autorelease
|
|
8
|
+
* pool, resize detection, and the relayout of the hosted content (the root
|
|
9
|
+
* `Container` from `win.set_content` plus every `Scrollable.set_content`
|
|
10
|
+
* document). The app implements four hooks:
|
|
11
|
+
*
|
|
12
|
+
* - `start` — called once, after the app has been moved into its final
|
|
13
|
+
* storage but before the window is shown. Register the layout roots here
|
|
14
|
+
* (`win.set_content(ref grid)`, `scroll.set_content(ref grid)`) and do
|
|
15
|
+
* any wiring that needs stable addresses — including click handlers
|
|
16
|
+
* (`self.btn.on_click(func () { ... })`).
|
|
17
|
+
* - `frame` — called every iteration of the run loop with a `FrameEvents`
|
|
18
|
+
* value: the full input record for this frame (click kind/coordinates,
|
|
19
|
+
* `mouse_button`/`mouse_click_count`/`mouse_modifiers` — every button,
|
|
20
|
+
* `scroll_dx`/`scroll_dy`, the keyboard record
|
|
21
|
+
* `key_code`/`key_modifiers`/`key_repeat`/`key_up_code`, the pointer
|
|
22
|
+
* position `mouse_x`/`mouse_y`, and frame time `dt`), and `resized`
|
|
23
|
+
* + the new size when the window's content rect changed. Per-frame value
|
|
24
|
+
* polling (slider → progress mirrors), coordinate-driven input that no
|
|
25
|
+
* event names, and app-owned pane relayouts live here — registered
|
|
26
|
+
* click, right-click, mouse-down, scroll, key, move, and resize handlers
|
|
27
|
+
* dispatch earlier, in `handle_events` (the `.on_click` /
|
|
28
|
+
* `.on_right_click` / `.on_mouse_down` / `.on_scroll` / `.on_key_down` /
|
|
29
|
+
* `.on_key_up` / `.on_mouse_move` / `.on_resize` desugars), and close
|
|
30
|
+
* requests consult `close_requested`.
|
|
31
|
+
* - `handle_events` — the per-frame event pump: drains every registered
|
|
32
|
+
* control event (clicks, focus/blur, text input). Declared here as a
|
|
33
|
+
* default-empty method; the `.on_<event>(closure)` desugars
|
|
34
|
+
* (docs/HANDLERS.md) synthesize the override on conformers with
|
|
35
|
+
* registrations, so user code only writes the registration and never
|
|
36
|
+
* sees the machinery. New control events extend the pump's arms — the
|
|
37
|
+
* App contract is fixed.
|
|
38
|
+
* - `run_handler` — the up-call protocol (Stage 3): a composite with an
|
|
39
|
+
* enrolled event calls back `owner.run_handler(id, ref win)` from its
|
|
40
|
+
* `tick` (the app forwards itself down once per tick). Default-empty;
|
|
41
|
+
* the desugar synthesizes the override dispatching ids to the app's
|
|
42
|
+
* `.on_<event>` handlers.
|
|
43
|
+
*
|
|
44
|
+
* Handlers are METHODS on the app (the `ref self` receiver), so app state —
|
|
45
|
+
* every control field — is reachable without lambda captures (capturing a
|
|
46
|
+
* control MOVES it; a capture-free method reference moves nothing). The
|
|
47
|
+
* `.on_click` desugar is that shape with registration ergonomics: the
|
|
48
|
+
* closure you write IS hoisted into a hidden method, and the dispatch
|
|
49
|
+
* borrow of `self` is taken by the run loop per frame.
|
|
50
|
+
**/
|
|
51
|
+
pub trait App {
|
|
52
|
+
// Called once before the window is shown, after the app is in its
|
|
53
|
+
// final storage. Register layout roots here.
|
|
54
|
+
func start = (ref self, ref Window win) {
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Called every frame until the window closes.
|
|
58
|
+
func frame = (ref self, ref Window win, FrameEvents ev) {
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// The per-frame event pump: drains every registered control event —
|
|
62
|
+
// clicks, focus/blur, text input — through arms the `.on_<event>`
|
|
63
|
+
// desugar (docs/HANDLERS.md) synthesizes on conformers with
|
|
64
|
+
// registrations: one hidden method per closure, one drain arm per
|
|
65
|
+
// registered control, one event-source prologue per family.
|
|
66
|
+
// `Window.run` calls it before `frame`. New control events are new arms
|
|
67
|
+
// in this one slot — the App contract never grows with the event
|
|
68
|
+
// catalog. Conformers without registrations inherit this empty default
|
|
69
|
+
// (trait defaults have precedent: `Enumerable.length`).
|
|
70
|
+
func handle_events = (ref self, ref Window win) {
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The up-call protocol (docs/HANDLERS.md Stage 3): a composite the app
|
|
74
|
+
// has enrolled events on calls back into this — `owner.run_handler(id,
|
|
75
|
+
// ref win)` from its `tick` — one vtable hop into the desugar's
|
|
76
|
+
// synthesized override, whose arms dispatch the id to the app's handler.
|
|
77
|
+
// The borrow flows down per call; nothing outlives it. Default-empty,
|
|
78
|
+
// like `handle_events`.
|
|
79
|
+
func run_handler = (ref self, int id, ref Window win) {
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Close interception (the unsaved-changes pattern): run consults this
|
|
83
|
+
// on the frame after the user requests close (the red button — the
|
|
84
|
+
// delegate refuses the native close and sets a pending flag). Return
|
|
85
|
+
// false to refuse: the window stays, the flag is cleared, and a later
|
|
86
|
+
// close request consults again. Programmatic `win.close()` is FORCED
|
|
87
|
+
// and bypasses this — handlers closing their own window never trip the
|
|
88
|
+
// interception. Default: allow.
|
|
89
|
+
func close_requested = (ref self, ref Window win, out bool) {
|
|
90
|
+
return true
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* One frame's input state, passed to App.frame
|
|
96
|
+
*
|
|
97
|
+
* Pure scalars, so the by-value parameter copies safely (no destroy).
|
|
98
|
+
* Click coordinates are the window's content coordinates, top-left origin
|
|
99
|
+
* (the same values `Window.click_x`/`click_y` report) — translate through
|
|
100
|
+
* `content_click` before hit-testing controls hosted on a Scrollable.
|
|
101
|
+
**/
|
|
102
|
+
pub mv struct FrameEvents {
|
|
103
|
+
// 0 = no mouse-down this frame, 1 = left, 2 = right (edge-triggered:
|
|
104
|
+
// only the frame that pumped the event reports it).
|
|
105
|
+
pub var int click = 0
|
|
106
|
+
pub var int click_x = -1
|
|
107
|
+
pub var int click_y = -1
|
|
108
|
+
// The full mouse record for this frame (0 = no mouse-down): the 1-based
|
|
109
|
+
// button number (1 left, 2 right, 3 middle, 4+ extra buttons), the
|
|
110
|
+
// AppKit click count (2 = double-click), and the device-independent
|
|
111
|
+
// modifier flags (Command = 0x100000, Option = 0x80000, Control =
|
|
112
|
+
// 0x40000, Shift = 0x20000). The same values the `win.mouse_button()` /
|
|
113
|
+
// `mouse_click_count()` / `mouse_modifiers()` getters report to
|
|
114
|
+
// `on_mouse_down` handlers. `click` remains the left/right compat view.
|
|
115
|
+
pub var int mouse_button = 0
|
|
116
|
+
pub var int mouse_click_count = 0
|
|
117
|
+
pub var int mouse_modifiers = 0
|
|
118
|
+
// This frame's accumulated scroll-wheel deltas (dy positive scrolling
|
|
119
|
+
// up/away, dx positive right; trackpad frames sum every small event).
|
|
120
|
+
// `Scrollable.on_scroll` is the registered-handler form.
|
|
121
|
+
pub var int scroll_dx = 0
|
|
122
|
+
pub var int scroll_dy = 0
|
|
123
|
+
// The keyboard record for this frame (-1 = no key this frame): the
|
|
124
|
+
// hardware keycode of the last key-down (Space = 49, Return = 36,
|
|
125
|
+
// arrows = 123–126, letters a…z = 0–25), the modifiers at key-down,
|
|
126
|
+
// whether it was an auto-repeat, and the keycode of the last key-up.
|
|
127
|
+
// `on_key_down` / `on_key_up` are the registered-handler forms; text
|
|
128
|
+
// ENTRY flows through `on_input` (the field editor), not here.
|
|
129
|
+
pub var int key_code = -1
|
|
130
|
+
pub var int key_modifiers = 0
|
|
131
|
+
pub var bool key_repeat = false
|
|
132
|
+
pub var int key_up_code = -1
|
|
133
|
+
// The pointer-MOVE record for this frame (-1 = no movement): the
|
|
134
|
+
// current pointer position. `on_mouse_move` is the registered-handler
|
|
135
|
+
// form; hover/tooltips hit-test this against Container.contains.
|
|
136
|
+
pub var int mouse_x = -1
|
|
137
|
+
pub var int mouse_y = -1
|
|
138
|
+
// Milliseconds since the previous frame (0 on the first) — the
|
|
139
|
+
// animation clock. `win.dt()` reports the same value.
|
|
140
|
+
pub var int dt = 0
|
|
141
|
+
// True when the window's content rect changed since the last frame —
|
|
142
|
+
// the framework has already re-laid-out the registered roots; re-layout
|
|
143
|
+
// App-owned panes (tab pages, split panes) here.
|
|
144
|
+
pub var bool resized = false
|
|
145
|
+
pub var int width = 0
|
|
146
|
+
pub var int height = 0
|
|
147
|
+
}
|