@cssints/apg-specs 0.5.2 → 0.6.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/README.md +9 -4
- package/dist/patterns/resizable-panels.bridge.d.mts +44 -0
- package/dist/patterns/resizable-panels.bridge.mjs +287 -0
- package/dist/patterns/resizable-panels.model.json +11221 -0
- package/package.json +8 -1
- package/scenarios/patterns/README.md +12 -0
- package/scenarios/patterns/resizable-panels.spec.json +539 -0
- package/specs/patterns/resizable-panels.qnt +831 -0
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
// Resizable panels: a group of N panes and N-1 separators (bean cssints-pyit).
|
|
2
|
+
//
|
|
3
|
+
// Not an APG pattern: it is a group of APG window splitters, so the vocabulary
|
|
4
|
+
// and the keyboard contract come from windowsplitter.qnt, the layout from
|
|
5
|
+
// react-resizable-panels. Researched for the decisions below:
|
|
6
|
+
// - react-resizable-panels v4 (bvaughn): panels carry min/max in % of the
|
|
7
|
+
// group, `collapsible` + `collapsedSize`, a layout is a list of percentages
|
|
8
|
+
// that always sums to 100, `onLayoutChange` fires on every pointer move and
|
|
9
|
+
// `onLayoutChanged` on release (persist there), drag is pointer capture,
|
|
10
|
+
// double-click resets to the default layout, Home/End and arrows resize,
|
|
11
|
+
// Enter toggles collapse.
|
|
12
|
+
// - Radix/Ark splitter: the same model (sizes %, min/max, collapsible, arrows,
|
|
13
|
+
// Enter), one separator between two neighbours.
|
|
14
|
+
// - APG window splitter: the separator is the focusable widget; aria-valuenow
|
|
15
|
+
// is the size of the pane it resizes (aria-controls), aria-valuemin / -max
|
|
16
|
+
// its bounds, orientation names the bar, arrows move by a step, Home/End are
|
|
17
|
+
// optional jumps, Enter collapses and restores, F6 cycles panes.
|
|
18
|
+
//
|
|
19
|
+
// MODELLED: three panes in percentages on a 10% grid, 100 in total, MIN 10 and
|
|
20
|
+
// MAX 80 per pane, pane 0 collapsible at collapsedSize 0. One separator sits
|
|
21
|
+
// between each pair, its aria-valuenow is the size of the pane on its left.
|
|
22
|
+
// Focus is per separator (the group's tab stops; no F6: with three panes the
|
|
23
|
+
// cycle buys nothing a Tab does not, so the primitive leaves it out).
|
|
24
|
+
//
|
|
25
|
+
// A MOVE (arrow, Home/End, drag) changes only the separator's two neighbours:
|
|
26
|
+
// pane i grows or shrinks, pane i+1 takes the opposite amount, and the result is
|
|
27
|
+
// clamped by BOTH panes' bounds (no cascade past the neighbour). Collapsing pane
|
|
28
|
+
// 0 gives its space to the nearest pane that can take it and cascades outward
|
|
29
|
+
// (pane 1 up to MAX, then pane 2); restoring takes it back in the same order, so
|
|
30
|
+
// a restore always returns exactly the remembered size (prev0 <= 80 and the
|
|
31
|
+
// panes right of a collapsed pane hold 100, so the space is always there).
|
|
32
|
+
// A separator next to a collapsed pane is immovable: its arrows and its drag are
|
|
33
|
+
// no-ops, and only Enter (the restore) acts. Collapsed size 0 is the collapsed
|
|
34
|
+
// state; a pane cannot be dragged below MIN while expanded.
|
|
35
|
+
//
|
|
36
|
+
// DRAG is snapshot + delta, as in canvas/pointer.qnt: pointerdown remembers the
|
|
37
|
+
// layout (k0..k2) and the separator (dr), each move adds NOTCH to the delta (dd,
|
|
38
|
+
// bounded to +/-100) and the layout is re-solved from the snapshot, never
|
|
39
|
+
// accumulated, so dragging back past a clamp recovers exactly. pointerup ends
|
|
40
|
+
// the drag (the newest pointerdown takes over and re-snapshots); a host write
|
|
41
|
+
// cancels it, and the keyboard is a no-op while it runs. A drag never changes a
|
|
42
|
+
// pane outside its pair (DragMovesOnlyNeighbours).
|
|
43
|
+
//
|
|
44
|
+
// REQUEST VS COMMIT is the windowsplitter contract (map ticket rt1p), applied to
|
|
45
|
+
// the whole layout: every move requests the target layout (rq0..rq2) and bumps
|
|
46
|
+
// `requests` when it differs from the current sizes; uncontrolled (or a
|
|
47
|
+
// controlled host that accepts, `accepting`) commits it, a controlled host that
|
|
48
|
+
// holds ignores it ("rejected"). The host writes the layout with hostEqual /
|
|
49
|
+
// hostWide / hostNarrow / hostCollapsed (the only commit while controlled) and
|
|
50
|
+
// settles `outcome` back to "none". base0..base2 is the layout a request found.
|
|
51
|
+
//
|
|
52
|
+
// NOT MODELLED: pane min/max other than 10/80, collapsedSize other than 0, more
|
|
53
|
+
// than three panes (the primitive takes N; this model is the three-pane instance
|
|
54
|
+
// its tests run), collapsing a pane other than pane 0, the collapsed threshold
|
|
55
|
+
// react-resizable-panels uses (a pane collapses on Enter or at the host's
|
|
56
|
+
// request, never by dragging through MIN), persistence (host storage), nested
|
|
57
|
+
// groups, and F6.
|
|
58
|
+
//
|
|
59
|
+
// GENERATOR GAPS HIT: no parameterized actions and no collections, so a drag
|
|
60
|
+
// delta is a bounded int advanced by dragNext/dragPrev and the three sizes are
|
|
61
|
+
// three vars; every action assigns every var.
|
|
62
|
+
module patterns_resizable_panels {
|
|
63
|
+
import aria.* from "../../shared/aria"
|
|
64
|
+
|
|
65
|
+
var o: str // orientation: "vertical" (columns) | "horizontal" (rows)
|
|
66
|
+
var s0: int // committed size of pane 0, in percent (0 = collapsed)
|
|
67
|
+
var s1: int // pane 1
|
|
68
|
+
var s2: int // pane 2
|
|
69
|
+
var prev0: int // pane 0's size remembered at its last collapse
|
|
70
|
+
var focus: str // "none" | "sep0" | "sep1"
|
|
71
|
+
var justRestored: bool // the last event was an Enter that restored pane 0
|
|
72
|
+
var rq0: int // target of the last request: pane 0
|
|
73
|
+
var rq1: int // pane 1
|
|
74
|
+
var rq2: int // pane 2
|
|
75
|
+
var b0: int // sizes when the last request was received
|
|
76
|
+
var b1: int
|
|
77
|
+
var b2: int
|
|
78
|
+
var k0: int // pointerdown snapshot of a drag
|
|
79
|
+
var k1: int
|
|
80
|
+
var k2: int
|
|
81
|
+
var dd: int // drag delta since pointerdown, percent
|
|
82
|
+
var dr: int // separator being dragged (-1 = none)
|
|
83
|
+
var outcome: str // "none" | "accepted" | "rejected"
|
|
84
|
+
var controlled: bool // the host owns the layout (`sizes` prop present)
|
|
85
|
+
var accepting: bool // controlled host that answers every request with its intent
|
|
86
|
+
var requests: int // onSizesChange calls
|
|
87
|
+
|
|
88
|
+
def MIN: int = 10
|
|
89
|
+
def MAX: int = 80
|
|
90
|
+
def ZERO: int = 0
|
|
91
|
+
def FULL: int = 100
|
|
92
|
+
def STEP: int = 10
|
|
93
|
+
def NOTCH: int = 10
|
|
94
|
+
def DMAX: int = 100
|
|
95
|
+
def FAR: int = 100
|
|
96
|
+
def INIT0: int = 20
|
|
97
|
+
def INIT1: int = 40
|
|
98
|
+
def INIT2: int = 40
|
|
99
|
+
|
|
100
|
+
def clampI(v: int, lo: int, hi: int): int = if (v < lo) lo else if (v > hi) hi else v
|
|
101
|
+
def minI(a: int, b: int): int = if (a < b) a else b
|
|
102
|
+
def maxI(a: int, b: int): int = if (a > b) a else b
|
|
103
|
+
|
|
104
|
+
// --- the layout ---------------------------------------------------------
|
|
105
|
+
def isCollapsed(i: int): bool = and(i == 0, s0 == ZERO)
|
|
106
|
+
def onSep(i: int): bool = focus == (if (i == 0) "sep0" else "sep1")
|
|
107
|
+
def sepA(i: int): int = if (i == 0) s0 else s1
|
|
108
|
+
def sepB(i: int): int = if (i == 0) s1 else s2
|
|
109
|
+
// the new size of the left pane of a pair (a, b) moved by d, clamped by both
|
|
110
|
+
def solved(a: int, b: int, d: int): int =
|
|
111
|
+
clampI(a + d, maxI(MIN, a + b - MAX), minI(MAX, a + b - MIN))
|
|
112
|
+
|
|
113
|
+
// the focused separator, or -1
|
|
114
|
+
def fIdx: int = if (focus == "sep0") 0 else if (focus == "sep1") 1 else 0 - 1
|
|
115
|
+
def fA: int = sepA(fIdx)
|
|
116
|
+
def fB: int = sepB(fIdx)
|
|
117
|
+
def fMovable: bool = and(fIdx >= 0, and(not(isCollapsed(fIdx)), not(isCollapsed(fIdx + 1))))
|
|
118
|
+
// the pointer owns the interaction while a drag runs: keys are no-ops then
|
|
119
|
+
def dragging: bool = dr >= 0
|
|
120
|
+
def arrowA(axis: str, d: int): int =
|
|
121
|
+
if (and(fMovable, and(o == axis, not(dragging)))) solved(fA, fB, d) else fA
|
|
122
|
+
def jumpA(d: int): int = if (and(fMovable, not(dragging))) solved(fA, fB, d) else fA
|
|
123
|
+
// the requested layout after the focused separator's left pane becomes na
|
|
124
|
+
def triple0(na: int): int = if (fIdx == 0) na else s0
|
|
125
|
+
def triple1(na: int): int = if (fIdx == 0) fA + fB - na else if (fIdx == 1) na else s1
|
|
126
|
+
def triple2(na: int): int = if (fIdx == 1) fA + fB - na else s2
|
|
127
|
+
|
|
128
|
+
// --- collapse / restore (pane 0 only) -----------------------------------
|
|
129
|
+
def enterOn: bool = and(focus == "sep0", not(dragging))
|
|
130
|
+
def collapsedNow: bool = s0 == ZERO
|
|
131
|
+
def restGive1: int = minI(prev0, s1 - MIN)
|
|
132
|
+
def enterA: int = if (enterOn) (if (collapsedNow) prev0 else ZERO) else s0
|
|
133
|
+
def enterB: int =
|
|
134
|
+
if (enterOn) (if (collapsedNow) s1 - restGive1 else minI(s0 + s1, MAX)) else s1
|
|
135
|
+
def enterC: int = if (enterOn) FULL - enterA - enterB else s2
|
|
136
|
+
|
|
137
|
+
// --- drag (snapshot + delta) --------------------------------------------
|
|
138
|
+
def dragOk: bool = and(dr >= 0, and(not(isCollapsed(dr)), not(isCollapsed(dr + 1))))
|
|
139
|
+
def dragA: int = if (dr == 0) k0 else k1
|
|
140
|
+
def dragB: int = if (dr == 0) k1 else k2
|
|
141
|
+
def dragSolved(d: int): int = if (dragOk) solved(dragA, dragB, d) else dragA
|
|
142
|
+
def dragT0(d: int): int = if (dragOk) (if (dr == 0) dragSolved(d) else k0) else s0
|
|
143
|
+
def dragT1(d: int): int =
|
|
144
|
+
if (dragOk) (if (dr == 0) dragA + dragB - dragSolved(d) else dragSolved(d)) else s1
|
|
145
|
+
def dragT2(d: int): int = if (dragOk) (if (dr == 1) dragA + dragB - dragSolved(d) else k2) else s2
|
|
146
|
+
def ddNext(d: int): int = clampI(dd + d, 0 - DMAX, DMAX)
|
|
147
|
+
|
|
148
|
+
// --- request / commit ---------------------------------------------------
|
|
149
|
+
def holds: bool = and(controlled, not(accepting))
|
|
150
|
+
def verdict: str = if (holds) "rejected" else "accepted"
|
|
151
|
+
def landed(h: bool, v: int, want: int): int = if (h) v else want
|
|
152
|
+
def differs(a0: int, a1: int, a2: int): bool = or(s0 != a0, or(s1 != a1, s2 != a2))
|
|
153
|
+
def moved(a0: int, a1: int, a2: int): int = if (differs(a0, a1, a2)) 1 else 0
|
|
154
|
+
def enterChanged: bool = differs(enterA, enterB, enterC)
|
|
155
|
+
def rejectedEnter: bool = and(holds, enterChanged)
|
|
156
|
+
|
|
157
|
+
def left0: int = triple0(arrowA("vertical", 0 - STEP))
|
|
158
|
+
def left1: int = triple1(arrowA("vertical", 0 - STEP))
|
|
159
|
+
def left2: int = triple2(arrowA("vertical", 0 - STEP))
|
|
160
|
+
def leftChanged: bool = differs(left0, left1, left2)
|
|
161
|
+
|
|
162
|
+
def right0: int = triple0(arrowA("vertical", STEP))
|
|
163
|
+
def right1: int = triple1(arrowA("vertical", STEP))
|
|
164
|
+
def right2: int = triple2(arrowA("vertical", STEP))
|
|
165
|
+
def rightChanged: bool = differs(right0, right1, right2)
|
|
166
|
+
|
|
167
|
+
def up0: int = triple0(arrowA("horizontal", 0 - STEP))
|
|
168
|
+
def up1: int = triple1(arrowA("horizontal", 0 - STEP))
|
|
169
|
+
def up2: int = triple2(arrowA("horizontal", 0 - STEP))
|
|
170
|
+
def upChanged: bool = differs(up0, up1, up2)
|
|
171
|
+
|
|
172
|
+
def down0: int = triple0(arrowA("horizontal", STEP))
|
|
173
|
+
def down1: int = triple1(arrowA("horizontal", STEP))
|
|
174
|
+
def down2: int = triple2(arrowA("horizontal", STEP))
|
|
175
|
+
def downChanged: bool = differs(down0, down1, down2)
|
|
176
|
+
|
|
177
|
+
def home0: int = triple0(jumpA(0 - FAR))
|
|
178
|
+
def home1: int = triple1(jumpA(0 - FAR))
|
|
179
|
+
def home2: int = triple2(jumpA(0 - FAR))
|
|
180
|
+
def homeChanged: bool = differs(home0, home1, home2)
|
|
181
|
+
|
|
182
|
+
def end0: int = triple0(jumpA(FAR))
|
|
183
|
+
def end1: int = triple1(jumpA(FAR))
|
|
184
|
+
def end2: int = triple2(jumpA(FAR))
|
|
185
|
+
def endChanged: bool = differs(end0, end1, end2)
|
|
186
|
+
|
|
187
|
+
def dragNextD: int = ddNext(NOTCH)
|
|
188
|
+
def dragNext0: int = dragT0(dragNextD)
|
|
189
|
+
def dragNext1: int = dragT1(dragNextD)
|
|
190
|
+
def dragNext2: int = dragT2(dragNextD)
|
|
191
|
+
def dragNextChanged: bool = differs(dragNext0, dragNext1, dragNext2)
|
|
192
|
+
|
|
193
|
+
def dragPrevD: int = ddNext(0 - NOTCH)
|
|
194
|
+
def dragPrev0: int = dragT0(dragPrevD)
|
|
195
|
+
def dragPrev1: int = dragT1(dragPrevD)
|
|
196
|
+
def dragPrev2: int = dragT2(dragPrevD)
|
|
197
|
+
def dragPrevChanged: bool = differs(dragPrev0, dragPrev1, dragPrev2)
|
|
198
|
+
|
|
199
|
+
action init = all {
|
|
200
|
+
o' = "vertical",
|
|
201
|
+
s0' = INIT0,
|
|
202
|
+
s1' = INIT1,
|
|
203
|
+
s2' = INIT2,
|
|
204
|
+
prev0' = INIT0,
|
|
205
|
+
focus' = "none",
|
|
206
|
+
justRestored' = false,
|
|
207
|
+
rq0' = INIT0,
|
|
208
|
+
rq1' = INIT1,
|
|
209
|
+
rq2' = INIT2,
|
|
210
|
+
b0' = INIT0,
|
|
211
|
+
b1' = INIT1,
|
|
212
|
+
b2' = INIT2,
|
|
213
|
+
k0' = INIT0,
|
|
214
|
+
k1' = INIT1,
|
|
215
|
+
k2' = INIT2,
|
|
216
|
+
dd' = 0,
|
|
217
|
+
dr' = 0 - 1,
|
|
218
|
+
outcome' = "none",
|
|
219
|
+
controlled' = false,
|
|
220
|
+
accepting' = false,
|
|
221
|
+
requests' = 0
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
action focusSep0 = all {
|
|
225
|
+
o' = o,
|
|
226
|
+
s0' = s0,
|
|
227
|
+
s1' = s1,
|
|
228
|
+
s2' = s2,
|
|
229
|
+
prev0' = prev0,
|
|
230
|
+
focus' = "sep0",
|
|
231
|
+
justRestored' = false,
|
|
232
|
+
rq0' = rq0,
|
|
233
|
+
rq1' = rq1,
|
|
234
|
+
rq2' = rq2,
|
|
235
|
+
b0' = b0,
|
|
236
|
+
b1' = b1,
|
|
237
|
+
b2' = b2,
|
|
238
|
+
k0' = k0,
|
|
239
|
+
k1' = k1,
|
|
240
|
+
k2' = k2,
|
|
241
|
+
dd' = dd,
|
|
242
|
+
dr' = dr,
|
|
243
|
+
outcome' = outcome,
|
|
244
|
+
controlled' = controlled,
|
|
245
|
+
accepting' = accepting,
|
|
246
|
+
requests' = requests
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
action focusSep1 = all {
|
|
250
|
+
o' = o,
|
|
251
|
+
s0' = s0,
|
|
252
|
+
s1' = s1,
|
|
253
|
+
s2' = s2,
|
|
254
|
+
prev0' = prev0,
|
|
255
|
+
focus' = "sep1",
|
|
256
|
+
justRestored' = false,
|
|
257
|
+
rq0' = rq0,
|
|
258
|
+
rq1' = rq1,
|
|
259
|
+
rq2' = rq2,
|
|
260
|
+
b0' = b0,
|
|
261
|
+
b1' = b1,
|
|
262
|
+
b2' = b2,
|
|
263
|
+
k0' = k0,
|
|
264
|
+
k1' = k1,
|
|
265
|
+
k2' = k2,
|
|
266
|
+
dd' = dd,
|
|
267
|
+
dr' = dr,
|
|
268
|
+
outcome' = outcome,
|
|
269
|
+
controlled' = controlled,
|
|
270
|
+
accepting' = accepting,
|
|
271
|
+
requests' = requests
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
action blur = all {
|
|
275
|
+
o' = o,
|
|
276
|
+
s0' = s0,
|
|
277
|
+
s1' = s1,
|
|
278
|
+
s2' = s2,
|
|
279
|
+
prev0' = prev0,
|
|
280
|
+
focus' = "none",
|
|
281
|
+
justRestored' = false,
|
|
282
|
+
rq0' = rq0,
|
|
283
|
+
rq1' = rq1,
|
|
284
|
+
rq2' = rq2,
|
|
285
|
+
b0' = b0,
|
|
286
|
+
b1' = b1,
|
|
287
|
+
b2' = b2,
|
|
288
|
+
k0' = k0,
|
|
289
|
+
k1' = k1,
|
|
290
|
+
k2' = k2,
|
|
291
|
+
dd' = dd,
|
|
292
|
+
dr' = dr,
|
|
293
|
+
outcome' = outcome,
|
|
294
|
+
controlled' = controlled,
|
|
295
|
+
accepting' = accepting,
|
|
296
|
+
requests' = requests
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
action left = all {
|
|
300
|
+
o' = o,
|
|
301
|
+
s0' = landed(holds, s0, left0),
|
|
302
|
+
s1' = landed(holds, s1, left1),
|
|
303
|
+
s2' = landed(holds, s2, left2),
|
|
304
|
+
prev0' = prev0,
|
|
305
|
+
focus' = focus,
|
|
306
|
+
justRestored' = false,
|
|
307
|
+
rq0' = if (leftChanged) left0 else rq0,
|
|
308
|
+
rq1' = if (leftChanged) left1 else rq1,
|
|
309
|
+
rq2' = if (leftChanged) left2 else rq2,
|
|
310
|
+
b0' = if (leftChanged) s0 else b0,
|
|
311
|
+
b1' = if (leftChanged) s1 else b1,
|
|
312
|
+
b2' = if (leftChanged) s2 else b2,
|
|
313
|
+
k0' = k0,
|
|
314
|
+
k1' = k1,
|
|
315
|
+
k2' = k2,
|
|
316
|
+
dd' = dd,
|
|
317
|
+
dr' = dr,
|
|
318
|
+
outcome' = if (leftChanged) verdict else outcome,
|
|
319
|
+
controlled' = controlled,
|
|
320
|
+
accepting' = accepting,
|
|
321
|
+
requests' = requests + moved(left0, left1, left2)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
action right = all {
|
|
325
|
+
o' = o,
|
|
326
|
+
s0' = landed(holds, s0, right0),
|
|
327
|
+
s1' = landed(holds, s1, right1),
|
|
328
|
+
s2' = landed(holds, s2, right2),
|
|
329
|
+
prev0' = prev0,
|
|
330
|
+
focus' = focus,
|
|
331
|
+
justRestored' = false,
|
|
332
|
+
rq0' = if (rightChanged) right0 else rq0,
|
|
333
|
+
rq1' = if (rightChanged) right1 else rq1,
|
|
334
|
+
rq2' = if (rightChanged) right2 else rq2,
|
|
335
|
+
b0' = if (rightChanged) s0 else b0,
|
|
336
|
+
b1' = if (rightChanged) s1 else b1,
|
|
337
|
+
b2' = if (rightChanged) s2 else b2,
|
|
338
|
+
k0' = k0,
|
|
339
|
+
k1' = k1,
|
|
340
|
+
k2' = k2,
|
|
341
|
+
dd' = dd,
|
|
342
|
+
dr' = dr,
|
|
343
|
+
outcome' = if (rightChanged) verdict else outcome,
|
|
344
|
+
controlled' = controlled,
|
|
345
|
+
accepting' = accepting,
|
|
346
|
+
requests' = requests + moved(right0, right1, right2)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
action up = all {
|
|
350
|
+
o' = o,
|
|
351
|
+
s0' = landed(holds, s0, up0),
|
|
352
|
+
s1' = landed(holds, s1, up1),
|
|
353
|
+
s2' = landed(holds, s2, up2),
|
|
354
|
+
prev0' = prev0,
|
|
355
|
+
focus' = focus,
|
|
356
|
+
justRestored' = false,
|
|
357
|
+
rq0' = if (upChanged) up0 else rq0,
|
|
358
|
+
rq1' = if (upChanged) up1 else rq1,
|
|
359
|
+
rq2' = if (upChanged) up2 else rq2,
|
|
360
|
+
b0' = if (upChanged) s0 else b0,
|
|
361
|
+
b1' = if (upChanged) s1 else b1,
|
|
362
|
+
b2' = if (upChanged) s2 else b2,
|
|
363
|
+
k0' = k0,
|
|
364
|
+
k1' = k1,
|
|
365
|
+
k2' = k2,
|
|
366
|
+
dd' = dd,
|
|
367
|
+
dr' = dr,
|
|
368
|
+
outcome' = if (upChanged) verdict else outcome,
|
|
369
|
+
controlled' = controlled,
|
|
370
|
+
accepting' = accepting,
|
|
371
|
+
requests' = requests + moved(up0, up1, up2)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
action down = all {
|
|
375
|
+
o' = o,
|
|
376
|
+
s0' = landed(holds, s0, down0),
|
|
377
|
+
s1' = landed(holds, s1, down1),
|
|
378
|
+
s2' = landed(holds, s2, down2),
|
|
379
|
+
prev0' = prev0,
|
|
380
|
+
focus' = focus,
|
|
381
|
+
justRestored' = false,
|
|
382
|
+
rq0' = if (downChanged) down0 else rq0,
|
|
383
|
+
rq1' = if (downChanged) down1 else rq1,
|
|
384
|
+
rq2' = if (downChanged) down2 else rq2,
|
|
385
|
+
b0' = if (downChanged) s0 else b0,
|
|
386
|
+
b1' = if (downChanged) s1 else b1,
|
|
387
|
+
b2' = if (downChanged) s2 else b2,
|
|
388
|
+
k0' = k0,
|
|
389
|
+
k1' = k1,
|
|
390
|
+
k2' = k2,
|
|
391
|
+
dd' = dd,
|
|
392
|
+
dr' = dr,
|
|
393
|
+
outcome' = if (downChanged) verdict else outcome,
|
|
394
|
+
controlled' = controlled,
|
|
395
|
+
accepting' = accepting,
|
|
396
|
+
requests' = requests + moved(down0, down1, down2)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
action home = all {
|
|
400
|
+
o' = o,
|
|
401
|
+
s0' = landed(holds, s0, home0),
|
|
402
|
+
s1' = landed(holds, s1, home1),
|
|
403
|
+
s2' = landed(holds, s2, home2),
|
|
404
|
+
prev0' = prev0,
|
|
405
|
+
focus' = focus,
|
|
406
|
+
justRestored' = false,
|
|
407
|
+
rq0' = if (homeChanged) home0 else rq0,
|
|
408
|
+
rq1' = if (homeChanged) home1 else rq1,
|
|
409
|
+
rq2' = if (homeChanged) home2 else rq2,
|
|
410
|
+
b0' = if (homeChanged) s0 else b0,
|
|
411
|
+
b1' = if (homeChanged) s1 else b1,
|
|
412
|
+
b2' = if (homeChanged) s2 else b2,
|
|
413
|
+
k0' = k0,
|
|
414
|
+
k1' = k1,
|
|
415
|
+
k2' = k2,
|
|
416
|
+
dd' = dd,
|
|
417
|
+
dr' = dr,
|
|
418
|
+
outcome' = if (homeChanged) verdict else outcome,
|
|
419
|
+
controlled' = controlled,
|
|
420
|
+
accepting' = accepting,
|
|
421
|
+
requests' = requests + moved(home0, home1, home2)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
action end = all {
|
|
425
|
+
o' = o,
|
|
426
|
+
s0' = landed(holds, s0, end0),
|
|
427
|
+
s1' = landed(holds, s1, end1),
|
|
428
|
+
s2' = landed(holds, s2, end2),
|
|
429
|
+
prev0' = prev0,
|
|
430
|
+
focus' = focus,
|
|
431
|
+
justRestored' = false,
|
|
432
|
+
rq0' = if (endChanged) end0 else rq0,
|
|
433
|
+
rq1' = if (endChanged) end1 else rq1,
|
|
434
|
+
rq2' = if (endChanged) end2 else rq2,
|
|
435
|
+
b0' = if (endChanged) s0 else b0,
|
|
436
|
+
b1' = if (endChanged) s1 else b1,
|
|
437
|
+
b2' = if (endChanged) s2 else b2,
|
|
438
|
+
k0' = k0,
|
|
439
|
+
k1' = k1,
|
|
440
|
+
k2' = k2,
|
|
441
|
+
dd' = dd,
|
|
442
|
+
dr' = dr,
|
|
443
|
+
outcome' = if (endChanged) verdict else outcome,
|
|
444
|
+
controlled' = controlled,
|
|
445
|
+
accepting' = accepting,
|
|
446
|
+
requests' = requests + moved(end0, end1, end2)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
action enter = all {
|
|
450
|
+
o' = o,
|
|
451
|
+
s0' = landed(holds, s0, enterA),
|
|
452
|
+
s1' = landed(holds, s1, enterB),
|
|
453
|
+
s2' = landed(holds, s2, enterC),
|
|
454
|
+
prev0' = if (rejectedEnter) prev0 else (if (and(enterOn, not(collapsedNow))) s0 else prev0),
|
|
455
|
+
focus' = focus,
|
|
456
|
+
justRestored' = if (rejectedEnter) justRestored else (and(enterOn, collapsedNow)),
|
|
457
|
+
rq0' = if (enterChanged) enterA else rq0,
|
|
458
|
+
rq1' = if (enterChanged) enterB else rq1,
|
|
459
|
+
rq2' = if (enterChanged) enterC else rq2,
|
|
460
|
+
b0' = if (enterChanged) s0 else b0,
|
|
461
|
+
b1' = if (enterChanged) s1 else b1,
|
|
462
|
+
b2' = if (enterChanged) s2 else b2,
|
|
463
|
+
k0' = k0,
|
|
464
|
+
k1' = k1,
|
|
465
|
+
k2' = k2,
|
|
466
|
+
dd' = dd,
|
|
467
|
+
dr' = dr,
|
|
468
|
+
outcome' = if (enterChanged) verdict else outcome,
|
|
469
|
+
controlled' = controlled,
|
|
470
|
+
accepting' = accepting,
|
|
471
|
+
requests' = requests + moved(enterA, enterB, enterC)
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
action orientVertical = all {
|
|
475
|
+
o' = "vertical",
|
|
476
|
+
s0' = s0,
|
|
477
|
+
s1' = s1,
|
|
478
|
+
s2' = s2,
|
|
479
|
+
prev0' = prev0,
|
|
480
|
+
focus' = focus,
|
|
481
|
+
justRestored' = false,
|
|
482
|
+
rq0' = rq0,
|
|
483
|
+
rq1' = rq1,
|
|
484
|
+
rq2' = rq2,
|
|
485
|
+
b0' = b0,
|
|
486
|
+
b1' = b1,
|
|
487
|
+
b2' = b2,
|
|
488
|
+
k0' = k0,
|
|
489
|
+
k1' = k1,
|
|
490
|
+
k2' = k2,
|
|
491
|
+
dd' = dd,
|
|
492
|
+
dr' = dr,
|
|
493
|
+
outcome' = outcome,
|
|
494
|
+
controlled' = controlled,
|
|
495
|
+
accepting' = accepting,
|
|
496
|
+
requests' = requests
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
action orientHorizontal = all {
|
|
500
|
+
o' = "horizontal",
|
|
501
|
+
s0' = s0,
|
|
502
|
+
s1' = s1,
|
|
503
|
+
s2' = s2,
|
|
504
|
+
prev0' = prev0,
|
|
505
|
+
focus' = focus,
|
|
506
|
+
justRestored' = false,
|
|
507
|
+
rq0' = rq0,
|
|
508
|
+
rq1' = rq1,
|
|
509
|
+
rq2' = rq2,
|
|
510
|
+
b0' = b0,
|
|
511
|
+
b1' = b1,
|
|
512
|
+
b2' = b2,
|
|
513
|
+
k0' = k0,
|
|
514
|
+
k1' = k1,
|
|
515
|
+
k2' = k2,
|
|
516
|
+
dd' = dd,
|
|
517
|
+
dr' = dr,
|
|
518
|
+
outcome' = outcome,
|
|
519
|
+
controlled' = controlled,
|
|
520
|
+
accepting' = accepting,
|
|
521
|
+
requests' = requests
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
action dragDown0 = all {
|
|
525
|
+
o' = o,
|
|
526
|
+
s0' = s0,
|
|
527
|
+
s1' = s1,
|
|
528
|
+
s2' = s2,
|
|
529
|
+
prev0' = prev0,
|
|
530
|
+
focus' = "sep0",
|
|
531
|
+
justRestored' = false,
|
|
532
|
+
rq0' = rq0,
|
|
533
|
+
rq1' = rq1,
|
|
534
|
+
rq2' = rq2,
|
|
535
|
+
b0' = b0,
|
|
536
|
+
b1' = b1,
|
|
537
|
+
b2' = b2,
|
|
538
|
+
k0' = if (isCollapsed(0)) k0 else s0,
|
|
539
|
+
k1' = if (isCollapsed(0)) k1 else s1,
|
|
540
|
+
k2' = if (isCollapsed(0)) k2 else s2,
|
|
541
|
+
dd' = if (isCollapsed(0)) dd else 0,
|
|
542
|
+
dr' = if (isCollapsed(0)) dr else 0,
|
|
543
|
+
outcome' = outcome,
|
|
544
|
+
controlled' = controlled,
|
|
545
|
+
accepting' = accepting,
|
|
546
|
+
requests' = requests
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
action dragDown1 = all {
|
|
550
|
+
o' = o,
|
|
551
|
+
s0' = s0,
|
|
552
|
+
s1' = s1,
|
|
553
|
+
s2' = s2,
|
|
554
|
+
prev0' = prev0,
|
|
555
|
+
focus' = "sep1",
|
|
556
|
+
justRestored' = false,
|
|
557
|
+
rq0' = rq0,
|
|
558
|
+
rq1' = rq1,
|
|
559
|
+
rq2' = rq2,
|
|
560
|
+
b0' = b0,
|
|
561
|
+
b1' = b1,
|
|
562
|
+
b2' = b2,
|
|
563
|
+
k0' = if (isCollapsed(1)) k0 else s0,
|
|
564
|
+
k1' = if (isCollapsed(1)) k1 else s1,
|
|
565
|
+
k2' = if (isCollapsed(1)) k2 else s2,
|
|
566
|
+
dd' = if (isCollapsed(1)) dd else 0,
|
|
567
|
+
dr' = if (isCollapsed(1)) dr else 1,
|
|
568
|
+
outcome' = outcome,
|
|
569
|
+
controlled' = controlled,
|
|
570
|
+
accepting' = accepting,
|
|
571
|
+
requests' = requests
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
action dragNext = all {
|
|
575
|
+
o' = o,
|
|
576
|
+
s0' = landed(holds, s0, dragNext0),
|
|
577
|
+
s1' = landed(holds, s1, dragNext1),
|
|
578
|
+
s2' = landed(holds, s2, dragNext2),
|
|
579
|
+
prev0' = prev0,
|
|
580
|
+
focus' = focus,
|
|
581
|
+
justRestored' = false,
|
|
582
|
+
rq0' = if (dragNextChanged) dragNext0 else rq0,
|
|
583
|
+
rq1' = if (dragNextChanged) dragNext1 else rq1,
|
|
584
|
+
rq2' = if (dragNextChanged) dragNext2 else rq2,
|
|
585
|
+
b0' = if (dragNextChanged) s0 else b0,
|
|
586
|
+
b1' = if (dragNextChanged) s1 else b1,
|
|
587
|
+
b2' = if (dragNextChanged) s2 else b2,
|
|
588
|
+
k0' = k0,
|
|
589
|
+
k1' = k1,
|
|
590
|
+
k2' = k2,
|
|
591
|
+
dd' = dragNextD,
|
|
592
|
+
dr' = dr,
|
|
593
|
+
outcome' = if (dragNextChanged) verdict else outcome,
|
|
594
|
+
controlled' = controlled,
|
|
595
|
+
accepting' = accepting,
|
|
596
|
+
requests' = requests + moved(dragNext0, dragNext1, dragNext2)
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
action dragPrev = all {
|
|
600
|
+
o' = o,
|
|
601
|
+
s0' = landed(holds, s0, dragPrev0),
|
|
602
|
+
s1' = landed(holds, s1, dragPrev1),
|
|
603
|
+
s2' = landed(holds, s2, dragPrev2),
|
|
604
|
+
prev0' = prev0,
|
|
605
|
+
focus' = focus,
|
|
606
|
+
justRestored' = false,
|
|
607
|
+
rq0' = if (dragPrevChanged) dragPrev0 else rq0,
|
|
608
|
+
rq1' = if (dragPrevChanged) dragPrev1 else rq1,
|
|
609
|
+
rq2' = if (dragPrevChanged) dragPrev2 else rq2,
|
|
610
|
+
b0' = if (dragPrevChanged) s0 else b0,
|
|
611
|
+
b1' = if (dragPrevChanged) s1 else b1,
|
|
612
|
+
b2' = if (dragPrevChanged) s2 else b2,
|
|
613
|
+
k0' = k0,
|
|
614
|
+
k1' = k1,
|
|
615
|
+
k2' = k2,
|
|
616
|
+
dd' = dragPrevD,
|
|
617
|
+
dr' = dr,
|
|
618
|
+
outcome' = if (dragPrevChanged) verdict else outcome,
|
|
619
|
+
controlled' = controlled,
|
|
620
|
+
accepting' = accepting,
|
|
621
|
+
requests' = requests + moved(dragPrev0, dragPrev1, dragPrev2)
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
action dragUp = all {
|
|
625
|
+
o' = o,
|
|
626
|
+
s0' = s0,
|
|
627
|
+
s1' = s1,
|
|
628
|
+
s2' = s2,
|
|
629
|
+
prev0' = prev0,
|
|
630
|
+
focus' = focus,
|
|
631
|
+
justRestored' = false,
|
|
632
|
+
rq0' = rq0,
|
|
633
|
+
rq1' = rq1,
|
|
634
|
+
rq2' = rq2,
|
|
635
|
+
b0' = b0,
|
|
636
|
+
b1' = b1,
|
|
637
|
+
b2' = b2,
|
|
638
|
+
k0' = k0,
|
|
639
|
+
k1' = k1,
|
|
640
|
+
k2' = k2,
|
|
641
|
+
dd' = 0,
|
|
642
|
+
dr' = 0 - 1,
|
|
643
|
+
outcome' = outcome,
|
|
644
|
+
controlled' = controlled,
|
|
645
|
+
accepting' = accepting,
|
|
646
|
+
requests' = requests
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
action hostEqual = all {
|
|
650
|
+
o' = o,
|
|
651
|
+
s0' = if (controlled) 30 else s0,
|
|
652
|
+
s1' = if (controlled) 30 else s1,
|
|
653
|
+
s2' = if (controlled) 40 else s2,
|
|
654
|
+
prev0' = if (controlled) (if (30 == ZERO) (if (s0 == ZERO) prev0 else s0) else 30) else prev0,
|
|
655
|
+
focus' = focus,
|
|
656
|
+
justRestored' = if (controlled) false else justRestored,
|
|
657
|
+
rq0' = rq0,
|
|
658
|
+
rq1' = rq1,
|
|
659
|
+
rq2' = rq2,
|
|
660
|
+
b0' = b0,
|
|
661
|
+
b1' = b1,
|
|
662
|
+
b2' = b2,
|
|
663
|
+
k0' = k0,
|
|
664
|
+
k1' = k1,
|
|
665
|
+
k2' = k2,
|
|
666
|
+
dd' = if (controlled) 0 else dd,
|
|
667
|
+
dr' = if (controlled) 0 - 1 else dr,
|
|
668
|
+
outcome' = if (controlled) "none" else outcome,
|
|
669
|
+
controlled' = controlled,
|
|
670
|
+
accepting' = accepting,
|
|
671
|
+
requests' = requests
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
action hostWide = all {
|
|
675
|
+
o' = o,
|
|
676
|
+
s0' = if (controlled) 50 else s0,
|
|
677
|
+
s1' = if (controlled) 30 else s1,
|
|
678
|
+
s2' = if (controlled) 20 else s2,
|
|
679
|
+
prev0' = if (controlled) (if (50 == ZERO) (if (s0 == ZERO) prev0 else s0) else 50) else prev0,
|
|
680
|
+
focus' = focus,
|
|
681
|
+
justRestored' = if (controlled) false else justRestored,
|
|
682
|
+
rq0' = rq0,
|
|
683
|
+
rq1' = rq1,
|
|
684
|
+
rq2' = rq2,
|
|
685
|
+
b0' = b0,
|
|
686
|
+
b1' = b1,
|
|
687
|
+
b2' = b2,
|
|
688
|
+
k0' = k0,
|
|
689
|
+
k1' = k1,
|
|
690
|
+
k2' = k2,
|
|
691
|
+
dd' = if (controlled) 0 else dd,
|
|
692
|
+
dr' = if (controlled) 0 - 1 else dr,
|
|
693
|
+
outcome' = if (controlled) "none" else outcome,
|
|
694
|
+
controlled' = controlled,
|
|
695
|
+
accepting' = accepting,
|
|
696
|
+
requests' = requests
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
action hostNarrow = all {
|
|
700
|
+
o' = o,
|
|
701
|
+
s0' = if (controlled) 10 else s0,
|
|
702
|
+
s1' = if (controlled) 40 else s1,
|
|
703
|
+
s2' = if (controlled) 50 else s2,
|
|
704
|
+
prev0' = if (controlled) (if (10 == ZERO) (if (s0 == ZERO) prev0 else s0) else 10) else prev0,
|
|
705
|
+
focus' = focus,
|
|
706
|
+
justRestored' = if (controlled) false else justRestored,
|
|
707
|
+
rq0' = rq0,
|
|
708
|
+
rq1' = rq1,
|
|
709
|
+
rq2' = rq2,
|
|
710
|
+
b0' = b0,
|
|
711
|
+
b1' = b1,
|
|
712
|
+
b2' = b2,
|
|
713
|
+
k0' = k0,
|
|
714
|
+
k1' = k1,
|
|
715
|
+
k2' = k2,
|
|
716
|
+
dd' = if (controlled) 0 else dd,
|
|
717
|
+
dr' = if (controlled) 0 - 1 else dr,
|
|
718
|
+
outcome' = if (controlled) "none" else outcome,
|
|
719
|
+
controlled' = controlled,
|
|
720
|
+
accepting' = accepting,
|
|
721
|
+
requests' = requests
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
action hostCollapsed = all {
|
|
725
|
+
o' = o,
|
|
726
|
+
s0' = if (controlled) ZERO else s0,
|
|
727
|
+
s1' = if (controlled) 50 else s1,
|
|
728
|
+
s2' = if (controlled) 50 else s2,
|
|
729
|
+
prev0' = if (controlled) (if (ZERO == ZERO) (if (s0 == ZERO) prev0 else s0) else ZERO) else prev0,
|
|
730
|
+
focus' = focus,
|
|
731
|
+
justRestored' = if (controlled) false else justRestored,
|
|
732
|
+
rq0' = rq0,
|
|
733
|
+
rq1' = rq1,
|
|
734
|
+
rq2' = rq2,
|
|
735
|
+
b0' = b0,
|
|
736
|
+
b1' = b1,
|
|
737
|
+
b2' = b2,
|
|
738
|
+
k0' = k0,
|
|
739
|
+
k1' = k1,
|
|
740
|
+
k2' = k2,
|
|
741
|
+
dd' = if (controlled) 0 else dd,
|
|
742
|
+
dr' = if (controlled) 0 - 1 else dr,
|
|
743
|
+
outcome' = if (controlled) "none" else outcome,
|
|
744
|
+
controlled' = controlled,
|
|
745
|
+
accepting' = accepting,
|
|
746
|
+
requests' = requests
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
action control = all {
|
|
750
|
+
o' = o,
|
|
751
|
+
s0' = s0,
|
|
752
|
+
s1' = s1,
|
|
753
|
+
s2' = s2,
|
|
754
|
+
prev0' = prev0,
|
|
755
|
+
focus' = focus,
|
|
756
|
+
justRestored' = false,
|
|
757
|
+
rq0' = rq0,
|
|
758
|
+
rq1' = rq1,
|
|
759
|
+
rq2' = rq2,
|
|
760
|
+
b0' = b0,
|
|
761
|
+
b1' = b1,
|
|
762
|
+
b2' = b2,
|
|
763
|
+
k0' = k0,
|
|
764
|
+
k1' = k1,
|
|
765
|
+
k2' = k2,
|
|
766
|
+
dd' = dd,
|
|
767
|
+
dr' = dr,
|
|
768
|
+
outcome' = "none",
|
|
769
|
+
controlled' = true,
|
|
770
|
+
accepting' = accepting,
|
|
771
|
+
requests' = requests
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
action acceptRequests = all {
|
|
775
|
+
o' = o,
|
|
776
|
+
s0' = s0,
|
|
777
|
+
s1' = s1,
|
|
778
|
+
s2' = s2,
|
|
779
|
+
prev0' = prev0,
|
|
780
|
+
focus' = focus,
|
|
781
|
+
justRestored' = false,
|
|
782
|
+
rq0' = rq0,
|
|
783
|
+
rq1' = rq1,
|
|
784
|
+
rq2' = rq2,
|
|
785
|
+
b0' = b0,
|
|
786
|
+
b1' = b1,
|
|
787
|
+
b2' = b2,
|
|
788
|
+
k0' = k0,
|
|
789
|
+
k1' = k1,
|
|
790
|
+
k2' = k2,
|
|
791
|
+
dd' = dd,
|
|
792
|
+
dr' = dr,
|
|
793
|
+
outcome' = "none",
|
|
794
|
+
controlled' = controlled,
|
|
795
|
+
accepting' = true,
|
|
796
|
+
requests' = requests
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
action step = any {
|
|
800
|
+
init, focusSep0, focusSep1, blur, left, right, up, down, home, end, enter, orientVertical, orientHorizontal, dragDown0, dragDown1, dragNext, dragPrev, dragUp, hostEqual, hostWide, hostNarrow, hostCollapsed, control, acceptRequests
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// the three panes are a layout: percentages always add up to 100
|
|
804
|
+
val PaneSizesSumTo100: bool = s0 + s1 + s2 == FULL
|
|
805
|
+
// every pane is inside its own bounds; only pane 0 can sit at collapsedSize
|
|
806
|
+
val PaneInBounds: bool =
|
|
807
|
+
and(s0 >= ZERO, and(s0 <= MAX, and(s1 >= MIN, and(s1 <= MAX, and(s2 >= MIN, s2 <= MAX)))))
|
|
808
|
+
// the remembered size is always a size a pane can have
|
|
809
|
+
val PrevInBounds: bool = and(prev0 >= MIN, prev0 <= MAX)
|
|
810
|
+
// restoring returns pane 0 to exactly the remembered size
|
|
811
|
+
val RestoreReturnsPrev: bool = or(not(justRestored), s0 == prev0)
|
|
812
|
+
// focus is one of the modelled separators
|
|
813
|
+
val FocusKnown: bool = or(focus == "none", or(focus == "sep0", focus == "sep1"))
|
|
814
|
+
// orientation is one of the two APG orientations
|
|
815
|
+
val OrientationKnown: bool = ariaOrientationKnown(o)
|
|
816
|
+
// callbacks only ever count up from zero
|
|
817
|
+
val RequestsNonNegative: bool = requests >= 0
|
|
818
|
+
// a holding host never sees an accepted request: nothing commits
|
|
819
|
+
val HoldingLayoutStable: bool = or(not(holds), not(outcome == "accepted"))
|
|
820
|
+
// a rejected request leaves the layout as it found it
|
|
821
|
+
val RejectedRequestUntouched: bool =
|
|
822
|
+
or(not(outcome == "rejected"), and(s0 == b0, and(s1 == b1, s2 == b2)))
|
|
823
|
+
// an accepted request committed exactly its target
|
|
824
|
+
val AcceptedRequestCommits: bool =
|
|
825
|
+
or(not(outcome == "accepted"), and(s0 == rq0, and(s1 == rq1, s2 == rq2)))
|
|
826
|
+
// a drag only ever moves the two panes around the dragged separator
|
|
827
|
+
val DragMovesOnlyNeighbours: bool =
|
|
828
|
+
and(or(not(dr == 0), s2 == k2), or(not(dr == 1), s0 == k0))
|
|
829
|
+
// the drag delta stays bounded (the layout is clamped, the delta is not the state)
|
|
830
|
+
val DragDeltaBounded: bool = and(dd >= 0 - DMAX, dd <= DMAX)
|
|
831
|
+
}
|