mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-23 08:42:20 +00:00

Currently, the min-with don't account for the text. That means that, for example, the switch on the top bar of the gallery, get the text to overflow which doesn't look good by default
137 lines
4.6 KiB
Text
137 lines
4.6 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
|
|
|
import { FluentFontSettings, FluentPalette } from "styling.slint";
|
|
import { FocusBorder } from "components.slint";
|
|
|
|
export component Switch {
|
|
in property <bool> enabled: true;
|
|
in property <string> text;
|
|
in-out property <bool> checked;
|
|
out property <bool> has-focus: focus-scope.has-focus;
|
|
|
|
callback toggled;
|
|
|
|
private property <color> text-color: FluentPalette.foreground;
|
|
|
|
function toggle-checked() {
|
|
if(!root.enabled) {
|
|
return;
|
|
}
|
|
|
|
root.checked = !root.checked;
|
|
root.toggled();
|
|
}
|
|
|
|
min-width: max(40px, layout.min-width);
|
|
min-height: max(20px, layout.min-height);
|
|
vertical-stretch: 0;
|
|
horizontal-stretch: 0;
|
|
accessible-enabled: root.enabled;
|
|
accessible-label: root.text;
|
|
accessible-checkable: true;
|
|
accessible-checked <=> root.checked;
|
|
accessible-role: switch;
|
|
accessible-action-default => {
|
|
root.checked = !root.checked;
|
|
root.toggled();
|
|
}
|
|
forward-focus: focus-scope;
|
|
|
|
states [
|
|
disabled when !root.enabled : {
|
|
rail.background: root.checked ? FluentPalette.accent-disabled : transparent;
|
|
rail.border-color: FluentPalette.control-strong-stroke-disabled;
|
|
thumb.background: FluentPalette.text-disabled;
|
|
root.text-color: FluentPalette.text-disabled;
|
|
thumb.background: root.checked ? FluentPalette.text-accent-foreground-disabled : FluentPalette.text-secondary;
|
|
}
|
|
pressed when touch-area.pressed : {
|
|
rail.background: root.checked ? FluentPalette.tertiary-accent-background : FluentPalette.control-alt-quartiary;
|
|
thumb.width: 17px;
|
|
thumb.height: 14px;
|
|
thumb.border-width: root.checked ? 1px : 0;
|
|
thumb.background: root.checked ? FluentPalette.accent-foreground : FluentPalette.text-secondary;
|
|
}
|
|
hover when touch-area.has-hover : {
|
|
rail.background: root.checked ? FluentPalette.secondary-accent-background : FluentPalette.control-alt-tertiary;
|
|
thumb.width: 14px;
|
|
thumb.border-width: root.checked ? 1px : 0;
|
|
thumb.background: root.checked ? FluentPalette.accent-foreground : FluentPalette.text-secondary;
|
|
}
|
|
selected when root.checked : {
|
|
rail.background: FluentPalette.accent-background;
|
|
thumb.border-width: 1px;
|
|
thumb.border-color: FluentPalette.circle-border;
|
|
thumb.background: FluentPalette.accent-foreground;
|
|
}
|
|
]
|
|
|
|
layout := HorizontalLayout {
|
|
spacing: 12px;
|
|
|
|
VerticalLayout {
|
|
alignment: center;
|
|
|
|
Rectangle {
|
|
width: 40px;
|
|
height: 20px;
|
|
|
|
rail := Rectangle {
|
|
border-radius: 10px;
|
|
border-width: root.checked ? 0 : 1px;
|
|
border-color: FluentPalette.control-strong-stroke;
|
|
background: FluentPalette.control-alt-secondary;
|
|
}
|
|
|
|
thumb := Rectangle {
|
|
x: root.checked ? parent.width - self.width - 4px : 4px;
|
|
y: (parent.height - self.height) / 2;
|
|
width: 12px;
|
|
height: self.width;
|
|
border-radius: self.height / 2;
|
|
background: FluentPalette.text-secondary;
|
|
border-color: FluentPalette.circle-border;
|
|
|
|
animate background, width { duration: 150ms; easing: linear; }
|
|
}
|
|
|
|
// focus border
|
|
if root.has-focus && root.enabled : FocusBorder {
|
|
border-radius: rail.border-radius;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (root.text != "") : Text {
|
|
text: root.text;
|
|
color: root.text-color;
|
|
font-size: FluentFontSettings.body.font-size;
|
|
font-weight: FluentFontSettings.body.font-weight;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: left;
|
|
}
|
|
}
|
|
|
|
touch-area := TouchArea {
|
|
enabled <=> root.enabled;
|
|
|
|
clicked => {
|
|
root.toggle-checked();
|
|
}
|
|
}
|
|
|
|
focus-scope := FocusScope {
|
|
x:0;
|
|
width: 0px; // Do not react on clicks
|
|
enabled <=> root.enabled;
|
|
|
|
key-pressed(event) => {
|
|
if (event.text == " " || event.text == "\n") {
|
|
root.toggle-checked();
|
|
return accept;
|
|
}
|
|
return reject;
|
|
}
|
|
}
|
|
}
|