Loading files
bae9c0e4eThis file is pinned to the selected release. Download the original to open it in your design tool.
import { ControlIconButton } from "iconbutton.slint";
import { TextInput } from "textinput.slint";
import { ToolTip } from "tooltip.slint";
import {
AngleEditData,
AngleEditParseResult,
Backend,
Data,
} from "../api.slint";
export component AngleEdit inherits Rectangle {
in property <AngleEditData> data;
in-out property <int> value: data.value;
in property <image> icon: @image-url("../../../font-awesome/svgs/solid/compass-drafting.svg");
in property <string> tooltip;
in property <string> min-width-text: "123.456 °";
in property <bool> enabled: true;
property <AngleEditParseResult> parse-result;
property <bool> disable-update: false;
callback value-changed(int);
value-changed(value) => {
self.value = value;
}
callback value-accepted(int);
callback increase-triggered;
callback decrease-triggered;
public function select-all() {
edt.select-all();
}
function update-text-from-value() {
edt.text = Backend.format-angle(root.value) + "°";
parse-result.valid = true;
}
// Accessibility
accessible-role: spinbox;
accessible-description: tooltip.is-empty ? "angle" : tooltip;
accessible-enabled: enabled;
accessible-value: edt.text + " degrees";
accessible-action-increment => {
up-btn.clicked();
}
accessible-action-decrement => {
down-btn.clicked();
}
accessible-action-set-value(s) => {
edt.text = s;
edt.edited();
}
changed value => {
if !disable-update {
update-text-from-value();
}
}
preferred-height: 25px;
background: enabled ? Data.theme.control : Data.theme.control-disabled;
border-color: {
if !enabled {
Data.theme.control-border-disabled
} else if edt.has-focus {
if !parse-result.valid {
Data.theme.base-text-error
} else {
Data.theme.accent
}
} else if !parse-result.valid {
Data.theme.control-border.mix(Data.theme.base-text-error, 0.6)
} else {
Data.theme.control-border
}
};
border-width: 1px;
forward-focus: edt;
// A bit ugly: Ensure enough space for numbers in the typical range.
metrics-edt := TextInput {
width: 0;
height: 0;
font-size: 13px;
single-line: true;
wrap: no-wrap;
text: min-width-text;
visible: false;
accessible-role: none;
}
ta := TouchArea {
enabled: enabled;
l := HorizontalLayout {
padding-left: 5px;
padding-right: 1px;
padding-top: self.padding-right;
padding-bottom: self.padding-top;
spacing: 5px;
if icon.width > 0: Rectangle {
width: 12px;
Image {
width: 100%;
height: self.width;
image-fit: contain;
colorize: edt.color;
source: icon;
accessible-role: none;
}
}
edt := TextInput {
min-width: max(self.preferred-width, metrics-edt.preferred-width);
font-size: 13px;
single-line: true;
horizontal-alignment: right;
vertical-alignment: center;
enabled: enabled;
accessible-role: none;
changed has-focus => {
if !self.has-focus {
disable-update = false;
update-text-from-value();
}
}
init => {
update-text-from-value();
}
edited => {
disable-update = true;
parse-result = Backend.parse-angle-input(self.text);
if parse-result.valid {
if parse-result.evaluated-value != value {
value-changed(parse-result.evaluated-value);
}
}
}
accepted => {
disable-update = false;
update-text-from-value();
value-accepted(parse-result.evaluated-value);
}
key-pressed(event) => {
if event.text == Key.UpArrow {
disable-update = false;
increase-triggered();
return accept;
} else if event.text == Key.DownArrow {
disable-update = false;
decrease-triggered();
return accept;
} else if (event.text == Key.Escape) && disable-update {
disable-update = false;
update-text-from-value();
return accept;
}
reject
}
}
VerticalLayout {
up-btn := ControlIconButton {
width: 15px;
enabled: enabled;
background-color: transparent;
icon: @image-url("../../../font-awesome/svgs/solid/caret-up.svg");
icon-offset-y: 1px;
accessible-label: "increase";
clicked => {
disable-update = false;
increase-triggered();
}
}
down-btn := ControlIconButton {
width: 15px;
enabled: enabled;
background-color: transparent;
icon: @image-url("../../../font-awesome/svgs/solid/caret-down.svg");
icon-offset-y: -1px;
accessible-label: "decrease";
clicked => {
disable-update = false;
decrease-triggered();
}
}
}
}
scroll-event(event) => {
if event.delta-y > 0 {
disable-update = false;
increase-triggered();
return accept;
} else if event.delta-y < 0 {
disable-update = false;
decrease-triggered();
return accept;
}
reject
}
}
if ta.has-hover && (!ta.pressed) && (!tooltip.is-empty): tt := ToolTip {
x: (parent.width - self.width) / 2;
y: parent.height + 5px;
text: tooltip;
}
}