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

125 lines
3.6 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";
import { Item } from "widget-item.slint";
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];
callback selected(string);
out property has-focus <=> fs.has-focus;
in property enabled <=> fs.enabled;
accessible-role: combobox;
accessible-value <=> root.current-value;
horizontal-stretch: 1;
vertical-stretch: 0;
min-width: 160px;
height: 56px;
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;
}
return reject;
}
}
container := Rectangle {
width: 100%;
height: 100%;
border-radius: 4px;
border-width: 1px;
border-color: md.sys.color.outline;
}
layout := HorizontalLayout {
padding-left: 16px;
padding-right: 12px;
spacing: 16px;
label := Text {
text <=> root.current-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;
}
icon := Path {
width: 16px;
height: 16px;
y: (parent.height - self.height) / 2;
commands: "m24 30.75-12-12 2.15-2.15L24 26.5l9.85-9.85L36 18.8Z";
fill: md.sys.color.on-surface;
}
}
touch := TouchArea {
enabled <=> root.enabled;
clicked => {
root.focus();
popup.show();
}
}
popup := PopupWindow {
x:0;
y: root.height;
width: root.width;
popup-container := Rectangle {
background: md.sys.color.surface;
drop-shadow-color: md.sys.color.shadow;
drop-shadow-blur: md.sys.elevation.level2;
drop-shadow-offset-y: 1px;
border-radius: 4px;
}
VerticalLayout {
for value[idx] in root.model: Item {
text: value;
selected: idx == root.current-index;
clicked => {
if (root.enabled) {
root.current-index = idx;
root.current-value = value;
root.selected(root.current-value);
}
}
}
}
}
states [
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
label.opacity: 0.38;
icon.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;
icon.fill: md.sys.color.primary;
}
]
}