@effindomv2/fui-as 0.1.37 → 0.1.39

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 (118) hide show
  1. package/browser/routed-app-conventions.ts +1 -1
  2. package/browser/src/common-harness.ts +1 -27
  3. package/browser/src/index.ts +19 -26
  4. package/browser/src/routed-harness.ts +1 -194
  5. package/browser/src/shared-browser.ts +6 -0
  6. package/package.json +23 -13
  7. package/scripts/build.sh +47 -46
  8. package/scripts/framework-host-services.ts +1 -1
  9. package/scripts/generate-host-events.ts +15 -241
  10. package/scripts/generate-host-services.ts +13 -261
  11. package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
  12. package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
  13. package/scripts/hostgen/common.ts +73 -0
  14. package/scripts/hostgen/registry.ts +159 -0
  15. package/src/Fui.ts +65 -5
  16. package/src/FuiExports.ts +12 -1
  17. package/src/bindings/ui.ts +157 -8
  18. package/src/controls/Button.ts +98 -71
  19. package/src/controls/Checkbox.ts +23 -21
  20. package/src/controls/ComboBox.ts +1201 -0
  21. package/src/controls/ContextMenu.ts +279 -165
  22. package/src/controls/Dialog.ts +91 -17
  23. package/src/controls/Dropdown.ts +101 -333
  24. package/src/controls/NavLink.ts +29 -6
  25. package/src/controls/Popup.ts +10 -5
  26. package/src/controls/ProgressBar.ts +1 -2
  27. package/src/controls/RadioButton.ts +34 -13
  28. package/src/controls/RadioGroup.ts +32 -19
  29. package/src/controls/Slider.ts +21 -23
  30. package/src/controls/Switch.ts +34 -17
  31. package/src/controls/index.ts +2 -1
  32. package/src/controls/internal/ButtonPresenter.ts +5 -2
  33. package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
  34. package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
  35. package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
  36. package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
  37. package/src/controls/internal/PressableLabeledControl.ts +4 -7
  38. package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
  39. package/src/controls/internal/SelectablePopupList.ts +463 -0
  40. package/src/controls/internal/SliderPresenter.ts +5 -5
  41. package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
  42. package/src/controls/internal/TextInputCore.ts +307 -41
  43. package/src/controls/internal/TextInputPresenter.ts +2 -2
  44. package/src/controls/templating.ts +10 -0
  45. package/src/core/Application.ts +17 -8
  46. package/src/core/Bitmap.ts +192 -3
  47. package/src/core/ContextMenuManager.ts +128 -44
  48. package/src/core/DebugApi.ts +17 -2
  49. package/src/core/DragGesture.ts +8 -7
  50. package/src/core/EventRouter.ts +332 -12
  51. package/src/core/Fetch.ts +15 -7
  52. package/src/core/FetchFfi.ts +1 -15
  53. package/src/core/File.ts +75 -34
  54. package/src/core/FocusAdornerManager.ts +3 -3
  55. package/src/core/FocusVisibility.ts +7 -0
  56. package/src/core/FrameScheduler.ts +104 -5
  57. package/src/core/ImageSampling.ts +43 -0
  58. package/src/core/Logger.ts +2 -0
  59. package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
  60. package/src/core/Node.ts +1039 -97
  61. package/src/core/Platform.ts +16 -16
  62. package/src/core/SelectionHandleAdornerManager.ts +697 -0
  63. package/src/core/Theme.ts +34 -20
  64. package/src/core/ToolTipManager.ts +3 -3
  65. package/src/core/Typography.ts +411 -19
  66. package/src/core/Worker.ts +69 -33
  67. package/src/core/event_exports.ts +123 -5
  68. package/src/core/ffi.ts +5 -865
  69. package/src/core/generated/FetchHostAbi.ts +10 -0
  70. package/src/core/generated/FrameworkHostServices.ts +1 -1
  71. package/src/core/generated/HostAbi.ts +220 -0
  72. package/src/core/generated/UiAbi.ts +356 -0
  73. package/src/core/generated/UiEnums.ts +186 -0
  74. package/src/drawing/DrawCallback.ts +17 -1
  75. package/src/drawing/DrawContext.ts +140 -32
  76. package/src/nodes/CustomDrawable.ts +8 -1
  77. package/src/nodes/FlexBox.ts +40 -11
  78. package/src/nodes/Grid.ts +5 -5
  79. package/src/nodes/Image.ts +20 -1
  80. package/src/nodes/RichText.ts +36 -25
  81. package/src/nodes/ScrollBar.ts +2 -1
  82. package/src/nodes/ScrollBox.ts +7 -2
  83. package/src/nodes/ScrollView.ts +17 -6
  84. package/src/nodes/Svg.ts +18 -1
  85. package/src/nodes/Text.ts +1 -1
  86. package/src/nodes/TextCore.ts +115 -20
  87. package/src/nodes/index.ts +1 -1
  88. package/src/text/DynamicTextLayout.ts +275 -0
  89. package/src/text/TextLayout.ts +308 -0
  90. package/src/worker/Worker.ts +3 -36
  91. package/src/worker/WorkerJob.ts +5 -9
  92. package/src/worker/ffi.ts +0 -6
  93. package/browser/src/common-harness/host-imports.ts +0 -447
  94. package/browser/src/common-harness/interop.ts +0 -39
  95. package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
  96. package/browser/src/common-harness/managed-harness-canvas-host.ts +0 -72
  97. package/browser/src/common-harness/managed-harness-fetch-host.ts +0 -201
  98. package/browser/src/common-harness/managed-harness-file-host.ts +0 -1066
  99. package/browser/src/common-harness/managed-harness-file-payloads.ts +0 -143
  100. package/browser/src/common-harness/managed-harness-file-types.ts +0 -71
  101. package/browser/src/common-harness/managed-harness-session.ts +0 -15
  102. package/browser/src/common-harness/managed-harness.ts +0 -1472
  103. package/browser/src/common-harness/managed-history.ts +0 -168
  104. package/browser/src/common-harness/persisted-restore-policy.ts +0 -50
  105. package/browser/src/common-harness/persisted-ui-state-controller.ts +0 -309
  106. package/browser/src/common-harness/text-session-bridge.ts +0 -452
  107. package/browser/src/common-harness/types.ts +0 -206
  108. package/browser/src/common-harness/ui-chrome.ts +0 -206
  109. package/browser/src/common-harness/ui-imports.ts +0 -559
  110. package/browser/src/common-harness/wasm-module-cache.ts +0 -47
  111. package/browser/src/file-processing-worker.ts +0 -89
  112. package/browser/src/host-events.ts +0 -118
  113. package/browser/src/host-services.ts +0 -483
  114. package/browser/src/persisted-ui-state.ts +0 -206
  115. package/browser/src/routed-app-conventions.ts +0 -292
  116. package/browser/src/worker-bootstrap.ts +0 -916
  117. package/browser/src/worker-manager.ts +0 -234
  118. package/browser/src/worker-types.ts +0 -68
package/src/core/Node.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  fui_set_pointer_capture,
31
31
  HandleValue,
32
32
  KeyEventType,
33
+ KeyModifier,
33
34
  Orientation,
34
35
  PointerEventType,
35
36
  SemanticCheckedState,
@@ -44,6 +45,442 @@ export enum DragDropEffects {
44
45
  Link = 4,
45
46
  }
46
47
 
