mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-29 13:24:48 +00:00

Don't make our widgets inherit element that we didn't want to expose in the API The other styles will be synchronized with later
677 lines
22 KiB
Text
677 lines
22 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
|
|
|
// cSpell: ignore combobox spinbox standardbutton
|
|
|
|
import { LineEditInner, TextEdit, AboutSlint } from "../common/common.slint";
|
|
import { StandardButton } from "../common/standardbutton.slint";
|
|
import { StyleMetrics, ScrollView, Button, Palette } from "std-widgets-impl.slint";
|
|
export { StyleMetrics, ScrollView, Button, StandardButton, TextEdit, AboutSlint }
|
|
export * from "widget-table-view.slint";
|
|
|
|
export component CheckBox {
|
|
callback toggled;
|
|
in property <string> text <=> text.text;
|
|
in-out property <bool> checked;
|
|
out property <bool> has-focus: fs.has-focus;
|
|
in property<bool> enabled: true;
|
|
min-height: 20px;
|
|
horizontal-stretch: 0;
|
|
vertical-stretch: 0;
|
|
|
|
accessible-label <=> text.text;
|
|
accessible-checkable: true;
|
|
accessible-checked <=> root.checked;
|
|
accessible-role: checkbox;
|
|
|
|
HorizontalLayout {
|
|
spacing: 8px;
|
|
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
border-width: 1px;
|
|
border-radius: 2px;
|
|
/* border-color: !enabled ? Palette.neutralLighter : Palette.neutralSecondaryAlt;
|
|
background: !enabled ? Palette.white
|
|
: touch.pressed ? Palette.neutralLight
|
|
: touch.has-hover ? Palette.neutralLighter
|
|
: Palette.themePrimary;*/
|
|
|
|
border-color: root.checked ? self.background : !root.enabled ? Palette.neutralTertiaryAlt : Palette.neutralSecondaryAlt;
|
|
background: !root.checked ? Palette.white
|
|
: !root.enabled ? Palette.neutralTertiaryAlt
|
|
: touch.has-hover || touch.pressed ? Palette.themeDark
|
|
: Palette.themePrimary;
|
|
animate background { duration: 250ms; easing: ease; }
|
|
|
|
//width: height;
|
|
vertical-stretch: 0;
|
|
width: 20px;
|
|
height: 20px;
|
|
|
|
if (root.checked || touch.has-hover || touch.pressed) : Path {
|
|
width: 66%;
|
|
height: 66%;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
commands: "M.22.5.42.7.78.34.74.3.42.62.26.54z";
|
|
fill: root.checked ? Palette.white : Palette.neutralSecondaryAlt;
|
|
}
|
|
}
|
|
}
|
|
|
|
text := Text {
|
|
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
|
|
horizontal-alignment: left;
|
|
vertical-alignment: center;
|
|
vertical-stretch: 1;
|
|
}
|
|
|
|
}
|
|
|
|
touch := TouchArea {
|
|
enabled <=> root.enabled;
|
|
clicked => {
|
|
if (root.enabled) {
|
|
root.checked = !root.checked;
|
|
root.toggled();
|
|
}
|
|
}
|
|
}
|
|
|
|
fs := FocusScope {
|
|
x:0;
|
|
width: 0px; // Do not react on clicks
|
|
enabled <=> root.enabled;
|
|
|
|
key-pressed(event) => {
|
|
if (event.text == " " || event.text == "\n") {
|
|
touch.clicked();
|
|
return accept;
|
|
}
|
|
return reject;
|
|
}
|
|
}
|
|
|
|
Rectangle { // Focus rectangle
|
|
x: -3px;
|
|
y: self.x;
|
|
width: parent.width - 2*self.x;
|
|
height: parent.height - 2*self.y;
|
|
border-width: root.enabled && root.has-focus ? 1px : 0px;
|
|
border-color: Palette.black;
|
|
}
|
|
}
|
|
|
|
component SpinBoxButton inherits Rectangle {
|
|
callback clicked <=> touch.clicked;
|
|
in-out property<bool> enabled <=> touch.enabled;
|
|
background: !root.enabled ? transparent
|
|
: touch.pressed ? Palette.neutralLight
|
|
: touch.has-hover ? Palette.neutralLighter
|
|
: Palette.white;
|
|
|
|
in-out property <color> symbol-color: !root.enabled ? Palette.neutralTertiary
|
|
: touch.pressed || touch.has-hover ? Palette.neutralPrimary
|
|
: Palette.neutralSecondary;
|
|
touch := TouchArea { }
|
|
}
|
|
|
|
export component SpinBox {
|
|
in-out property <int> value;
|
|
in property <int> minimum;
|
|
in property <int> maximum: 100;
|
|
in property <bool> enabled <=> fs.enabled;
|
|
out property <bool> has-focus <=> fs.has-focus;
|
|
forward-focus: fs;
|
|
|
|
min-height: max(32px, l.min-height);
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 0;
|
|
|
|
accessible-role: spinbox;
|
|
accessible-value: root.value;
|
|
accessible-value-minimum: root.minimum;
|
|
accessible-value-maximum: root.maximum;
|
|
accessible-value-step: (root.maximum - root.minimum) / 100;
|
|
|
|
fs := FocusScope {
|
|
|
|
Rectangle {
|
|
background: !root.enabled ? Palette.neutralLighter : Palette.white;
|
|
}
|
|
|
|
l := GridLayout {
|
|
padding-left: 8px;
|
|
padding-top: 3px;
|
|
padding-bottom: 3px;
|
|
text := Text {
|
|
rowspan: 2;
|
|
text: root.value;
|
|
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
|
|
horizontal-alignment: left;
|
|
vertical-alignment: center;
|
|
}
|
|
Rectangle { width: 8px; }
|
|
button := SpinBoxButton {
|
|
width: 25px;
|
|
enabled: root.enabled;
|
|
Path {
|
|
commands: "M978.2,688.9l-84.2,82.1c-15.7,15.3-41.1,15.3-56.7,0l-341-304.2L162.6,764.5c-15.5,15.1-41,15.1-56.6,0l-84.3-82.1c-15.6-15.2-15.6-39.9,0-55.2l446.6-398.2c15.7-15.3,41-15.3,56.7,0l6.9,6.7l446.3,398.1C993.9,649,993.9,673.7,978.2,688.9z";
|
|
fill: parent.symbol-color;
|
|
height: 33%;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
}
|
|
clicked => {
|
|
if (root.value < root.maximum) {
|
|
root.value += 1;
|
|
}
|
|
root.focus();
|
|
}
|
|
}
|
|
SpinBoxButton {
|
|
row: 1; col: 2;
|
|
enabled: root.enabled;
|
|
Path {
|
|
commands: "M21.8,311.1l84.2-82.1c15.7-15.2,41-15.2,56.7,0l341.1,304.1l333.7-297.5c15.5-15.2,41-15.2,56.6,0l84.3,82.1c15.6,15.2,15.6,40,0,55.2L531.7,771c-15.7,15.3-41,15.3-56.7,0l-6.9-6.7L21.8,366.3C6.1,351,6.1,326.3,21.8,311.1z";
|
|
fill: parent.symbol-color;
|
|
height: 33%;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
}
|
|
clicked => {
|
|
if (root.value > root.minimum) {
|
|
root.value -= 1;
|
|
}
|
|
root.focus();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Rectangle {
|
|
x: root.enabled && root.has-focus ? -2px : 0px;
|
|
y: self.x;
|
|
width: parent.width - 2*self.x;
|
|
height: parent.height - 2*self.y;
|
|
border-radius: 2px;
|
|
border-width: !root.enabled ? 0px : root.has-focus ? 3px : 1px;
|
|
border-color: !root.enabled ? Palette.neutralLighter
|
|
: root.has-focus ? Palette.themeSecondary
|
|
: Palette.neutralDark;
|
|
}
|
|
|
|
key-pressed(event) => {
|
|
if (root.enabled && event.text == Key.UpArrow && root.value < root.maximum) {
|
|
root.value += 1;
|
|
accept
|
|
} else if (root.enabled && event.text == Key.DownArrow && root.value > root.minimum) {
|
|
root.value -= 1;
|
|
accept
|
|
} else {
|
|
reject
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component Slider {
|
|
in property<float> maximum: 100;
|
|
in property<float> minimum: 0;
|
|
in-out property<float> value;
|
|
out property<bool> has-focus: fs.has-focus;
|
|
in property<bool> enabled <=> touch.enabled;
|
|
callback changed(float);
|
|
|
|
min-height: 24px;
|
|
min-width: 100px;
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 0;
|
|
|
|
accessible-role: slider;
|
|
accessible-value: root.value;
|
|
accessible-value-minimum: root.minimum;
|
|
accessible-value-maximum: root.maximum;
|
|
accessible-value-step: (root.maximum - root.minimum) / 100;
|
|
|
|
|
|
Rectangle {
|
|
width: parent.width - parent.min-height;
|
|
x: parent.height / 2;
|
|
height: parent.min-height / 4;
|
|
y: (parent.height - self.height) / 2;
|
|
border-radius: self.height/2;
|
|
background: !root.enabled ? Palette.neutralLighter
|
|
: touch.has-hover ? Palette.themeLight
|
|
: Palette.neutralTertiaryAlt;
|
|
}
|
|
|
|
Rectangle {
|
|
width: (parent.width - parent.min-height) * ((root.value - root.minimum) / (root.maximum - root.minimum));
|
|
x: parent.height / 2;
|
|
height: parent.min-height / 4;
|
|
y: (parent.height - self.height) / 2;
|
|
border-radius: self.height/2;
|
|
background: !root.enabled ? Palette.neutralTertiary
|
|
: touch.has-hover ? Palette.themeSecondary
|
|
: Palette.neutralSecondary;
|
|
}
|
|
|
|
handle := Rectangle {
|
|
property<length> border: 3px;
|
|
width: self.height;
|
|
height: parent.height - 2 * self.border;
|
|
border-width: 3px;
|
|
border-radius: self.height / 2;
|
|
border-color: !root.enabled ? Palette.neutralTertiaryAlt
|
|
: touch.has-hover ? Palette.themePrimary
|
|
: Palette.neutralSecondary;
|
|
background: Palette.white;
|
|
x: (root.width - handle.width) * (root.value - root.minimum)/(root.maximum - root.minimum);
|
|
y: self.border;
|
|
}
|
|
touch := TouchArea {
|
|
width: parent.width;
|
|
height: parent.height;
|
|
property <float> pressed-value;
|
|
pointer-event(event) => {
|
|
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
|
|
self.pressed-value = root.value;
|
|
}
|
|
}
|
|
moved => {
|
|
if (self.enabled && self.pressed) {
|
|
root.value = max(root.minimum, min(root.maximum,
|
|
self.pressed-value + (touch.mouse-x - touch.pressed-x) * (root.maximum - root.minimum) / (root.width - handle.width)));
|
|
root.changed(root.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
fs := FocusScope {
|
|
x:0;
|
|
width: 0px;
|
|
|
|
key-pressed(event) => {
|
|
if (self.enabled && event.text == Key.RightArrow) {
|
|
root.value = Math.min(root.value + 1, root.maximum);
|
|
accept
|
|
} else if (self.enabled && event.text == Key.LeftArrow) {
|
|
root.value = Math.max(root.value - 1, root.minimum);
|
|
accept
|
|
} else {
|
|
reject
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle { // Focus rectangle
|
|
border-width: root.enabled && root.has-focus ? 1px : 0px;
|
|
border-color: Palette.black;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export component GroupBox {
|
|
in property <string> title <=> label.text;
|
|
in property<bool> enabled: true;
|
|
VerticalLayout {
|
|
spacing: 8px;
|
|
padding-top: 16px;
|
|
padding-bottom: 8px;
|
|
|
|
label := Text {
|
|
vertical-stretch: 0;
|
|
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
|
|
font-weight: 600;
|
|
}
|
|
Rectangle {
|
|
vertical-stretch: 1;
|
|
GridLayout {
|
|
@children
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component TabWidgetImpl {
|
|
out property <length> content-x: 0;
|
|
out property <length> content-y: root.tabbar-preferred-height;
|
|
out property <length> content-height: root.height - root.tabbar-preferred-height;
|
|
out property <length> content-width: root.width;
|
|
out property <length> tabbar-x: 0;
|
|
out property <length> tabbar-y: 0;
|
|
out property <length> tabbar-height: root.tabbar-preferred-height;
|
|
out property <length> tabbar-width: root.width;
|
|
|
|
in property <length> tabbar-preferred-height;
|
|
in property <length> tabbar-preferred-width;
|
|
in property <length> content-min-height;
|
|
in property <length> content-min-width;
|
|
in property <int> current-index;
|
|
in property <int> current-focused;
|
|
|
|
preferred-width: root.content-min-width;
|
|
min-width: max(root.content-min-width, root.tabbar-preferred-width);
|
|
preferred-height: root.content-min-height + root.tabbar-preferred-height;
|
|
min-height: root.content-min-height + root.tabbar-preferred-height;
|
|
}
|
|
|
|
export component TabImpl inherits Rectangle {
|
|
in property<string> title <=> t.text;
|
|
in property<bool> enabled: true;
|
|
property<bool> has-focus: root.current-focused == root.tab-index;
|
|
in-out property<int> current; // The currently selected tab
|
|
in property<int> current-focused; // The currently focused tab
|
|
in property<int> tab-index; // The index of this tab
|
|
in property<int> num-tabs; // The total number of tabs
|
|
|
|
min-height: t.preferred-height + 16px;
|
|
preferred-width: t.preferred-width + 16px;
|
|
|
|
background: !root.enabled ? Palette.neutralLighter
|
|
: touch.pressed ? Palette.neutralLight
|
|
: touch.has-hover ? Palette.neutralLighter
|
|
: Palette.white;
|
|
horizontal-stretch: 0;
|
|
vertical-stretch: 0;
|
|
|
|
accessible-role: tab;
|
|
accessible-label: root.title;
|
|
|
|
touch := TouchArea {
|
|
enabled <=> root.enabled;
|
|
clicked => {
|
|
root.current = root.tab-index;
|
|
}
|
|
}
|
|
t := Text {
|
|
width: parent.width;
|
|
height: parent.height;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: center;
|
|
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralPrimary;
|
|
font-weight: root.current == root.tab-index ? 600 : 500;
|
|
}
|
|
|
|
Rectangle {
|
|
height: 3px;
|
|
width: touch.has-hover && root.current == root.tab-index ? parent.width : parent.width - 16px;
|
|
animate width { duration: 250ms; easing: ease-out; }
|
|
background: root.current == root.tab-index ? Palette.themeSecondary : transparent;
|
|
y: parent.height - self.height;
|
|
x: (parent.width - self.width) / 2;
|
|
}
|
|
|
|
Rectangle { // Focus Rectangle
|
|
border-width: root.enabled && root.has-focus ? 1px : 0px;
|
|
border-color: Palette.black;
|
|
}
|
|
}
|
|
|
|
export component TabBarImpl {
|
|
// injected properties:
|
|
in-out property<int> current; // The currently selected tab
|
|
in-out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
|
|
in-out property<int> num-tabs; // The total number of tabs
|
|
|
|
HorizontalLayout {
|
|
spacing: 8px;
|
|
alignment: start;
|
|
@children
|
|
}
|
|
|
|
accessible-role: tab;
|
|
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current;
|
|
|
|
fs := FocusScope {
|
|
x:0;
|
|
width: 0px; // Do not react on clicks
|
|
property<int> focused-tab: 0;
|
|
|
|
key-pressed(event) => {
|
|
if (event.text == "\n") {
|
|
root.current = root.current-focused;
|
|
return accept;
|
|
}
|
|
if (event.text == Key.LeftArrow) {
|
|
self.focused-tab = Math.max(self.focused-tab - 1, 0);
|
|
return accept;
|
|
}
|
|
if (event.text == Key.RightArrow) {
|
|
self.focused-tab = Math.min(self.focused-tab + 1, root.num-tabs - 1);
|
|
return accept;
|
|
}
|
|
return reject;
|
|
}
|
|
|
|
key-released(event) => {
|
|
if (event.text == " ") {
|
|
root.current = root.current-focused;
|
|
return accept;
|
|
}
|
|
return reject;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component TabWidget inherits TabWidget {}
|
|
|
|
export component LineEdit {
|
|
in property <length> font-size <=> inner.font-size;
|
|
in-out property <string> text <=> inner.text;
|
|
in property <string> placeholder-text <=> inner.placeholder-text;
|
|
out property <bool> has-focus: inner.has-focus;
|
|
in property <bool> enabled <=> inner.enabled;
|
|
in property input-type <=> inner.input-type;
|
|
in property horizontal-alignment <=> inner.horizontal-alignment;
|
|
in property read-only <=> inner.read-only;
|
|
callback accepted <=> inner.accepted;
|
|
callback edited <=> inner.edited;
|
|
forward-focus: inner;
|
|
// border-color: root.has-focus ? Palette.highlight-background : #ffffff;
|
|
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 0;
|
|
min-height: max(32px, l.min-height);
|
|
|
|
Rectangle {
|
|
background: !root.enabled ? Palette.neutralLighter : Palette.white;
|
|
border-radius: 2px;
|
|
border-width: !root.enabled ? 0px : root.has-focus ? 2px : 1px;
|
|
border-color: !root.enabled ? Palette.neutralLighter
|
|
: root.has-focus ? Palette.themeSecondary
|
|
: Palette.neutralPrimary;
|
|
}
|
|
|
|
l := HorizontalLayout {
|
|
padding-left: 8px;
|
|
padding-right: 8px;
|
|
padding-top: 3px;
|
|
padding-bottom: 3px;
|
|
inner := LineEditInner {
|
|
placeholder-color: !self.enabled ? Palette.neutralTertiary : Palette.neutralSecondary;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component ListView inherits ScrollView {
|
|
@children
|
|
}
|
|
|
|
component StandardListViewBase inherits ListView {
|
|
in property<[StandardListViewItem]> model;
|
|
in-out property<int> current-item: -1;
|
|
for item[idx] in root.model : Rectangle {
|
|
l := HorizontalLayout {
|
|
padding: 8px;
|
|
spacing: 0px;
|
|
t := Text {
|
|
text: item.text;
|
|
color: Palette.neutralPrimary;
|
|
}
|
|
}
|
|
background: idx == root.current-item ? Palette.neutralLighter
|
|
: touch.has-hover ? Palette.neutralLighterAlt : transparent;
|
|
touch := TouchArea {
|
|
width: parent.width;
|
|
height: parent.height;
|
|
clicked => { root.current-item = idx; }
|
|
}
|
|
}
|
|
}
|
|
|
|
export component StandardListView inherits StandardListViewBase {
|
|
FocusScope {
|
|
key-pressed(event) => {
|
|
if (event.text == Key.UpArrow && root.current-item > 0) {
|
|
root.current-item -= 1;
|
|
return accept;
|
|
} else if (event.text == Key.DownArrow && root.current-item + 1 < root.model.length) {
|
|
root.current-item += 1;
|
|
return accept;
|
|
}
|
|
reject
|
|
}
|
|
}
|
|
}
|
|
|
|
export component ComboBox {
|
|
in property <[string]> model;
|
|
in-out property <int> current-index : 0;
|
|
in-out property <string> current-value: root.model[root.current-index];
|
|
//property <bool> is-open: false;
|
|
callback selected(string);
|
|
|
|
accessible-role: combobox;
|
|
accessible-value <=> root.current-value;
|
|
|
|
out property has-focus <=> fs.has-focus;
|
|
in property enabled <=> fs.enabled;
|
|
forward-focus: fs;
|
|
|
|
fs := FocusScope {
|
|
|
|
key-pressed(event) => {
|
|
if (event.text == Key.UpArrow) {
|
|
root.current-index = Math.max(root.current-index - 1, 0);
|
|
root.current-value = root.model[root.current-index];
|
|
return accept;
|
|
} else if (event.text == Key.DownArrow) {
|
|
root.current-index = Math.min(root.current-index + 1, root.model.length - 1);
|
|
root.current-value = root.model[root.current-index];
|
|
return accept;
|
|
// PopupWindow can not get hidden again at this time, so do not allow to pop that up.
|
|
// } else if (event.text == Key.Return) {
|
|
// touch.clicked()
|
|
// return accept;
|
|
}
|
|
return reject;
|
|
}
|
|
|
|
touch := TouchArea {
|
|
enabled <=> root.enabled;
|
|
clicked => {
|
|
root.focus();
|
|
popup.show();
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
background: !root.enabled ? Palette.neutralLighter : Palette.white;
|
|
border-radius: 2px;
|
|
border-width: !root.enabled ? 0px : root.has-focus ? 3px : 1px;
|
|
border-color: !root.enabled ? Palette.neutralLighter
|
|
: root.has-focus ? Palette.themeSecondary
|
|
: Palette.neutralPrimary;
|
|
}
|
|
|
|
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 0;
|
|
min-width: 170px;
|
|
min-height: max(32px, l.min-height);
|
|
|
|
l := HorizontalLayout {
|
|
padding-left: 8px;
|
|
padding-right: 8px;
|
|
padding-bottom: 3px;
|
|
padding-top: 3px;
|
|
spacing: 8px;
|
|
t := Text {
|
|
text <=> root.current-value;
|
|
horizontal-alignment: left;
|
|
vertical-alignment: center;
|
|
horizontal-stretch: 1;
|
|
color: !root.enabled ? Palette.neutralTertiary
|
|
: root.has-focus || touch.has-hover ? Palette.neutralPrimary
|
|
: Palette.neutralSecondary;
|
|
min-width: 0;
|
|
}
|
|
Rectangle {
|
|
width: 25px;
|
|
Path {
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
height: 8px;
|
|
width: 25px;
|
|
commands: "M.22.4.5.64.78.4.74.36.5.6.26.36z";
|
|
fill: t.color;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
popup := PopupWindow {
|
|
x:0;
|
|
y: root.height;
|
|
width: root.width;
|
|
Rectangle {
|
|
border-color: Palette.neutralLighter;
|
|
border-width: 1px;
|
|
/*drop-shadow-color: Palette.neutralTertiary;
|
|
drop-shadow-blur: 5px;*/
|
|
background: Palette.white;
|
|
}
|
|
VerticalLayout {
|
|
for value[idx] in root.model: Rectangle {
|
|
background: idx == root.current-index ? Palette.neutralLighter
|
|
: item-area.has-hover ? Palette.neutralLighterAlt : transparent;
|
|
VerticalLayout {
|
|
padding: 10px;
|
|
Text {
|
|
text: value;
|
|
}
|
|
}
|
|
item-area := TouchArea {
|
|
width: 100%;
|
|
height: 100%;
|
|
clicked => {
|
|
if (root.enabled) {
|
|
root.current-index = idx;
|
|
root.current-value = value;
|
|
root.selected(root.current-value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component VerticalBox inherits VerticalLayout {
|
|
spacing: StyleMetrics.layout-spacing;
|
|
padding: StyleMetrics.layout-padding;
|
|
}
|
|
export component HorizontalBox inherits HorizontalLayout {
|
|
spacing: StyleMetrics.layout-spacing;
|
|
padding: StyleMetrics.layout-padding;
|
|
}
|
|
export component GridBox inherits GridLayout {
|
|
spacing: StyleMetrics.layout-spacing;
|
|
padding: StyleMetrics.layout-padding;
|
|
}
|