Files
crossdesk/apps/desktop/src/gui/ui/gallery_menu_button.slint
T

113 lines
5.0 KiB
Plaintext

import { UiRadius } from "ui_radius.slint";
import { CompactButton, FontAwesomeIcons } from "common.slint";
export struct GalleryMenuItem { label: string, enabled: bool }
export component GalleryMenuButton inherits Rectangle {
in property <string> text;
in property <bool> primary: false;
in property <bool> enabled: true;
in property <bool> opens-up: false;
in property <length> menu-width: 200px;
in property <length> horizontal-padding: 12px;
out property <length> preferred-button-width: ceil(button-label.preferred-width / 1px) * 1px + root.horizontal-padding * 2 + 18px;
in property <[GalleryMenuItem]> items;
private property <int> current-index: 0;
callback opened;
callback selected(int);
height: 24px;
forward-focus: trigger-focus;
accessible-role: button;
accessible-label: root.text;
accessible-enabled: root.enabled;
accessible-expandable: true;
accessible-expanded: popup.is-open;
accessible-action-default => { root.open-menu(); }
changed enabled => { if !root.enabled { popup.close(); } }
changed visible => { if !root.visible { popup.close(); } }
public function close-menu() { popup.close(); }
function open-menu() {
if !root.enabled || root.items.length == 0 { return; }
if popup.is-open { popup.close(); return; }
root.opened();
root.current-index = 0;
popup.show();
}
function choose(index: int) {
if !root.enabled || index < 0 || index >= root.items.length || !root.items[index].enabled { return; }
popup.close();
trigger-focus.focus();
root.selected(index);
}
function handle-key(event: KeyEvent) -> EventResult {
if !root.enabled { return reject; }
if event.text == Key.Escape && popup.is-open {
popup.close(); trigger-focus.focus(); return accept;
}
if event.text == Key.Return || event.text == " " {
if popup.is-open { root.choose(root.current-index); } else { root.open-menu(); }
return accept;
}
if event.text == Key.UpArrow || event.text == Key.DownArrow {
if !popup.is-open { root.open-menu(); }
else { root.current-index = clamp(root.current-index + (event.text == Key.UpArrow ? -1 : 1), 0, root.items.length - 1); }
return accept;
}
return reject;
}
trigger-focus := FocusScope {
enabled: root.enabled;
key-pressed(event) => { return root.handle-key(event); }
CompactButton {
width: parent.width; height: parent.height;
border-radius: UiRadius.control;
enabled: root.enabled; primary: root.primary;
clicked => { trigger-focus.focus(); root.open-menu(); }
}
button-label := Text {
x: root.horizontal-padding; width: parent.width - root.horizontal-padding * 2 - 18px; height: parent.height;
text: root.text; color: root.enabled ? #24272d : #8e9298;
font-size: 11px; overflow: elide; horizontal-alignment: center; vertical-alignment: center;
}
Text {
x: parent.width - root.horizontal-padding - 12px; width: 12px; height: parent.height;
text: root.opens-up ? FontAwesomeIcons.angle-up : FontAwesomeIcons.angle-down;
font-family: "Font Awesome 6 Free"; font-weight: 900; font-size: 9px;
color: root.enabled ? #62666d : #8e9298;
horizontal-alignment: center; vertical-alignment: center;
}
}
popup := PopupWindow {
x: root.width - self.width;
y: root.opens-up ? -self.height - 4px : root.height + 4px;
width: root.menu-width; height: root.items.length * 30px + 8px;
close-policy: close-on-click-outside;
forward-focus: popup-focus;
popup-focus := FocusScope {
key-pressed(event) => { return root.handle-key(event); }
Rectangle {
background: white; border-width: 1px; border-color: #c9cdd2; border-radius: UiRadius.menu;
for item[index] in root.items: Rectangle {
x: 4px; y: 4px + index * 30px; width: parent.width - 8px; height: 30px;
border-radius: UiRadius.control;
background: item.enabled && index == root.current-index ? #edf4fc : transparent;
accessible-role: button; accessible-label: item.label; accessible-enabled: item.enabled;
accessible-action-default => { root.choose(index); }
Text {
x: 10px; width: parent.width - 20px; height: parent.height;
text: item.label; color: item.enabled ? #30343b : #92979f;
font-size: 12px; vertical-alignment: center;
}
TouchArea {
enabled: item.enabled;
changed has-hover => { if self.has-hover { root.current-index = index; } }
clicked => { root.choose(index); }
}
}
}
}
}
}