Loading files
import { Constants, Data } from "../api.slint";
export enum TextSide {
left,
right,
}
export component Switch inherits Rectangle {
in-out property <bool> checked: false;
in property <bool> enabled: true;
in property <string> text;
in property <TextSide> text-side: right;
in property <length> size: 25px;
in property <length> font-size: 12px;
in property <string> status-tip;
in property <color> checked-color: Constants.librepcb-color;
in property <color> unchecked-color: #606060;
in property <bool> focusable: true;
out property has-focus <=> fs.has-focus;
preferred-width: l.preferred-width;
preferred-height: l.preferred-height;
max-width: text.is-empty ? l.preferred-width : l.max-width;
forward-focus: fs;
// Accessibility
accessible-role: switch;
accessible-description: status-tip;
accessible-checkable: true;
accessible-checked: checked;
accessible-enabled: enabled;
accessible-label: text;
accessible-action-default => {
ta.clicked();
}
callback toggled(checked: bool);
toggled(state) => {
checked = state;
}
fs := FocusScope {
enabled: enabled && focusable;
key-pressed(event) => {
// Only consume Space, but not Return as the Return key is often
// used to confirm a dialog or something like that.
if event.text == Key.Space {
toggled(!checked);
return accept;
}
reject
}
}
l := HorizontalLayout {
spacing: 8px;
if (!text.is-empty) && (text-side == TextSide.left): Text {
text: text;
wrap: word-wrap;
horizontal-alignment: right;
vertical-alignment: center;
font-size: font-size;
accessible-role: none;
}
Rectangle {
property <float> darkness: {
if !enabled {
0.5
} else if ta.pressed {
0.3
} else {
0
}
};
y: (parent.height - self.height) / 2;
width: size * 1.8;
height: size;
background: (checked ? checked-color : unchecked-color).darker(darkness);
border-radius: self.height / 2;
border-color: checked ? white : Constants.librepcb-color;
border-width: has-focus ? 1px : 0;
Rectangle {
x: checked ? (parent.width - self.width - 3px) : 3px;
width: self.height;
height: parent.height - 6px;
background: ta.has-hover ? #303030 : #101010;
border-radius: self.height / 2;
animate x { duration: 50ms; }
}
}
if (!text.is-empty) && (text-side == TextSide.right): Text {
text: text;
wrap: word-wrap;
vertical-alignment: center;
font-size: font-size;
accessible-role: none;
}
}
ta := TouchArea {
enabled: enabled;
changed has-hover => {
if !root.status-tip.is-empty {
if self.has-hover {
Data.status-tip = root.status-tip;
} else {
Data.status-tip = "";
}
}
}
clicked => {
// The click may destroy this element without calling the
// has-hover handler anymore, so we clear the status tip
// manually to be on the safe side.
if !root.status-tip.is-empty {
Data.status-tip = "";
}
toggled(!checked);
}
}
}
9d2aa90beThis file is pinned to the selected release. Download the original to open it in your design tool.