slint/internal/compiler/widgets/fluent-base/combobox.slint
Olivier Goffart 34ea148c48 Fluent combobox: always put the first item on top
Currently it's always the second, but that's not great.
Ideally it should be the current active element, but that's hard to
compute

This becomes extra-relevent when our preview UI has a combobox on the
top and that it is clipped to the window by winit

Fixes https://github.com/slint-ui/slint/issues/3345
2023-11-07 11:12:27 +01:00

110 lines
No EOL
3.4 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
import { Typography, Palette, Icons } from "styling.slint";
import { MenuBorder, ListItem, FocusBorder } from "components.slint";
import { ComboBoxBase } from "../common/combobox-base.slint";
export component ComboBox {
in property <[string]> model <=> i-base.model;
in property <bool> enabled <=> i-base.enabled;
out property <bool> has-focus <=> i-base.has-focus;
in-out property <int> current-index <=> i-base.current-index;
in-out property <string> current-value <=> i-base.current-value;
callback selected <=> i-base.selected;
min-width: max(160px, i-layout.min-height);
min-height: max(32px, i-layout.min-height);
horizontal-stretch: 1;
vertical-stretch: 0;
forward-focus: i-base;
states [
disabled when !root.enabled : {
i-background.background: Palette.control-disabled;
i-background.border-color: Palette.control-stroke;
i-text.color: Palette.text-disabled;
i-icon.colorize: Palette.text-disabled;
}
pressed when i-base.pressed : {
i-background.background: Palette.control-alt-tertiary;
i-background.border-color: Palette.control-stroke;
i-text.color: Palette.text-secondary;
i-icon.colorize: Palette.text-tertiary;
}
hover when i-base.has-hover : {
i-background.background: Palette.control-secondary;
}
]
i-base := ComboBoxBase {
width: 100%;
height: 100%;
show-popup => {
i-popup.show();
}
}
i-background := Rectangle {
border-radius: 3px;
background: Palette.control-default;
border-width: 1px;
border-color: Palette.control-border;
animate border-color { duration: 200ms; }
i-layout := HorizontalLayout {
padding-left: 11px;
padding-right: 11px;
spacing: 8px;
i-text := Text {
horizontal-alignment: left;
vertical-alignment: center;
font-size: Typography.body.font-size;
font-weight: Typography.body.font-weight;
color: Palette.text-primary;
text: root.current-value;
}
i-icon := Image {
colorize: Palette.text-secondary;
width: 12px;
source: Icons.dropdown;
y: 2px;
animate colorize { duration: 150ms; }
}
}
}
// focus border
if (root.has-focus && root.enabled) : FocusBorder {
border-radius: i-background.border-radius;
}
i-popup := PopupWindow {
x: 0;
// Position the popup so that the first element is over the popup.
// Ideally it should be so that the current element is over the popup.
y: -4px;
width: root.width;
MenuBorder {
VerticalLayout {
padding: 4px;
for value[index] in root.model : ListItem {
text: value;
selected: index == root.current-index;
clicked => {
i-base.select(index);
}
}
}
}
}
}