// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.0 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 current-index : 0; in-out property 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; } ] }