48
+ export enum WheelDeltaMode {
49
+ Pixel = 0,
50
+ Line = 1,
51
+ Page = 2,
52
+ }
53
+
54
+ export enum PointerType {
55
+ Unknown = 0,
56
+ Mouse = 1,
57
+ Touch = 2,
58
+ Pen = 3,
59
+ }
60
+
61
+ export enum PointerButton {
62
+ None = -1,
63
+ Primary = 0,
64
+ Auxiliary = 1,
65
+ Secondary = 2,
66
+ Back = 3,
67
+ Forward = 4,
68
+ }
69
+
70
+ export enum PointerButtons {
71
+ None = 0,
72
+ Primary = 1 << 0,
73
+ Secondary = 1 << 1,
74
+ Auxiliary = 1 << 2,
75
+ Back = 1 << 3,
76
+ Forward = 1 << 4,
77
+ }
78
+
79
+ function isPrimaryActivationPointer(event: PointerEventArgs): bool {
80
+ return event.button == 0 || event.pointerType == PointerType.Touch || event.pointerType == PointerType.Pen;
81
+ }
82
+
83
+ export enum GestureIntent {
84
+ None = 0,
85
+ Pan = 1,
86
+ Pinch = 2,
87
+ PanAndPinch = 3,
88
+ }
89
+
90
+ export enum GestureEventPhase {
91
+ Begin = 1,
92
+ Update = 2,
93
+ End = 3,
94
+ Cancel = 4,
95
+ }
96
+
97
+ export enum GestureEventKind {
98
+ None = 0,
99
+ Pan = 1,
100
+ Pinch = 2,
101
+ }
102
+
103
+ export class GestureEventArgs {
104
+ readonly phase: GestureEventPhase;
105
+ readonly kind: GestureEventKind;
106
+ readonly sceneX: f32;
107
+ readonly sceneY: f32;
108
+ readonly deltaX: f32;
109
+ readonly deltaY: f32;
110
+ readonly scale: f32;
111
+ readonly pointerCount: i32;
112
+ x: f32;
113
+ y: f32;
114
+ handled: bool = false;
115
+
116
+ constructor(
117
+ phase: GestureEventPhase,
118
+ kind: GestureEventKind,
119
+ sceneX: f32,
120
+ sceneY: f32,
121
+ deltaX: f32,
122
+ deltaY: f32,
123
+ scale: f32,
124
+ pointerCount: i32,
125
+ ) {
126
+ this.phase = phase;
127
+ this.kind = kind;
128
+ this.sceneX = sceneX;
129
+ this.sceneY = sceneY;
130
+ this.deltaX = deltaX;
131
+ this.deltaY = deltaY;
132
+ this.scale = scale;
133
+ this.pointerCount = pointerCount;
134
+ this.x = sceneX;
135
+ this.y = sceneY;
136
+ }
137
+ }
138
+
139
+ export type PanGestureEventArgs = GestureEventArgs;
140
+ export type PinchGestureEventArgs = GestureEventArgs;
141
+
142
+ export const DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS: i32 = 500;
143
+ export const DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE: f32 = 10.0;
144
+
145
+ export class LongPressEventArgs {
146
+ readonly sceneX: f32;
147
+ readonly sceneY: f32;
148
+ readonly pointerId: i32;
149
+ readonly pointerType: PointerType;
150
+ readonly modifiers: KeyModifier;
151
+ readonly durationMs: i32;
152
+ x: f32;
153
+ y: f32;
154
+ handled: bool = false;
155
+
156
+ constructor(
157
+ sceneX: f32,
158
+ sceneY: f32,
159
+ pointerId: i32,
160
+ pointerType: PointerType,
161
+ modifiers: KeyModifier,
162
+ durationMs: i32,
163
+ ) {
164
+ this.sceneX = sceneX;
165
+ this.sceneY = sceneY;
166
+ this.x = sceneX;
167
+ this.y = sceneY;
168
+ this.pointerId = pointerId;
169
+ this.pointerType = pointerType;
170
+ this.modifiers = modifiers;
171
+ this.durationMs = durationMs;
172
+ }
173
+ }
174
+
175
+ export class LongPressGesture {
176
+ private minimumDurationMsValue: i32 = DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS;
177
+ private movementToleranceValue: f32 = DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE;
178
+ private recognizedCallback: ((event: LongPressEventArgs) => void) | null = null;
179
+ private recognizedBinding: Callback1<LongPressEventArgs> | null = null;
180
+
181
+ static create(): LongPressGesture {
182
+ return new LongPressGesture();
183
+ }
184
+
185
+ minimumDuration(ms: i32): LongPressGesture {
186
+ this.minimumDurationMsValue = ms < 0 ? 0 : ms;
187
+ return this;
188
+ }
189
+
190
+ movementTolerance(px: f32): LongPressGesture {
191
+ this.movementToleranceValue = px < 0.0 ? 0.0 : px;
192
+ return this;
193
+ }
194
+
195
+ onRecognized(cb: ((event: LongPressEventArgs) => void) | null): LongPressGesture {
196
+ this.recognizedCallback = cb;
197
+ this.recognizedBinding = null;
198
+ return this;
199
+ }
200
+
201
+ onRecognizedWith<Owner>(owner: Owner, handler: Handler1<Owner, LongPressEventArgs>): LongPressGesture {
202
+ this.recognizedCallback = null;
203
+ this.recognizedBinding = bind1<Owner, LongPressEventArgs>(owner, handler);
204
+ return this;
205
+ }
206
+
207
+ get minimumDurationMs(): i32 {
208
+ return this.minimumDurationMsValue;
209
+ }
210
+
211
+ get movementTolerancePx(): f32 {
212
+ return this.movementToleranceValue;
213
+ }
214
+
215
+ get callback(): ((event: LongPressEventArgs) => void) | null {
216
+ return this.recognizedCallback;
217
+ }
218
+
219
+ get binding(): Callback1<LongPressEventArgs> | null {
220
+ return this.recognizedBinding;
221
+ }
222
+
223
+ get hasHandler(): bool {
224
+ return this.recognizedCallback !== null || this.recognizedBinding !== null;
225
+ }
226
+ }
227
+
228
+ export class PointerEventArgs {
229
+ readonly eventType: PointerEventType;
230
+ readonly sceneX: f32;
231
+ readonly sceneY: f32;
232
+ readonly pointerId: i32;
233
+ readonly pointerType: PointerType;
234
+ readonly button: PointerButton;
235
+ readonly buttons: PointerButtons;
236
+ readonly modifiers: KeyModifier;
237
+ readonly pressure: f32;
238
+ readonly width: f32;
239
+ readonly height: f32;
240
+ readonly clickCount: i32;
241
+ x: f32;
242
+ y: f32;
243
+ handled: bool = false;
244
+
245
+ constructor(
246
+ eventType: PointerEventType,
247
+ sceneX: f32,
248
+ sceneY: f32,
249
+ modifiers: KeyModifier = 0,
250
+ pointerId: i32 = -1,
251
+ pointerType: PointerType = PointerType.Unknown,
252
+ button: PointerButton = PointerButton.None,
253
+ buttons: PointerButtons = PointerButtons.None,
254
+ pressure: f32 = 0.0,
255
+ width: f32 = 0.0,
256
+ height: f32 = 0.0,
257
+ clickCount: i32 = 0,
258
+ ) {
259
+ this.eventType = eventType;
260
+ this.sceneX = sceneX;
261
+ this.sceneY = sceneY;
262
+ this.x = sceneX;
263
+ this.y = sceneY;
264
+ this.modifiers = modifiers;
265
+ this.pointerId = pointerId;
266
+ this.pointerType = pointerType;
267
+ this.button = button;
268
+ this.buttons = buttons;
269
+ this.pressure = pressure;
270
+ this.width = width;
271
+ this.height = height;
272
+ this.clickCount = clickCount;
273
+ }
274
+ }
275
+
276
+ export class PointerClickEventArgs {
277
+ readonly sceneX: f32;
278
+ readonly sceneY: f32;
279
+ readonly pointerType: PointerType;
280
+ readonly button: PointerButton;
281
+ readonly buttons: PointerButtons;
282
+ readonly modifiers: KeyModifier;
283
+ readonly clickCount: i32;
284
+ x: f32;
285
+ y: f32;
286
+ handled: bool = false;
287
+
288
+ constructor(
289
+ sceneX: f32,
290
+ sceneY: f32,
291
+ pointerType: PointerType = PointerType.Unknown,
292
+ button: PointerButton = PointerButton.None,
293
+ buttons: PointerButtons = PointerButtons.None,
294
+ modifiers: KeyModifier = 0,
295
+ clickCount: i32 = 0,
296
+ ) {
297
+ this.sceneX = sceneX;
298
+ this.sceneY = sceneY;
299
+ this.x = sceneX;
300
+ this.y = sceneY;
301
+ this.pointerType = pointerType;
302
+ this.button = button;
303
+ this.buttons = buttons;
304
+ this.modifiers = modifiers;
305
+ this.clickCount = clickCount;
306
+ }
307
+ }
308
+
309
+ export class ClickEventArgs {
310
+ static readonly Empty: ClickEventArgs = new ClickEventArgs();
311
+ }
312
+
313
+ export class KeyEventArgs {
314
+ readonly eventType: KeyEventType;
315
+ readonly key: string;
316
+ readonly modifiers: KeyModifier;
317
+ handled: bool = false;
318
+
319
+ constructor(
320
+ eventType: KeyEventType,
321
+ key: string,
322
+ modifiers: KeyModifier = 0,
323
+ ) {
324
+ this.eventType = eventType;
325
+ this.key = key;
326
+ this.modifiers = modifiers;
327
+ }
328
+ }
329
+
330
+ export class FocusChangedEventArgs {
331
+ readonly focused: bool;
332
+
333
+ constructor(focused: bool) {
334
+ this.focused = focused;
335
+ }
336
+ }
337
+
338
+ export class HoverChangedEventArgs {
339
+ readonly hovered: bool;
340
+
341
+ constructor(hovered: bool) {
342
+ this.hovered = hovered;
343
+ }
344
+ }
345
+
346
+ export class TextChangedEventArgs {
347
+ readonly text: string;
348
+
349
+ constructor(text: string) {
350
+ this.text = text;
351
+ }
352
+ }
353
+
354
+ export class SelectionChangedEventArgs {
355
+ readonly start: u32;
356
+ readonly end: u32;
357
+
358
+ constructor(start: u32, end: u32) {
359
+ this.start = start;
360
+ this.end = end;
361
+ }
362
+ }
363
+
364
+ export class CheckboxChangedEventArgs {
365
+ readonly state: SemanticCheckedState;
366
+ readonly checked: bool;
367
+
368
+ constructor(state: SemanticCheckedState) {
369
+ this.state = state;
370
+ this.checked = state == SemanticCheckedState.True;
371
+ }
372
+ }
373
+
374
+ export class SwitchChangedEventArgs {
375
+ readonly checked: bool;
376
+
377
+ constructor(checked: bool) {
378
+ this.checked = checked;
379
+ }
380
+ }
381
+
382
+ export class RadioButtonChangedEventArgs {
383
+ readonly checked: bool;
384
+
385
+ constructor(checked: bool) {
386
+ this.checked = checked;
387
+ }
388
+ }
389
+
390
+ export class RadioGroupChangedEventArgs {
391
+ readonly value: string;
392
+
393
+ constructor(value: string) {
394
+ this.value = value;
395
+ }
396
+ }
397
+
398
+ export class SliderChangedEventArgs {
399
+ readonly value: f32;
400
+
401
+ constructor(value: f32) {
402
+ this.value = value;
403
+ }
404
+ }
405
+
406
+ export class DropdownChangedEventArgs<TItem> {
407
+ readonly item: TItem;
408
+ readonly index: i32;
409
+
410
+ constructor(item: TItem, index: i32) {
411
+ this.item = item;
412
+ this.index = index;
413
+ }
414
+ }
415
+
416
+ export class ComboBoxChangedEventArgs<TItem> {
417
+ readonly item: TItem;
418
+ readonly index: i32;
419
+
420
+ constructor(item: TItem, index: i32) {
421
+ this.item = item;
422
+ this.index = index;
423
+ }
424
+ }
425
+
426
+ export class DragCompletedEventArgs {
427
+ readonly effect: DragDropEffects;
428
+
429
+ constructor(effect: DragDropEffects) {
430
+ this.effect = effect;
431
+ }
432
+ }
433
+
434
+ export class ContextMenuEventArgs {
435
+ readonly target: Node | null;
436
+ readonly x: f32;
437
+ readonly y: f32;
438
+
439
+ constructor(target: Node | null, x: f32, y: f32) {
440
+ this.target = target;
441
+ this.x = x;
442
+ this.y = y;
443
+ }
444
+ }
445
+
446
+ export class VisibilityChangedEventArgs {
447
+ readonly visible: bool;
448
+
449
+ constructor(visible: bool) {
450
+ this.visible = visible;
451
+ }
452
+ }
453
+
454
+ export class WheelEventArgs {
455
+ readonly sceneX: f32;
456
+ readonly sceneY: f32;
457
+ readonly deltaX: f32;
458
+ readonly deltaY: f32;
459
+ readonly deltaMode: WheelDeltaMode;
460
+ readonly modifiers: KeyModifier;
461
+ x: f32;
462
+ y: f32;
463
+ handled: bool = false;
464
+
465
+ constructor(
466
+ sceneX: f32,
467
+ sceneY: f32,
468
+ deltaX: f32,
469
+ deltaY: f32,
470
+ deltaMode: WheelDeltaMode,
471
+ modifiers: KeyModifier,
472
+ ) {
473
+ this.sceneX = sceneX;
474
+ this.sceneY = sceneY;
475
+ this.x = sceneX;
476
+ this.y = sceneY;
477
+ this.deltaX = deltaX;
478
+ this.deltaY = deltaY;
479
+ this.deltaMode = deltaMode;
480
+ this.modifiers = modifiers;
481
+ }
482
+ }
483
+
47
484
  const DRAG_DROP_TEXT_FORMAT = "text/plain";
