@effindomv2/fui-as 0.1.5 → 0.1.7
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/src/common-harness/ui-imports.ts +6 -3
- package/package.json +2 -2
- package/scripts/build.sh +7 -5
- package/scripts/generate-host-events.ts +1 -0
- package/scripts/generate-host-services.ts +1 -0
- package/src/bindings/ui.ts +8 -4
- package/src/controls/Dropdown.ts +3 -3
- package/src/controls/internal/DropdownFieldPresenter.ts +2 -4
- package/src/controls/internal/PressableLabeledControl.ts +1 -2
- package/src/controls/internal/TextInputCore.ts +2 -3
- package/src/core/Errors.ts +8 -0
- package/src/core/ffi.ts +6 -3
- package/src/core/generated/FrameworkHostServices.ts +1 -0
- package/src/nodes/FlexBox.ts +32 -31
- package/src/nodes/ScrollBox.ts +4 -6
- package/src/nodes/ScrollView.ts +19 -21
- package/src/nodes/VirtualList.ts +32 -6
|
@@ -128,12 +128,15 @@ export function createUiImportModule(deps: UiImportDeps) {
|
|
|
128
128
|
ui_set_height(handle: AppHandleLike, value: number, unit: number): void {
|
|
129
129
|
deps.getRuntime().ui._ui_set_height(toBigIntHandle(handle), value, unit);
|
|
130
130
|
},
|
|
131
|
+
ui_set_fill_width(handle: AppHandleLike, fill: number): void {
|
|
132
|
+
deps.getRuntime().ui._ui_set_fill_width(toBigIntHandle(handle), fill);
|
|
133
|
+
},
|
|
134
|
+
ui_set_fill_height(handle: AppHandleLike, fill: number): void {
|
|
135
|
+
deps.getRuntime().ui._ui_set_fill_height(toBigIntHandle(handle), fill);
|
|
136
|
+
},
|
|
131
137
|
ui_set_flex_direction(handle: AppHandleLike, direction: number): void {
|
|
132
138
|
deps.getRuntime().ui._ui_set_flex_direction(toBigIntHandle(handle), direction);
|
|
133
139
|
},
|
|
134
|
-
ui_set_flex_grow(handle: AppHandleLike, grow: number): void {
|
|
135
|
-
deps.getRuntime().ui._ui_set_flex_grow(toBigIntHandle(handle), grow);
|
|
136
|
-
},
|
|
137
140
|
ui_set_flex_basis(handle: AppHandleLike, basis: number): void {
|
|
138
141
|
deps.getRuntime().ui._ui_set_flex_basis(toBigIntHandle(handle), basis);
|
|
139
142
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effindomv2/fui-as",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "AGPL-3.0-only OR LicenseRef-EffinDom-Commercial",
|
|
6
6
|
"description": "EffinDom v2 AssemblyScript frontend framework SDK and browser harness",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@assemblyscript/loader": "^0.28.17",
|
|
81
|
-
"@effindomv2/runtime": "0.1.
|
|
81
|
+
"@effindomv2/runtime": "0.1.2"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@as-pect/assembly": "8.1.0",
|
package/scripts/build.sh
CHANGED
|
@@ -124,10 +124,10 @@ resolve_runtime_dist_dir() {
|
|
|
124
124
|
fi
|
|
125
125
|
|
|
126
126
|
candidates+=(
|
|
127
|
+
"${REPO_ROOT}/public/v2/browser-bridge"
|
|
128
|
+
"${REPO_ROOT}/v2/browser-bridge/dist"
|
|
127
129
|
"${PACKAGE_DIR}/node_modules/@effindomv2/runtime/dist"
|
|
128
130
|
"${REPO_ROOT}/node_modules/@effindomv2/runtime/dist"
|
|
129
|
-
"${REPO_ROOT}/v2/browser-bridge/dist"
|
|
130
|
-
"${REPO_ROOT}/public/v2/browser-bridge"
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
for candidate in "${candidates[@]}"; do
|
|
@@ -177,9 +177,11 @@ copy_runtime_assets() {
|
|
|
177
177
|
cp "${RUNTIME_DIST_DIR}/icu-asset.json" "${destination}/runtime/dist/icu-asset.json"
|
|
178
178
|
fi
|
|
179
179
|
cp -R "${RUNTIME_DIST_DIR}/runtime" "${destination}/runtime/dist/runtime"
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
cp -R "${
|
|
180
|
+
mkdir -p "${destination}/runtime/fonts"
|
|
181
|
+
if [ -d "${REPO_ROOT}/public/v2/fonts" ]; then
|
|
182
|
+
cp -R "${REPO_ROOT}/public/v2/fonts/." "${destination}/runtime/fonts/"
|
|
183
|
+
elif [ -d "${RUNTIME_DIST_DIR}/fonts" ]; then
|
|
184
|
+
cp -R "${RUNTIME_DIST_DIR}/fonts/." "${destination}/runtime/fonts/"
|
|
183
185
|
fi
|
|
184
186
|
}
|
|
185
187
|
|
|
@@ -217,6 +217,7 @@ function emitBindingsFile(
|
|
|
217
217
|
): string {
|
|
218
218
|
const callbackImport = primitivesImportOverride ?? relativeImport(outputPath, path.resolve(PACKAGE_DIR, "src/FuiPrimitives.ts"));
|
|
219
219
|
const blocks: Array<string> = [
|
|
220
|
+
"// @ts-nocheck",
|
|
220
221
|
`// Generated by scripts/generate-host-events.ts from ${sourcePathForHeader(sourceModulePath)}#${exportName}.`,
|
|
221
222
|
`import { Callback0, Callback1, Callback2 } from "${callbackImport}";`,
|
|
222
223
|
"",
|
|
@@ -199,6 +199,7 @@ function emitBindingsFile(
|
|
|
199
199
|
): string {
|
|
200
200
|
const runtimeImport = primitivesImportOverride ?? relativeImport(outputPath, path.resolve(PACKAGE_DIR, "src/FuiPrimitives.ts"));
|
|
201
201
|
const blocks: Array<string> = [
|
|
202
|
+
"// @ts-nocheck",
|
|
202
203
|
`// Generated by scripts/generate-host-services.ts from ${sourcePathForHeader(sourceModulePath)}#${exportName}.`,
|
|
203
204
|
];
|
|
204
205
|
if (methods.some((method) => returnsBufferType(method.returns))) {
|
package/src/bindings/ui.ts
CHANGED
|
@@ -100,12 +100,16 @@ export function setHeight(handle: u64, value: f32, unit: u32): void {
|
|
|
100
100
|
ffi.ui_set_height(handle, value, unit);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
export function
|
|
104
|
-
ffi.
|
|
103
|
+
export function setFillWidth(handle: u64, fill: bool): void {
|
|
104
|
+
ffi.ui_set_fill_width(handle, fill);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function setFillHeight(handle: u64, fill: bool): void {
|
|
108
|
+
ffi.ui_set_fill_height(handle, fill);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
|
-
export function
|
|
108
|
-
ffi.
|
|
111
|
+
export function setFlexDirection(handle: u64, direction: u32): void {
|
|
112
|
+
ffi.ui_set_flex_direction(handle, direction);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
export function setFlexBasis(handle: u64, basis: f32): void {
|
package/src/controls/Dropdown.ts
CHANGED
|
@@ -251,7 +251,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
251
251
|
this.cursor(CursorStyle.Pointer);
|
|
252
252
|
this.flexDirection(FlexDirection.Row);
|
|
253
253
|
this.alignItems(AlignItems.Center);
|
|
254
|
-
fieldPresenter.root.
|
|
254
|
+
fieldPresenter.root.fillWidth();
|
|
255
255
|
fieldPresenter.chevronHost.child(chevronPresenter.root);
|
|
256
256
|
this.child(fieldPresenter.root);
|
|
257
257
|
this.child(this.popupRoot);
|
|
@@ -780,7 +780,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
780
780
|
this.padding(0.0, 0.0, 0.0, 0.0);
|
|
781
781
|
this.bgColor(0x00000000);
|
|
782
782
|
this.opacity(this.isEnabled ? 1.0 : 0.6);
|
|
783
|
-
this.fieldPresenter.root.
|
|
783
|
+
this.fieldPresenter.root.fillWidth();
|
|
784
784
|
this.fieldPresenter.apply(
|
|
785
785
|
theme,
|
|
786
786
|
new DropdownFieldVisualState(
|
|
@@ -845,7 +845,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
845
845
|
const previousFieldRoot = this.fieldPresenter.root;
|
|
846
846
|
this.fieldPresenter = nextFieldPresenter;
|
|
847
847
|
this.chevronPresenter = nextChevronPresenter;
|
|
848
|
-
nextFieldPresenter.root.
|
|
848
|
+
nextFieldPresenter.root.fillWidth();
|
|
849
849
|
nextFieldPresenter.chevronHost.addChildNode(nextChevronPresenter.root);
|
|
850
850
|
const children = new Array<Node>();
|
|
851
851
|
children.push(nextFieldPresenter.root);
|
|
@@ -63,8 +63,7 @@ class DefaultDropdownFieldPresenter extends DropdownFieldPresenter {
|
|
|
63
63
|
.overflowFade(true, false)
|
|
64
64
|
.verticalAlign(TextVerticalAlign.Center);
|
|
65
65
|
const valueHost = new FlexBox()
|
|
66
|
-
.
|
|
67
|
-
.flexGrow(1.0)
|
|
66
|
+
.fillWidth()
|
|
68
67
|
.child(valueNode) as FlexBox;
|
|
69
68
|
const chevronHost = new FlexBox()
|
|
70
69
|
.width(DEFAULT_CHEVRON_BOX_SIZE, Unit.Pixel)
|
|
@@ -88,8 +87,7 @@ class DefaultDropdownFieldPresenter extends DropdownFieldPresenter {
|
|
|
88
87
|
.padding(theme.spacing.md, theme.spacing.sm, theme.spacing.md, theme.spacing.sm)
|
|
89
88
|
.bgColor(state.pressed && state.enabled ? theme.colors.background : theme.colors.surface);
|
|
90
89
|
this.valueHost
|
|
91
|
-
.
|
|
92
|
-
.flexGrow(1.0);
|
|
90
|
+
.fillWidth();
|
|
93
91
|
this.valueNode
|
|
94
92
|
.font(theme.fonts.body, theme.fonts.sizeBody)
|
|
95
93
|
.textColor(state.enabled ? theme.colors.textPrimary : theme.colors.textMuted);
|
|
@@ -44,8 +44,7 @@ export class PressableLabeledControl extends FlexBox {
|
|
|
44
44
|
.width(activeTheme.value.spacing.sm, Unit.Pixel)
|
|
45
45
|
.height(1.0, Unit.Pixel);
|
|
46
46
|
this.labelHost = new FlexBox()
|
|
47
|
-
.
|
|
48
|
-
.flexGrow(1.0);
|
|
47
|
+
.fillWidth();
|
|
49
48
|
this.labelNode.width(100.0, Unit.Percent);
|
|
50
49
|
this.labelHost.child(this.labelNode);
|
|
51
50
|
|
|
@@ -190,6 +190,7 @@ export class TextInputCore extends FlexBox {
|
|
|
190
190
|
this.placeholderHost = new TextInputPlaceholderHost(this, this.placeholderText);
|
|
191
191
|
if (profile.multiline) {
|
|
192
192
|
const scrollBox = new ScrollBox(new ScrollState(), new TextInputEditorViewport(this))
|
|
193
|
+
.fillSize()
|
|
193
194
|
.child(this.editorText) as ScrollBox;
|
|
194
195
|
this.editorScrollBox = scrollBox;
|
|
195
196
|
this.child(scrollBox);
|
|
@@ -488,9 +489,7 @@ export class TextInputCore extends FlexBox {
|
|
|
488
489
|
if (scrollBox !== null) {
|
|
489
490
|
scrollBox.cursor(CursorStyle.Default);
|
|
490
491
|
scrollBox.viewport.cursor(editableCursor);
|
|
491
|
-
scrollBox.
|
|
492
|
-
scrollBox.height(100.0, Unit.Percent);
|
|
493
|
-
scrollBox.flexGrow(1.0);
|
|
492
|
+
scrollBox.fillSize();
|
|
494
493
|
this.syncScrollChromeState();
|
|
495
494
|
}
|
|
496
495
|
this.syncFocusChrome(theme);
|
package/src/core/Errors.ts
CHANGED
|
@@ -8,6 +8,14 @@ export class ObjectDisposedError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export class VirtualListItemBindingError extends Error {
|
|
12
|
+
constructor() {
|
|
13
|
+
const message = "VirtualList: item renderer not configured. Call .onBindItem() or .onBindItemWith() after construction.";
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "VirtualListItemBindingError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
export function throwNullArgument(functionName: string, argumentName: string): void {
|
|
12
20
|
error("Validation", functionName + ": " + argumentName + " must not be null");
|
|
13
21
|
throw new TypeError(functionName + ": " + argumentName + " must not be null");
|
package/src/core/ffi.ts
CHANGED
|
@@ -228,12 +228,15 @@ export declare function ui_set_width(handle: u64, value: f32, unit: u32): void;
|
|
|
228
228
|
@external("effindom_v2_ui", "ui_set_height")
|
|
229
229
|
export declare function ui_set_height(handle: u64, value: f32, unit: u32): void;
|
|
230
230
|
|
|
231
|
+
@external("effindom_v2_ui", "ui_set_fill_width")
|
|
232
|
+
export declare function ui_set_fill_width(handle: u64, fill: bool): void;
|
|
233
|
+
|
|
234
|
+
@external("effindom_v2_ui", "ui_set_fill_height")
|
|
235
|
+
export declare function ui_set_fill_height(handle: u64, fill: bool): void;
|
|
236
|
+
|
|
231
237
|
@external("effindom_v2_ui", "ui_set_flex_direction")
|
|
232
238
|
export declare function ui_set_flex_direction(handle: u64, direction: u32): void;
|
|
233
239
|
|
|
234
|
-
@external("effindom_v2_ui", "ui_set_flex_grow")
|
|
235
|
-
export declare function ui_set_flex_grow(handle: u64, grow: f32): void;
|
|
236
|
-
|
|
237
240
|
@external("effindom_v2_ui", "ui_set_flex_basis")
|
|
238
241
|
export declare function ui_set_flex_basis(handle: u64, basis: f32): void;
|
|
239
242
|
|
package/src/nodes/FlexBox.ts
CHANGED
|
@@ -38,17 +38,17 @@ export class FlexBoxProps {
|
|
|
38
38
|
widthValue: f32 = 0.0;
|
|
39
39
|
widthUnit: Unit = Unit.Pixel;
|
|
40
40
|
hasWidth: bool = false;
|
|
41
|
+
hasFillWidth: bool = false;
|
|
41
42
|
heightValue: f32 = 0.0;
|
|
42
43
|
heightUnit: Unit = Unit.Pixel;
|
|
43
44
|
hasHeight: bool = false;
|
|
45
|
+
hasFillHeight: bool = false;
|
|
44
46
|
flexBasisValue: f32 = 0.0;
|
|
45
47
|
hasFlexBasis: bool = false;
|
|
46
48
|
backgroundColor: u32 = 0;
|
|
47
49
|
hasBackgroundColor: bool = false;
|
|
48
50
|
flexDirectionValue: FlexDirection = FlexDirection.Column;
|
|
49
51
|
hasFlexDirection: bool = false;
|
|
50
|
-
flexGrowValue: f32 = 0.0;
|
|
51
|
-
hasFlexGrow: bool = false;
|
|
52
52
|
justifyContentValue: JustifyContent = JustifyContent.Start;
|
|
53
53
|
hasJustifyContent: bool = false;
|
|
54
54
|
alignItemsValue: AlignItems = AlignItems.Start;
|
|
@@ -72,9 +72,11 @@ export class FlexBox extends Node {
|
|
|
72
72
|
private widthValue: f32 = 0.0;
|
|
73
73
|
private widthUnit: Unit = Unit.Pixel;
|
|
74
74
|
private hasWidth: bool = false;
|
|
75
|
+
private hasFillWidth: bool = false;
|
|
75
76
|
private heightValue: f32 = 0.0;
|
|
76
77
|
private heightUnit: Unit = Unit.Pixel;
|
|
77
78
|
private hasHeight: bool = false;
|
|
79
|
+
private hasFillHeight: bool = false;
|
|
78
80
|
private flexBasisValue: f32 = 0.0;
|
|
79
81
|
private hasFlexBasis: bool = false;
|
|
80
82
|
private backgroundColor: u32 = 0;
|
|
@@ -91,8 +93,6 @@ export class FlexBox extends Node {
|
|
|
91
93
|
private borderDashOff: f32 = 0.0;
|
|
92
94
|
private flexDirectionValue: FlexDirection = FlexDirection.Column;
|
|
93
95
|
private hasFlexDirection: bool = false;
|
|
94
|
-
private flexGrowValue: f32 = 0.0;
|
|
95
|
-
private hasFlexGrow: bool = false;
|
|
96
96
|
private justifyContentValue: JustifyContent = JustifyContent.Start;
|
|
97
97
|
private hasJustifyContent: bool = false;
|
|
98
98
|
private alignItemsValue: AlignItems = AlignItems.Start;
|
|
@@ -149,6 +149,7 @@ export class FlexBox extends Node {
|
|
|
149
149
|
this.widthValue = value;
|
|
150
150
|
this.widthUnit = unit;
|
|
151
151
|
this.hasWidth = true;
|
|
152
|
+
this.hasFillWidth = false;
|
|
152
153
|
if (this.hasBuiltHandle()) {
|
|
153
154
|
ui.setWidth(this.handle, value, <u32>unit);
|
|
154
155
|
this.notifyRetainedLayoutMutation();
|
|
@@ -160,6 +161,7 @@ export class FlexBox extends Node {
|
|
|
160
161
|
this.heightValue = value;
|
|
161
162
|
this.heightUnit = unit;
|
|
162
163
|
this.hasHeight = true;
|
|
164
|
+
this.hasFillHeight = false;
|
|
163
165
|
if (this.hasBuiltHandle()) {
|
|
164
166
|
ui.setHeight(this.handle, value, <u32>unit);
|
|
165
167
|
this.notifyRetainedLayoutMutation();
|
|
@@ -168,12 +170,20 @@ export class FlexBox extends Node {
|
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
fillWidth(): this {
|
|
171
|
-
this.
|
|
173
|
+
this.hasFillWidth = true;
|
|
174
|
+
if (this.hasBuiltHandle()) {
|
|
175
|
+
ui.setFillWidth(this.handle, true);
|
|
176
|
+
this.notifyRetainedLayoutMutation();
|
|
177
|
+
}
|
|
172
178
|
return this;
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
fillHeight(): this {
|
|
176
|
-
this.
|
|
182
|
+
this.hasFillHeight = true;
|
|
183
|
+
if (this.hasBuiltHandle()) {
|
|
184
|
+
ui.setFillHeight(this.handle, true);
|
|
185
|
+
this.notifyRetainedLayoutMutation();
|
|
186
|
+
}
|
|
177
187
|
return this;
|
|
178
188
|
}
|
|
179
189
|
|
|
@@ -274,21 +284,6 @@ export class FlexBox extends Node {
|
|
|
274
284
|
return this;
|
|
275
285
|
}
|
|
276
286
|
|
|
277
|
-
flexGrow(grow: f32): this {
|
|
278
|
-
this.flexGrowValue = grow;
|
|
279
|
-
this.hasFlexGrow = true;
|
|
280
|
-
if (this.hasBuiltHandle()) {
|
|
281
|
-
ui.setFlexGrow(this.handle, grow);
|
|
282
|
-
this.notifyRetainedLayoutMutation();
|
|
283
|
-
}
|
|
284
|
-
return this;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
grow(grow: f32 = 1.0): this {
|
|
288
|
-
this.flexGrow(grow);
|
|
289
|
-
return this;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
287
|
justifyContent(justify: JustifyContent): this {
|
|
293
288
|
this.justifyContentValue = justify;
|
|
294
289
|
this.hasJustifyContent = true;
|
|
@@ -530,15 +525,18 @@ export class FlexBox extends Node {
|
|
|
530
525
|
if (this.hasWidth) {
|
|
531
526
|
ui.setWidth(this.handle, this.widthValue, <u32>this.widthUnit);
|
|
532
527
|
}
|
|
528
|
+
if (this.hasFillWidth) {
|
|
529
|
+
ui.setFillWidth(this.handle, true);
|
|
530
|
+
}
|
|
533
531
|
if (this.hasHeight) {
|
|
534
532
|
ui.setHeight(this.handle, this.heightValue, <u32>this.heightUnit);
|
|
535
533
|
}
|
|
534
|
+
if (this.hasFillHeight) {
|
|
535
|
+
ui.setFillHeight(this.handle, true);
|
|
536
|
+
}
|
|
536
537
|
if (this.hasFlexDirection) {
|
|
537
538
|
ui.setFlexDirection(this.handle, <u32>this.flexDirectionValue);
|
|
538
539
|
}
|
|
539
|
-
if (this.hasFlexGrow) {
|
|
540
|
-
ui.setFlexGrow(this.handle, this.flexGrowValue);
|
|
541
|
-
}
|
|
542
540
|
if (this.hasFlexBasis) {
|
|
543
541
|
ui.setFlexBasis(this.handle, this.flexBasisValue);
|
|
544
542
|
}
|
|
@@ -569,9 +567,15 @@ export class FlexBox extends Node {
|
|
|
569
567
|
if (props.hasWidth) {
|
|
570
568
|
this.width(props.widthValue, props.widthUnit);
|
|
571
569
|
}
|
|
570
|
+
if (props.hasFillWidth) {
|
|
571
|
+
this.fillWidth();
|
|
572
|
+
}
|
|
572
573
|
if (props.hasHeight) {
|
|
573
574
|
this.height(props.heightValue, props.heightUnit);
|
|
574
575
|
}
|
|
576
|
+
if (props.hasFillHeight) {
|
|
577
|
+
this.fillHeight();
|
|
578
|
+
}
|
|
575
579
|
if (props.hasFlexBasis) {
|
|
576
580
|
this.flexBasis(props.flexBasisValue);
|
|
577
581
|
}
|
|
@@ -581,9 +585,6 @@ export class FlexBox extends Node {
|
|
|
581
585
|
if (props.hasFlexDirection) {
|
|
582
586
|
this.flexDirection(props.flexDirectionValue);
|
|
583
587
|
}
|
|
584
|
-
if (props.hasFlexGrow) {
|
|
585
|
-
this.flexGrow(props.flexGrowValue);
|
|
586
|
-
}
|
|
587
588
|
if (props.hasJustifyContent) {
|
|
588
589
|
this.justifyContent(props.justifyContentValue);
|
|
589
590
|
}
|
|
@@ -722,16 +723,16 @@ export class FlexBox extends Node {
|
|
|
722
723
|
|
|
723
724
|
private buildFullMainAxisPercentWarning(isRow: bool): string {
|
|
724
725
|
if (isRow) {
|
|
725
|
-
return "A row container has an in-flow child using width(100.0, Unit.Percent)
|
|
726
|
+
return "A row container has an in-flow child using width(100.0, Unit.Percent) alongside siblings. Unit.Percent is literal parent-relative sizing, not flex sharing. Use fillWidth() when the child should take remaining row space.";
|
|
726
727
|
}
|
|
727
|
-
return "A column container has an in-flow child using height(100.0, Unit.Percent)
|
|
728
|
+
return "A column container has an in-flow child using height(100.0, Unit.Percent) alongside siblings. Unit.Percent is literal parent-relative sizing, not flex sharing. Use fillHeight() when the child should take remaining column space.";
|
|
728
729
|
}
|
|
729
730
|
|
|
730
731
|
private buildMainAxisPercentOverflowWarning(isRow: bool): string {
|
|
731
732
|
if (isRow) {
|
|
732
|
-
return "A row container has in-flow children whose explicit width percentages exceed 100% in total. Unit.Percent is literal parent-relative sizing, not flex sharing. Use
|
|
733
|
+
return "A row container has in-flow children whose explicit width percentages exceed 100% in total. Unit.Percent is literal parent-relative sizing, not flex sharing. Use fillWidth() for the child that should expand, or reduce the percentages so they fit.";
|
|
733
734
|
}
|
|
734
|
-
return "A column container has in-flow children whose explicit height percentages exceed 100% in total. Unit.Percent is literal parent-relative sizing, not flex sharing. Use
|
|
735
|
+
return "A column container has in-flow children whose explicit height percentages exceed 100% in total. Unit.Percent is literal parent-relative sizing, not flex sharing. Use fillHeight() for the child that should expand, or reduce the percentages so they fit.";
|
|
735
736
|
}
|
|
736
737
|
|
|
737
738
|
protected applyVisualStyle(): void {
|
package/src/nodes/ScrollBox.ts
CHANGED
|
@@ -49,12 +49,10 @@ export class ScrollBox extends FlexBox {
|
|
|
49
49
|
const viewportValue = (viewportOverride === null ? new ScrollView() : viewportOverride)
|
|
50
50
|
.bindScrollState(scrollState)
|
|
51
51
|
.showScrollbars(false)
|
|
52
|
-
.
|
|
53
|
-
.height(100.0, Unit.Percent)
|
|
54
|
-
.flexGrow(1.0);
|
|
52
|
+
.fillSize();
|
|
55
53
|
const verticalGutterValue = new FlexBox()
|
|
56
54
|
.width(DEFAULT_SCROLLBAR_GUTTER, Unit.Pixel)
|
|
57
|
-
.
|
|
55
|
+
.fillHeight()
|
|
58
56
|
.onPointerDown(noopPointerCallback) as FlexBox;
|
|
59
57
|
const verticalScrollBarValue = new ScrollBar(scrollState, Orientation.Vertical);
|
|
60
58
|
const cornerValue = new FlexBox()
|
|
@@ -68,13 +66,13 @@ export class ScrollBox extends FlexBox {
|
|
|
68
66
|
verticalScrollBarValue.render(),
|
|
69
67
|
);
|
|
70
68
|
topRowValue.onPointerDown(noopPointerCallback);
|
|
71
|
-
topRowValue.
|
|
69
|
+
topRowValue.fillSize();
|
|
72
70
|
const bottomRowValue = Row(
|
|
73
71
|
horizontalScrollBarValue.render(),
|
|
74
72
|
cornerValue,
|
|
75
73
|
);
|
|
76
74
|
bottomRowValue.onPointerDown(noopPointerCallback);
|
|
77
|
-
bottomRowValue.
|
|
75
|
+
bottomRowValue.fillWidth();
|
|
78
76
|
|
|
79
77
|
this.viewportValue = viewportValue;
|
|
80
78
|
this.topRowValue = topRowValue;
|
package/src/nodes/ScrollView.ts
CHANGED
|
@@ -38,13 +38,13 @@ export class ScrollView extends Node {
|
|
|
38
38
|
private widthValue: f32 = 0.0;
|
|
39
39
|
private widthUnit: Unit = Unit.Pixel;
|
|
40
40
|
private hasWidth: bool = false;
|
|
41
|
+
private hasFillWidth: bool = false;
|
|
41
42
|
private heightValue: f32 = 0.0;
|
|
42
43
|
private heightUnit: Unit = Unit.Pixel;
|
|
43
44
|
private hasHeight: bool = false;
|
|
45
|
+
private hasFillHeight: bool = false;
|
|
44
46
|
private flexBasisValue: f32 = 0.0;
|
|
45
47
|
private hasFlexBasis: bool = false;
|
|
46
|
-
private flexGrowValue: f32 = 0.0;
|
|
47
|
-
private hasFlexGrow: bool = false;
|
|
48
48
|
private enableScrollX: bool = true;
|
|
49
49
|
private enableScrollY: bool = true;
|
|
50
50
|
private showScrollbarsValue: bool = true;
|
|
@@ -99,6 +99,7 @@ export class ScrollView extends Node {
|
|
|
99
99
|
this.widthValue = value;
|
|
100
100
|
this.widthUnit = unit;
|
|
101
101
|
this.hasWidth = true;
|
|
102
|
+
this.hasFillWidth = false;
|
|
102
103
|
if (unit == Unit.Pixel) {
|
|
103
104
|
this._scrollState.viewportWidth.value = value;
|
|
104
105
|
}
|
|
@@ -113,6 +114,7 @@ export class ScrollView extends Node {
|
|
|
113
114
|
this.heightValue = value;
|
|
114
115
|
this.heightUnit = unit;
|
|
115
116
|
this.hasHeight = true;
|
|
117
|
+
this.hasFillHeight = false;
|
|
116
118
|
if (unit == Unit.Pixel) {
|
|
117
119
|
this._scrollState.viewportHeight.value = value;
|
|
118
120
|
}
|
|
@@ -124,12 +126,20 @@ export class ScrollView extends Node {
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
fillWidth(): this {
|
|
127
|
-
this.
|
|
129
|
+
this.hasFillWidth = true;
|
|
130
|
+
if (this.hasBuiltHandle()) {
|
|
131
|
+
ui.setFillWidth(this.handle, true);
|
|
132
|
+
this.notifyRetainedLayoutMutation();
|
|
133
|
+
}
|
|
128
134
|
return this;
|
|
129
135
|
}
|
|
130
136
|
|
|
131
137
|
fillHeight(): this {
|
|
132
|
-
this.
|
|
138
|
+
this.hasFillHeight = true;
|
|
139
|
+
if (this.hasBuiltHandle()) {
|
|
140
|
+
ui.setFillHeight(this.handle, true);
|
|
141
|
+
this.notifyRetainedLayoutMutation();
|
|
142
|
+
}
|
|
133
143
|
return this;
|
|
134
144
|
}
|
|
135
145
|
|
|
@@ -149,21 +159,6 @@ export class ScrollView extends Node {
|
|
|
149
159
|
return this;
|
|
150
160
|
}
|
|
151
161
|
|
|
152
|
-
flexGrow(value: f32): this {
|
|
153
|
-
this.flexGrowValue = value;
|
|
154
|
-
this.hasFlexGrow = true;
|
|
155
|
-
if (this.hasBuiltHandle()) {
|
|
156
|
-
ui.setFlexGrow(this.handle, value);
|
|
157
|
-
this.notifyRetainedLayoutMutation();
|
|
158
|
-
}
|
|
159
|
-
return this;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
grow(value: f32 = 1.0): this {
|
|
163
|
-
this.flexGrow(value);
|
|
164
|
-
return this;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
162
|
scrollEnabledX(flag: bool): this {
|
|
168
163
|
this.enableScrollX = flag;
|
|
169
164
|
if (this.hasBuiltHandle()) {
|
|
@@ -319,11 +314,14 @@ export class ScrollView extends Node {
|
|
|
319
314
|
if (this.hasWidth) {
|
|
320
315
|
ui.setWidth(this.handle, this.widthValue, <u32>this.widthUnit);
|
|
321
316
|
}
|
|
317
|
+
if (this.hasFillWidth) {
|
|
318
|
+
ui.setFillWidth(this.handle, true);
|
|
319
|
+
}
|
|
322
320
|
if (this.hasHeight) {
|
|
323
321
|
ui.setHeight(this.handle, this.heightValue, <u32>this.heightUnit);
|
|
324
322
|
}
|
|
325
|
-
if (this.
|
|
326
|
-
ui.
|
|
323
|
+
if (this.hasFillHeight) {
|
|
324
|
+
ui.setFillHeight(this.handle, true);
|
|
327
325
|
}
|
|
328
326
|
if (this.hasFlexBasis) {
|
|
329
327
|
ui.setFlexBasis(this.handle, this.flexBasisValue);
|
package/src/nodes/VirtualList.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { HandlerAction } from "../core/Action";
|
|
|
2
2
|
import { Disposable, disposeAll } from "../core/Disposable";
|
|
3
3
|
import { markNeedsCommit } from "../core/FrameScheduler";
|
|
4
4
|
import { FlexDirection, HandleValue, Unit } from "../core/ffi";
|
|
5
|
+
import { VirtualListItemBindingError } from "../core/Errors";
|
|
5
6
|
import { Node } from "../core/Node";
|
|
6
7
|
import { FlexBox } from "./FlexBox";
|
|
7
8
|
import { ScrollBar } from "./ScrollBar";
|
|
@@ -20,7 +21,7 @@ export type VirtualListBinder = (container: FlexBox, index: i32) => void;
|
|
|
20
21
|
export class VirtualList extends FlexBox {
|
|
21
22
|
private totalItemsValue: i32;
|
|
22
23
|
private readonly itemHeightValue: f32;
|
|
23
|
-
private
|
|
24
|
+
private bindItemValue: VirtualListBinder;
|
|
24
25
|
private readonly scrollStateValue: ScrollState;
|
|
25
26
|
private readonly scrollBoxValue: ScrollBox;
|
|
26
27
|
private readonly contentValue: FlexBox;
|
|
@@ -33,7 +34,7 @@ export class VirtualList extends FlexBox {
|
|
|
33
34
|
private currentFirstVisibleIndex: i32 = -1;
|
|
34
35
|
private currentLastVisibleIndex: i32 = -1;
|
|
35
36
|
|
|
36
|
-
constructor(totalItems: i32, itemHeight: f32,
|
|
37
|
+
constructor(totalItems: i32, itemHeight: f32, maxVisible: i32 = DEFAULT_MAX_VISIBLE_ITEMS) {
|
|
37
38
|
super();
|
|
38
39
|
const scrollStateValue = new ScrollState();
|
|
39
40
|
const poolValue = new Array<SelectionArea>();
|
|
@@ -44,7 +45,9 @@ export class VirtualList extends FlexBox {
|
|
|
44
45
|
const poolSizeValue = maxVisible > 0 ? maxVisible + POOL_OVERSCAN_ITEMS : POOL_OVERSCAN_ITEMS;
|
|
45
46
|
this.totalItemsValue = totalItemsValue;
|
|
46
47
|
this.itemHeightValue = itemHeightValue;
|
|
47
|
-
this.bindItemValue =
|
|
48
|
+
this.bindItemValue = (): void => {
|
|
49
|
+
throw new VirtualListItemBindingError();
|
|
50
|
+
};
|
|
48
51
|
this.scrollStateValue = scrollStateValue;
|
|
49
52
|
this.poolSizeValue = poolSizeValue;
|
|
50
53
|
|
|
@@ -95,9 +98,7 @@ export class VirtualList extends FlexBox {
|
|
|
95
98
|
.child(this.scrollBoxValue)
|
|
96
99
|
.width(FULL_SIZE, Unit.Percent)
|
|
97
100
|
.height(FULL_SIZE, Unit.Percent);
|
|
98
|
-
|
|
99
101
|
this.attachListeners();
|
|
100
|
-
this.rebuildVisibleRange(false);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
get scrollState(): ScrollState {
|
|
@@ -150,6 +151,9 @@ export class VirtualList extends FlexBox {
|
|
|
150
151
|
return this.builtHandle;
|
|
151
152
|
}
|
|
152
153
|
const handle = super.build();
|
|
154
|
+
if (this.currentFirstVisibleIndex < 0 && this.totalItemsValue > 0) {
|
|
155
|
+
this.rebuildVisibleRange(false);
|
|
156
|
+
}
|
|
153
157
|
ui.setSelectionAreaBarrier(handle, true);
|
|
154
158
|
return handle;
|
|
155
159
|
}
|
|
@@ -174,6 +178,24 @@ export class VirtualList extends FlexBox {
|
|
|
174
178
|
return this;
|
|
175
179
|
}
|
|
176
180
|
|
|
181
|
+
onBindItem(renderer: VirtualListBinder): this {
|
|
182
|
+
this.bindItemValue = renderer;
|
|
183
|
+
this.currentFirstVisibleIndex = -1;
|
|
184
|
+
this.currentLastVisibleIndex = -1;
|
|
185
|
+
this.rebuildVisibleRange(true);
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
onBindItemWith<Owner>(owner: Owner, renderer: (owner: Owner, container: FlexBox, index: i32) => void): this {
|
|
190
|
+
this.bindItemValue = (container: FlexBox, index: i32): void => {
|
|
191
|
+
renderer(owner, container, index);
|
|
192
|
+
};
|
|
193
|
+
this.currentFirstVisibleIndex = -1;
|
|
194
|
+
this.currentLastVisibleIndex = -1;
|
|
195
|
+
this.rebuildVisibleRange(true);
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
|
|
177
199
|
updateItemCount(next: i32): void {
|
|
178
200
|
this.totalItemsValue = next > 0 ? next : 0;
|
|
179
201
|
this.scrollStateValue.contentHeight.value = this.totalContentHeight;
|
|
@@ -301,7 +323,7 @@ export class VirtualList extends FlexBox {
|
|
|
301
323
|
const nextItemIndex = firstVisibleIndex + poolIndex;
|
|
302
324
|
rowArea.height(this.itemHeightValue, Unit.Pixel);
|
|
303
325
|
const container = changetype<FlexBox>(rowArea.getChildAt(0));
|
|
304
|
-
this.
|
|
326
|
+
this.renderItem(container, nextItemIndex);
|
|
305
327
|
unchecked(this.poolItemIndexByRow[poolIndex] = nextItemIndex);
|
|
306
328
|
} else {
|
|
307
329
|
this.hidePoolItem(rowArea, poolIndex);
|
|
@@ -421,6 +443,10 @@ export class VirtualList extends FlexBox {
|
|
|
421
443
|
markNeedsCommit();
|
|
422
444
|
}
|
|
423
445
|
|
|
446
|
+
private renderItem(container: FlexBox, index: i32): void {
|
|
447
|
+
this.bindItemValue(container, index);
|
|
448
|
+
}
|
|
449
|
+
|
|
424
450
|
private maxOffsetForCurrentViewport(): f32 {
|
|
425
451
|
const viewportHeight = this.scrollStateValue.viewportHeight.value > 0.0
|
|
426
452
|
? this.scrollStateValue.viewportHeight.value
|