mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-17 01:13:19 +08:00
113 lines
5.0 KiB
Plaintext
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); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|