slint/internal/compiler/widgets/material-base/widget-spinbox.slint
2023-02-10 16:49:25 +01:00

178 lines
5 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { md } from "md.slint";
component SpinBoxButton inherits Rectangle {
callback clicked <=> touch.clicked;
in-out property<bool> pressed: self.enabled && touch.pressed;
in-out property<bool> enabled <=> touch.enabled;
in-out property<float> icon-opacity: 1;
in-out property<brush> icon-fill: md.sys.color.on-primary;
width: root.height;
container := Rectangle {
width: 100%;
height: 100%;
border-radius: max(self.width, self.height) / 2;
background: md.sys.color.primary;
}
state-layer := Rectangle {
x:0;y:0;
opacity: 0;
width: container.width;
height: container.height;
border-radius: container.border-radius;
background: md.sys.color.on-primary;
animate opacity { duration: 250ms; easing: ease; }
}
Rectangle {
width: 100%;
height: 100%;
@children
}
touch := TouchArea { }
states [
disabled when !root.enabled : {
container.background: md.sys.color.on-surface;
container.opacity: 0.12;
icon-opacity: 0.38;
icon-fill: md.sys.color.on-surface;
}
pressed when touch.pressed : {
state-layer.opacity: 0.12;
}
hover when touch.has-hover : {
state-layer.opacity: 0.08;
}
]
}
// Increment and decrement a value in the given range.
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;
horizontal-stretch: 1;
vertical-stretch: 0;
min-width: 60px;
height: 56px;
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 {
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
}
}
}
container := Rectangle {
width: 100%;
height: 100%;
border-radius: 4px;
border-width: 1px;
border-color: md.sys.color.outline;
}
layout := HorizontalLayout {
padding-top: 8px;
padding-bottom: 8px;
padding-left: 16px;
padding-right: 12px;
spacing: 16px;
label := Text {
text: root.value;
height: 100%;
color: md.sys.color.on-surface;
vertical-alignment: center;
// FIXME after Roboto font can be loaded
//font-family: md.sys.typescale.body-large.font;
font-size: md.sys.typescale.body-large.size;
font-weight: md.sys.typescale.body-large.weight;
}
VerticalLayout {
spacing: 4px;
SpinBoxButton {
enabled: root.enabled;
Path {
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
width: 44%;
height: 44%;
commands: "M14.15 30.75 12 28.6l12-12 12 11.95-2.15 2.15L24 20.85Z";
opacity: parent.icon-opacity;
fill: parent.icon-fill;
}
clicked => {
if (root.value < root.maximum) {
root.value += 1;
}
root.focus();
}
}
SpinBoxButton {
enabled: root.enabled;
Path {
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
width: 44%;
height: 44%;
commands: "m24 30.75-12-12 2.15-2.15L24 26.5l9.85-9.85L36 18.8Z";
opacity: parent.icon-opacity;
fill: parent.icon-fill;
}
clicked => {
if (root.value > root.minimum) {
root.value -= 1;
}
root.focus();
}
}
}
}
states [
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
label.opacity: 0.38;
}
focused when root.has-focus : {
container.border-width: 2px;
container.border-color: md.sys.color.primary;
label.color: md.sys.color.primary;
}
]
}