@effindomv2/fui-as 0.1.12 → 0.1.13
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/package.json +1 -1
- package/src/Fui.ts +4 -0
- package/src/controls/Checkbox.ts +29 -4
- package/src/controls/ControlSizing.ts +158 -0
- package/src/controls/Dropdown.ts +87 -20
- package/src/controls/RadioButton.ts +29 -4
- package/src/controls/Slider.ts +31 -5
- package/src/controls/index.ts +1 -0
- package/src/controls/internal/CheckboxIndicatorPresenter.ts +45 -8
- package/src/controls/internal/DropdownChevronPresenter.ts +32 -5
- package/src/controls/internal/DropdownFieldPresenter.ts +69 -8
- package/src/controls/internal/DropdownOptionRowPresenter.ts +38 -6
- package/src/controls/internal/PressableLabeledControl.ts +10 -1
- package/src/controls/internal/RadioIndicatorPresenter.ts +59 -13
- package/src/controls/internal/SliderPresenter.ts +62 -22
- package/src/controls/templating.ts +1 -0
package/package.json
CHANGED
package/src/Fui.ts
CHANGED
|
@@ -148,10 +148,12 @@ export {
|
|
|
148
148
|
ControlTemplateSet,
|
|
149
149
|
ContextMenu,
|
|
150
150
|
Dialog,
|
|
151
|
+
DropdownSizing,
|
|
151
152
|
DropdownChevronPresenter,
|
|
152
153
|
DropdownChevronTemplate,
|
|
153
154
|
DropdownChevronVisualState,
|
|
154
155
|
Dropdown,
|
|
156
|
+
DropdownFieldMetrics,
|
|
155
157
|
DropdownFieldPresenter,
|
|
156
158
|
DropdownFieldTemplate,
|
|
157
159
|
DropdownFieldVisualState,
|
|
@@ -164,6 +166,7 @@ export {
|
|
|
164
166
|
getControlTemplates,
|
|
165
167
|
MenuItem,
|
|
166
168
|
NavLink,
|
|
169
|
+
LabeledControlSizing,
|
|
167
170
|
PressableIndicatorMetrics,
|
|
168
171
|
ProgressBar,
|
|
169
172
|
RadioIndicatorPresenter,
|
|
@@ -173,6 +176,7 @@ export {
|
|
|
173
176
|
RadioGroup,
|
|
174
177
|
SelectionArea,
|
|
175
178
|
Slider,
|
|
179
|
+
SliderSizing,
|
|
176
180
|
SliderPresenter,
|
|
177
181
|
SliderPresenterMetrics,
|
|
178
182
|
SliderTemplate,
|
package/src/controls/Checkbox.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Callback1, Handler1 } from "../core/BoundCallback";
|
|
|
2
2
|
import { SemanticCheckedState, SemanticRole } from "../core/ffi";
|
|
3
3
|
import { PersistedInt32Codec, PersistedValueState } from "../core/PersistedState";
|
|
4
4
|
import { bind1 } from "../core/bind";
|
|
5
|
+
import { LabeledControlSizing } from "./ControlSizing";
|
|
5
6
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
6
7
|
import { activeTheme } from "../core/Theme";
|
|
7
8
|
import { PressableLabeledControl } from "./internal/PressableLabeledControl";
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
CheckboxIndicatorPresenter,
|
|
10
11
|
CheckboxIndicatorTemplate,
|
|
11
12
|
CheckboxIndicatorVisualState,
|
|
12
|
-
|
|
13
|
+
createDefaultCheckboxIndicatorPresenter,
|
|
13
14
|
} from "./internal/CheckboxIndicatorPresenter";
|
|
14
15
|
const CHECKBOX_PERSISTED_CODEC = new PersistedInt32Codec();
|
|
15
16
|
|
|
@@ -39,18 +40,21 @@ class PersistedCheckboxState extends PersistedValueState<Checkbox, i32> {
|
|
|
39
40
|
|
|
40
41
|
const CHECKBOX_PERSISTED_STATE = new PersistedCheckboxState();
|
|
41
42
|
|
|
42
|
-
function createIndicatorPresenter(template: CheckboxIndicatorTemplate | null): CheckboxIndicatorPresenter {
|
|
43
|
+
function createIndicatorPresenter(template: CheckboxIndicatorTemplate | null, sizing: LabeledControlSizing | null = null): CheckboxIndicatorPresenter {
|
|
43
44
|
if (template !== null) {
|
|
44
45
|
return template.create();
|
|
45
46
|
}
|
|
46
47
|
const templateSet = getControlTemplates();
|
|
47
48
|
const appTemplate = templateSet !== null ? templateSet.checkboxIndicator : null;
|
|
48
|
-
return
|
|
49
|
+
return appTemplate === null
|
|
50
|
+
? createDefaultCheckboxIndicatorPresenter(sizing)
|
|
51
|
+
: appTemplate.create();
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
export class Checkbox extends PressableLabeledControl {
|
|
52
55
|
private indicatorPresenter: CheckboxIndicatorPresenter;
|
|
53
56
|
private templateOverride: CheckboxIndicatorTemplate | null = null;
|
|
57
|
+
private sizingValue: LabeledControlSizing | null = null;
|
|
54
58
|
private checkedStateValue: SemanticCheckedState = SemanticCheckedState.False;
|
|
55
59
|
private triStateEnabled: bool = false;
|
|
56
60
|
private changedCallback: ((state: SemanticCheckedState) => void) | null = null;
|
|
@@ -94,9 +98,22 @@ export class Checkbox extends PressableLabeledControl {
|
|
|
94
98
|
return this;
|
|
95
99
|
}
|
|
96
100
|
|
|
101
|
+
sizing(sizing: LabeledControlSizing | null): this {
|
|
102
|
+
this.sizingValue = sizing;
|
|
103
|
+
this.setLabelFontSizeOverride(
|
|
104
|
+
sizing !== null && sizing.hasLabelFontSize ? sizing.labelFontSizePx : 0.0,
|
|
105
|
+
);
|
|
106
|
+
if (this.usesDefaultIndicatorPresenter()) {
|
|
107
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
108
|
+
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
109
|
+
this.syncVisualState();
|
|
110
|
+
}
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
97
114
|
template(template: CheckboxIndicatorTemplate | null): this {
|
|
98
115
|
this.templateOverride = template;
|
|
99
|
-
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride);
|
|
116
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
100
117
|
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
101
118
|
this.syncVisualState();
|
|
102
119
|
return this;
|
|
@@ -178,4 +195,12 @@ export class Checkbox extends PressableLabeledControl {
|
|
|
178
195
|
}
|
|
179
196
|
}
|
|
180
197
|
|
|
198
|
+
private usesDefaultIndicatorPresenter(): bool {
|
|
199
|
+
if (this.templateOverride !== null) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const templateSet = getControlTemplates();
|
|
203
|
+
return templateSet === null || templateSet.checkboxIndicator === null;
|
|
204
|
+
}
|
|
205
|
+
|
|
181
206
|
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { warn } from "../core/Logger";
|
|
2
|
+
|
|
3
|
+
function sanitizePositive(owner: string, property: string, value: f32): f32 {
|
|
4
|
+
if (value <= 0.0) {
|
|
5
|
+
warn("Layout", owner + "." + property + "() received " + value.toString() + "; ignoring.");
|
|
6
|
+
return 0.0;
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class LabeledControlSizing {
|
|
12
|
+
private indicatorSizeValue: f32 = 0.0;
|
|
13
|
+
private labelFontSizeValue: f32 = 0.0;
|
|
14
|
+
|
|
15
|
+
indicatorSize(value: f32): this {
|
|
16
|
+
this.indicatorSizeValue = sanitizePositive("LabeledControlSizing", "indicatorSize", value);
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
labelFontSize(value: f32): this {
|
|
21
|
+
this.labelFontSizeValue = sanitizePositive("LabeledControlSizing", "labelFontSize", value);
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get hasIndicatorSize(): bool {
|
|
26
|
+
return this.indicatorSizeValue > 0.0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get hasLabelFontSize(): bool {
|
|
30
|
+
return this.labelFontSizeValue > 0.0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get indicatorSizePx(): f32 {
|
|
34
|
+
return this.indicatorSizeValue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get labelFontSizePx(): f32 {
|
|
38
|
+
return this.labelFontSizeValue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class SliderSizing {
|
|
43
|
+
private thumbSizeValue: f32 = 0.0;
|
|
44
|
+
private trackThicknessValue: f32 = 0.0;
|
|
45
|
+
|
|
46
|
+
thumbSize(value: f32): this {
|
|
47
|
+
this.thumbSizeValue = sanitizePositive("SliderSizing", "thumbSize", value);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
trackThickness(value: f32): this {
|
|
52
|
+
this.trackThicknessValue = sanitizePositive("SliderSizing", "trackThickness", value);
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get hasThumbSize(): bool {
|
|
57
|
+
return this.thumbSizeValue > 0.0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get hasTrackThickness(): bool {
|
|
61
|
+
return this.trackThicknessValue > 0.0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get thumbSizePx(): f32 {
|
|
65
|
+
return this.thumbSizeValue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get trackThicknessPx(): f32 {
|
|
69
|
+
return this.trackThicknessValue;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class DropdownSizing {
|
|
74
|
+
private fieldFontSizeValue: f32 = 0.0;
|
|
75
|
+
private optionFontSizeValue: f32 = 0.0;
|
|
76
|
+
private fieldHeightValue: f32 = 0.0;
|
|
77
|
+
private optionHeightValue: f32 = 0.0;
|
|
78
|
+
private chevronBoxSizeValue: f32 = 0.0;
|
|
79
|
+
private chevronIconSizeValue: f32 = 0.0;
|
|
80
|
+
|
|
81
|
+
fieldFontSize(value: f32): this {
|
|
82
|
+
this.fieldFontSizeValue = sanitizePositive("DropdownSizing", "fieldFontSize", value);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
optionFontSize(value: f32): this {
|
|
87
|
+
this.optionFontSizeValue = sanitizePositive("DropdownSizing", "optionFontSize", value);
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fieldHeight(value: f32): this {
|
|
92
|
+
this.fieldHeightValue = sanitizePositive("DropdownSizing", "fieldHeight", value);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
optionHeight(value: f32): this {
|
|
97
|
+
this.optionHeightValue = sanitizePositive("DropdownSizing", "optionHeight", value);
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
chevronBoxSize(value: f32): this {
|
|
102
|
+
this.chevronBoxSizeValue = sanitizePositive("DropdownSizing", "chevronBoxSize", value);
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
chevronIconSize(value: f32): this {
|
|
107
|
+
this.chevronIconSizeValue = sanitizePositive("DropdownSizing", "chevronIconSize", value);
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get hasFieldFontSize(): bool {
|
|
112
|
+
return this.fieldFontSizeValue > 0.0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get hasOptionFontSize(): bool {
|
|
116
|
+
return this.optionFontSizeValue > 0.0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get hasFieldHeight(): bool {
|
|
120
|
+
return this.fieldHeightValue > 0.0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
get hasOptionHeight(): bool {
|
|
124
|
+
return this.optionHeightValue > 0.0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get hasChevronBoxSize(): bool {
|
|
128
|
+
return this.chevronBoxSizeValue > 0.0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get hasChevronIconSize(): bool {
|
|
132
|
+
return this.chevronIconSizeValue > 0.0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get fieldFontSizePx(): f32 {
|
|
136
|
+
return this.fieldFontSizeValue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
get optionFontSizePx(): f32 {
|
|
140
|
+
return this.optionFontSizeValue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get fieldHeightPx(): f32 {
|
|
144
|
+
return this.fieldHeightValue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get optionHeightPx(): f32 {
|
|
148
|
+
return this.optionHeightValue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get chevronBoxSizePx(): f32 {
|
|
152
|
+
return this.chevronBoxSizeValue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
get chevronIconSizePx(): f32 {
|
|
156
|
+
return this.chevronIconSizeValue;
|
|
157
|
+
}
|
|
158
|
+
}
|
package/src/controls/Dropdown.ts
CHANGED
|
@@ -22,21 +22,22 @@ import { PersistedInt32Codec, PersistedValueState } from "../core/PersistedState
|
|
|
22
22
|
import { registerScrollHook } from "../core/ScrollHooks";
|
|
23
23
|
import { FlexBox, Portal, ScrollBarVisibility, ScrollBox, ScrollView } from "../nodes";
|
|
24
24
|
import { bind2 } from "../core/bind";
|
|
25
|
+
import { DropdownSizing } from "./ControlSizing";
|
|
25
26
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
26
27
|
import {
|
|
27
|
-
|
|
28
|
+
createDefaultDropdownChevronPresenter,
|
|
28
29
|
DropdownChevronPresenter,
|
|
29
30
|
DropdownChevronTemplate,
|
|
30
31
|
DropdownChevronVisualState,
|
|
31
32
|
} from "./internal/DropdownChevronPresenter";
|
|
32
33
|
import {
|
|
33
|
-
|
|
34
|
+
createDefaultDropdownFieldPresenter,
|
|
34
35
|
DropdownFieldPresenter,
|
|
35
36
|
DropdownFieldTemplate,
|
|
36
37
|
DropdownFieldVisualState,
|
|
37
38
|
} from "./internal/DropdownFieldPresenter";
|
|
38
39
|
import {
|
|
39
|
-
|
|
40
|
+
createDefaultDropdownOptionRowPresenter,
|
|
40
41
|
DropdownOptionRowPresenter,
|
|
41
42
|
DropdownOptionRowTemplate,
|
|
42
43
|
DropdownOptionRowVisualState,
|
|
@@ -74,31 +75,37 @@ class PersistedDropdownState extends PersistedValueState<Dropdown, i32> {
|
|
|
74
75
|
|
|
75
76
|
const DROPDOWN_PERSISTED_STATE = new PersistedDropdownState();
|
|
76
77
|
|
|
77
|
-
function createFieldPresenter(template: DropdownFieldTemplate | null): DropdownFieldPresenter {
|
|
78
|
+
function createFieldPresenter(template: DropdownFieldTemplate | null, sizing: DropdownSizing | null = null): DropdownFieldPresenter {
|
|
78
79
|
if (template !== null) {
|
|
79
80
|
return template.create();
|
|
80
81
|
}
|
|
81
82
|
const templateSet = getControlTemplates();
|
|
82
83
|
const appTemplate = templateSet !== null ? templateSet.dropdownField : null;
|
|
83
|
-
return
|
|
84
|
+
return appTemplate === null
|
|
85
|
+
? createDefaultDropdownFieldPresenter(sizing)
|
|
86
|
+
: appTemplate.create();
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
function createChevronPresenter(template: DropdownChevronTemplate | null): DropdownChevronPresenter {
|
|
89
|
+
function createChevronPresenter(template: DropdownChevronTemplate | null, sizing: DropdownSizing | null = null): DropdownChevronPresenter {
|
|
87
90
|
if (template !== null) {
|
|
88
91
|
return template.create();
|
|
89
92
|
}
|
|
90
93
|
const templateSet = getControlTemplates();
|
|
91
94
|
const appTemplate = templateSet !== null ? templateSet.dropdownChevron : null;
|
|
92
|
-
return
|
|
95
|
+
return appTemplate === null
|
|
96
|
+
? createDefaultDropdownChevronPresenter(sizing)
|
|
97
|
+
: appTemplate.create();
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
function createOptionRowPresenter(template: DropdownOptionRowTemplate | null): DropdownOptionRowPresenter {
|
|
100
|
+
function createOptionRowPresenter(template: DropdownOptionRowTemplate | null, sizing: DropdownSizing | null = null): DropdownOptionRowPresenter {
|
|
96
101
|
if (template !== null) {
|
|
97
102
|
return template.create();
|
|
98
103
|
}
|
|
99
104
|
const templateSet = getControlTemplates();
|
|
100
105
|
const appTemplate = templateSet !== null ? templateSet.dropdownOptionRow : null;
|
|
101
|
-
return
|
|
106
|
+
return appTemplate === null
|
|
107
|
+
? createDefaultDropdownOptionRowPresenter(sizing)
|
|
108
|
+
: appTemplate.create();
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
export class DropdownItem {
|
|
@@ -111,9 +118,9 @@ class DropdownOptionNode extends FlexBox {
|
|
|
111
118
|
private slotIndex: i32 = -1;
|
|
112
119
|
private currentLabel: string = "";
|
|
113
120
|
|
|
114
|
-
constructor(template: DropdownOptionRowTemplate | null) {
|
|
121
|
+
constructor(template: DropdownOptionRowTemplate | null, sizing: DropdownSizing | null) {
|
|
115
122
|
super();
|
|
116
|
-
this.presenter = createOptionRowPresenter(template);
|
|
123
|
+
this.presenter = createOptionRowPresenter(template, sizing);
|
|
117
124
|
this.semanticRole(SemanticRole.ListItem);
|
|
118
125
|
this.width(100.0, Unit.Percent);
|
|
119
126
|
this.cursor(CursorStyle.Pointer);
|
|
@@ -136,9 +143,9 @@ class DropdownOptionNode extends FlexBox {
|
|
|
136
143
|
return this;
|
|
137
144
|
}
|
|
138
145
|
|
|
139
|
-
template(template: DropdownOptionRowTemplate | null): void {
|
|
146
|
+
template(template: DropdownOptionRowTemplate | null, sizing: DropdownSizing | null): void {
|
|
140
147
|
const previousPresenter = this.presenter;
|
|
141
|
-
const nextPresenter = createOptionRowPresenter(template);
|
|
148
|
+
const nextPresenter = createOptionRowPresenter(template, sizing);
|
|
142
149
|
this.presenter = nextPresenter;
|
|
143
150
|
this.removeChildNode(previousPresenter.root);
|
|
144
151
|
this.addChildNode(nextPresenter.root);
|
|
@@ -185,6 +192,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
185
192
|
private fieldTemplateValue: DropdownFieldTemplate | null = null;
|
|
186
193
|
private chevronTemplateValue: DropdownChevronTemplate | null = null;
|
|
187
194
|
private optionRowTemplateValue: DropdownOptionRowTemplate | null = null;
|
|
195
|
+
private sizingValue: DropdownSizing | null = null;
|
|
188
196
|
private fieldPresenter: DropdownFieldPresenter;
|
|
189
197
|
private chevronPresenter: DropdownChevronPresenter;
|
|
190
198
|
private readonly popupRoot: Portal;
|
|
@@ -215,8 +223,8 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
215
223
|
constructor() {
|
|
216
224
|
super();
|
|
217
225
|
Dropdown.ensureScrollHook();
|
|
218
|
-
const fieldPresenter = createFieldPresenter(null);
|
|
219
|
-
const chevronPresenter = createChevronPresenter(null);
|
|
226
|
+
const fieldPresenter = createFieldPresenter(null, null);
|
|
227
|
+
const chevronPresenter = createChevronPresenter(null, null);
|
|
220
228
|
const popupRoot = new Portal()
|
|
221
229
|
.positionAbsolute()
|
|
222
230
|
.position(0.0, 0.0)
|
|
@@ -340,11 +348,38 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
340
348
|
return this;
|
|
341
349
|
}
|
|
342
350
|
|
|
351
|
+
sizing(sizing: DropdownSizing | null): this {
|
|
352
|
+
this.close();
|
|
353
|
+
this.sizingValue = sizing;
|
|
354
|
+
if (this.usesDefaultFieldPresenter()) {
|
|
355
|
+
this.replaceFieldPresenter(
|
|
356
|
+
createFieldPresenter(this.fieldTemplateValue, this.sizingValue),
|
|
357
|
+
createChevronPresenter(this.chevronTemplateValue, this.sizingValue),
|
|
358
|
+
);
|
|
359
|
+
} else if (this.usesDefaultChevronPresenter()) {
|
|
360
|
+
const previousPresenter = this.chevronPresenter;
|
|
361
|
+
const nextPresenter = createChevronPresenter(this.chevronTemplateValue, this.sizingValue);
|
|
362
|
+
this.chevronPresenter = nextPresenter;
|
|
363
|
+
this.fieldPresenter.chevronHost.removeChildNode(previousPresenter.root);
|
|
364
|
+
this.fieldPresenter.chevronHost.addChildNode(nextPresenter.root);
|
|
365
|
+
previousPresenter.root.dispose();
|
|
366
|
+
}
|
|
367
|
+
if (this.usesDefaultOptionRowPresenter()) {
|
|
368
|
+
for (let index = 0; index < this.optionNodes.length; ++index) {
|
|
369
|
+
unchecked(this.optionNodes[index]).template(this.optionRowTemplateValue, this.sizingValue);
|
|
370
|
+
}
|
|
371
|
+
this.refreshPanelLayout();
|
|
372
|
+
}
|
|
373
|
+
this.syncValueLabel();
|
|
374
|
+
this.handleThemeChanged();
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
343
378
|
fieldTemplate(template: DropdownFieldTemplate | null): this {
|
|
344
379
|
this.close();
|
|
345
380
|
this.fieldTemplateValue = template;
|
|
346
|
-
const nextFieldPresenter = createFieldPresenter(template);
|
|
347
|
-
const nextChevronPresenter = createChevronPresenter(this.chevronTemplateValue);
|
|
381
|
+
const nextFieldPresenter = createFieldPresenter(template, this.sizingValue);
|
|
382
|
+
const nextChevronPresenter = createChevronPresenter(this.chevronTemplateValue, this.sizingValue);
|
|
348
383
|
this.replaceFieldPresenter(nextFieldPresenter, nextChevronPresenter);
|
|
349
384
|
this.syncValueLabel();
|
|
350
385
|
this.handleThemeChanged();
|
|
@@ -355,7 +390,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
355
390
|
this.close();
|
|
356
391
|
this.chevronTemplateValue = template;
|
|
357
392
|
const previousPresenter = this.chevronPresenter;
|
|
358
|
-
const nextPresenter = createChevronPresenter(template);
|
|
393
|
+
const nextPresenter = createChevronPresenter(template, this.sizingValue);
|
|
359
394
|
this.chevronPresenter = nextPresenter;
|
|
360
395
|
this.fieldPresenter.chevronHost.removeChildNode(previousPresenter.root);
|
|
361
396
|
this.fieldPresenter.chevronHost.addChildNode(nextPresenter.root);
|
|
@@ -368,7 +403,7 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
368
403
|
this.close();
|
|
369
404
|
this.optionRowTemplateValue = template;
|
|
370
405
|
for (let index = 0; index < this.optionNodes.length; ++index) {
|
|
371
|
-
unchecked(this.optionNodes[index]).template(template);
|
|
406
|
+
unchecked(this.optionNodes[index]).template(template, this.sizingValue);
|
|
372
407
|
}
|
|
373
408
|
this.refreshPanelLayout();
|
|
374
409
|
this.syncOptionVisuals();
|
|
@@ -763,13 +798,21 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
763
798
|
|
|
764
799
|
private ensureOptionNodes(): void {
|
|
765
800
|
while (this.optionNodes.length < this.itemsValue.length) {
|
|
766
|
-
const optionNode = new DropdownOptionNode(this.optionRowTemplateValue).bindOwner(this, this.optionNodes.length);
|
|
801
|
+
const optionNode = new DropdownOptionNode(this.optionRowTemplateValue, this.sizingValue).bindOwner(this, this.optionNodes.length);
|
|
767
802
|
this.optionNodes.push(optionNode);
|
|
768
803
|
}
|
|
769
804
|
}
|
|
770
805
|
|
|
771
806
|
private resolveOptionRowHeight(): f32 {
|
|
772
807
|
if (this.optionNodes.length == 0) {
|
|
808
|
+
const sizing = this.sizingValue;
|
|
809
|
+
if (
|
|
810
|
+
sizing !== null &&
|
|
811
|
+
sizing.hasOptionHeight &&
|
|
812
|
+
this.usesDefaultOptionRowPresenter()
|
|
813
|
+
) {
|
|
814
|
+
return sizing.optionHeightPx;
|
|
815
|
+
}
|
|
773
816
|
return OPTION_HEIGHT;
|
|
774
817
|
}
|
|
775
818
|
return unchecked(this.optionNodes[0]).rowHeight;
|
|
@@ -922,4 +965,28 @@ export class Dropdown extends FlexBox implements GlobalKeyHandler {
|
|
|
922
965
|
this.replaceChildren(children);
|
|
923
966
|
previousFieldRoot.dispose();
|
|
924
967
|
}
|
|
968
|
+
|
|
969
|
+
private usesDefaultFieldPresenter(): bool {
|
|
970
|
+
if (this.fieldTemplateValue !== null) {
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
const templateSet = getControlTemplates();
|
|
974
|
+
return templateSet === null || templateSet.dropdownField === null;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
private usesDefaultChevronPresenter(): bool {
|
|
978
|
+
if (this.chevronTemplateValue !== null) {
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
981
|
+
const templateSet = getControlTemplates();
|
|
982
|
+
return templateSet === null || templateSet.dropdownChevron === null;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
private usesDefaultOptionRowPresenter(): bool {
|
|
986
|
+
if (this.optionRowTemplateValue !== null) {
|
|
987
|
+
return false;
|
|
988
|
+
}
|
|
989
|
+
const templateSet = getControlTemplates();
|
|
990
|
+
return templateSet === null || templateSet.dropdownOptionRow === null;
|
|
991
|
+
}
|
|
925
992
|
}
|
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import { KeyEventType, SemanticCheckedState, SemanticRole } from "../core/ffi";
|
|
2
2
|
import { activeTheme } from "../core/Theme";
|
|
3
|
+
import { LabeledControlSizing } from "./ControlSizing";
|
|
3
4
|
import { PressableLabeledControl } from "./internal/PressableLabeledControl";
|
|
4
5
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
5
6
|
import { RadioGroup } from "./RadioGroup";
|
|
6
7
|
import {
|
|
7
|
-
|
|
8
|
+
createDefaultRadioIndicatorPresenter,
|
|
8
9
|
RadioIndicatorPresenter,
|
|
9
10
|
RadioIndicatorTemplate,
|
|
10
11
|
RadioIndicatorVisualState,
|
|
11
12
|
} from "./internal/RadioIndicatorPresenter";
|
|
12
13
|
|
|
13
|
-
function createIndicatorPresenter(template: RadioIndicatorTemplate | null): RadioIndicatorPresenter {
|
|
14
|
+
function createIndicatorPresenter(template: RadioIndicatorTemplate | null, sizing: LabeledControlSizing | null = null): RadioIndicatorPresenter {
|
|
14
15
|
if (template !== null) {
|
|
15
16
|
return template.create();
|
|
16
17
|
}
|
|
17
18
|
const templateSet = getControlTemplates();
|
|
18
19
|
const appTemplate = templateSet !== null ? templateSet.radioIndicator : null;
|
|
19
|
-
return
|
|
20
|
+
return appTemplate === null
|
|
21
|
+
? createDefaultRadioIndicatorPresenter(sizing)
|
|
22
|
+
: appTemplate.create();
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export class RadioButton extends PressableLabeledControl {
|
|
23
26
|
private indicatorPresenter: RadioIndicatorPresenter;
|
|
24
27
|
private templateOverride: RadioIndicatorTemplate | null = null;
|
|
28
|
+
private sizingValue: LabeledControlSizing | null = null;
|
|
25
29
|
private readonly valueText: string;
|
|
26
30
|
private checkedValue: bool = false;
|
|
27
31
|
private changedCallback: ((checked: bool) => void) | null = null;
|
|
@@ -54,9 +58,22 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
54
58
|
return this;
|
|
55
59
|
}
|
|
56
60
|
|
|
61
|
+
sizing(sizing: LabeledControlSizing | null): this {
|
|
62
|
+
this.sizingValue = sizing;
|
|
63
|
+
this.setLabelFontSizeOverride(
|
|
64
|
+
sizing !== null && sizing.hasLabelFontSize ? sizing.labelFontSizePx : 0.0,
|
|
65
|
+
);
|
|
66
|
+
if (this.usesDefaultIndicatorPresenter()) {
|
|
67
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
68
|
+
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
69
|
+
this.syncVisualState();
|
|
70
|
+
}
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
template(template: RadioIndicatorTemplate | null): this {
|
|
58
75
|
this.templateOverride = template;
|
|
59
|
-
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride);
|
|
76
|
+
this.indicatorPresenter = createIndicatorPresenter(this.templateOverride, this.sizingValue);
|
|
60
77
|
this.replaceIndicatorRoot(this.indicatorPresenter.root);
|
|
61
78
|
this.syncVisualState();
|
|
62
79
|
return this;
|
|
@@ -132,4 +149,12 @@ export class RadioButton extends PressableLabeledControl {
|
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
}
|
|
152
|
+
|
|
153
|
+
private usesDefaultIndicatorPresenter(): bool {
|
|
154
|
+
if (this.templateOverride !== null) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
const templateSet = getControlTemplates();
|
|
158
|
+
return templateSet === null || templateSet.radioIndicator === null;
|
|
159
|
+
}
|
|
135
160
|
}
|
package/src/controls/Slider.ts
CHANGED
|
@@ -20,9 +20,10 @@ import { PersistedFloat32Codec, PersistedValueState } from "../core/PersistedSta
|
|
|
20
20
|
import { Node } from "../core/Node";
|
|
21
21
|
import { FlexBox } from "../nodes";
|
|
22
22
|
import { bind1 } from "../core/bind";
|
|
23
|
+
import { SliderSizing } from "./ControlSizing";
|
|
23
24
|
import { getControlTemplates } from "./ControlTemplateSet";
|
|
24
25
|
import {
|
|
25
|
-
|
|
26
|
+
createDefaultSliderPresenter,
|
|
26
27
|
SliderPresenter,
|
|
27
28
|
SliderTemplate,
|
|
28
29
|
SliderVisualState,
|
|
@@ -63,18 +64,21 @@ const SLIDER_CONTENT_INSET: f32 = 1.0;
|
|
|
63
64
|
const SLIDER_OUTER_INSET: f32 = SLIDER_CHROME_INSET + SLIDER_CONTENT_INSET;
|
|
64
65
|
const SLIDER_CHILD_INSET: f32 = SLIDER_PADDING + SLIDER_CONTENT_INSET;
|
|
65
66
|
|
|
66
|
-
function createSliderPresenter(template: SliderTemplate | null): SliderPresenter {
|
|
67
|
+
function createSliderPresenter(template: SliderTemplate | null, sizing: SliderSizing | null = null): SliderPresenter {
|
|
67
68
|
if (template !== null) {
|
|
68
69
|
return template.create();
|
|
69
70
|
}
|
|
70
71
|
const templateSet = getControlTemplates();
|
|
71
72
|
const appTemplate = templateSet !== null ? templateSet.slider : null;
|
|
72
|
-
return
|
|
73
|
+
return appTemplate === null
|
|
74
|
+
? createDefaultSliderPresenter(sizing)
|
|
75
|
+
: appTemplate.create();
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
export class Slider extends FlexBox implements DragGestureHost {
|
|
76
|
-
private sliderPresenter: SliderPresenter = createSliderPresenter(null);
|
|
79
|
+
private sliderPresenter: SliderPresenter = createSliderPresenter(null, null);
|
|
77
80
|
private templateOverride: SliderTemplate | null = null;
|
|
81
|
+
private sizingValue: SliderSizing | null = null;
|
|
78
82
|
private readonly disposables: Array<Disposable> = new Array<Disposable>();
|
|
79
83
|
private readonly dragGesture!: DragGesture;
|
|
80
84
|
private changedCallback: ((value: f32) => void) | null = null;
|
|
@@ -172,9 +176,23 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
172
176
|
return this;
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
sizing(sizing: SliderSizing | null): this {
|
|
180
|
+
this.sizingValue = sizing;
|
|
181
|
+
if (!this.usesDefaultPresenter()) {
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
this.replacePresenter(createSliderPresenter(this.templateOverride, this.sizingValue));
|
|
185
|
+
const thumbSize = this.sliderPresenter.metrics.thumbSize;
|
|
186
|
+
if (this.lengthValue <= thumbSize) {
|
|
187
|
+
this.lengthValue = thumbSize + 1.0;
|
|
188
|
+
}
|
|
189
|
+
this.syncPresentation();
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
|
|
175
193
|
template(template: SliderTemplate | null): this {
|
|
176
194
|
this.templateOverride = template;
|
|
177
|
-
const nextPresenter = createSliderPresenter(this.templateOverride);
|
|
195
|
+
const nextPresenter = createSliderPresenter(this.templateOverride, this.sizingValue);
|
|
178
196
|
this.replacePresenter(nextPresenter);
|
|
179
197
|
const thumbSize = this.sliderPresenter.metrics.thumbSize;
|
|
180
198
|
if (this.lengthValue <= thumbSize) {
|
|
@@ -447,6 +465,14 @@ export class Slider extends FlexBox implements DragGestureHost {
|
|
|
447
465
|
previousRoot.dispose();
|
|
448
466
|
}
|
|
449
467
|
|
|
468
|
+
private usesDefaultPresenter(): bool {
|
|
469
|
+
if (this.templateOverride !== null) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
const templateSet = getControlTemplates();
|
|
473
|
+
return templateSet === null || templateSet.slider === null;
|
|
474
|
+
}
|
|
475
|
+
|
|
450
476
|
private track(disposable: Disposable): void {
|
|
451
477
|
this.disposables.push(disposable);
|
|
452
478
|
}
|
package/src/controls/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Button } from "./Button";
|
|
2
2
|
export { Checkbox } from "./Checkbox";
|
|
3
|
+
export { DropdownSizing, LabeledControlSizing, SliderSizing } from "./ControlSizing";
|
|
3
4
|
export { ContextMenu, MenuItem } from "./ContextMenu";
|
|
4
5
|
export { Dialog } from "./Dialog";
|
|
5
6
|
export { Dropdown, DropdownItem } from "./Dropdown";
|