48
485
 
49
486
  export class DragDataObject {
@@ -96,8 +533,8 @@ export class DragSession {
96
533
  readonly allowedEffects: DragDropEffects;
97
534
  private currentEffectValue: DragDropEffects = DragDropEffects.None;
98
535
  private activeValue: bool = true;
99
- private completedCallback: ((effect: DragDropEffects) => void) | null = null;
100
- private completedBinding: Callback1<DragDropEffects> | null = null;
536
+ private completedCallback: ((event: DragCompletedEventArgs) => void) | null = null;
537
+ private completedBinding: Callback1<DragCompletedEventArgs> | null = null;
101
538
 
102
539
  constructor(source: Node, data: DragDataObject, allowedEffects: DragDropEffects) {
103
540
  this.source = source;
@@ -113,15 +550,15 @@ export class DragSession {
113
550
  return this.activeValue;
114
551
  }
115
552
 
116
- onCompleted(cb: ((effect: DragDropEffects) => void) | null): DragSession {
553
+ onCompleted(cb: ((event: DragCompletedEventArgs) => void) | null): DragSession {
117
554
  this.completedCallback = cb;
118
555
  this.completedBinding = null;
119
556
  return this;
120
557
  }
121
558
 
122
- onCompletedWith<Owner>(owner: Owner, handler: Handler1<Owner, DragDropEffects>): DragSession {
559
+ onCompletedWith<Owner>(owner: Owner, handler: Handler1<Owner, DragCompletedEventArgs>): DragSession {
123
560
  this.completedCallback = null;
124
- this.completedBinding = bind1<Owner, DragDropEffects>(owner, handler);
561
+ this.completedBinding = bind1<Owner, DragCompletedEventArgs>(owner, handler);
125
562
  return this;
126
563
  }
127
564
 
@@ -142,14 +579,15 @@ export class DragSession {
142
579
  }
143
580
  this.activeValue = false;
144
581
  this.currentEffectValue = effect;
582
+ const event = new DragCompletedEventArgs(effect);
145
583
  const callback = this.completedCallback;
146
584
  if (callback !== null) {
147
- callback(effect);
585
+ callback(event);
148
586
  return;
149
587
  }
150
588
  const binding = this.completedBinding;
151
589
  if (binding !== null) {
152
- binding.invoke(effect);
590
+ binding.invoke(event);
153
591
  }
154
592
  }
155
593
  }
@@ -158,9 +596,9 @@ export class DragEventArgs {
158
596
  readonly session: DragSession;
159
597
  readonly x: f32;
160
598
  readonly y: f32;
161
- readonly modifiers: u32;
599
+ readonly modifiers: KeyModifier;
162
600
 
163
- constructor(session: DragSession, x: f32, y: f32, modifiers: u32) {
601
+ constructor(session: DragSession, x: f32, y: f32, modifiers: KeyModifier) {
164
602
  this.session = session;
165
603
  this.x = x;
166
604
  this.y = y;
@@ -202,10 +640,10 @@ export class ExternalDropItemInfo {
202
640
  export class ExternalDropEventArgs {
203
641
  readonly x: f32;
204
642
  readonly y: f32;
205
- readonly modifiers: u32;
643
+ readonly modifiers: KeyModifier;
206
644
  readonly items: Array<ExternalDropItemInfo>;
207
645
 
208
- constructor(x: f32, y: f32, modifiers: u32, items: Array<ExternalDropItemInfo>) {
646
+ constructor(x: f32, y: f32, modifiers: KeyModifier, items: Array<ExternalDropItemInfo>) {
209
647
  this.x = x;
210
648
  this.y = y;
211
649
  this.modifiers = modifiers;
@@ -214,6 +652,7 @@ export class ExternalDropEventArgs {
214
652
  }
215
653
 
216
654
  export abstract class Node implements DragGestureHost, Disposable {
655
+ protected static pendingPointerEventArgs: PointerEventArgs | null = null;
217
656
  protected handle: u64 = <u64>HandleValue.Invalid;
218
657
  protected childNodes: Array<Node> = new Array<Node>();
219
658
  protected retainedParent: Node | null = null;
@@ -243,18 +682,36 @@ export abstract class Node implements DragGestureHost, Disposable {
243
682
  private semanticValueMax: f32 = 0.0;
244
683
  private semanticOrientationValue: Orientation = Orientation.None;
245
684
  private portalFlag: bool = false;
246
- private clickCallback: (() => void) | null = null;
247
- private clickBinding: Callback0 | null = null;
248
- private pointerDownCallback: ((x: f32, y: f32) => void) | null = null;
249
- private pointerMoveCallback: ((x: f32, y: f32) => void) | null = null;
250
- private pointerUpCallback: ((x: f32, y: f32) => void) | null = null;
251
- private pointerEnterCallback: (() => void) | null = null;
252
- private pointerLeaveCallback: (() => void) | null = null;
685
+ private pointerClickCallback: ((event: PointerClickEventArgs) => void) | null = null;
686
+ private pointerClickBinding: Callback1<PointerClickEventArgs> | null = null;
687
+ private pointerDownEventCallback: ((event: PointerEventArgs) => void) | null = null;
688
+ private pointerDownEventBinding: Callback1<PointerEventArgs> | null = null;
689
+ private pointerMoveEventCallback: ((event: PointerEventArgs) => void) | null = null;
690
+ private pointerMoveEventBinding: Callback1<PointerEventArgs> | null = null;
691
+ private pointerUpEventCallback: ((event: PointerEventArgs) => void) | null = null;
692
+ private pointerUpEventBinding: Callback1<PointerEventArgs> | null = null;
693
+ private pointerEnterEventCallback: ((event: PointerEventArgs) => void) | null = null;
694
+ private pointerEnterEventBinding: Callback1<PointerEventArgs> | null = null;
695
+ private pointerLeaveEventCallback: ((event: PointerEventArgs) => void) | null = null;
696
+ private pointerLeaveEventBinding: Callback1<PointerEventArgs> | null = null;
697
+ private pointerCancelEventCallback: ((event: PointerEventArgs) => void) | null = null;
698
+ private pointerCancelEventBinding: Callback1<PointerEventArgs> | null = null;
699
+ private wheelCallback: ((event: WheelEventArgs) => void) | null = null;
700
+ private wheelBinding: Callback1<WheelEventArgs> | null = null;
701
+ private gestureIntentValue: GestureIntent = GestureIntent.None;
702
+ private panGestureCallback: ((event: PanGestureEventArgs) => void) | null = null;
703
+ private panGestureBinding: Callback1<PanGestureEventArgs> | null = null;
704
+ private pinchGestureCallback: ((event: PinchGestureEventArgs) => void) | null = null;
705
+ private pinchGestureBinding: Callback1<PinchGestureEventArgs> | null = null;
706
+ private longPressGestureCallback: ((event: LongPressEventArgs) => void) | null = null;
707
+ private longPressGestureBinding: Callback1<LongPressEventArgs> | null = null;
708
+ private longPressMinimumDurationMsValue: i32 = DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS;
709
+ private longPressMovementToleranceValue: f32 = DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE;
253
710
  private dragDataCallback: (() => DragDataObject | null) | null = null;
254
711
  private dragDataBinding: ResultCallback0<DragDataObject | null> | null = null;
255
712
  private dragAllowedEffectsValue: DragDropEffects = DragDropEffects.Copy;
256
- private dragCompletedCallback: ((effect: DragDropEffects) => void) | null = null;
257
- private dragCompletedBinding: Callback1<DragDropEffects> | null = null;
713
+ private dragCompletedCallback: ((event: DragCompletedEventArgs) => void) | null = null;
714
+ private dragCompletedBinding: Callback1<DragCompletedEventArgs> | null = null;
258
715
  private dropAllowedValue: bool = false;
259
716
  private dragEnterCallback: ((args: DragEventArgs) => DropProposal) | null = null;
260
717
  private dragEnterBinding: ResultCallback1<DragEventArgs, DropProposal> | null = null;
@@ -275,16 +732,21 @@ export abstract class Node implements DragGestureHost, Disposable {
275
732
  private externalDropBinding: Callback1<ExternalDropEventArgs> | null = null;
276
733
  private dragGestureValue: DragGesture | null = null;
277
734
  private dragClickPending: bool = false;
278
- private contextMenuCallback: ((target: Node | null, x: f32, y: f32) => void) | null = null;
735
+ private dragClickPendingCount: i32 = 0;
736
+ private clickPending: bool = false;
737
+ private clickPendingCount: i32 = 0;
738
+ private contextMenuCallback: ((event: ContextMenuEventArgs) => void) | null = null;
279
739
  private contextMenuDisabledValue: bool = false;
280
740
  private focusableFlag: bool = false;
281
741
  private focusableTabIndex: i32 = 0;
282
- private focusChangedCb: ((focused: bool) => void) | null = null;
283
- private focusChangedBinding: Callback1<bool> | null = null;
284
- private keyDownCb: ((key: string, mods: u32) => void) | null = null;
285
- private keyDownBinding: Callback2<string, u32> | null = null;
286
- private keyUpCb: ((key: string, mods: u32) => void) | null = null;
742
+ private focusChangedCb: ((event: FocusChangedEventArgs) => void) | null = null;
743
+ private focusChangedBinding: Callback1<FocusChangedEventArgs> | null = null;
744
+ private keyDownCb: ((event: KeyEventArgs) => void) | null = null;
745
+ private keyDownBinding: Callback1<KeyEventArgs> | null = null;
746
+ private keyUpCb: ((event: KeyEventArgs) => void) | null = null;
747
+ private keyUpBinding: Callback1<KeyEventArgs> | null = null;
287
748
  private hasPointerCallbacks: bool = false;
749
+ private preserveSelectionOnPointerDownValue: bool = false;
288
750
  private cursorValue: CursorStyle = CursorStyle.Default;
289
751
  private ownEnabled: bool = true;
290
752
  private inheritedEnabled: bool = true;
@@ -364,10 +826,34 @@ export abstract class Node implements DragGestureHost, Disposable {
364
826
  return this.contextMenuDisabledValue;
365
827
  }
366
828
 
367
- get contextMenuHandler(): ((target: Node | null, x: f32, y: f32) => void) | null {
829
+ get isSelectableText(): bool {
830
+ return false;
831
+ }
832
+
833
+ get isEditableText(): bool {
834
+ return false;
835
+ }
836
+
837
+ get contextMenuHandler(): ((event: ContextMenuEventArgs) => void) | null {
368
838
  return this.contextMenuCallback;
369
839
  }
370
840
 
841
+ get gestureIntentValueForRouting(): GestureIntent {
842
+ return this.gestureIntentValue;
843
+ }
844
+
845
+ get hasLongPressGestureForRouting(): bool {
846
+ return this.longPressGestureCallback !== null || this.longPressGestureBinding !== null;
847
+ }
848
+
849
+ get longPressMinimumDurationMsForRouting(): i32 {
850
+ return this.longPressMinimumDurationMsValue;
851
+ }
852
+
853
+ get longPressMovementToleranceForRouting(): f32 {
854
+ return this.longPressMovementToleranceValue;
855
+ }
856
+
371
857
  getChildAt(index: i32): Node | null {
372
858
  if (index < 0 || index >= this.childNodes.length) {
373
859
  return null;
@@ -595,55 +1081,208 @@ export abstract class Node implements DragGestureHost, Disposable {
595
1081
  return this;
596
1082
  }
597
1083
 
598
- onClick(cb: () => void): this {
599
- this.clickCallback = cb;
600
- this.clickBinding = null;
1084
+ onPointerClick(cb: (event: PointerClickEventArgs) => void): this {
1085
+ this.pointerClickCallback = cb;
1086
+ this.pointerClickBinding = null;
1087
+ this.requireInteractive();
1088
+ return this;
1089
+ }
1090
+
1091
+ bindPointerClick<Owner>(owner: Owner, handler: Handler1<Owner, PointerClickEventArgs>): this {
1092
+ this.pointerClickCallback = null;
1093
+ this.pointerClickBinding = bind1<Owner, PointerClickEventArgs>(owner, handler);
1094
+ this.requireInteractive();
1095
+ return this;
1096
+ }
1097
+
1098
+ onPointerClickWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerClickEventArgs>): this {
1099
+ this.bindPointerClick(owner, handler);
1100
+ return this;
1101
+ }
1102
+
1103
+ onPointerDown(cb: (event: PointerEventArgs) => void): this {
1104
+ this.pointerDownEventCallback = cb;
1105
+ this.pointerDownEventBinding = null;
1106
+ this.requireInteractive();
1107
+ return this;
1108
+ }
1109
+
1110
+ onPointerDownWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1111
+ this.pointerDownEventCallback = null;
1112
+ this.pointerDownEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
1113
+ this.requireInteractive();
1114
+ return this;
1115
+ }
1116
+
1117
+ onPointerMove(cb: (event: PointerEventArgs) => void): this {
1118
+ this.pointerMoveEventCallback = cb;
1119
+ this.pointerMoveEventBinding = null;
1120
+ this.requireInteractive();
1121
+ return this;
1122
+ }
1123
+
1124
+ onPointerMoveWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1125
+ this.pointerMoveEventCallback = null;
1126
+ this.pointerMoveEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
1127
+ this.requireInteractive();
1128
+ return this;
1129
+ }
1130
+
1131
+ onPointerUp(cb: (event: PointerEventArgs) => void): this {
1132
+ this.pointerUpEventCallback = cb;
1133
+ this.pointerUpEventBinding = null;
1134
+ this.requireInteractive();
1135
+ return this;
1136
+ }
1137
+
1138
+ onPointerUpWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1139
+ this.pointerUpEventCallback = null;
1140
+ this.pointerUpEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
1141
+ this.requireInteractive();
1142
+ return this;
1143
+ }
1144
+
1145
+ onPointerEnter(cb: (event: PointerEventArgs) => void): this {
1146
+ this.pointerEnterEventCallback = cb;
1147
+ this.pointerEnterEventBinding = null;
601
1148
  this.requireInteractive();
602
1149
  return this;
603
1150
  }
604
1151
 
605
- bindClick<Owner>(owner: Owner, handler: Handler0<Owner>): this {
606
- this.clickCallback = null;
607
- this.clickBinding = bind0<Owner>(owner, handler);
1152
+ onPointerEnterWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1153
+ this.pointerEnterEventCallback = null;
1154
+ this.pointerEnterEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
608
1155
  this.requireInteractive();
609
1156
  return this;
610
1157
  }
611
1158
 
612
- onClickWith<Owner>(owner: Owner, handler: Handler0<Owner>): this {
613
- this.bindClick(owner, handler);
1159
+ onPointerLeave(cb: (event: PointerEventArgs) => void): this {
1160
+ this.pointerLeaveEventCallback = cb;
1161
+ this.pointerLeaveEventBinding = null;
1162
+ this.requireInteractive();
614
1163
  return this;
615
1164
  }
616
1165
 
617
- onPointerDown(cb: (x: f32, y: f32) => void): this {
618
- this.pointerDownCallback = cb;
1166
+ onPointerLeaveWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1167
+ this.pointerLeaveEventCallback = null;
1168
+ this.pointerLeaveEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
619
1169
  this.requireInteractive();
620
1170
  return this;
621
1171
  }
622
1172
 
623
- onPointerMove(cb: (x: f32, y: f32) => void): this {
624
- this.pointerMoveCallback = cb;
1173
+ onPointerCancel(cb: (event: PointerEventArgs) => void): this {
1174
+ this.pointerCancelEventCallback = cb;
1175
+ this.pointerCancelEventBinding = null;
625
1176
  this.requireInteractive();
626
1177
  return this;
627
1178
  }
628
1179
 
629
- onPointerUp(cb: (x: f32, y: f32) => void): this {
630
- this.pointerUpCallback = cb;
1180
+ onPointerCancelWith<Owner>(owner: Owner, handler: Handler1<Owner, PointerEventArgs>): this {
1181
+ this.pointerCancelEventCallback = null;
1182
+ this.pointerCancelEventBinding = bind1<Owner, PointerEventArgs>(owner, handler);
631
1183
  this.requireInteractive();
632
1184
  return this;
633
1185
  }
634
1186
 
635
- onPointerEnter(cb: () => void): this {
636
- this.pointerEnterCallback = cb;
1187
+ onWheel(cb: (event: WheelEventArgs) => void): this {
1188
+ this.wheelCallback = cb;
1189
+ this.wheelBinding = null;
637
1190
  this.requireInteractive();
638
1191
  return this;
639
1192
  }
640
1193
 
641
- onPointerLeave(cb: () => void): this {
642
- this.pointerLeaveCallback = cb;
1194
+ bindWheel<Owner>(owner: Owner, handler: Handler1<Owner, WheelEventArgs>): this {
1195
+ this.wheelCallback = null;
1196
+ this.wheelBinding = bind1<Owner, WheelEventArgs>(owner, handler);
643
1197
  this.requireInteractive();
644
1198
  return this;
645
1199
  }
646
1200
 
1201
+ onWheelWith<Owner>(owner: Owner, handler: Handler1<Owner, WheelEventArgs>): this {
1202
+ this.bindWheel(owner, handler);
1203
+ return this;
1204
+ }
1205
+
1206
+ panGesture(cb: ((event: PanGestureEventArgs) => void) | null): this {
1207
+ this.panGestureCallback = cb;
1208
+ this.panGestureBinding = null;
1209
+ this.updateRecognizerGestureIntent();
1210
+ return this;
1211
+ }
1212
+
1213
+ panGestureWith<Owner>(owner: Owner, handler: Handler1<Owner, PanGestureEventArgs>): this {
1214
+ this.panGestureCallback = null;
1215
+ this.panGestureBinding = bind1<Owner, PanGestureEventArgs>(owner, handler);
1216
+ this.updateRecognizerGestureIntent();
1217
+ return this;
1218
+ }
1219
+
1220
+ pinchGesture(cb: ((event: PinchGestureEventArgs) => void) | null): this {
1221
+ this.pinchGestureCallback = cb;
1222
+ this.pinchGestureBinding = null;
1223
+ this.updateRecognizerGestureIntent();
1224
+ return this;
1225
+ }
1226
+
1227
+ pinchGestureWith<Owner>(owner: Owner, handler: Handler1<Owner, PinchGestureEventArgs>): this {
1228
+ this.pinchGestureCallback = null;
1229
+ this.pinchGestureBinding = bind1<Owner, PinchGestureEventArgs>(owner, handler);
1230
+ this.updateRecognizerGestureIntent();
1231
+ return this;
1232
+ }
1233
+
1234
+ longPressGesture(cb: ((event: LongPressEventArgs) => void) | null): this {
1235
+ this.longPressGestureCallback = cb;
1236
+ this.longPressGestureBinding = null;
1237
+ this.longPressMinimumDurationMsValue = DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS;
1238
+ this.longPressMovementToleranceValue = DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE;
1239
+ if (cb !== null) {
1240
+ this.requireInteractive();
1241
+ }
1242
+ return this;
1243
+ }
1244
+
1245
+ longPressGestureWith<Owner>(owner: Owner, handler: Handler1<Owner, LongPressEventArgs>): this {
1246
+ this.longPressGestureCallback = null;
1247
+ this.longPressGestureBinding = bind1<Owner, LongPressEventArgs>(owner, handler);
1248
+ this.longPressMinimumDurationMsValue = DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS;
1249
+ this.longPressMovementToleranceValue = DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE;
1250
+ this.requireInteractive();
1251
+ return this;
1252
+ }
1253
+
1254
+ longPressRecognizer(gesture: LongPressGesture | null): this {
1255
+ if (gesture === null) {
1256
+ this.longPressGestureCallback = null;
1257
+ this.longPressGestureBinding = null;
1258
+ this.longPressMinimumDurationMsValue = DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS;
1259
+ this.longPressMovementToleranceValue = DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE;
1260
+ return this;
1261
+ }
1262
+ this.longPressGestureCallback = gesture.callback;
1263
+ this.longPressGestureBinding = gesture.binding;
1264
+ this.longPressMinimumDurationMsValue = gesture.minimumDurationMs;
1265
+ this.longPressMovementToleranceValue = gesture.movementTolerancePx;
1266
+ if (gesture.hasHandler) {
1267
+ this.requireInteractive();
1268
+ }
1269
+ return this;
1270
+ }
1271
+
1272
+ private updateRecognizerGestureIntent(): void {
1273
+ let intent = GestureIntent.None;
1274
+ if (this.panGestureCallback !== null || this.panGestureBinding !== null) {
1275
+ intent = <GestureIntent>(<u32>intent | <u32>GestureIntent.Pan);
1276
+ }
1277
+ if (this.pinchGestureCallback !== null || this.pinchGestureBinding !== null) {
1278
+ intent = <GestureIntent>(<u32>intent | <u32>GestureIntent.Pinch);
1279
+ }
1280
+ this.gestureIntentValue = intent;
1281
+ if (intent != GestureIntent.None) {
1282
+ this.requireInteractive();
1283
+ }
1284
+ }
1285
+
647
1286
  dragAllowedEffects(effects: DragDropEffects): this {
648
1287
  this.dragAllowedEffectsValue = effects;
649
1288
  return this;
@@ -675,15 +1314,15 @@ export abstract class Node implements DragGestureHost, Disposable {
675
1314
  return this;
676
1315
  }
677
1316
 
678
- onDragCompleted(cb: ((effect: DragDropEffects) => void) | null): this {
1317
+ onDragCompleted(cb: ((event: DragCompletedEventArgs) => void) | null): this {
679
1318
  this.dragCompletedCallback = cb;
680
1319
  this.dragCompletedBinding = null;
681
1320
  return this;
682
1321
  }
683
1322
 
684
- onDragCompletedWith<Owner>(owner: Owner, handler: Handler1<Owner, DragDropEffects>): this {
1323
+ onDragCompletedWith<Owner>(owner: Owner, handler: Handler1<Owner, DragCompletedEventArgs>): this {
685
1324
  this.dragCompletedCallback = null;
686
- this.dragCompletedBinding = bind1<Owner, DragDropEffects>(owner, handler);
1325
+ this.dragCompletedBinding = bind1<Owner, DragCompletedEventArgs>(owner, handler);
687
1326
  return this;
688
1327
  }
689
1328
 
@@ -836,6 +1475,22 @@ export abstract class Node implements DragGestureHost, Disposable {
836
1475
  return this;
837
1476
  }
838
1477
 
1478
+ preserveSelectionOnPointerDown(preserve: bool = true): this {
1479
+ if (this.preserveSelectionOnPointerDownValue == preserve) {
1480
+ return this;
1481
+ }
1482
+ this.preserveSelectionOnPointerDownValue = preserve;
1483
+ if (this.hasBuiltHandle()) {
1484
+ ui.setPreserveSelectionOnPointerDown(this.handle, preserve);
1485
+ this.notifyRetainedMutation();
1486
+ }
1487
+ return this;
1488
+ }
1489
+
1490
+ get preservesSelectionOnPointerDownForRouting(): bool {
1491
+ return this.preserveSelectionOnPointerDownValue;
1492
+ }
1493
+
839
1494
  toolTipText(text: string): this {
840
1495
  this.toolTip(ToolTip.text(text));
841
1496
  return this;
@@ -846,7 +1501,7 @@ export abstract class Node implements DragGestureHost, Disposable {
846
1501
  return this;
847
1502
  }
848
1503
 
849
- onContextMenu(cb: ((target: Node | null, x: f32, y: f32) => void) | null): this {
1504
+ onContextMenu(cb: ((event: ContextMenuEventArgs) => void) | null): this {
850
1505
  this.contextMenuCallback = cb;
851
1506
  return this;
852
1507
  }
@@ -896,42 +1551,54 @@ export abstract class Node implements DragGestureHost, Disposable {
896
1551
  return this;
897
1552
  }
898
1553
 
899
- onFocusChanged(cb: (focused: bool) => void): this {
1554
+ onFocusChanged(cb: (event: FocusChangedEventArgs) => void): this {
900
1555
  this.focusChangedCb = cb;
901
1556
  this.focusChangedBinding = null;
902
1557
  return this;
903
1558
  }
904
1559
 
905
- bindFocusChanged<Owner>(owner: Owner, handler: Handler1<Owner, bool>): this {
1560
+ bindFocusChanged<Owner>(owner: Owner, handler: Handler1<Owner, FocusChangedEventArgs>): this {
906
1561
  this.focusChangedCb = null;
907
- this.focusChangedBinding = bind1<Owner, bool>(owner, handler);
1562
+ this.focusChangedBinding = bind1<Owner, FocusChangedEventArgs>(owner, handler);
908
1563
  return this;
909
1564
  }
910
1565
 
911
- onFocusChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, bool>): this {
1566
+ onFocusChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, FocusChangedEventArgs>): this {
912
1567
  this.bindFocusChanged(owner, handler);
913
1568
  return this;
914
1569
  }
915
1570
 
916
- onKeyDown(cb: (key: string, mods: u32) => void): this {
1571
+ onKeyDown(cb: (event: KeyEventArgs) => void): this {
917
1572
  this.keyDownCb = cb;
918
1573
  this.keyDownBinding = null;
919
1574
  return this;
920
1575
  }
921
1576
 
922
- bindKeyDown<Owner>(owner: Owner, handler: Handler2<Owner, string, u32>): this {
1577
+ bindKeyDown<Owner>(owner: Owner, handler: Handler1<Owner, KeyEventArgs>): this {
923
1578
  this.keyDownCb = null;
924
- this.keyDownBinding = bind2<Owner, string, u32>(owner, handler);
1579
+ this.keyDownBinding = bind1<Owner, KeyEventArgs>(owner, handler);
925
1580
  return this;
926
1581
  }
927
1582
 
928
- onKeyDownWith<Owner>(owner: Owner, handler: Handler2<Owner, string, u32>): this {
1583
+ onKeyDownWith<Owner>(owner: Owner, handler: Handler1<Owner, KeyEventArgs>): this {
929
1584
  this.bindKeyDown(owner, handler);
930
1585
  return this;
931
1586
  }
932
1587
 
933
- onKeyUp(cb: (key: string, mods: u32) => void): this {
1588
+ onKeyUp(cb: (event: KeyEventArgs) => void): this {
934
1589
  this.keyUpCb = cb;
1590
+ this.keyUpBinding = null;
1591
+ return this;
1592
+ }
1593
+
1594
+ bindKeyUp<Owner>(owner: Owner, handler: Handler1<Owner, KeyEventArgs>): this {
1595
+ this.keyUpCb = null;
1596
+ this.keyUpBinding = bind1<Owner, KeyEventArgs>(owner, handler);
1597
+ return this;
1598
+ }
1599
+
1600
+ onKeyUpWith<Owner>(owner: Owner, handler: Handler1<Owner, KeyEventArgs>): this {
1601
+ this.bindKeyUp(owner, handler);
935
1602
  return this;
936
1603
  }
937
1604
 
@@ -1083,6 +1750,8 @@ export abstract class Node implements DragGestureHost, Disposable {
1083
1750
 
1084
1751
  protected finishBuild(): void {
1085
1752
  this.disposedValue = false;
1753
+ this.lastEffectiveEnabled = this.isEnabled;
1754
+ this.lastEffectiveVisibility = this.effectiveVisibility();
1086
1755
  EventRouter.register(this.handle, this);
1087
1756
  if (this.focusableFlag && this.isEnabled && this.isVisible) {
1088
1757
  ui.setFocusable(this.handle, this.focusableFlag, this.focusableTabIndex);
@@ -1090,6 +1759,9 @@ export abstract class Node implements DragGestureHost, Disposable {
1090
1759
  if (this.hasPointerCallbacks && this.isEnabled && this.isVisible) {
1091
1760
  ui.setInteractive(this.handle, true);
1092
1761
  }
1762
+ if (this.preserveSelectionOnPointerDownValue) {
1763
+ ui.setPreserveSelectionOnPointerDown(this.handle, true);
1764
+ }
1093
1765
  }
1094
1766
 
1095
1767
  protected buildChildren(): void {
@@ -1206,13 +1878,14 @@ export abstract class Node implements DragGestureHost, Disposable {
1206
1878
  }
1207
1879
 
1208
1880
  _notifyDragCompleted(effect: DragDropEffects): void {
1881
+ const event = new DragCompletedEventArgs(effect);
1209
1882
  const callback = this.dragCompletedCallback;
1210
1883
  if (callback !== null) {
1211
- callback(effect);
1884
+ callback(event);
1212
1885
  } else {
1213
1886
  const binding = this.dragCompletedBinding;
1214
1887
  if (binding !== null) {
1215
- binding.invoke(effect);
1888
+ binding.invoke(event);
1216
1889
  }
1217
1890
  }
1218
1891
  }
@@ -1415,6 +2088,10 @@ export abstract class Node implements DragGestureHost, Disposable {
1415
2088
  return this.attachedPropertyKey;
1416
2089
  }
1417
2090
 
2091
+ _requiredFontIds(): Array<u32> {
2092
+ return new Array<u32>();
2093
+ }
2094
+
1418
2095
  _capturePersistedStateTree(): void {
1419
2096
  this.capturePersistedState();
1420
2097
  for (let index = 0; index < this.childNodes.length; ++index) {
@@ -1470,20 +2147,34 @@ export abstract class Node implements DragGestureHost, Disposable {
1470
2147
  }
1471
2148
  }
1472
2149
 
1473
- private fireClick(): void {
1474
- const callback = this.clickCallback;
2150
+ private fireClick(count: i32, event: PointerEventArgs): void {
2151
+ const clickEvent = new PointerClickEventArgs(
2152
+ event.sceneX,
2153
+ event.sceneY,
2154
+ event.pointerType,
2155
+ event.button,
2156
+ event.buttons,
2157
+ event.modifiers,
2158
+ count > 0 ? count : 1,
2159
+ );
2160
+ clickEvent.x = event.x;
2161
+ clickEvent.y = event.y;
2162
+ const callback = this.pointerClickCallback;
1475
2163
  if (callback !== null) {
1476
- callback();
2164
+ callback(clickEvent);
1477
2165
  return;
1478
2166
  }
1479
- const binding = this.clickBinding;
2167
+ const binding = this.pointerClickBinding;
1480
2168
  if (binding !== null) {
1481
- binding.invoke();
2169
+ binding.invoke(clickEvent);
1482
2170
  }
1483
2171
  }
1484
2172
 
1485
2173
  private cancelDragState(): void {
1486
2174
  this.dragClickPending = false;
2175
+ this.dragClickPendingCount = 0;
2176
+ this.clickPending = false;
2177
+ this.clickPendingCount = 0;
1487
2178
  const gesture = this.dragGestureValue;
1488
2179
  if (gesture !== null) {
1489
2180
  gesture.cancel();
@@ -1491,82 +2182,323 @@ export abstract class Node implements DragGestureHost, Disposable {
1491
2182
  }
1492
2183
 
1493
2184
  _handlePointerEvent(eventType: PointerEventType, _x: f32, _y: f32, _modifiers: u32 = 0): void {
2185
+ const pending = Node.pendingPointerEventArgs;
2186
+ let event = pending !== null
2187
+ ? changetype<PointerEventArgs>(pending)
2188
+ : new PointerEventArgs(eventType, _x, _y, _modifiers);
2189
+ if (pending === event) {
2190
+ Node.pendingPointerEventArgs = null;
2191
+ }
2192
+ this.handlePointerEventCore(event);
2193
+ }
2194
+
2195
+ _handlePointerEventWithArgs(event: PointerEventArgs): void {
2196
+ this.handlePointerEventCore(event);
2197
+ }
2198
+
2199
+ _handleBubbledPointerEvent(event: PointerEventArgs): bool {
2200
+ if (!this.isEnabled || !this.isVisible) {
2201
+ return false;
2202
+ }
2203
+ const nodeX: f32 = this.hasBuiltHandle() ? (event.sceneX - this.getBounds()[0]) : event.sceneX;
2204
+ const nodeY: f32 = this.hasBuiltHandle() ? (event.sceneY - this.getBounds()[1]) : event.sceneY;
2205
+ event.x = nodeX;
2206
+ event.y = nodeY;
2207
+ this.invokePointerEventCallback(event);
2208
+ if (!event.handled) {
2209
+ if (event.eventType == PointerEventType.Down) {
2210
+ const isPrimaryButton = isPrimaryActivationPointer(event);
2211
+ this.clickPending = isPrimaryButton && (this.pointerClickCallback !== null || this.pointerClickBinding !== null);
2212
+ this.clickPendingCount = event.clickCount;
2213
+ } else if (event.eventType == PointerEventType.Up) {
2214
+ if (this.clickPending) {
2215
+ this.fireClick(this.clickPendingCount, event);
2216
+ }
2217
+ this.clickPending = false;
2218
+ this.clickPendingCount = 0;
2219
+ } else if (event.eventType == PointerEventType.Leave || event.eventType == PointerEventType.Cancel) {
2220
+ this.clickPending = false;
2221
+ this.clickPendingCount = 0;
2222
+ }
2223
+ }
2224
+ return event.handled;
2225
+ }
2226
+
2227
+ static _dispatchPointerEventWithArgs(node: Node, event: PointerEventArgs): void {
2228
+ Node.pendingPointerEventArgs = event;
2229
+ node._handlePointerEvent(event.eventType, event.sceneX, event.sceneY, event.modifiers);
2230
+ if (Node.pendingPointerEventArgs === event) {
2231
+ Node.pendingPointerEventArgs = null;
2232
+ }
2233
+ }
2234
+
2235
+ private handlePointerEventCore(event: PointerEventArgs): void {
1494
2236
  if (!this.isEnabled || !this.isVisible) {
1495
2237
  return;
1496
2238
  }
2239
+ const _x = event.sceneX;
2240
+ const _y = event.sceneY;
2241
+ const _modifiers = event.modifiers;
2242
+ const nodeX: f32 = this.hasBuiltHandle() ? (_x - this.getBounds()[0]) : _x;
2243
+ const nodeY: f32 = this.hasBuiltHandle() ? (_y - this.getBounds()[1]) : _y;
2244
+ event.x = nodeX;
2245
+ event.y = nodeY;
2246
+ const eventType = event.eventType;
1497
2247
  if (eventType == PointerEventType.Down) {
1498
2248
  ToolTipManager.handlePointerDown(this);
2249
+ this.invokePointerEventCallback(event);
2250
+ if (event.handled) {
2251
+ return;
2252
+ }
1499
2253
  const dragGesture = this._hasDragSource() ? this.dragGestureValue : null;
1500
- if (dragGesture !== null) {
1501
- dragGesture.handlePointerDown(_x, _y, _modifiers);
1502
- this.dragClickPending = this.clickCallback !== null || this.clickBinding !== null;
2254
+ const isPrimaryButton = isPrimaryActivationPointer(event);
2255
+ if (dragGesture !== null && isPrimaryButton) {
2256
+ dragGesture.handlePointerDown(nodeX, nodeY, _modifiers);
2257
+ this.dragClickPending = this.pointerClickCallback !== null || this.pointerClickBinding !== null;
2258
+ this.dragClickPendingCount = event.clickCount;
2259
+ this.clickPending = false;
2260
+ this.clickPendingCount = 0;
1503
2261
  } else {
1504
2262
  this.dragClickPending = false;
1505
- }
1506
- const pointerDown = this.pointerDownCallback;
1507
- if (pointerDown !== null) {
1508
- pointerDown(_x, _y);
1509
- }
1510
- if (dragGesture === null) {
1511
- this.fireClick();
2263
+ this.dragClickPendingCount = 0;
2264
+ this.clickPending = isPrimaryButton && (this.pointerClickCallback !== null || this.pointerClickBinding !== null);
2265
+ this.clickPendingCount = event.clickCount;
1512
2266
  }
1513
2267
  return;
1514
2268
  }
1515
2269
  if (eventType == PointerEventType.Move) {
1516
2270
  ToolTipManager.handlePointerMove(this, _x, _y);
2271
+ this.invokePointerEventCallback(event);
2272
+ if (event.handled) {
2273
+ return;
2274
+ }
1517
2275
  const dragGesture = this.dragGestureValue;
1518
2276
  if (dragGesture !== null && (this._hasDragSource() || dragGesture.isDragging)) {
1519
- dragGesture.handlePointerMove(_x, _y, _modifiers);
1520
- }
1521
- const callback = this.pointerMoveCallback;
1522
- if (callback !== null) {
1523
- callback(_x, _y);
2277
+ dragGesture.handlePointerMove(nodeX, nodeY, _modifiers);
1524
2278
  }
1525
2279
  return;
1526
2280
  }
1527
2281
  if (eventType == PointerEventType.Up) {
2282
+ this.invokePointerEventCallback(event);
2283
+ if (event.handled) {
2284
+ this.dragClickPending = false;
2285
+ this.dragClickPendingCount = 0;
2286
+ this.clickPending = false;
2287
+ this.clickPendingCount = 0;
2288
+ return;
2289
+ }
1528
2290
  const dragGesture = this.dragGestureValue;
1529
2291
  const dragGestureActive = dragGesture !== null && (this._hasDragSource() || dragGesture.isDragging);
1530
2292
  const canFirePendingClick = this.dragClickPending && (!dragGestureActive || !changetype<DragGesture>(dragGesture).isDragging);
2293
+ const canFireClick = this.clickPending;
1531
2294
  if (dragGestureActive) {
1532
- changetype<DragGesture>(dragGesture).handlePointerUp(_x, _y, _modifiers);
2295
+ changetype<DragGesture>(dragGesture).handlePointerUp(nodeX, nodeY, _modifiers);
1533
2296
  }
1534
- const callback = this.pointerUpCallback;
1535
- if (callback !== null) {
1536
- callback(_x, _y);
2297
+ if (canFireClick) {
2298
+ this.fireClick(this.clickPendingCount, event);
1537
2299
  }
2300
+ this.clickPending = false;
2301
+ this.clickPendingCount = 0;
1538
2302
  if (canFirePendingClick) {
1539
- this.fireClick();
2303
+ this.fireClick(this.dragClickPendingCount, event);
1540
2304
  }
1541
2305
  this.dragClickPending = false;
2306
+ this.dragClickPendingCount = 0;
1542
2307
  return;
1543
2308
  }
1544
2309
  if (eventType == PointerEventType.Enter) {
1545
- const callback = this.pointerEnterCallback;
1546
- if (callback !== null) {
1547
- callback();
2310
+ this.invokePointerEventCallback(event);
2311
+ if (event.handled) {
2312
+ return;
1548
2313
  }
1549
2314
  ToolTipManager.handlePointerEnter(this, this.toolTipValue, _x, _y);
1550
2315
  return;
1551
2316
  }
1552
2317
  if (eventType == PointerEventType.Leave) {
1553
- const callback = this.pointerLeaveCallback;
1554
- if (callback !== null) {
1555
- callback();
2318
+ this.invokePointerEventCallback(event);
2319
+ if (event.handled) {
2320
+ this.dragClickPending = false;
2321
+ this.clickPending = false;
2322
+ this.clickPendingCount = 0;
2323
+ ToolTipManager.handlePointerLeave(this);
2324
+ return;
1556
2325
  }
1557
2326
  this.dragClickPending = false;
2327
+ this.clickPending = false;
2328
+ this.clickPendingCount = 0;
2329
+ ToolTipManager.handlePointerLeave(this);
2330
+ return;
2331
+ }
2332
+ if (eventType == PointerEventType.Cancel) {
2333
+ this.invokePointerEventCallback(event);
2334
+ if (event.handled) {
2335
+ this.cancelDragState();
2336
+ ToolTipManager.handlePointerLeave(this);
2337
+ return;
2338
+ }
2339
+ this.cancelDragState();
1558
2340
  ToolTipManager.handlePointerLeave(this);
1559
2341
  }
1560
2342
  }
1561
2343
 
2344
+ private invokePointerEventCallback(event: PointerEventArgs): void {
2345
+ if (event.eventType == PointerEventType.Down) {
2346
+ const callback = this.pointerDownEventCallback;
2347
+ if (callback !== null) {
2348
+ callback(event);
2349
+ }
2350
+ const binding = this.pointerDownEventBinding;
2351
+ if (binding !== null) {
2352
+ binding.invoke(event);
2353
+ }
2354
+ return;
2355
+ }
2356
+ if (event.eventType == PointerEventType.Move) {
2357
+ const callback = this.pointerMoveEventCallback;
2358
+ if (callback !== null) {
2359
+ callback(event);
2360
+ }
2361
+ const binding = this.pointerMoveEventBinding;
2362
+ if (binding !== null) {
2363
+ binding.invoke(event);
2364
+ }
2365
+ return;
2366
+ }
2367
+ if (event.eventType == PointerEventType.Up) {
2368
+ const callback = this.pointerUpEventCallback;
2369
+ if (callback !== null) {
2370
+ callback(event);
2371
+ }
2372
+ const binding = this.pointerUpEventBinding;
2373
+ if (binding !== null) {
2374
+ binding.invoke(event);
2375
+ }
2376
+ return;
2377
+ }
2378
+ if (event.eventType == PointerEventType.Enter) {
2379
+ const callback = this.pointerEnterEventCallback;
2380
+ if (callback !== null) {
2381
+ callback(event);
2382
+ }
2383
+ const binding = this.pointerEnterEventBinding;
2384
+ if (binding !== null) {
2385
+ binding.invoke(event);
2386
+ }
2387
+ return;
2388
+ }
2389
+ if (event.eventType == PointerEventType.Leave) {
2390
+ const callback = this.pointerLeaveEventCallback;
2391
+ if (callback !== null) {
2392
+ callback(event);
2393
+ }
2394
+ const binding = this.pointerLeaveEventBinding;
2395
+ if (binding !== null) {
2396
+ binding.invoke(event);
2397
+ }
2398
+ return;
2399
+ }
2400
+ if (event.eventType == PointerEventType.Cancel) {
2401
+ const callback = this.pointerCancelEventCallback;
2402
+ if (callback !== null) {
2403
+ callback(event);
2404
+ }
2405
+ const binding = this.pointerCancelEventBinding;
2406
+ if (binding !== null) {
2407
+ binding.invoke(event);
2408
+ }
2409
+ }
2410
+ }
2411
+
2412
+ _handleWheelEvent(event: WheelEventArgs): bool {
2413
+ if (!this.isEnabled || !this.isVisible) {
2414
+ return false;
2415
+ }
2416
+ const bounds = this.hasBuiltHandle() ? this.getBounds() : new Float32Array(4);
2417
+ event.x = event.sceneX - unchecked(bounds[0]);
2418
+ event.y = event.sceneY - unchecked(bounds[1]);
2419
+ const callback = this.wheelCallback;
2420
+ if (callback !== null) {
2421
+ callback(event);
2422
+ }
2423
+ const binding = this.wheelBinding;
2424
+ if (binding !== null) {
2425
+ binding.invoke(event);
2426
+ }
2427
+ return event.handled;
2428
+ }
2429
+
2430
+ _handleGestureEvent(event: GestureEventArgs): bool {
2431
+ if (!this.isEnabled || !this.isVisible) {
2432
+ return false;
2433
+ }
2434
+ const bounds = this.hasBuiltHandle() ? this.getBounds() : new Float32Array(4);
2435
+ event.x = event.sceneX - unchecked(bounds[0]);
2436
+ event.y = event.sceneY - unchecked(bounds[1]);
2437
+ if (event.kind == GestureEventKind.Pan) {
2438
+ const panCallback = this.panGestureCallback;
2439
+ if (panCallback !== null) {
2440
+ panCallback(event);
2441
+ }
2442
+ const panBinding = this.panGestureBinding;
2443
+ if (panBinding !== null) {
2444
+ panBinding.invoke(event);
2445
+ }
2446
+ } else if (event.kind == GestureEventKind.Pinch) {
2447
+ const pinchCallback = this.pinchGestureCallback;
2448
+ if (pinchCallback !== null) {
2449
+ pinchCallback(event);
2450
+ }
2451
+ const pinchBinding = this.pinchGestureBinding;
2452
+ if (pinchBinding !== null) {
2453
+ pinchBinding.invoke(event);
2454
+ }
2455
+ }
2456
+ return event.handled;
2457
+ }
2458
+
2459
+ _handleBubbledGestureEvent(event: GestureEventArgs): bool {
2460
+ return this._handleGestureEvent(event);
2461
+ }
2462
+
2463
+ static _dispatchGestureEventWithArgs(node: Node, event: GestureEventArgs): void {
2464
+ node._handleGestureEvent(event);
2465
+ }
2466
+
2467
+ _handleLongPressEvent(event: LongPressEventArgs): bool {
2468
+ if (!this.isEnabled || !this.isVisible) {
2469
+ return false;
2470
+ }
2471
+ const bounds = this.hasBuiltHandle() ? this.getBounds() : new Float32Array(4);
2472
+ event.x = event.sceneX - unchecked(bounds[0]);
2473
+ event.y = event.sceneY - unchecked(bounds[1]);
2474
+ const callback = this.longPressGestureCallback;
2475
+ if (callback !== null) {
2476
+ callback(event);
2477
+ }
2478
+ const binding = this.longPressGestureBinding;
2479
+ if (binding !== null) {
2480
+ binding.invoke(event);
2481
+ }
2482
+ return event.handled;
2483
+ }
2484
+
2485
+ _handleBubbledLongPressEvent(event: LongPressEventArgs): bool {
2486
+ return this._handleLongPressEvent(event);
2487
+ }
2488
+
2489
+ static _dispatchLongPressEventWithArgs(node: Node, event: LongPressEventArgs): void {
2490
+ node._handleLongPressEvent(event);
2491
+ }
2492
+
1562
2493
  _handleFocusChanged(focused: bool): void {
2494
+ const event = new FocusChangedEventArgs(focused);
1563
2495
  const callback = this.focusChangedCb;
1564
2496
  if (callback !== null) {
1565
- callback(focused);
2497
+ callback(event);
1566
2498
  }
1567
2499
  const binding = this.focusChangedBinding;
1568
2500
  if (binding !== null) {
1569
- binding.invoke(focused);
2501
+ binding.invoke(event);
1570
2502
  }
1571
2503
  ToolTipManager.handleFocusChanged(this, this.toolTipValue, focused);
1572
2504
  }
@@ -1575,15 +2507,16 @@ export abstract class Node implements DragGestureHost, Disposable {
1575
2507
  if (!this.isEnabled || !this.isVisible) {
1576
2508
  return false;
1577
2509
  }
2510
+ const event = new KeyEventArgs(eventType, key, modifiers);
1578
2511
  if (eventType == KeyEventType.Down) {
1579
2512
  const callback = this.keyDownCb;
1580
2513
  if (callback !== null) {
1581
- callback(key, modifiers);
2514
+ callback(event);
1582
2515
  return true;
1583
2516
  }
1584
2517
  const binding = this.keyDownBinding;
1585
2518
  if (binding !== null) {
1586
- binding.invoke(key, modifiers);
2519
+ binding.invoke(event);
1587
2520
  return true;
1588
2521
  }
1589
2522
  return false;
@@ -1591,7 +2524,12 @@ export abstract class Node implements DragGestureHost, Disposable {
1591
2524
  if (eventType == KeyEventType.Up) {
1592
2525
  const callback = this.keyUpCb;
1593
2526
  if (callback !== null) {
1594
- callback(key, modifiers);
2527
+ callback(event);
2528
+ return true;
2529
+ }
2530
+ const binding = this.keyUpBinding;
2531
+ if (binding !== null) {
2532
+ binding.invoke(event);
1595
2533
  return true;
1596
2534
  }
1597
2535
  }
@@ -1619,6 +2557,10 @@ export abstract class Node implements DragGestureHost, Disposable {
1619
2557
  if (!this.hasPointerCallbacks) {
1620
2558
  this.hasPointerCallbacks = true;
1621
2559
  }
2560
+ if (this.hasBuiltHandle() && this.isEnabled && this.isVisible) {
2561
+ ui.setInteractive(this.handle, true);
2562
+ this.notifyRetainedMutation();
2563
+ }
1622
2564
  }
1623
2565
 
1624
2566
  _bindScrollProxyTarget(handle: u64): void {
@@ -1739,4 +2681,4 @@ export abstract class Node implements DragGestureHost, Disposable {
1739
2681
  }
1740
2682
  }
1741
2683
 
1742
- }
2684
+ }