@effindomv2/fui-as 0.1.36 → 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.
- package/browser/routed-app-conventions.ts +1 -1
- package/browser/src/common-harness.ts +1 -27
- package/browser/src/index.ts +19 -26
- package/browser/src/routed-harness.ts +1 -194
- package/browser/src/shared-browser.ts +6 -0
- package/package.json +26 -16
- package/scripts/build.sh +51 -47
- package/scripts/framework-host-services.ts +1 -1
- package/scripts/generate-host-events.ts +15 -241
- package/scripts/generate-host-services.ts +13 -261
- package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
- package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
- package/scripts/hostgen/common.ts +73 -0
- package/scripts/hostgen/registry.ts +159 -0
- package/src/Fui.ts +70 -4
- package/src/FuiExports.ts +13 -1
- package/src/bindings/ui.ts +165 -8
- package/src/controls/Button.ts +98 -71
- package/src/controls/Checkbox.ts +23 -21
- package/src/controls/ComboBox.ts +1201 -0
- package/src/controls/ContextMenu.ts +279 -165
- package/src/controls/Dialog.ts +91 -17
- package/src/controls/Dropdown.ts +101 -333
- package/src/controls/NavLink.ts +29 -6
- package/src/controls/Popup.ts +10 -5
- package/src/controls/ProgressBar.ts +1 -2
- package/src/controls/RadioButton.ts +34 -13
- package/src/controls/RadioGroup.ts +32 -19
- package/src/controls/Slider.ts +21 -23
- package/src/controls/Switch.ts +34 -17
- package/src/controls/index.ts +2 -1
- package/src/controls/internal/ButtonPresenter.ts +5 -2
- package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
- package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
- package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
- package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
- package/src/controls/internal/PressableLabeledControl.ts +4 -7
- package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
- package/src/controls/internal/SelectablePopupList.ts +463 -0
- package/src/controls/internal/SliderPresenter.ts +5 -5
- package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
- package/src/controls/internal/TextInputCore.ts +307 -41
- package/src/controls/internal/TextInputPresenter.ts +2 -2
- package/src/controls/templating.ts +10 -0
- package/src/core/Application.ts +19 -9
- package/src/core/Bitmap.ts +219 -1
- package/src/core/ContextMenuManager.ts +128 -44
- package/src/core/DebugApi.ts +17 -2
- package/src/core/DragGesture.ts +8 -7
- package/src/core/EventRouter.ts +332 -12
- package/src/core/Fetch.ts +15 -7
- package/src/core/FetchFfi.ts +1 -15
- package/src/core/File.ts +75 -34
- package/src/core/FocusAdornerManager.ts +3 -3
- package/src/core/FocusVisibility.ts +7 -0
- package/src/core/FrameScheduler.ts +126 -0
- package/src/core/ImageSampling.ts +43 -0
- package/src/core/Logger.ts +2 -0
- package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
- package/src/core/Node.ts +1039 -97
- package/src/core/Platform.ts +16 -16
- package/src/core/SelectionHandleAdornerManager.ts +697 -0
- package/src/core/Theme.ts +34 -20
- package/src/core/ToolTipManager.ts +3 -3
- package/src/core/Typography.ts +411 -19
- package/src/core/Worker.ts +69 -33
- package/src/core/event_exports.ts +123 -5
- package/src/core/ffi.ts +5 -746
- package/src/core/generated/FetchHostAbi.ts +10 -0
- package/src/core/generated/FrameworkHostServices.ts +1 -1
- package/src/core/generated/HostAbi.ts +220 -0
- package/src/core/generated/UiAbi.ts +356 -0
- package/src/core/generated/UiEnums.ts +186 -0
- package/src/drawing/DrawCallback.ts +34 -0
- package/src/drawing/DrawContext.ts +189 -0
- package/src/drawing/Paint.ts +34 -0
- package/src/drawing/Path.ts +40 -0
- package/src/nodes/CustomDrawable.ts +61 -0
- package/src/nodes/FlexBox.ts +57 -11
- package/src/nodes/Grid.ts +5 -5
- package/src/nodes/Image.ts +20 -1
- package/src/nodes/RichText.ts +36 -25
- package/src/nodes/ScrollBar.ts +2 -1
- package/src/nodes/ScrollBox.ts +7 -2
- package/src/nodes/ScrollView.ts +17 -6
- package/src/nodes/Svg.ts +18 -1
- package/src/nodes/Text.ts +1 -1
- package/src/nodes/TextCore.ts +115 -20
- package/src/nodes/index.ts +3 -1
- package/src/text/DynamicTextLayout.ts +275 -0
- package/src/text/TextLayout.ts +308 -0
- package/src/worker/Worker.ts +3 -36
- package/src/worker/WorkerJob.ts +5 -9
- package/src/worker/ffi.ts +0 -6
- package/browser/src/common-harness/host-imports.ts +0 -447
- package/browser/src/common-harness/interop.ts +0 -39
- package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
- package/browser/src/common-harness/managed-harness-fetch-host.ts +0 -201
- package/browser/src/common-harness/managed-harness-file-host.ts +0 -1066
- package/browser/src/common-harness/managed-harness-file-payloads.ts +0 -143
- package/browser/src/common-harness/managed-harness-file-types.ts +0 -71
- package/browser/src/common-harness/managed-harness-session.ts +0 -15
- package/browser/src/common-harness/managed-harness.ts +0 -1451
- package/browser/src/common-harness/managed-history.ts +0 -168
- package/browser/src/common-harness/persisted-restore-policy.ts +0 -50
- package/browser/src/common-harness/persisted-ui-state-controller.ts +0 -309
- package/browser/src/common-harness/text-session-bridge.ts +0 -452
- package/browser/src/common-harness/types.ts +0 -205
- package/browser/src/common-harness/ui-chrome.ts +0 -206
- package/browser/src/common-harness/ui-imports.ts +0 -553
- package/browser/src/common-harness/wasm-module-cache.ts +0 -47
- package/browser/src/file-processing-worker.ts +0 -89
- package/browser/src/host-events.ts +0 -118
- package/browser/src/host-services.ts +0 -483
- package/browser/src/persisted-ui-state.ts +0 -206
- package/browser/src/routed-app-conventions.ts +0 -292
- package/browser/src/worker-bootstrap.ts +0 -916
- package/browser/src/worker-manager.ts +0 -234
- package/browser/src/worker-types.ts +0 -68
package/src/core/File.ts
CHANGED
|
@@ -23,6 +23,7 @@ const FUNCTION_SAVE_TEXT_WITH = "FileSaveRequest.saveTextWith";
|
|
|
23
23
|
const FUNCTION_SAVE_BYTES_WITH = "FileSaveRequest.saveBytesWith";
|
|
24
24
|
const FUNCTION_CREATE_WRITER_WITH = "FileSaveRequest.createWriterWith";
|
|
25
25
|
const FUNCTION_FILE_WORKER_PROCESS_START = "FileWorkerProcessRequest.start";
|
|
26
|
+
const FUNCTION_FILE_WORKER_PROCESS_WORKER = "FileWorkerProcessRequest.worker";
|
|
26
27
|
const FUNCTION_WRITE_TEXT_CHUNK_WITH = "BrowserFileWriter.writeTextChunkWith";
|
|
27
28
|
const FUNCTION_WRITE_BYTES_CHUNK_WITH = "BrowserFileWriter.writeBytesChunkWith";
|
|
28
29
|
const FUNCTION_FINISH_WITH = "BrowserFileWriter.finishWith";
|
|
@@ -70,9 +71,9 @@ function describeFileFailure(status: u32, fallback: string): string {
|
|
|
70
71
|
return fallback;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
function dispatchFileError(binding: Callback1<
|
|
74
|
+
function dispatchFileError(binding: Callback1<FileErrorEventArgs> | null, message: string): void {
|
|
74
75
|
if (binding !== null) {
|
|
75
|
-
binding.invoke(message);
|
|
76
|
+
binding.invoke(new FileErrorEventArgs(message));
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
79
|
warn("File", message);
|
|
@@ -163,43 +164,43 @@ class FileRequestDisposable implements Disposable {
|
|
|
163
164
|
|
|
164
165
|
class PendingOpenRequest {
|
|
165
166
|
constructor(
|
|
166
|
-
readonly completeBinding: Callback1<
|
|
167
|
-
readonly errorBinding: Callback1<
|
|
167
|
+
readonly completeBinding: Callback1<FileOpenEventArgs>,
|
|
168
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
168
169
|
) {}
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
class PendingReadRequest {
|
|
172
173
|
constructor(
|
|
173
174
|
readonly completeBinding: Callback1<FileReadChunk>,
|
|
174
|
-
readonly errorBinding: Callback1<
|
|
175
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
175
176
|
) {}
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
class PendingSaveRequest {
|
|
179
180
|
constructor(
|
|
180
181
|
readonly completeBinding: Callback1<FileSaveResult>,
|
|
181
|
-
readonly errorBinding: Callback1<
|
|
182
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
182
183
|
) {}
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
class PendingWriterCreateRequest {
|
|
186
187
|
constructor(
|
|
187
188
|
readonly completeBinding: Callback1<BrowserFileWriter>,
|
|
188
|
-
readonly errorBinding: Callback1<
|
|
189
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
189
190
|
) {}
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
class PendingWriterWriteRequest {
|
|
193
194
|
constructor(
|
|
194
195
|
readonly completeBinding: Callback1<FileWriteProgress>,
|
|
195
|
-
readonly errorBinding: Callback1<
|
|
196
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
196
197
|
) {}
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
class PendingWriterFinishRequest {
|
|
200
201
|
constructor(
|
|
201
202
|
readonly completeBinding: Callback1<FileSaveResult>,
|
|
202
|
-
readonly errorBinding: Callback1<
|
|
203
|
+
readonly errorBinding: Callback1<FileErrorEventArgs> | null,
|
|
203
204
|
) {}
|
|
204
205
|
}
|
|
205
206
|
|
|
@@ -228,6 +229,22 @@ export class FileCapabilities {
|
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
231
|
|
|
232
|
+
export class FileOpenEventArgs {
|
|
233
|
+
readonly files: Array<BrowserFile>;
|
|
234
|
+
|
|
235
|
+
constructor(files: Array<BrowserFile>) {
|
|
236
|
+
this.files = files;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export class FileErrorEventArgs {
|
|
241
|
+
readonly message: string;
|
|
242
|
+
|
|
243
|
+
constructor(message: string) {
|
|
244
|
+
this.message = message;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
231
248
|
export class FileReadChunk {
|
|
232
249
|
readonly offsetBytes: u64;
|
|
233
250
|
readonly fileSizeBytes: u64;
|
|
@@ -314,14 +331,14 @@ export class BrowserFile {
|
|
|
314
331
|
offsetBytes: u64,
|
|
315
332
|
maxBytes: u32,
|
|
316
333
|
handler: Handler1<Owner, FileReadChunk>,
|
|
317
|
-
errorHandler: Handler1<Owner,
|
|
334
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
318
335
|
): Disposable {
|
|
319
336
|
if (changetype<usize>(handler) == 0) {
|
|
320
337
|
throwNullArgument(FUNCTION_READ_BYTES_CHUNK_WITH, "handler");
|
|
321
338
|
}
|
|
322
339
|
if (maxBytes == 0) {
|
|
323
340
|
dispatchFileError(
|
|
324
|
-
errorHandler === null ? null : bind1<Owner,
|
|
341
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
325
342
|
"BrowserFile.readBytesChunkWith: maxBytes must be greater than zero.",
|
|
326
343
|
);
|
|
327
344
|
return new FileRequestDisposable(REQUEST_KIND_READ, 0);
|
|
@@ -329,7 +346,7 @@ export class BrowserFile {
|
|
|
329
346
|
const fileIdBytes = encodeUtf8(this.id);
|
|
330
347
|
const requestId = registerPendingReadRequest(new PendingReadRequest(
|
|
331
348
|
bind1<Owner, FileReadChunk>(owner, handler),
|
|
332
|
-
errorHandler === null ? null : bind1<Owner,
|
|
349
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
333
350
|
));
|
|
334
351
|
fui_file_read_chunk(
|
|
335
352
|
requestId,
|
|
@@ -344,13 +361,15 @@ export class BrowserFile {
|
|
|
344
361
|
|
|
345
362
|
export class FileWorkerProcessRequest implements Disposable {
|
|
346
363
|
private readonly file: BrowserFile;
|
|
364
|
+
private workerWasmPathValue: string = "";
|
|
365
|
+
private workerEntryNameValue: string = "";
|
|
347
366
|
private suggestedNameValue: string;
|
|
348
367
|
private saveToPickedFileEnabled: bool = false;
|
|
349
368
|
private chunkBytesValue: u32 = 64 * 1024;
|
|
350
369
|
private chunkBinding: Callback1<FileReadChunk> | null = null;
|
|
351
370
|
private progressBinding: Callback1<FileWorkerProcessProgress> | null = null;
|
|
352
371
|
private completeBinding: Callback1<FileWorkerProcessResult> | null = null;
|
|
353
|
-
private errorBinding: Callback1<
|
|
372
|
+
private errorBinding: Callback1<FileErrorEventArgs> | null = null;
|
|
354
373
|
private requestId: u32 = 0;
|
|
355
374
|
private started: bool = false;
|
|
356
375
|
private finished: bool = false;
|
|
@@ -368,6 +387,18 @@ export class FileWorkerProcessRequest implements Disposable {
|
|
|
368
387
|
return this;
|
|
369
388
|
}
|
|
370
389
|
|
|
390
|
+
worker(wasmPath: string, entryName: string): this {
|
|
391
|
+
if (changetype<usize>(wasmPath) == 0) {
|
|
392
|
+
throwNullArgument(FUNCTION_FILE_WORKER_PROCESS_WORKER, "wasmPath");
|
|
393
|
+
}
|
|
394
|
+
if (changetype<usize>(entryName) == 0) {
|
|
395
|
+
throwNullArgument(FUNCTION_FILE_WORKER_PROCESS_WORKER, "entryName");
|
|
396
|
+
}
|
|
397
|
+
this.workerWasmPathValue = wasmPath;
|
|
398
|
+
this.workerEntryNameValue = entryName;
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
401
|
+
|
|
371
402
|
saveToPickedFile(value: string): this {
|
|
372
403
|
this.saveToPickedFileEnabled = true;
|
|
373
404
|
return this.suggestedName(value);
|
|
@@ -414,15 +445,15 @@ export class FileWorkerProcessRequest implements Disposable {
|
|
|
414
445
|
return this.onComplete<Owner>(owner, handler);
|
|
415
446
|
}
|
|
416
447
|
|
|
417
|
-
onError<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
448
|
+
onError<Owner>(owner: Owner, handler: Handler1<Owner, FileErrorEventArgs>): this {
|
|
418
449
|
if (changetype<usize>(handler) == 0) {
|
|
419
450
|
throwNullArgument("FileWorkerProcessRequest.onError", "handler");
|
|
420
451
|
}
|
|
421
|
-
this.errorBinding = bind1<Owner,
|
|
452
|
+
this.errorBinding = bind1<Owner, FileErrorEventArgs>(owner, handler);
|
|
422
453
|
return this;
|
|
423
454
|
}
|
|
424
455
|
|
|
425
|
-
onErrorWith<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
456
|
+
onErrorWith<Owner>(owner: Owner, handler: Handler1<Owner, FileErrorEventArgs>): this {
|
|
426
457
|
return this.onError<Owner>(owner, handler);
|
|
427
458
|
}
|
|
428
459
|
|
|
@@ -439,16 +470,26 @@ export class FileWorkerProcessRequest implements Disposable {
|
|
|
439
470
|
dispatchFileError(this.errorBinding, "FileWorkerProcessRequest.start: chunkBytes must be greater than zero.");
|
|
440
471
|
return this;
|
|
441
472
|
}
|
|
473
|
+
if (this.workerWasmPathValue.length == 0 || this.workerEntryNameValue.length == 0) {
|
|
474
|
+
dispatchFileError(this.errorBinding, "FileWorkerProcessRequest.start: worker(wasmPath, entryName) is required.");
|
|
475
|
+
return this;
|
|
476
|
+
}
|
|
442
477
|
if (!this.saveToPickedFileEnabled && this.chunkBinding === null) {
|
|
443
478
|
dispatchFileError(this.errorBinding, "FileWorkerProcessRequest.start: either saveToPickedFile(...) or onChunk(...) is required.");
|
|
444
479
|
return this;
|
|
445
480
|
}
|
|
481
|
+
const workerWasmPathBytes = encodeUtf8(this.workerWasmPathValue);
|
|
482
|
+
const workerEntryNameBytes = encodeUtf8(this.workerEntryNameValue);
|
|
446
483
|
const fileIdBytes = encodeUtf8(this.file.id);
|
|
447
484
|
const suggestedNameBytes = encodeUtf8(this.suggestedNameValue);
|
|
448
485
|
this.requestId = registerPendingWorkerProcessRequest(this);
|
|
449
486
|
this.started = true;
|
|
450
487
|
fui_file_process_worker_start(
|
|
451
488
|
this.requestId,
|
|
489
|
+
workerWasmPathBytes.length > 0 ? workerWasmPathBytes.dataStart : 0,
|
|
490
|
+
<u32>workerWasmPathBytes.length,
|
|
491
|
+
workerEntryNameBytes.length > 0 ? workerEntryNameBytes.dataStart : 0,
|
|
492
|
+
<u32>workerEntryNameBytes.length,
|
|
452
493
|
fileIdBytes.length > 0 ? fileIdBytes.dataStart : 0,
|
|
453
494
|
<u32>fileIdBytes.length,
|
|
454
495
|
suggestedNameBytes.length > 0 ? suggestedNameBytes.dataStart : 0,
|
|
@@ -550,7 +591,7 @@ export class BrowserFileWriter {
|
|
|
550
591
|
owner: Owner,
|
|
551
592
|
text: string,
|
|
552
593
|
handler: Handler1<Owner, FileWriteProgress>,
|
|
553
|
-
errorHandler: Handler1<Owner,
|
|
594
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
554
595
|
): Disposable {
|
|
555
596
|
if (changetype<usize>(text) == 0) {
|
|
556
597
|
throwNullArgument(FUNCTION_WRITE_TEXT_CHUNK_WITH, "text");
|
|
@@ -562,7 +603,7 @@ export class BrowserFileWriter {
|
|
|
562
603
|
const textBytes = encodeUtf8(text);
|
|
563
604
|
const requestId = registerPendingWriterWriteRequest(new PendingWriterWriteRequest(
|
|
564
605
|
bind1<Owner, FileWriteProgress>(owner, handler),
|
|
565
|
-
errorHandler === null ? null : bind1<Owner,
|
|
606
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
566
607
|
));
|
|
567
608
|
fui_file_writer_write_text(
|
|
568
609
|
requestId,
|
|
@@ -578,7 +619,7 @@ export class BrowserFileWriter {
|
|
|
578
619
|
owner: Owner,
|
|
579
620
|
bytes: Uint8Array,
|
|
580
621
|
handler: Handler1<Owner, FileWriteProgress>,
|
|
581
|
-
errorHandler: Handler1<Owner,
|
|
622
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
582
623
|
): Disposable {
|
|
583
624
|
if (changetype<usize>(bytes) == 0) {
|
|
584
625
|
throwNullArgument(FUNCTION_WRITE_BYTES_CHUNK_WITH, "bytes");
|
|
@@ -589,7 +630,7 @@ export class BrowserFileWriter {
|
|
|
589
630
|
const writerIdBytes = encodeUtf8(this.writerId);
|
|
590
631
|
const requestId = registerPendingWriterWriteRequest(new PendingWriterWriteRequest(
|
|
591
632
|
bind1<Owner, FileWriteProgress>(owner, handler),
|
|
592
|
-
errorHandler === null ? null : bind1<Owner,
|
|
633
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
593
634
|
));
|
|
594
635
|
fui_file_writer_write_bytes(
|
|
595
636
|
requestId,
|
|
@@ -604,7 +645,7 @@ export class BrowserFileWriter {
|
|
|
604
645
|
finishWith<Owner>(
|
|
605
646
|
owner: Owner,
|
|
606
647
|
handler: Handler1<Owner, FileSaveResult>,
|
|
607
|
-
errorHandler: Handler1<Owner,
|
|
648
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
608
649
|
): Disposable {
|
|
609
650
|
if (changetype<usize>(handler) == 0) {
|
|
610
651
|
throwNullArgument(FUNCTION_FINISH_WITH, "handler");
|
|
@@ -612,7 +653,7 @@ export class BrowserFileWriter {
|
|
|
612
653
|
const writerIdBytes = encodeUtf8(this.writerId);
|
|
613
654
|
const requestId = registerPendingWriterFinishRequest(new PendingWriterFinishRequest(
|
|
614
655
|
bind1<Owner, FileSaveResult>(owner, handler),
|
|
615
|
-
errorHandler === null ? null : bind1<Owner,
|
|
656
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
616
657
|
));
|
|
617
658
|
fui_file_writer_finish(
|
|
618
659
|
requestId,
|
|
@@ -642,16 +683,16 @@ export class FileOpenRequest {
|
|
|
642
683
|
|
|
643
684
|
pickWith<Owner>(
|
|
644
685
|
owner: Owner,
|
|
645
|
-
handler: Handler1<Owner,
|
|
646
|
-
errorHandler: Handler1<Owner,
|
|
686
|
+
handler: Handler1<Owner, FileOpenEventArgs>,
|
|
687
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
647
688
|
): Disposable {
|
|
648
689
|
if (changetype<usize>(handler) == 0) {
|
|
649
690
|
throwNullArgument(FUNCTION_PICK_WITH, "handler");
|
|
650
691
|
}
|
|
651
692
|
const acceptBytes = encodeUtf8(this.acceptValue);
|
|
652
693
|
const requestId = registerPendingOpenRequest(new PendingOpenRequest(
|
|
653
|
-
bind1<Owner,
|
|
654
|
-
errorHandler === null ? null : bind1<Owner,
|
|
694
|
+
bind1<Owner, FileOpenEventArgs>(owner, handler),
|
|
695
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
655
696
|
));
|
|
656
697
|
fui_file_pick(
|
|
657
698
|
requestId,
|
|
@@ -696,7 +737,7 @@ export class FileSaveRequest {
|
|
|
696
737
|
owner: Owner,
|
|
697
738
|
text: string,
|
|
698
739
|
handler: Handler1<Owner, FileSaveResult>,
|
|
699
|
-
errorHandler: Handler1<Owner,
|
|
740
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
700
741
|
): Disposable {
|
|
701
742
|
if (changetype<usize>(text) == 0) {
|
|
702
743
|
throwNullArgument(FUNCTION_SAVE_TEXT_WITH, "text");
|
|
@@ -710,7 +751,7 @@ export class FileSaveRequest {
|
|
|
710
751
|
const textBytes = encodeUtf8(text);
|
|
711
752
|
const requestId = registerPendingSaveRequest(new PendingSaveRequest(
|
|
712
753
|
bind1<Owner, FileSaveResult>(owner, handler),
|
|
713
|
-
errorHandler === null ? null : bind1<Owner,
|
|
754
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
714
755
|
));
|
|
715
756
|
fui_file_save_text(
|
|
716
757
|
requestId,
|
|
@@ -730,7 +771,7 @@ export class FileSaveRequest {
|
|
|
730
771
|
owner: Owner,
|
|
731
772
|
bytes: Uint8Array,
|
|
732
773
|
handler: Handler1<Owner, FileSaveResult>,
|
|
733
|
-
errorHandler: Handler1<Owner,
|
|
774
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
734
775
|
): Disposable {
|
|
735
776
|
if (changetype<usize>(bytes) == 0) {
|
|
736
777
|
throwNullArgument(FUNCTION_SAVE_BYTES_WITH, "bytes");
|
|
@@ -743,7 +784,7 @@ export class FileSaveRequest {
|
|
|
743
784
|
const extensionBytes = encodeUtf8(this.fileExtensionValue);
|
|
744
785
|
const requestId = registerPendingSaveRequest(new PendingSaveRequest(
|
|
745
786
|
bind1<Owner, FileSaveResult>(owner, handler),
|
|
746
|
-
errorHandler === null ? null : bind1<Owner,
|
|
787
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
747
788
|
));
|
|
748
789
|
fui_file_save_bytes(
|
|
749
790
|
requestId,
|
|
@@ -762,7 +803,7 @@ export class FileSaveRequest {
|
|
|
762
803
|
createWriterWith<Owner>(
|
|
763
804
|
owner: Owner,
|
|
764
805
|
handler: Handler1<Owner, BrowserFileWriter>,
|
|
765
|
-
errorHandler: Handler1<Owner,
|
|
806
|
+
errorHandler: Handler1<Owner, FileErrorEventArgs> | null = null,
|
|
766
807
|
): Disposable {
|
|
767
808
|
if (changetype<usize>(handler) == 0) {
|
|
768
809
|
throwNullArgument(FUNCTION_CREATE_WRITER_WITH, "handler");
|
|
@@ -772,7 +813,7 @@ export class FileSaveRequest {
|
|
|
772
813
|
const extensionBytes = encodeUtf8(this.fileExtensionValue);
|
|
773
814
|
const requestId = registerPendingWriterCreateRequest(new PendingWriterCreateRequest(
|
|
774
815
|
bind1<Owner, BrowserFileWriter>(owner, handler),
|
|
775
|
-
errorHandler === null ? null : bind1<Owner,
|
|
816
|
+
errorHandler === null ? null : bind1<Owner, FileErrorEventArgs>(owner, errorHandler),
|
|
776
817
|
));
|
|
777
818
|
fui_file_create_writer(
|
|
778
819
|
requestId,
|
|
@@ -842,7 +883,7 @@ export function handleFilePickResult(requestId: u32, status: u32, files: Array<B
|
|
|
842
883
|
return;
|
|
843
884
|
}
|
|
844
885
|
if (status == FILE_STATUS_SUCCESS) {
|
|
845
|
-
request.completeBinding.invoke(files);
|
|
886
|
+
request.completeBinding.invoke(new FileOpenEventArgs(files));
|
|
846
887
|
return;
|
|
847
888
|
}
|
|
848
889
|
dispatchFileError(request.errorBinding, message === null ? describeFileFailure(status, "File picker failed.") : message);
|
|
@@ -998,7 +1039,7 @@ export function disposeAllFileRequests(): void {
|
|
|
998
1039
|
pendingWorkerProcessRequests.clear();
|
|
999
1040
|
}
|
|
1000
1041
|
|
|
1001
|
-
export function
|
|
1042
|
+
export function resetFileRuntime(): void {
|
|
1002
1043
|
disposeAllFileRequests();
|
|
1003
1044
|
browserFiles.clear();
|
|
1004
1045
|
nextFileRequestId = 1;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ui from "../bindings/ui";
|
|
2
|
-
import {
|
|
2
|
+
import { Unit } from "./ffi";
|
|
3
3
|
import { Node } from "./Node";
|
|
4
4
|
import { activeTheme } from "./Theme";
|
|
5
5
|
import { Portal, FlexBox } from "../nodes";
|
|
@@ -53,7 +53,7 @@ export class FocusAdornerManager {
|
|
|
53
53
|
const ringNode = new FlexBox()
|
|
54
54
|
.positionAbsolute()
|
|
55
55
|
.bgColor(0x00000000)
|
|
56
|
-
.border(STANDARD_FOCUS_RING_WIDTH, 0x00000000
|
|
56
|
+
.border(STANDARD_FOCUS_RING_WIDTH, 0x00000000);
|
|
57
57
|
const hostRoot = new Portal()
|
|
58
58
|
.positionAbsolute()
|
|
59
59
|
.position(0.0, 0.0)
|
|
@@ -168,7 +168,7 @@ export class FocusAdornerManager {
|
|
|
168
168
|
style.bottomLeftRadius != this.lastBottomLeftRadius
|
|
169
169
|
) {
|
|
170
170
|
ringNode.corners(style.topLeftRadius, style.topRightRadius, style.bottomRightRadius, style.bottomLeftRadius);
|
|
171
|
-
ringNode.border(STANDARD_FOCUS_RING_WIDTH, color
|
|
171
|
+
ringNode.border(STANDARD_FOCUS_RING_WIDTH, color);
|
|
172
172
|
this.lastColor = color;
|
|
173
173
|
this.lastTopLeftRadius = style.topLeftRadius;
|
|
174
174
|
this.lastTopRightRadius = style.topRightRadius;
|
|
@@ -17,6 +17,10 @@ function hasNonShiftModifier(modifiers: u32): bool {
|
|
|
17
17
|
return (modifiers & (KeyModifier.Ctrl | KeyModifier.Alt | KeyModifier.Meta)) != 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function isCaretNavigationKey(key: string): bool {
|
|
21
|
+
return key == "ArrowLeft" || key == "ArrowRight" || key == "ArrowUp" || key == "ArrowDown" || key == "Home" || key == "End" || key == "PageUp" || key == "PageDown";
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
export function showKeyboardFocusForKeyEvent(eventType: KeyEventType, key: string, modifiers: u32 = 0): void {
|
|
21
25
|
if (eventType != KeyEventType.Down || isModifierKey(key)) {
|
|
22
26
|
return;
|
|
@@ -24,6 +28,9 @@ export function showKeyboardFocusForKeyEvent(eventType: KeyEventType, key: strin
|
|
|
24
28
|
if (hasNonShiftModifier(modifiers)) {
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
31
|
+
if (isCaretNavigationKey(key)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
27
34
|
if (key == "Escape") {
|
|
28
35
|
keyboardFocusVisible.value = false;
|
|
29
36
|
return;
|
|
@@ -2,6 +2,71 @@ import * as ui from "../bindings/ui";
|
|
|
2
2
|
|
|
3
3
|
let needsCommit: bool = false;
|
|
4
4
|
let flushScheduled: bool = false;
|
|
5
|
+
let didFirstCommit: bool = false;
|
|
6
|
+
const nextCommitCallbacks = new Array<() => void>();
|
|
7
|
+
export type AfterCommitHandler<Owner> = (owner: Owner) => void;
|
|
8
|
+
abstract class NextCommitRegistration {
|
|
9
|
+
abstract invoke(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class NextCommitCallbackRegistration extends NextCommitRegistration {
|
|
13
|
+
constructor(private readonly callback: () => void) {
|
|
14
|
+
super();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
invoke(): void {
|
|
18
|
+
this.callback();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class NextCommitHandlerRegistration<Owner> extends NextCommitRegistration {
|
|
23
|
+
constructor(
|
|
24
|
+
private readonly owner: Owner,
|
|
25
|
+
private readonly handler: AfterCommitHandler<Owner>,
|
|
26
|
+
) {
|
|
27
|
+
super();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
invoke(): void {
|
|
31
|
+
this.handler(this.owner);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class LoadedEventArgs {
|
|
36
|
+
static readonly Empty: LoadedEventArgs = new LoadedEventArgs();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// WPF-style Loaded event — fires once after the tree is built and mounted.
|
|
40
|
+
export type LoadedHandler<Owner> = (owner: Owner, event: LoadedEventArgs) => void;
|
|
41
|
+
|
|
42
|
+
abstract class LoadedRegistration {
|
|
43
|
+
abstract invoke(): void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class LoadedCallbackRegistration extends LoadedRegistration {
|
|
47
|
+
constructor(private readonly callback: (event: LoadedEventArgs) => void) {
|
|
48
|
+
super();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
invoke(): void {
|
|
52
|
+
this.callback(LoadedEventArgs.Empty);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class LoadedHandlerRegistration<Owner> extends LoadedRegistration {
|
|
57
|
+
constructor(
|
|
58
|
+
private readonly owner: Owner,
|
|
59
|
+
private readonly handler: LoadedHandler<Owner>,
|
|
60
|
+
) {
|
|
61
|
+
super();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
invoke(): void {
|
|
65
|
+
this.handler(this.owner, LoadedEventArgs.Empty);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const loadedCallbacks = new Array<LoadedRegistration>();
|
|
5
70
|
|
|
6
71
|
export function markNeedsCommit(): void {
|
|
7
72
|
needsCommit = true;
|
|
@@ -12,6 +77,50 @@ export function markNeedsCommit(): void {
|
|
|
12
77
|
ui.requestRender();
|
|
13
78
|
}
|
|
14
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Register a callback that fires once after the page has been mounted and
|
|
82
|
+
* the first frame has been committed. Safe to call during `buildPage()` —
|
|
83
|
+
* timers started here survive `cancelAllTimers()` in `Application.mount()`.
|
|
84
|
+
*/
|
|
85
|
+
export function onLoaded(cb: (event: LoadedEventArgs) => void): void {
|
|
86
|
+
if (didFirstCommit) {
|
|
87
|
+
cb(LoadedEventArgs.Empty);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
loadedCallbacks.push(new LoadedCallbackRegistration(cb));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function onLoadedWith<Owner>(owner: Owner, handler: LoadedHandler<Owner>): void {
|
|
94
|
+
if (didFirstCommit) {
|
|
95
|
+
handler(owner, LoadedEventArgs.Empty);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
loadedCallbacks.push(new LoadedHandlerRegistration<Owner>(owner, handler));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function onLoadedFor<Owner>(owner: Owner, handler: LoadedHandler<Owner>): void {
|
|
102
|
+
onLoadedWith<Owner>(owner, handler);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function fireLoadedCallbacks(): void {
|
|
106
|
+
if (didFirstCommit) return;
|
|
107
|
+
didFirstCommit = true;
|
|
108
|
+
for (let i: i32 = 0; i < loadedCallbacks.length; i++) {
|
|
109
|
+
unchecked(loadedCallbacks[i]).invoke();
|
|
110
|
+
}
|
|
111
|
+
loadedCallbacks.length = 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function afterNextCommit(callback: () => void): void {
|
|
115
|
+
nextCommitCallbacks.push(callback);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const nextCommitRegistrations = new Array<NextCommitRegistration>();
|
|
119
|
+
|
|
120
|
+
export function afterNextCommitWith<Owner>(owner: Owner, handler: AfterCommitHandler<Owner>): void {
|
|
121
|
+
nextCommitRegistrations.push(new NextCommitHandlerRegistration<Owner>(owner, handler));
|
|
122
|
+
}
|
|
123
|
+
|
|
15
124
|
export function flushCommit(): bool {
|
|
16
125
|
flushScheduled = false;
|
|
17
126
|
if (!needsCommit) {
|
|
@@ -19,10 +128,27 @@ export function flushCommit(): bool {
|
|
|
19
128
|
}
|
|
20
129
|
needsCommit = false;
|
|
21
130
|
ui.commitFrame();
|
|
131
|
+
if (nextCommitCallbacks.length > 0) {
|
|
132
|
+
const callbacks = nextCommitCallbacks.slice();
|
|
133
|
+
nextCommitCallbacks.length = 0;
|
|
134
|
+
for (let i: i32 = 0; i < callbacks.length; i++) {
|
|
135
|
+
unchecked(callbacks[i])();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (nextCommitRegistrations.length > 0) {
|
|
139
|
+
const registrations = nextCommitRegistrations.slice();
|
|
140
|
+
nextCommitRegistrations.length = 0;
|
|
141
|
+
for (let i: i32 = 0; i < registrations.length; i++) {
|
|
142
|
+
unchecked(registrations[i]).invoke();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
22
145
|
return true;
|
|
23
146
|
}
|
|
24
147
|
|
|
25
148
|
export function resetCommitState(): void {
|
|
26
149
|
needsCommit = false;
|
|
27
150
|
flushScheduled = false;
|
|
151
|
+
didFirstCommit = false;
|
|
152
|
+
nextCommitCallbacks.length = 0;
|
|
153
|
+
nextCommitRegistrations.length = 0;
|
|
28
154
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ImageSamplingKind } from "./ffi";
|
|
2
|
+
|
|
3
|
+
export class ImageSampling {
|
|
4
|
+
private static LINEAR: ImageSampling = new ImageSampling(ImageSamplingKind.Linear, 0);
|
|
5
|
+
private static NEAREST: ImageSampling = new ImageSampling(ImageSamplingKind.Nearest, 0);
|
|
6
|
+
private static LINEAR_MIPMAP_NEAREST: ImageSampling = new ImageSampling(ImageSamplingKind.LinearMipmapNearest, 0);
|
|
7
|
+
private static LINEAR_MIPMAP_LINEAR: ImageSampling = new ImageSampling(ImageSamplingKind.LinearMipmapLinear, 0);
|
|
8
|
+
private static CUBIC_MITCHELL: ImageSampling = new ImageSampling(ImageSamplingKind.CubicMitchell, 0);
|
|
9
|
+
private static CUBIC_CATMULL_ROM: ImageSampling = new ImageSampling(ImageSamplingKind.CubicCatmullRom, 0);
|
|
10
|
+
|
|
11
|
+
static linear(): ImageSampling {
|
|
12
|
+
return ImageSampling.LINEAR;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static nearest(): ImageSampling {
|
|
16
|
+
return ImageSampling.NEAREST;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static linearMipmapNearest(): ImageSampling {
|
|
20
|
+
return ImageSampling.LINEAR_MIPMAP_NEAREST;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static linearMipmapLinear(): ImageSampling {
|
|
24
|
+
return ImageSampling.LINEAR_MIPMAP_LINEAR;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static cubicMitchell(): ImageSampling {
|
|
28
|
+
return ImageSampling.CUBIC_MITCHELL;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static cubicCatmullRom(): ImageSampling {
|
|
32
|
+
return ImageSampling.CUBIC_CATMULL_ROM;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static anisotropic(maxAniso: u32 = 8): ImageSampling {
|
|
36
|
+
return new ImageSampling(ImageSamplingKind.Anisotropic, maxAniso);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private constructor(
|
|
40
|
+
public readonly kind: ImageSamplingKind,
|
|
41
|
+
public readonly maxAniso: u32,
|
|
42
|
+
) {}
|
|
43
|
+
}
|
package/src/core/Logger.ts
CHANGED
|
@@ -63,6 +63,8 @@ export function describePointerEventType(eventType: PointerEventType): string {
|
|
|
63
63
|
return "enter";
|
|
64
64
|
case PointerEventType.Leave:
|
|
65
65
|
return "leave";
|
|
66
|
+
case PointerEventType.Cancel:
|
|
67
|
+
return "cancel";
|
|
66
68
|
default:
|
|
67
69
|
return "pointer(" + (<u32>eventType).toString() + ")";
|
|
68
70
|
}
|