@effindomv2/fui-as 0.1.37 → 0.1.41
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 +3 -0
- package/package.json +23 -13
- package/scripts/build.sh +70 -46
- package/scripts/check-runtime-dependency.sh +0 -19
- 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/controls/NavLink.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CursorStyle,
|
|
3
3
|
KeyEventType,
|
|
4
|
+
KeyModifier,
|
|
4
5
|
PointerEventType,
|
|
5
6
|
SemanticRole,
|
|
6
7
|
fui_hide_url_preview,
|
|
@@ -11,16 +12,25 @@ import { Disposable, disposeAll } from "../core/Disposable";
|
|
|
11
12
|
import { FocusAdornerManager } from "../core/FocusAdornerManager";
|
|
12
13
|
import { keyboardFocusVisible } from "../core/FocusVisibility";
|
|
13
14
|
import { navigateTo } from "../core/Navigation";
|
|
15
|
+
import { PointerEventArgs, PointerType } from "../core/Node";
|
|
14
16
|
import { hasPrimaryShortcutModifier } from "../core/Platform";
|
|
15
17
|
import { Theme, activeTheme } from "../core/Theme";
|
|
16
18
|
import { FlexBox } from "../nodes";
|
|
17
19
|
|
|
20
|
+
export class NavigateEventArgs {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
|
|
23
|
+
constructor(path: string) {
|
|
24
|
+
this.path = path;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
export class NavLink extends FlexBox {
|
|
19
29
|
private static activePreviewOwner: NavLink | null = null;
|
|
20
30
|
private hrefValue: string;
|
|
21
31
|
private openInNewTabValue: bool;
|
|
22
32
|
private readonly disposables: Array<Disposable> = new Array<Disposable>();
|
|
23
|
-
private navigateCallback: ((
|
|
33
|
+
private navigateCallback: ((event: NavigateEventArgs) => void) | null = null;
|
|
24
34
|
private pointerPressed: bool = false;
|
|
25
35
|
private pointerPressedOpenInNewTab: bool = false;
|
|
26
36
|
private enterPressed: bool = false;
|
|
@@ -60,7 +70,7 @@ export class NavLink extends FlexBox {
|
|
|
60
70
|
return this;
|
|
61
71
|
}
|
|
62
72
|
|
|
63
|
-
onNavigate(cb: (
|
|
73
|
+
onNavigate(cb: (event: NavigateEventArgs) => void): this {
|
|
64
74
|
this.navigateCallback = cb;
|
|
65
75
|
return this;
|
|
66
76
|
}
|
|
@@ -75,6 +85,10 @@ export class NavLink extends FlexBox {
|
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
_handlePointerEvent(eventType: PointerEventType, x: f32, y: f32, modifiers: u32 = 0): void {
|
|
88
|
+
const pending = NavLink.pendingPointerEventArgs;
|
|
89
|
+
const isPrimaryActivation = pending !== null
|
|
90
|
+
? this.isPrimaryActivationPointer(changetype<PointerEventArgs>(pending))
|
|
91
|
+
: true;
|
|
78
92
|
super._handlePointerEvent(eventType, x, y, modifiers);
|
|
79
93
|
if (eventType == PointerEventType.Enter) {
|
|
80
94
|
this.hovered = true;
|
|
@@ -91,11 +105,16 @@ export class NavLink extends FlexBox {
|
|
|
91
105
|
return;
|
|
92
106
|
}
|
|
93
107
|
if (eventType == PointerEventType.Down) {
|
|
108
|
+
if (!isPrimaryActivation) {
|
|
109
|
+
this.pointerPressed = false;
|
|
110
|
+
this.pointerPressedOpenInNewTab = false;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
94
113
|
this.pointerPressed = true;
|
|
95
114
|
this.pointerPressedOpenInNewTab = this.shouldOpenInNewTab(modifiers);
|
|
96
115
|
return;
|
|
97
116
|
}
|
|
98
|
-
if (eventType == PointerEventType.Up && this.pointerPressed) {
|
|
117
|
+
if (eventType == PointerEventType.Up && this.pointerPressed && isPrimaryActivation) {
|
|
99
118
|
this.pointerPressed = false;
|
|
100
119
|
this.activate(this.pointerPressedOpenInNewTab || this.shouldOpenInNewTab(modifiers));
|
|
101
120
|
this.pointerPressedOpenInNewTab = false;
|
|
@@ -123,7 +142,7 @@ export class NavLink extends FlexBox {
|
|
|
123
142
|
if (key != "Enter") {
|
|
124
143
|
return callbackHandled;
|
|
125
144
|
}
|
|
126
|
-
if (modifiers != 0 && !hasPrimaryShortcutModifier(modifiers)) {
|
|
145
|
+
if (modifiers != 0 && !hasPrimaryShortcutModifier(<KeyModifier>modifiers)) {
|
|
127
146
|
return callbackHandled;
|
|
128
147
|
}
|
|
129
148
|
if (eventType == KeyEventType.Down) {
|
|
@@ -144,12 +163,16 @@ export class NavLink extends FlexBox {
|
|
|
144
163
|
navigateTo(this.hrefValue, openInNewTab);
|
|
145
164
|
const callback = this.navigateCallback;
|
|
146
165
|
if (callback !== null) {
|
|
147
|
-
callback(this.hrefValue);
|
|
166
|
+
callback(new NavigateEventArgs(this.hrefValue));
|
|
148
167
|
}
|
|
149
168
|
}
|
|
150
169
|
|
|
151
170
|
private shouldOpenInNewTab(modifiers: u32): bool {
|
|
152
|
-
return this.openInNewTabValue || hasPrimaryShortcutModifier(modifiers);
|
|
171
|
+
return this.openInNewTabValue || hasPrimaryShortcutModifier(<KeyModifier>modifiers);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private isPrimaryActivationPointer(event: PointerEventArgs): bool {
|
|
175
|
+
return event.button == 0 || event.pointerType == PointerType.Touch || event.pointerType == PointerType.Pen;
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
pinPreviewForContextMenu(): void {
|
package/src/controls/Popup.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FlexDirection, Unit } from "../core/ffi";
|
|
2
2
|
import { Node } from "../core/Node";
|
|
3
3
|
import { throwNullArgument } from "../core/Errors";
|
|
4
|
-
import { FlexBox, Portal } from "../nodes";
|
|
4
|
+
import { Border, FlexBox, Portal } from "../nodes";
|
|
5
5
|
import { PopupPlacement, PopupPresenter } from "./internal/PopupPresenter";
|
|
6
6
|
|
|
7
7
|
export { PopupPlacement } from "./internal/PopupPresenter";
|
|
@@ -21,7 +21,7 @@ export class Popup extends Portal {
|
|
|
21
21
|
.position(0.0, 0.0)
|
|
22
22
|
.width(100.0, Unit.Percent)
|
|
23
23
|
.height(100.0, Unit.Percent);
|
|
24
|
-
this.presenter.overlayNode.
|
|
24
|
+
this.presenter.overlayNode.onPointerClickWith(this, (popup, _event) => popup.handleBackdropClick());
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
get isOpen(): bool {
|
|
@@ -90,8 +90,13 @@ export class Popup extends Portal {
|
|
|
90
90
|
return this;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
panelBorder(width: f32, color: u32
|
|
94
|
-
this.surfaceNode.border(width, color
|
|
93
|
+
panelBorder(width: f32, color: u32): this {
|
|
94
|
+
this.surfaceNode.border(width, color);
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
panelBorderConfig(border: Border): this {
|
|
99
|
+
this.surfaceNode.borderConfig(border);
|
|
95
100
|
return this;
|
|
96
101
|
}
|
|
97
102
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { BorderStyle } from "../core/ffi";
|
|
2
1
|
import { HandlerAction } from "../core/Action";
|
|
3
2
|
import { Disposable, disposeAll } from "../core/Disposable";
|
|
4
3
|
import { Theme, activeTheme } from "../core/Theme";
|
|
@@ -154,7 +153,7 @@ export class ProgressBar extends FlexBox {
|
|
|
154
153
|
this.fillNode.cornerRadius(this.thicknessValue * 0.5);
|
|
155
154
|
}
|
|
156
155
|
super.bgColor(trackColor);
|
|
157
|
-
super.border(1.0, theme.colors.border
|
|
156
|
+
super.border(1.0, theme.colors.border);
|
|
158
157
|
this.fillNode.bgColor(fillColor);
|
|
159
158
|
}
|
|
160
159
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { Callback1, Handler1 } from "../core/BoundCallback";
|
|
1
2
|
import { KeyEventType, SemanticCheckedState, SemanticRole } from "../core/ffi";
|
|
3
|
+
import { RadioButtonChangedEventArgs } from "../core/Node";
|
|
2
4
|
import { activeTheme } from "../core/Theme";
|
|
5
|
+
import { bind1 } from "../core/bind";
|
|
3
6
|
import { LabeledControlSizing } from "./ControlSizing";
|
|
4
7
|
import { PressableLabeledControl } from "./internal/PressableLabeledControl";
|
|
5
8
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
@@ -13,13 +16,13 @@ import {
|
|
|
13
16
|
|
|
14
17
|
function createIndicatorPresenter(template: RadioIndicatorTemplate | null, sizing: LabeledControlSizing | null = null): RadioIndicatorPresenter {
|
|
15
18
|
if (template !== null) {
|
|
16
|
-
return template.create();
|
|
19
|
+
return template.create(sizing);
|
|
17
20
|
}
|
|
18
21
|
const templateSet = getControlTemplates();
|
|
19
22
|
const appTemplate = templateSet !== null ? templateSet.radioIndicator : null;
|
|
20
23
|
return appTemplate === null
|
|
21
24
|
? createDefaultRadioIndicatorPresenter(sizing)
|
|
22
|
-
: appTemplate.create();
|
|
25
|
+
: appTemplate.create(sizing);
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
export class RadioButton extends PressableLabeledControl {
|
|
@@ -28,7 +31,8 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
28
31
|
private sizingValue: LabeledControlSizing | null = null;
|
|
29
32
|
private readonly valueText: string;
|
|
30
33
|
private checkedValue: bool = false;
|
|
31
|
-
private changedCallback: ((
|
|
34
|
+
private changedCallback: ((event: RadioButtonChangedEventArgs) => void) | null = null;
|
|
35
|
+
private changedBinding: Callback1<RadioButtonChangedEventArgs> | null = null;
|
|
32
36
|
private ownerGroup: RadioGroup | null = null;
|
|
33
37
|
|
|
34
38
|
constructor(value: string, label: string = value) {
|
|
@@ -54,7 +58,7 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
check(flag: bool): this {
|
|
57
|
-
this.updateChecked(flag, false);
|
|
61
|
+
this.updateChecked(flag, true, false);
|
|
58
62
|
return this;
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -63,11 +67,9 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
63
67
|
this.setLabelFontSizeOverride(
|
|
64
68
|
sizing !== null && sizing.hasLabelFontSize ? sizing.labelFontSizePx : 0.0,
|
|
65
69
|
);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.syncVisualState();
|
|
70
|
-
}
|
|
70
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
71
|
+
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
72
|
+
this.syncVisualState();
|
|
71
73
|
return this;
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -79,8 +81,20 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
79
81
|
return this;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
onChanged(callback: ((
|
|
84
|
+
onChanged(callback: ((event: RadioButtonChangedEventArgs) => void) | null): this {
|
|
83
85
|
this.changedCallback = callback;
|
|
86
|
+
this.changedBinding = null;
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner, RadioButtonChangedEventArgs>): this {
|
|
91
|
+
this.changedCallback = null;
|
|
92
|
+
this.changedBinding = bind1<Owner, RadioButtonChangedEventArgs>(owner, handler);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, RadioButtonChangedEventArgs>): this {
|
|
97
|
+
this.bindChanged(owner, handler);
|
|
84
98
|
return this;
|
|
85
99
|
}
|
|
86
100
|
|
|
@@ -135,7 +149,7 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
135
149
|
);
|
|
136
150
|
}
|
|
137
151
|
|
|
138
|
-
updateChecked(flag: bool, emit: bool): void {
|
|
152
|
+
updateChecked(flag: bool, emit: bool, announce: bool = emit): void {
|
|
139
153
|
if (this.checkedValue == flag) {
|
|
140
154
|
return;
|
|
141
155
|
}
|
|
@@ -143,10 +157,17 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
143
157
|
this.semanticChecked(flag ? SemanticCheckedState.True : SemanticCheckedState.False);
|
|
144
158
|
this.syncVisualState();
|
|
145
159
|
if (emit) {
|
|
146
|
-
|
|
160
|
+
if (announce) {
|
|
161
|
+
this.requestSemanticAnnouncement();
|
|
162
|
+
}
|
|
163
|
+
const event = new RadioButtonChangedEventArgs(flag);
|
|
147
164
|
const callback = this.changedCallback;
|
|
148
165
|
if (callback !== null) {
|
|
149
|
-
callback(
|
|
166
|
+
callback(event);
|
|
167
|
+
}
|
|
168
|
+
const binding = this.changedBinding;
|
|
169
|
+
if (binding !== null) {
|
|
170
|
+
binding.invoke(event);
|
|
150
171
|
}
|
|
151
172
|
}
|
|
152
173
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Callback1, Handler1 } from "../core/BoundCallback";
|
|
2
2
|
import { FlexDirection, SemanticRole } from "../core/ffi";
|
|
3
|
+
import { RadioGroupChangedEventArgs } from "../core/Node";
|
|
3
4
|
import { PersistedInt32Codec, PersistedValueState } from "../core/PersistedState";
|
|
4
5
|
import { bind1 } from "../core/bind";
|
|
5
6
|
import { warn } from "../core/Logger";
|
|
@@ -31,8 +32,8 @@ const RADIO_GROUP_PERSISTED_STATE = new PersistedRadioGroupState();
|
|
|
31
32
|
export class RadioGroup extends FlexBox {
|
|
32
33
|
private readonly radios: Array<RadioButton> = new Array<RadioButton>();
|
|
33
34
|
private selectedIndexValue: i32 = -1;
|
|
34
|
-
private changedCallback: ((
|
|
35
|
-
private changedBinding: Callback1<
|
|
35
|
+
private changedCallback: ((event: RadioGroupChangedEventArgs) => void) | null = null;
|
|
36
|
+
private changedBinding: Callback1<RadioGroupChangedEventArgs> | null = null;
|
|
36
37
|
|
|
37
38
|
constructor() {
|
|
38
39
|
super();
|
|
@@ -75,19 +76,19 @@ export class RadioGroup extends FlexBox {
|
|
|
75
76
|
return this;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
onChanged(callback: ((
|
|
79
|
+
onChanged(callback: ((event: RadioGroupChangedEventArgs) => void) | null): this {
|
|
79
80
|
this.changedCallback = callback;
|
|
80
81
|
this.changedBinding = null;
|
|
81
82
|
return this;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
85
|
+
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner, RadioGroupChangedEventArgs>): this {
|
|
85
86
|
this.changedCallback = null;
|
|
86
|
-
this.changedBinding = bind1<Owner,
|
|
87
|
+
this.changedBinding = bind1<Owner, RadioGroupChangedEventArgs>(owner, handler);
|
|
87
88
|
return this;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
91
|
+
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, RadioGroupChangedEventArgs>): this {
|
|
91
92
|
this.bindChanged(owner, handler);
|
|
92
93
|
return this;
|
|
93
94
|
}
|
|
@@ -95,7 +96,7 @@ export class RadioGroup extends FlexBox {
|
|
|
95
96
|
selectRadio(radio: RadioButton, focus: bool): void {
|
|
96
97
|
const index = this.indexOfRadio(radio);
|
|
97
98
|
if (index >= 0) {
|
|
98
|
-
this.selectIndexInternal(index, focus, true);
|
|
99
|
+
this.selectIndexInternal(index, focus, true, true);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -106,30 +107,42 @@ export class RadioGroup extends FlexBox {
|
|
|
106
107
|
}
|
|
107
108
|
const nextIndex = this.findEnabledIndex(startIndex, delta);
|
|
108
109
|
if (nextIndex >= 0) {
|
|
109
|
-
this.selectIndexInternal(nextIndex, true, true);
|
|
110
|
+
this.selectIndexInternal(nextIndex, true, true, true);
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
selectFirstEnabled(focus: bool): void {
|
|
114
115
|
const nextIndex = this.findBoundaryIndex(true);
|
|
115
116
|
if (nextIndex >= 0) {
|
|
116
|
-
this.selectIndexInternal(nextIndex, focus, true);
|
|
117
|
+
this.selectIndexInternal(nextIndex, focus, true, true);
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
selectLastEnabled(focus: bool): void {
|
|
121
122
|
const nextIndex = this.findBoundaryIndex(false);
|
|
122
123
|
if (nextIndex >= 0) {
|
|
123
|
-
this.selectIndexInternal(nextIndex, focus, true);
|
|
124
|
+
this.selectIndexInternal(nextIndex, focus, true, true);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
selectIndex(index: i32): this {
|
|
128
129
|
if (index == -1) {
|
|
130
|
+
const changed = this.selectedIndexValue != -1;
|
|
129
131
|
if (this.selectedIndexValue >= 0 && this.selectedIndexValue < this.radios.length) {
|
|
130
|
-
unchecked(this.radios[this.selectedIndexValue]).updateChecked(false, false);
|
|
132
|
+
unchecked(this.radios[this.selectedIndexValue]).updateChecked(false, true, false);
|
|
131
133
|
}
|
|
132
134
|
this.selectedIndexValue = -1;
|
|
135
|
+
if (changed) {
|
|
136
|
+
const event = new RadioGroupChangedEventArgs("");
|
|
137
|
+
const callback = this.changedCallback;
|
|
138
|
+
if (callback !== null) {
|
|
139
|
+
callback(event);
|
|
140
|
+
}
|
|
141
|
+
const binding = this.changedBinding;
|
|
142
|
+
if (binding !== null) {
|
|
143
|
+
binding.invoke(event);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
133
146
|
return this;
|
|
134
147
|
}
|
|
135
148
|
if (this.radios.length == 0) {
|
|
@@ -151,7 +164,7 @@ export class RadioGroup extends FlexBox {
|
|
|
151
164
|
".",
|
|
152
165
|
);
|
|
153
166
|
}
|
|
154
|
-
this.selectIndexInternal(clampedIndex, false, false);
|
|
167
|
+
this.selectIndexInternal(clampedIndex, false, true, false);
|
|
155
168
|
return this;
|
|
156
169
|
}
|
|
157
170
|
|
|
@@ -159,10 +172,10 @@ export class RadioGroup extends FlexBox {
|
|
|
159
172
|
if (index < 0) {
|
|
160
173
|
return;
|
|
161
174
|
}
|
|
162
|
-
this.selectIndexInternal(index, false, true);
|
|
175
|
+
this.selectIndexInternal(index, false, true, false);
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
private selectIndexInternal(index: i32, focus: bool, emit: bool): void {
|
|
178
|
+
private selectIndexInternal(index: i32, focus: bool, emit: bool, announce: bool = emit): void {
|
|
166
179
|
if (index < 0 || index >= this.radios.length) {
|
|
167
180
|
return;
|
|
168
181
|
}
|
|
@@ -177,22 +190,22 @@ export class RadioGroup extends FlexBox {
|
|
|
177
190
|
return;
|
|
178
191
|
}
|
|
179
192
|
if (this.selectedIndexValue >= 0 && this.selectedIndexValue < this.radios.length) {
|
|
180
|
-
unchecked(this.radios[this.selectedIndexValue]).updateChecked(false, false);
|
|
193
|
+
unchecked(this.radios[this.selectedIndexValue]).updateChecked(false, emit, false);
|
|
181
194
|
}
|
|
182
195
|
this.selectedIndexValue = index;
|
|
183
|
-
radio.updateChecked(true,
|
|
196
|
+
radio.updateChecked(true, emit, announce);
|
|
184
197
|
if (focus) {
|
|
185
198
|
radio.focusNow();
|
|
186
199
|
}
|
|
187
200
|
if (emit) {
|
|
188
|
-
radio.
|
|
201
|
+
const event = new RadioGroupChangedEventArgs(radio.value);
|
|
189
202
|
const callback = this.changedCallback;
|
|
190
203
|
if (callback !== null) {
|
|
191
|
-
callback(
|
|
204
|
+
callback(event);
|
|
192
205
|
}
|
|
193
206
|
const binding = this.changedBinding;
|
|
194
207
|
if (binding !== null) {
|
|
195
|
-
binding.invoke(
|
|
208
|
+
binding.invoke(event);
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
211
|
}
|
package/src/controls/Slider.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { DragCompletedEvent, DragDeltaEvent, DragGesture, DragGestureHost, DragS
|
|
|
6
6
|
import { FocusAdornerManager } from "../core/FocusAdornerManager";
|
|
7
7
|
import { keyboardFocusVisible } from "../core/FocusVisibility";
|
|
8
8
|
import {
|
|
9
|
-
BorderStyle,
|
|
10
9
|
CursorStyle,
|
|
11
10
|
KeyEventType,
|
|
12
11
|
Orientation,
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
import { Theme, activeTheme } from "../core/Theme";
|
|
18
17
|
import { warn } from "../core/Logger";
|
|
19
18
|
import { PersistedFloat32Codec, PersistedValueState } from "../core/PersistedState";
|
|
20
|
-
import { Node } from "../core/Node";
|
|
19
|
+
import { Node, SliderChangedEventArgs } from "../core/Node";
|
|
21
20
|
import { FlexBox } from "../nodes";
|
|
22
21
|
import { bind1 } from "../core/bind";
|
|
23
22
|
import { SliderSizing } from "./ControlSizing";
|
|
@@ -67,13 +66,13 @@ const SLIDER_CHILD_INSET: f32 = SLIDER_PADDING + SLIDER_CONTENT_INSET;
|
|
|
67
66
|
|
|
68
67
|
function createSliderPresenter(template: SliderTemplate | null, sizing: SliderSizing | null = null): SliderPresenter {
|
|
69
68
|
if (template !== null) {
|
|
70
|
-
return template.create();
|
|
69
|
+
return template.create(sizing);
|
|
71
70
|
}
|
|
72
71
|
const templateSet = getControlTemplates();
|
|
73
72
|
const appTemplate = templateSet !== null ? templateSet.slider : null;
|
|
74
73
|
return appTemplate === null
|
|
75
74
|
? createDefaultSliderPresenter(sizing)
|
|
76
|
-
: appTemplate.create();
|
|
75
|
+
: appTemplate.create(sizing);
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
export class Slider extends FlexBox implements DragGestureHost {
|
|
@@ -83,8 +82,8 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
83
82
|
private colorsValue: SliderColors | null = null;
|
|
84
83
|
private readonly disposables: Array<Disposable> = new Array<Disposable>();
|
|
85
84
|
private readonly dragGesture!: DragGesture;
|
|
86
|
-
private changedCallback: ((
|
|
87
|
-
private changedBinding: Callback1<
|
|
85
|
+
private changedCallback: ((event: SliderChangedEventArgs) => void) | null = null;
|
|
86
|
+
private changedBinding: Callback1<SliderChangedEventArgs> | null = null;
|
|
88
87
|
private disposed: bool = false;
|
|
89
88
|
private focusedState: bool = false;
|
|
90
89
|
private hoveredState: bool = false;
|
|
@@ -135,7 +134,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
135
134
|
if (this.maxValue < value) {
|
|
136
135
|
this.maxValue = value;
|
|
137
136
|
}
|
|
138
|
-
this.setValue(this.currentValue, false);
|
|
137
|
+
this.setValue(this.currentValue, true, false);
|
|
139
138
|
return this;
|
|
140
139
|
}
|
|
141
140
|
|
|
@@ -144,7 +143,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
144
143
|
if (this.minValue > value) {
|
|
145
144
|
this.minValue = value;
|
|
146
145
|
}
|
|
147
|
-
this.setValue(this.currentValue, false);
|
|
146
|
+
this.setValue(this.currentValue, true, false);
|
|
148
147
|
return this;
|
|
149
148
|
}
|
|
150
149
|
|
|
@@ -153,7 +152,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
153
152
|
warn("Layout", "Slider.step() received " + value.toString() + "; clamping to 1.0.");
|
|
154
153
|
}
|
|
155
154
|
this.stepValue = value > 0.0 ? value : 1.0;
|
|
156
|
-
this.setValue(this.currentValue, false);
|
|
155
|
+
this.setValue(this.currentValue, true, false);
|
|
157
156
|
return this;
|
|
158
157
|
}
|
|
159
158
|
|
|
@@ -180,9 +179,6 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
180
179
|
|
|
181
180
|
sizing(sizing: SliderSizing | null): this {
|
|
182
181
|
this.sizingValue = sizing;
|
|
183
|
-
if (!this.usesDefaultPresenter()) {
|
|
184
|
-
return this;
|
|
185
|
-
}
|
|
186
182
|
this.replacePresenter(createSliderPresenter(this.templateOverride, this.sizingValue));
|
|
187
183
|
const thumbSize = this.sliderPresenter.metrics.thumbSize;
|
|
188
184
|
if (this.lengthValue <= thumbSize) {
|
|
@@ -214,19 +210,19 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
214
210
|
return this;
|
|
215
211
|
}
|
|
216
212
|
|
|
217
|
-
onChanged(callback: ((
|
|
213
|
+
onChanged(callback: ((event: SliderChangedEventArgs) => void) | null): this {
|
|
218
214
|
this.changedCallback = callback;
|
|
219
215
|
this.changedBinding = null;
|
|
220
216
|
return this;
|
|
221
217
|
}
|
|
222
218
|
|
|
223
|
-
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
219
|
+
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner, SliderChangedEventArgs>): this {
|
|
224
220
|
this.changedCallback = null;
|
|
225
|
-
this.changedBinding = bind1<Owner,
|
|
221
|
+
this.changedBinding = bind1<Owner, SliderChangedEventArgs>(owner, handler);
|
|
226
222
|
return this;
|
|
227
223
|
}
|
|
228
224
|
|
|
229
|
-
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
225
|
+
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, SliderChangedEventArgs>): this {
|
|
230
226
|
this.bindChanged(owner, handler);
|
|
231
227
|
return this;
|
|
232
228
|
}
|
|
@@ -322,7 +318,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
322
318
|
}
|
|
323
319
|
|
|
324
320
|
_applyPersistedValue(value: f32): void {
|
|
325
|
-
this.setValue(value, true);
|
|
321
|
+
this.setValue(value, true, false);
|
|
326
322
|
}
|
|
327
323
|
|
|
328
324
|
private normalizeValue(value: f32): f32 {
|
|
@@ -334,7 +330,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
334
330
|
return clamp(this.minValue + snapped, this.minValue, this.maxValue);
|
|
335
331
|
}
|
|
336
332
|
|
|
337
|
-
private setValue(value: f32, emit: bool): void {
|
|
333
|
+
private setValue(value: f32, emit: bool, announce: bool = emit): void {
|
|
338
334
|
const normalized = this.normalizeValue(value);
|
|
339
335
|
if (normalized == this.currentValue) {
|
|
340
336
|
this.syncPresentation();
|
|
@@ -344,14 +340,17 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
344
340
|
this.semanticValueRange(this.currentValue, this.minValue, this.maxValue);
|
|
345
341
|
this.syncPresentation();
|
|
346
342
|
if (emit) {
|
|
347
|
-
|
|
343
|
+
if (announce) {
|
|
344
|
+
this.requestSemanticAnnouncement();
|
|
345
|
+
}
|
|
346
|
+
const event = new SliderChangedEventArgs(this.currentValue);
|
|
348
347
|
const callback = this.changedCallback;
|
|
349
348
|
if (callback !== null) {
|
|
350
|
-
callback(
|
|
349
|
+
callback(event);
|
|
351
350
|
}
|
|
352
351
|
const binding = this.changedBinding;
|
|
353
352
|
if (binding !== null) {
|
|
354
|
-
binding.invoke(
|
|
353
|
+
binding.invoke(event);
|
|
355
354
|
}
|
|
356
355
|
}
|
|
357
356
|
}
|
|
@@ -401,8 +400,7 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
401
400
|
this.cornerRadius(theme.spacing.sm);
|
|
402
401
|
this.border(
|
|
403
402
|
SLIDER_FOCUS_BORDER_WIDTH,
|
|
404
|
-
theme.colors.background
|
|
405
|
-
BorderStyle.Solid,
|
|
403
|
+
theme.colors.background
|
|
406
404
|
);
|
|
407
405
|
this.padding(SLIDER_PADDING, SLIDER_PADDING, SLIDER_PADDING, SLIDER_PADDING);
|
|
408
406
|
this.opacity(this.isEnabled ? 1.0 : 0.6);
|
package/src/controls/Switch.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Callback1, Handler1 } from "../core/BoundCallback";
|
|
2
2
|
import { SemanticCheckedState, SemanticRole } from "../core/ffi";
|
|
3
|
+
import { SwitchChangedEventArgs } from "../core/Node";
|
|
3
4
|
import { PersistedBoolCodec, PersistedValueState } from "../core/PersistedState";
|
|
4
5
|
import { bind1 } from "../core/bind";
|
|
5
6
|
import { activeTheme } from "../core/Theme";
|
|
7
|
+
import { LabeledControlSizing } from "./ControlSizing";
|
|
6
8
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
7
9
|
import { PressableLabeledControl } from "./internal/PressableLabeledControl";
|
|
8
10
|
import {
|
|
@@ -30,24 +32,25 @@ class PersistedSwitchState extends PersistedValueState<Switch, bool> {
|
|
|
30
32
|
|
|
31
33
|
const SWITCH_PERSISTED_STATE = new PersistedSwitchState();
|
|
32
34
|
|
|
33
|
-
function createIndicatorPresenter(template: SwitchIndicatorTemplate | null): SwitchIndicatorPresenter {
|
|
35
|
+
function createIndicatorPresenter(template: SwitchIndicatorTemplate | null, sizing: LabeledControlSizing | null = null): SwitchIndicatorPresenter {
|
|
34
36
|
if (template !== null) {
|
|
35
|
-
return template.create();
|
|
37
|
+
return template.create(sizing);
|
|
36
38
|
}
|
|
37
39
|
const templateSet = getControlTemplates();
|
|
38
40
|
const appTemplate = templateSet !== null ? templateSet.switchIndicator : null;
|
|
39
|
-
return (appTemplate === null ? defaultSwitchIndicatorTemplate : appTemplate).create();
|
|
41
|
+
return (appTemplate === null ? defaultSwitchIndicatorTemplate : appTemplate).create(sizing);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export class Switch extends PressableLabeledControl {
|
|
43
45
|
private indicatorPresenter: SwitchIndicatorPresenter;
|
|
44
46
|
private templateOverride: SwitchIndicatorTemplate | null = null;
|
|
47
|
+
private sizingValue: LabeledControlSizing | null = null;
|
|
45
48
|
private checkedValue: bool = false;
|
|
46
|
-
private changedCallback: ((
|
|
47
|
-
private changedBinding: Callback1<
|
|
49
|
+
private changedCallback: ((event: SwitchChangedEventArgs) => void) | null = null;
|
|
50
|
+
private changedBinding: Callback1<SwitchChangedEventArgs> | null = null;
|
|
48
51
|
|
|
49
52
|
constructor(label: string) {
|
|
50
|
-
const indicatorPresenter = createIndicatorPresenter(null);
|
|
53
|
+
const indicatorPresenter = createIndicatorPresenter(null, null);
|
|
51
54
|
super(SemanticRole.Switch, label, indicatorPresenter.root);
|
|
52
55
|
this.indicatorPresenter = indicatorPresenter;
|
|
53
56
|
this.semanticChecked(SemanticCheckedState.False);
|
|
@@ -60,31 +63,42 @@ export class Switch extends PressableLabeledControl {
|
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
check(flag: bool): this {
|
|
63
|
-
this.updateChecked(flag, false);
|
|
66
|
+
this.updateChecked(flag, true, false);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
sizing(sizing: LabeledControlSizing | null): this {
|
|
71
|
+
this.sizingValue = sizing;
|
|
72
|
+
this.setLabelFontSizeOverride(
|
|
73
|
+
sizing !== null && sizing.hasLabelFontSize ? sizing.labelFontSizePx : 0.0,
|
|
74
|
+
);
|
|
75
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
76
|
+
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
77
|
+
this.syncVisualState();
|
|
64
78
|
return this;
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
template(template: SwitchIndicatorTemplate | null): this {
|
|
68
82
|
this.templateOverride = template;
|
|
69
|
-
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride);
|
|
83
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
70
84
|
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
71
85
|
this.syncVisualState();
|
|
72
86
|
return this;
|
|
73
87
|
}
|
|
74
88
|
|
|
75
|
-
onChanged(callback: ((
|
|
89
|
+
onChanged(callback: ((event: SwitchChangedEventArgs) => void) | null): this {
|
|
76
90
|
this.changedCallback = callback;
|
|
77
91
|
this.changedBinding = null;
|
|
78
92
|
return this;
|
|
79
93
|
}
|
|
80
94
|
|
|
81
|
-
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
95
|
+
bindChanged<Owner>(owner: Owner, handler: Handler1<Owner, SwitchChangedEventArgs>): this {
|
|
82
96
|
this.changedCallback = null;
|
|
83
|
-
this.changedBinding = bind1<Owner,
|
|
97
|
+
this.changedBinding = bind1<Owner, SwitchChangedEventArgs>(owner, handler);
|
|
84
98
|
return this;
|
|
85
99
|
}
|
|
86
100
|
|
|
87
|
-
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner,
|
|
101
|
+
onChangedWith<Owner>(owner: Owner, handler: Handler1<Owner, SwitchChangedEventArgs>): this {
|
|
88
102
|
this.bindChanged(owner, handler);
|
|
89
103
|
return this;
|
|
90
104
|
}
|
|
@@ -108,10 +122,10 @@ export class Switch extends PressableLabeledControl {
|
|
|
108
122
|
}
|
|
109
123
|
|
|
110
124
|
_applyPersistedChecked(next: bool): void {
|
|
111
|
-
this.updateChecked(next, true);
|
|
125
|
+
this.updateChecked(next, true, false);
|
|
112
126
|
}
|
|
113
127
|
|
|
114
|
-
private updateChecked(next: bool, emit: bool): void {
|
|
128
|
+
private updateChecked(next: bool, emit: bool, announce: bool = emit): void {
|
|
115
129
|
if (this.checkedValue == next) {
|
|
116
130
|
return;
|
|
117
131
|
}
|
|
@@ -119,14 +133,17 @@ export class Switch extends PressableLabeledControl {
|
|
|
119
133
|
this.semanticChecked(next ? SemanticCheckedState.True : SemanticCheckedState.False);
|
|
120
134
|
this.syncVisualState();
|
|
121
135
|
if (emit) {
|
|
122
|
-
|
|
136
|
+
if (announce) {
|
|
137
|
+
this.requestSemanticAnnouncement();
|
|
138
|
+
}
|
|
139
|
+
const event = new SwitchChangedEventArgs(next);
|
|
123
140
|
const callback = this.changedCallback;
|
|
124
141
|
if (callback !== null) {
|
|
125
|
-
callback(
|
|
142
|
+
callback(event);
|
|
126
143
|
}
|
|
127
144
|
const binding = this.changedBinding;
|
|
128
145
|
if (binding !== null) {
|
|
129
|
-
binding.invoke(
|
|
146
|
+
binding.invoke(event);
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
}
|