@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.
- 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 +23 -13
- package/scripts/build.sh +47 -46
- 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 +65 -5
- package/src/FuiExports.ts +12 -1
- package/src/bindings/ui.ts +157 -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 +17 -8
- package/src/core/Bitmap.ts +192 -3
- 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 +104 -5
- 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 -865
- 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 +17 -1
- package/src/drawing/DrawContext.ts +140 -32
- package/src/nodes/CustomDrawable.ts +8 -1
- package/src/nodes/FlexBox.ts +40 -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 +1 -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-canvas-host.ts +0 -72
- 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 -1472
- 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 -206
- package/browser/src/common-harness/ui-chrome.ts +0 -206
- package/browser/src/common-harness/ui-imports.ts +0 -559
- 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/nodes/RichText.ts
CHANGED
|
@@ -147,10 +147,20 @@ export function span(text: string): RichTextSpan {
|
|
|
147
147
|
|
|
148
148
|
const STYLE_RUN_WORD_STRIDE: i32 = 7;
|
|
149
149
|
|
|
150
|
+
function pushUniqueFontId(fontIds: Array<u32>, fontId: u32): void {
|
|
151
|
+
if (fontId == 0) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (let index = 0; index < fontIds.length; ++index) {
|
|
155
|
+
if (unchecked(fontIds[index]) == fontId) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
fontIds.push(fontId);
|
|
160
|
+
}
|
|
161
|
+
|
|
150
162
|
export class RichText extends Text {
|
|
151
163
|
private hasBaseFontValue: bool = false;
|
|
152
|
-
private baseUsesDirectFontId: bool = false;
|
|
153
|
-
private baseFontIdValue: u32 = 0;
|
|
154
164
|
private baseFontFamilyValue: FontFamily | null = null;
|
|
155
165
|
private hasBaseFontSizeValue: bool = false;
|
|
156
166
|
private baseFontSizeValue: f32 = 0.0;
|
|
@@ -176,27 +186,17 @@ export class RichText extends Text {
|
|
|
176
186
|
return this;
|
|
177
187
|
}
|
|
178
188
|
|
|
179
|
-
|
|
189
|
+
fontStack(stack: FontStack, size: f32): this {
|
|
180
190
|
this.hasBaseFontValue = true;
|
|
181
|
-
this.
|
|
182
|
-
this.baseFontIdValue = fontId;
|
|
183
|
-
this.baseFontFamilyValue = null;
|
|
191
|
+
this.baseFontFamilyValue = FontFamily.withRegularStack(stack);
|
|
184
192
|
this.hasBaseFontSizeValue = true;
|
|
185
193
|
this.baseFontSizeValue = size;
|
|
186
|
-
if (fontId == 0) {
|
|
187
|
-
warn("Typography", "RichText.font() received font id 0; the text will render with the default font fallback.");
|
|
188
|
-
}
|
|
189
194
|
this.rebuildAttributedText();
|
|
190
195
|
return this;
|
|
191
196
|
}
|
|
192
197
|
|
|
193
|
-
fontStack(stack: FontStack, size: f32): this {
|
|
194
|
-
return this.font(stack.id, size);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
198
|
fontFamily(family: FontFamily): this {
|
|
198
199
|
this.hasBaseFontValue = true;
|
|
199
|
-
this.baseUsesDirectFontId = false;
|
|
200
200
|
this.baseFontFamilyValue = family;
|
|
201
201
|
this.rebuildAttributedText();
|
|
202
202
|
return this;
|
|
@@ -247,6 +247,23 @@ export class RichText extends Text {
|
|
|
247
247
|
return this.fragmentsValue([span(content)]);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
_requiredFontIds(): Array<u32> {
|
|
251
|
+
const fontIds = super._requiredFontIds();
|
|
252
|
+
const fonts = activeTheme.value.fonts;
|
|
253
|
+
const defaultFamily = this.baseFontFamilyValue !== null ? changetype<FontFamily>(this.baseFontFamilyValue) : fonts.bodyFamily;
|
|
254
|
+
const defaultWeight = this.hasBaseFontWeightValue ? this.baseFontWeightValue : FontWeight.Regular;
|
|
255
|
+
const defaultStyle = this.hasBaseFontStyleValue ? this.baseFontStyleValue : FontStyle.Normal;
|
|
256
|
+
for (let i = 0; i < this.fragments.length; ++i) {
|
|
257
|
+
const piece = unchecked(this.fragments[i]);
|
|
258
|
+
const pieceFamily = piece._hasFontFamily() ? piece._fontFamilyOr(defaultFamily) : defaultFamily;
|
|
259
|
+
const pieceWeight = piece._fontWeightOr(defaultWeight);
|
|
260
|
+
const pieceStyle = piece._fontStyleOr(defaultStyle);
|
|
261
|
+
const resolvedFontId = pieceFamily.resolve(pieceWeight, pieceStyle);
|
|
262
|
+
pushUniqueFontId(fontIds, resolvedFontId);
|
|
263
|
+
}
|
|
264
|
+
return fontIds;
|
|
265
|
+
}
|
|
266
|
+
|
|
250
267
|
private rebuildAttributedText(): void {
|
|
251
268
|
const fonts = activeTheme.value.fonts;
|
|
252
269
|
const defaultFamily = this.baseFontFamilyValue !== null ? changetype<FontFamily>(this.baseFontFamilyValue) : fonts.bodyFamily;
|
|
@@ -255,14 +272,10 @@ export class RichText extends Text {
|
|
|
255
272
|
const defaultSize = this.hasBaseFontSizeValue ? this.baseFontSizeValue : fonts.sizeBody;
|
|
256
273
|
const defaultColor = this.hasBaseColorValue ? this.baseColorValue : activeTheme.value.colors.textPrimary;
|
|
257
274
|
if (this.hasBaseFontValue || this.fragments.length > 0) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
defaultFamily.resolve(defaultWeight, defaultStyle),
|
|
263
|
-
defaultSize,
|
|
264
|
-
);
|
|
265
|
-
}
|
|
275
|
+
super._fontId(
|
|
276
|
+
defaultFamily.resolve(defaultWeight, defaultStyle),
|
|
277
|
+
defaultSize,
|
|
278
|
+
);
|
|
266
279
|
}
|
|
267
280
|
super.textColor(defaultColor);
|
|
268
281
|
let merged = "";
|
|
@@ -285,9 +298,7 @@ export class RichText extends Text {
|
|
|
285
298
|
const pieceFamily = piece._hasFontFamily() ? piece._fontFamilyOr(defaultFamily) : defaultFamily;
|
|
286
299
|
const pieceWeight = piece._fontWeightOr(defaultWeight);
|
|
287
300
|
const pieceStyle = piece._fontStyleOr(defaultStyle);
|
|
288
|
-
const resolvedFontId =
|
|
289
|
-
? this.baseFontIdValue
|
|
290
|
-
: pieceFamily.resolve(pieceWeight, pieceStyle);
|
|
301
|
+
const resolvedFontId = pieceFamily.resolve(pieceWeight, pieceStyle);
|
|
291
302
|
if (resolvedFontId == 0) {
|
|
292
303
|
warn(
|
|
293
304
|
"Typography",
|
package/src/nodes/ScrollBar.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { isCoarsePointer } from "../core/Platform";
|
|
|
8
8
|
import { Signal } from "../core/Signal";
|
|
9
9
|
import { Theme, activeTheme } from "../core/Theme";
|
|
10
10
|
import { warn } from "../core/Logger";
|
|
11
|
+
import { PointerEventArgs } from "../core/Node";
|
|
11
12
|
import { FlexBox } from "./FlexBox";
|
|
12
13
|
import { Column } from "./helpers";
|
|
13
14
|
import { ScrollState } from "./ScrollState";
|
|
@@ -16,7 +17,7 @@ const DEFAULT_TRACK_WIDTH: f32 = 8.0;
|
|
|
16
17
|
const DEFAULT_THUMB_WIDTH: f32 = 8.0;
|
|
17
18
|
const DEFAULT_MIN_THUMB_HEIGHT: f32 = 18.0;
|
|
18
19
|
|
|
19
|
-
function noopPointerCallback(
|
|
20
|
+
function noopPointerCallback(_event: PointerEventArgs): void {}
|
|
20
21
|
|
|
21
22
|
class ScrollMetrics {
|
|
22
23
|
viewportSize: f32 = 0.0;
|
package/src/nodes/ScrollBox.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { HandlerAction } from "../core/Action";
|
|
|
2
2
|
import { AnimationTiming } from "../core/Animation";
|
|
3
3
|
import { Disposable, disposeAll } from "../core/Disposable";
|
|
4
4
|
import { HandleValue, Orientation, Unit } from "../core/ffi";
|
|
5
|
-
import { Node } from "../core/Node";
|
|
5
|
+
import { Node, PointerEventArgs } from "../core/Node";
|
|
6
6
|
import { throwNullArgument } from "../core/Errors";
|
|
7
7
|
import {
|
|
8
8
|
canRestorePersistedScrollOffset,
|
|
@@ -20,7 +20,7 @@ import { NodeTransitions } from "../core/Transitions";
|
|
|
20
20
|
const DEFAULT_SCROLLBAR_GUTTER: f32 = 0.0;
|
|
21
21
|
const OVERFLOW_TOLERANCE: f32 = 0.5;
|
|
22
22
|
|
|
23
|
-
function noopPointerCallback(
|
|
23
|
+
function noopPointerCallback(_event: PointerEventArgs): void {}
|
|
24
24
|
|
|
25
25
|
export class ScrollBox extends FlexBox {
|
|
26
26
|
private readonly scrollStateValue: ScrollState;
|
|
@@ -140,6 +140,11 @@ export class ScrollBox extends FlexBox {
|
|
|
140
140
|
return this;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
smoothScrolling(flag: bool = true): this {
|
|
144
|
+
this.viewportValue.smoothScrolling(flag);
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
|
|
143
148
|
persistScroll(flag: bool = true): this {
|
|
144
149
|
this.persistScrollValue = flag;
|
|
145
150
|
if (!flag) {
|
package/src/nodes/ScrollView.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as ui from "../bindings/ui";
|
|
2
2
|
import { Animation, AnimationTiming, getAnimationManager } from "../core/Animation";
|
|
3
|
-
import { Node } from "../core/Node";
|
|
3
|
+
import { PointerClickEventArgs, PointerEventArgs, Node } from "../core/Node";
|
|
4
4
|
import { throwNullArgument } from "../core/Errors";
|
|
5
5
|
import { NodeTransitions } from "../core/Transitions";
|
|
6
6
|
import {
|
|
@@ -75,6 +75,7 @@ export class ScrollView extends Node {
|
|
|
75
75
|
private pendingProgrammaticOffsetX: f32 = 0.0;
|
|
76
76
|
private pendingProgrammaticOffsetY: f32 = 0.0;
|
|
77
77
|
private hasFriction: bool = false;
|
|
78
|
+
private smoothScrollingValue: bool = true;
|
|
78
79
|
private _scrollState: ScrollState = new ScrollState();
|
|
79
80
|
private persistScrollValue: bool = true;
|
|
80
81
|
private persistedScrollRestorePending: bool = false;
|
|
@@ -97,7 +98,7 @@ export class ScrollView extends Node {
|
|
|
97
98
|
super();
|
|
98
99
|
// Make the viewport hit-testable so blank interior/padding starts resolve to this
|
|
99
100
|
// scroll surface instead of only working over interactive descendants.
|
|
100
|
-
this.onPointerDown((
|
|
101
|
+
this.onPointerDown((_event: PointerEventArgs): void => {});
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
bindScrollState(state: ScrollState): this {
|
|
@@ -286,6 +287,15 @@ export class ScrollView extends Node {
|
|
|
286
287
|
return this;
|
|
287
288
|
}
|
|
288
289
|
|
|
290
|
+
smoothScrolling(flag: bool = true): this {
|
|
291
|
+
this.smoothScrollingValue = flag;
|
|
292
|
+
if (this.hasBuiltHandle()) {
|
|
293
|
+
ui.setSmoothScrolling(this.handle, flag);
|
|
294
|
+
this.notifyRetainedMutation();
|
|
295
|
+
}
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
|
|
289
299
|
persistScroll(flag: bool = true): this {
|
|
290
300
|
this.persistScrollValue = flag;
|
|
291
301
|
if (!flag) {
|
|
@@ -357,17 +367,17 @@ export class ScrollView extends Node {
|
|
|
357
367
|
this._applyAnimatedScrollOffset(x, y);
|
|
358
368
|
}
|
|
359
369
|
|
|
360
|
-
|
|
361
|
-
super.
|
|
370
|
+
onPointerClick(cb: (event: PointerClickEventArgs) => void): this {
|
|
371
|
+
super.onPointerClick(cb);
|
|
362
372
|
return this;
|
|
363
373
|
}
|
|
364
374
|
|
|
365
|
-
onPointerEnter(cb: () => void): this {
|
|
375
|
+
onPointerEnter(cb: (event: PointerEventArgs) => void): this {
|
|
366
376
|
super.onPointerEnter(cb);
|
|
367
377
|
return this;
|
|
368
378
|
}
|
|
369
379
|
|
|
370
|
-
onPointerLeave(cb: () => void): this {
|
|
380
|
+
onPointerLeave(cb: (event: PointerEventArgs) => void): this {
|
|
371
381
|
super.onPointerLeave(cb);
|
|
372
382
|
return this;
|
|
373
383
|
}
|
|
@@ -395,6 +405,7 @@ export class ScrollView extends Node {
|
|
|
395
405
|
this.finishBuild();
|
|
396
406
|
ui.setScrollEnabled(this.handle, this.enableScrollX, this.enableScrollY);
|
|
397
407
|
ui.setShowScrollbars(this.handle, this.showScrollbarsValue);
|
|
408
|
+
ui.setSmoothScrolling(this.handle, this.smoothScrollingValue);
|
|
398
409
|
if (this.hasFriction) {
|
|
399
410
|
ui.setScrollFriction(this.handle, this.frictionValue);
|
|
400
411
|
}
|
package/src/nodes/Svg.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { Action, HandlerAction } from "../core/Action";
|
|
12
12
|
import * as ui from "../bindings/ui";
|
|
13
13
|
import { NodeType, SemanticRole, Unit } from "../core/ffi";
|
|
14
|
+
import { ImageSampling } from "../core/ImageSampling";
|
|
14
15
|
import { Signal } from "../core/Signal";
|
|
15
16
|
import { FlexBox, FlexBoxProps } from "./FlexBox";
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ export class Svg extends FlexBox {
|
|
|
18
19
|
private svgIdValue: u32;
|
|
19
20
|
private sourceUrlValue: string = "";
|
|
20
21
|
private tintColorValue: u32 = 0;
|
|
22
|
+
private samplingValue: ImageSampling = ImageSampling.linear();
|
|
21
23
|
private ownedSvgAssetId: u32 = 0;
|
|
22
24
|
private requestedWidthValue: f32 = 0.0;
|
|
23
25
|
private requestedWidthUnit: Unit = Unit.Auto;
|
|
@@ -119,6 +121,15 @@ export class Svg extends FlexBox {
|
|
|
119
121
|
return this;
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
sampling(sampling: ImageSampling): this {
|
|
125
|
+
this.samplingValue = sampling;
|
|
126
|
+
if (this.hasBuiltHandle()) {
|
|
127
|
+
this.applySvgSource();
|
|
128
|
+
this.notifyRetainedMutation();
|
|
129
|
+
}
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
|
|
122
133
|
altText(value: string): this {
|
|
123
134
|
this.semanticRole(SemanticRole.Image);
|
|
124
135
|
this.semanticLabel(value);
|
|
@@ -163,7 +174,13 @@ export class Svg extends FlexBox {
|
|
|
163
174
|
}
|
|
164
175
|
|
|
165
176
|
private applySvgSource(): void {
|
|
166
|
-
ui.setSvg(
|
|
177
|
+
ui.setSvg(
|
|
178
|
+
this.handle,
|
|
179
|
+
this.svgIdValue,
|
|
180
|
+
this.tintColorValue,
|
|
181
|
+
<u32>this.samplingValue.kind,
|
|
182
|
+
this.samplingValue.maxAniso,
|
|
183
|
+
);
|
|
167
184
|
}
|
|
168
185
|
|
|
169
186
|
private applyResolvedSizing(): void {
|
package/src/nodes/Text.ts
CHANGED
|
@@ -51,7 +51,7 @@ export class Text extends TextCore {
|
|
|
51
51
|
if (props.hasFont && props.hasFontFamily) {
|
|
52
52
|
text.fontSize(props.fontSize);
|
|
53
53
|
} else if (props.hasFont) {
|
|
54
|
-
text.
|
|
54
|
+
text._fontId(props.fontId, props.fontSize);
|
|
55
55
|
}
|
|
56
56
|
if (props.hasFontWeight) {
|
|
57
57
|
text.fontWeight(props.fontWeightValue);
|
package/src/nodes/TextCore.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ui from "../bindings/ui";
|
|
2
2
|
import { HandlerAction } from "../core/Action";
|
|
3
3
|
import { Disposable, disposeAll } from "../core/Disposable";
|
|
4
|
-
import { Node } from "../core/Node";
|
|
4
|
+
import { PointerClickEventArgs, PointerEventArgs, Node, SelectionChangedEventArgs, TextChangedEventArgs } from "../core/Node";
|
|
5
5
|
import { warn } from "../core/Logger";
|
|
6
6
|
import { Theme, activeTheme } from "../core/Theme";
|
|
7
7
|
import { FontFamily, FontStack, FontStyle, FontWeight } from "../core/Typography";
|
|
@@ -78,6 +78,62 @@ export class TextProps {
|
|
|
78
78
|
hasSelectable: bool = false;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
function utf8CodeUnitByteLength(codeUnit: u32): u32 {
|
|
82
|
+
if (codeUnit <= 0x7F) {
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
if (codeUnit <= 0x7FF) {
|
|
86
|
+
return 2;
|
|
87
|
+
}
|
|
88
|
+
return 3;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function utf8CodePointByteLength(codePoint: u32): u32 {
|
|
92
|
+
if (codePoint <= 0x7F) {
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
if (codePoint <= 0x7FF) {
|
|
96
|
+
return 2;
|
|
97
|
+
}
|
|
98
|
+
if (codePoint <= 0xFFFF) {
|
|
99
|
+
return 3;
|
|
100
|
+
}
|
|
101
|
+
return 4;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function readCodePoint(text: string, index: i32): u32 {
|
|
105
|
+
const first = <u32>text.charCodeAt(index);
|
|
106
|
+
if (first < 0xD800 || first > 0xDBFF || index + 1 >= text.length) {
|
|
107
|
+
return first;
|
|
108
|
+
}
|
|
109
|
+
const second = <u32>text.charCodeAt(index + 1);
|
|
110
|
+
if (second < 0xDC00 || second > 0xDFFF) {
|
|
111
|
+
return first;
|
|
112
|
+
}
|
|
113
|
+
return 0x10000 + ((first - 0xD800) << 10) + (second - 0xDC00);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function codePointStringLength(codePoint: u32): i32 {
|
|
117
|
+
return codePoint > 0xFFFF ? 2 : 1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function stringOffsetFromUtf8ByteOffset(text: string, byteOffset: u32): i32 {
|
|
121
|
+
let bytes: u32 = 0;
|
|
122
|
+
let cursor = 0;
|
|
123
|
+
while (cursor < text.length) {
|
|
124
|
+
const codePoint = readCodePoint(text, cursor);
|
|
125
|
+
const byteLength = codePoint > 0xFFFF
|
|
126
|
+
? utf8CodePointByteLength(codePoint)
|
|
127
|
+
: utf8CodeUnitByteLength(codePoint);
|
|
128
|
+
if (bytes + byteLength > byteOffset) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
bytes += byteLength;
|
|
132
|
+
cursor += codePointStringLength(codePoint);
|
|
133
|
+
}
|
|
134
|
+
return cursor;
|
|
135
|
+
}
|
|
136
|
+
|
|
81
137
|
export class TextCore extends Node {
|
|
82
138
|
private contentValue: string;
|
|
83
139
|
private widthValue: f32 = 0.0;
|
|
@@ -133,13 +189,17 @@ export class TextCore extends Node {
|
|
|
133
189
|
private hasObscured: bool = false;
|
|
134
190
|
private editableValue: bool = false;
|
|
135
191
|
private hasEditable: bool = false;
|
|
192
|
+
private editorCommandKeysValue: bool = false;
|
|
193
|
+
private hasEditorCommandKeys: bool = false;
|
|
194
|
+
private editorAcceptsTabValue: bool = false;
|
|
195
|
+
private hasEditorAcceptsTab: bool = false;
|
|
136
196
|
private caretColorValue: u32 = 0;
|
|
137
197
|
private hasCaretColor: bool = false;
|
|
138
198
|
private selectableValue: bool = false;
|
|
139
199
|
private selectionColor: u32 = 0;
|
|
140
200
|
private hasSelectable: bool = false;
|
|
141
|
-
private textChangedCb: ((
|
|
142
|
-
private selectionChangedCb: ((
|
|
201
|
+
private textChangedCb: ((event: TextChangedEventArgs) => void) | null = null;
|
|
202
|
+
private selectionChangedCb: ((event: SelectionChangedEventArgs) => void) | null = null;
|
|
143
203
|
private selectionStartValue: u32 = 0;
|
|
144
204
|
private selectionEndValue: u32 = 0;
|
|
145
205
|
private readonly disposables: Array<Disposable> = new Array<Disposable>();
|
|
@@ -326,14 +386,15 @@ export class TextCore extends Node {
|
|
|
326
386
|
return this;
|
|
327
387
|
}
|
|
328
388
|
|
|
329
|
-
|
|
389
|
+
/** @internal */
|
|
390
|
+
_fontId(fontId: u32, size: f32): this {
|
|
330
391
|
this.usesDirectFontId = true;
|
|
331
392
|
this.fontFamilyValue = null;
|
|
332
393
|
this.fontId = fontId;
|
|
333
394
|
this.fontSizeValue = size;
|
|
334
395
|
this.hasFont = true;
|
|
335
396
|
if (fontId == 0) {
|
|
336
|
-
warn("Typography", "Text.
|
|
397
|
+
warn("Typography", "Text._fontId() received font id 0; the text will render with the default font fallback.");
|
|
337
398
|
}
|
|
338
399
|
if (this.hasBuiltHandle()) {
|
|
339
400
|
this.applyResolvedFont();
|
|
@@ -342,7 +403,7 @@ export class TextCore extends Node {
|
|
|
342
403
|
}
|
|
343
404
|
|
|
344
405
|
fontStack(stack: FontStack, size: f32): this {
|
|
345
|
-
this.
|
|
406
|
+
this._fontId(stack.id, size);
|
|
346
407
|
return this;
|
|
347
408
|
}
|
|
348
409
|
|
|
@@ -495,6 +556,26 @@ export class TextCore extends Node {
|
|
|
495
556
|
return this;
|
|
496
557
|
}
|
|
497
558
|
|
|
559
|
+
_editorCommandKeys(flag: bool = true): this {
|
|
560
|
+
this.editorCommandKeysValue = flag;
|
|
561
|
+
this.hasEditorCommandKeys = true;
|
|
562
|
+
if (this.hasBuiltHandle()) {
|
|
563
|
+
ui.setEditorCommandKeys(this.handle, flag);
|
|
564
|
+
this.notifyRetainedMutation();
|
|
565
|
+
}
|
|
566
|
+
return this;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
_editorAcceptsTab(flag: bool = true): this {
|
|
570
|
+
this.editorAcceptsTabValue = flag;
|
|
571
|
+
this.hasEditorAcceptsTab = true;
|
|
572
|
+
if (this.hasBuiltHandle()) {
|
|
573
|
+
ui.setEditorAcceptsTab(this.handle, flag);
|
|
574
|
+
this.notifyRetainedMutation();
|
|
575
|
+
}
|
|
576
|
+
return this;
|
|
577
|
+
}
|
|
578
|
+
|
|
498
579
|
caretColor(color: u32): this {
|
|
499
580
|
this.caretColorValue = color;
|
|
500
581
|
this.hasCaretColor = true;
|
|
@@ -522,27 +603,27 @@ export class TextCore extends Node {
|
|
|
522
603
|
return this;
|
|
523
604
|
}
|
|
524
605
|
|
|
525
|
-
onTextChanged(cb: (
|
|
606
|
+
onTextChanged(cb: (event: TextChangedEventArgs) => void): this {
|
|
526
607
|
this.textChangedCb = cb;
|
|
527
608
|
return this;
|
|
528
609
|
}
|
|
529
610
|
|
|
530
|
-
onSelectionChanged(cb: (
|
|
611
|
+
onSelectionChanged(cb: (event: SelectionChangedEventArgs) => void): this {
|
|
531
612
|
this.selectionChangedCb = cb;
|
|
532
613
|
return this;
|
|
533
614
|
}
|
|
534
615
|
|
|
535
|
-
|
|
536
|
-
super.
|
|
616
|
+
onPointerClick(cb: (event: PointerClickEventArgs) => void): this {
|
|
617
|
+
super.onPointerClick(cb);
|
|
537
618
|
return this;
|
|
538
619
|
}
|
|
539
620
|
|
|
540
|
-
onPointerEnter(cb: () => void): this {
|
|
621
|
+
onPointerEnter(cb: (event: PointerEventArgs) => void): this {
|
|
541
622
|
super.onPointerEnter(cb);
|
|
542
623
|
return this;
|
|
543
624
|
}
|
|
544
625
|
|
|
545
|
-
onPointerLeave(cb: () => void): this {
|
|
626
|
+
onPointerLeave(cb: (event: PointerEventArgs) => void): this {
|
|
546
627
|
super.onPointerLeave(cb);
|
|
547
628
|
return this;
|
|
548
629
|
}
|
|
@@ -620,6 +701,12 @@ export class TextCore extends Node {
|
|
|
620
701
|
if (this.hasEditable) {
|
|
621
702
|
ui.setEditable(this.handle, this.editableValue);
|
|
622
703
|
}
|
|
704
|
+
if (this.hasEditorCommandKeys) {
|
|
705
|
+
ui.setEditorCommandKeys(this.handle, this.editorCommandKeysValue);
|
|
706
|
+
}
|
|
707
|
+
if (this.hasEditorAcceptsTab) {
|
|
708
|
+
ui.setEditorAcceptsTab(this.handle, this.editorAcceptsTabValue);
|
|
709
|
+
}
|
|
623
710
|
if (this.hasSelectable) {
|
|
624
711
|
ui.setSelectable(this.handle, this.selectableValue, this.selectionColor);
|
|
625
712
|
}
|
|
@@ -641,6 +728,15 @@ export class TextCore extends Node {
|
|
|
641
728
|
return this.hasHeight && this.heightUnit == Unit.Percent ? this.heightValue : -1.0;
|
|
642
729
|
}
|
|
643
730
|
|
|
731
|
+
_requiredFontIds(): Array<u32> {
|
|
732
|
+
const fontIds = new Array<u32>();
|
|
733
|
+
const fontId = this.resolveFontId();
|
|
734
|
+
if (fontId != 0) {
|
|
735
|
+
fontIds.push(fontId);
|
|
736
|
+
}
|
|
737
|
+
return fontIds;
|
|
738
|
+
}
|
|
739
|
+
|
|
644
740
|
private handleThemeChanged(theme: Theme): void {
|
|
645
741
|
if (this.hasBuiltHandle() && !this.hasColor) {
|
|
646
742
|
ui.setTextColor(this.handle, theme.colors.textPrimary);
|
|
@@ -685,20 +781,19 @@ export class TextCore extends Node {
|
|
|
685
781
|
this.contentValue = text;
|
|
686
782
|
const callback = this.textChangedCb;
|
|
687
783
|
if (callback !== null) {
|
|
688
|
-
callback(text);
|
|
784
|
+
callback(new TextChangedEventArgs(text));
|
|
689
785
|
}
|
|
690
786
|
}
|
|
691
787
|
|
|
692
788
|
_handleTextReplaced(start: u32, end: u32, text: string): void {
|
|
693
|
-
const
|
|
694
|
-
const
|
|
695
|
-
const
|
|
696
|
-
const
|
|
697
|
-
const suffix = this.contentValue.substring(<i32>clampedEnd);
|
|
789
|
+
const startOffset = stringOffsetFromUtf8ByteOffset(this.contentValue, start);
|
|
790
|
+
const endOffset = stringOffsetFromUtf8ByteOffset(this.contentValue, max<u32>(start, end));
|
|
791
|
+
const prefix = this.contentValue.substring(0, startOffset);
|
|
792
|
+
const suffix = this.contentValue.substring(endOffset);
|
|
698
793
|
this.contentValue = prefix + text + suffix;
|
|
699
794
|
const callback = this.textChangedCb;
|
|
700
795
|
if (callback !== null) {
|
|
701
|
-
callback(this.contentValue);
|
|
796
|
+
callback(new TextChangedEventArgs(this.contentValue));
|
|
702
797
|
}
|
|
703
798
|
}
|
|
704
799
|
|
|
@@ -707,7 +802,7 @@ export class TextCore extends Node {
|
|
|
707
802
|
this.selectionEndValue = end;
|
|
708
803
|
const callback = this.selectionChangedCb;
|
|
709
804
|
if (callback !== null) {
|
|
710
|
-
callback(start, end);
|
|
805
|
+
callback(new SelectionChangedEventArgs(start, end));
|
|
711
806
|
}
|
|
712
807
|
}
|
|
713
808
|
|
package/src/nodes/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Column, Row, pct, px } from "./helpers";
|
|
2
2
|
export { CustomDrawable } from "./CustomDrawable";
|
|
3
|
-
export { FlexBox, FlexBoxProps } from "./FlexBox";
|
|
3
|
+
export { Border, FlexBox, FlexBoxProps } from "./FlexBox";
|
|
4
4
|
export { GradientStop } from "./GradientStop";
|
|
5
5
|
export { Grid } from "./Grid";
|
|
6
6
|
export { Image } from "./Image";
|