mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-26 21:34:08 +00:00
367 lines
11 KiB
Text
367 lines
11 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
import { Palette } from "std-widgets.slint";
|
|
|
|
struct ButtonColors {
|
|
base: color,
|
|
pressed: color,
|
|
hovered: color,
|
|
}
|
|
|
|
struct ModeColors {
|
|
background: color,
|
|
primary: color,
|
|
secondary: color,
|
|
text-primary: color,
|
|
text-secondary: color,
|
|
destructive: color,
|
|
}
|
|
|
|
export global DemoPalette {
|
|
in property <bool> dark-mode: Palette.color-scheme == ColorScheme.dark;
|
|
|
|
property <ModeColors> light-mode-colors: {
|
|
background: #FFFFFF,
|
|
primary: #0E133F,
|
|
secondary: #FFBF63,
|
|
text-primary: #000,
|
|
text-secondary: #6284FF,
|
|
destructive: #FF3B30,
|
|
};
|
|
|
|
property <ModeColors> dark-mode-colors: {
|
|
background: #122F7B,
|
|
primary: #0E133F,
|
|
secondary: #FFBF63,
|
|
text-primary: #F4F6FF,
|
|
text-secondary: #F4F6FF,
|
|
destructive: #FF3B30,
|
|
};
|
|
|
|
out property <color> background: dark-mode ? dark-mode-colors.background : light-mode-colors.background;
|
|
out property <color> primary: dark-mode ? dark-mode-colors.primary : light-mode-colors.primary;
|
|
out property <color> secondary: dark-mode ? dark-mode-colors.secondary : light-mode-colors.secondary;
|
|
out property <color> text-primary: dark-mode ? dark-mode-colors.text-primary : light-mode-colors.text-primary;
|
|
out property <color> text-secondary: dark-mode ? dark-mode-colors.text-secondary : light-mode-colors.text-secondary;
|
|
out property <color> destructive: dark-mode ? dark-mode-colors.destructive : light-mode-colors.destructive;
|
|
|
|
// Fixed (non-themeable) colors
|
|
out property <color> push-button-text-color: white;
|
|
|
|
// Color of the home/settings/ink buttons on the left side bar
|
|
out property <color> active-page-icon-color: root.dark-mode ? #6284FF : #122F7B;
|
|
out property <color> inactive-page-icon-color: #BDC0D1;
|
|
out property <color> neutral-box: #BDC0D1;
|
|
out property <color> secondary-foreground-color: root.dark-mode ? #C1C3CA : #6C6E7A;
|
|
|
|
// Color used for the border / outline of items that can be clicked on, such as the
|
|
// "Print"/"Scan" buttons, the printer queue items (for expansion) or controls such
|
|
// as the combo box or spin box.
|
|
out property <color> control-secondary: #6284FF;
|
|
out property <color> control-foreground: root.dark-mode ? white : #122F7B; // FIXME: the night mode color was not part of the design
|
|
out property <color> primary-push-button-base: #6284FF;
|
|
out property <ButtonColors> primary-push-button-colors: {
|
|
base: root.primary-push-button-base,
|
|
pressed: root.primary-push-button-base.darker(40%),
|
|
hovered: root.primary-push-button-base.darker(20%),
|
|
};
|
|
out property <color> secondary-push-button-base: destructive;
|
|
out property <ButtonColors> secondary-push-button-colors: {
|
|
base: root.secondary-push-button-base,
|
|
pressed: root.secondary-push-button-base.darker(40%),
|
|
hovered: root.secondary-push-button-base.darker(20%),
|
|
};
|
|
|
|
out property <length> base-font-size: 16px;
|
|
out property <length> button-width: 130px;
|
|
out property <length> button-height: button-width + 30px;
|
|
out property <length> side-bar-width: 67px;
|
|
out property <length> side-bar-margin: 10px;
|
|
|
|
}
|
|
|
|
export component Page inherits Rectangle {
|
|
in property <string> header <=> h.text;
|
|
in property <bool> has-back-button: false;
|
|
|
|
callback back;
|
|
|
|
background: DemoPalette.background;
|
|
// Stop accidentally getting clicks dur to animation only moving page half way offscreen
|
|
visible: self.opacity > 0;
|
|
|
|
TouchArea { } // protect underneath controls
|
|
|
|
|
|
|
|
if (root.has-back-button) : Image {
|
|
x:0;
|
|
source: @image-url("images/back.svg");
|
|
image-fit: contain;
|
|
colorize: DemoPalette.control-secondary;
|
|
y: h.y + (h.height - self.height) / 2;
|
|
width: 14px;
|
|
height: 24px;
|
|
|
|
TouchArea {
|
|
clicked => { root.back() }
|
|
|
|
x: -14px;
|
|
height: 200%;
|
|
width: self.height;
|
|
}
|
|
}
|
|
|
|
h := Text {
|
|
font-weight: 900;
|
|
font-size: DemoPalette.base-font-size * 2;
|
|
color: DemoPalette.text-primary;
|
|
y: 46px - self.font-size;
|
|
x: root.has-back-button ? 24px + 16px : 0px;
|
|
// Allow clicking on the title as well to get back easier when just
|
|
// using fingers on a small screen.
|
|
if (root.has-back-button) : TouchArea {
|
|
clicked => { root.back() }
|
|
}
|
|
}
|
|
}
|
|
export component Label inherits Text {
|
|
color: DemoPalette.text-primary;
|
|
vertical-alignment: center;
|
|
font-weight: 700;
|
|
vertical-stretch: 0;
|
|
}
|
|
|
|
component SquareButton inherits Rectangle {
|
|
in-out property <image> img;
|
|
|
|
callback clicked;
|
|
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
|
|
touch := TouchArea {
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
}
|
|
|
|
Image {
|
|
height: 40%;
|
|
width: 40%;
|
|
x: (parent.width - self.width)/2;
|
|
y: (parent.height - self.height)/2;
|
|
source <=> root.img;
|
|
image-fit: contain;
|
|
colorize: DemoPalette.control-secondary;
|
|
}
|
|
}
|
|
|
|
export component SpinBox inherits Rectangle {
|
|
in property <int> minimum;
|
|
in property <int> maximum: 100;
|
|
in-out property <int> value;
|
|
|
|
height: 32px;
|
|
|
|
HorizontalLayout {
|
|
spacing: 12px;
|
|
padding: 0;
|
|
|
|
SquareButton {
|
|
clicked => {
|
|
if (root.value > root.minimum) {
|
|
root.value -= 1;
|
|
}
|
|
}
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: @image-url("images/minus.svg");
|
|
}
|
|
|
|
Rectangle {
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
|
|
Text {
|
|
width: 100%;
|
|
height: 100%;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: center;
|
|
text: root.value;
|
|
color: DemoPalette.control-foreground;
|
|
}
|
|
}
|
|
|
|
SquareButton {
|
|
clicked => {
|
|
if (root.value < root.maximum) {
|
|
root.value += 1;
|
|
}
|
|
}
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: @image-url("images/plus.svg");
|
|
}
|
|
}
|
|
}
|
|
|
|
export component ComboBox inherits Rectangle {
|
|
in-out property <string> value;
|
|
in property <[string]> choices;
|
|
callback selected(int);
|
|
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
height: 32px;
|
|
min-width: label.x + label.width + i.width;
|
|
horizontal-stretch: 1; // Work around #2284
|
|
|
|
label := Text {
|
|
vertical-alignment: center;
|
|
horizontal-alignment: left;
|
|
text <=> root.value;
|
|
color: DemoPalette.control-foreground;
|
|
height: 100%;
|
|
x: 12px;
|
|
}
|
|
|
|
i := Image {
|
|
source: @image-url("images/down.svg");
|
|
colorize: DemoPalette.control-secondary;
|
|
height: 40%;
|
|
width: self.height;
|
|
image-fit: contain;
|
|
x: parent.width - self.width - self.y;
|
|
y: (parent.height - self.height)/2;
|
|
}
|
|
|
|
TouchArea {
|
|
clicked => { popup.show(); }
|
|
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
popup := PopupWindow {
|
|
x:0;
|
|
y: root.height;
|
|
width: root.width;
|
|
|
|
Rectangle {
|
|
background: DemoPalette.background;
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
}
|
|
|
|
VerticalLayout {
|
|
spacing: 6px;
|
|
padding: 3px;
|
|
function textColor(hashover: bool) -> color {
|
|
if DemoPalette.dark-mode {
|
|
return DemoPalette.text-primary;
|
|
}
|
|
// if hashover {
|
|
return DemoPalette.text-primary;
|
|
// }
|
|
|
|
}
|
|
|
|
for value[idx] in root.choices: Rectangle {
|
|
border-radius: 3px;
|
|
background: item-area.has-hover ? DemoPalette.primary-push-button-colors.hovered : #0000;
|
|
|
|
HorizontalLayout {
|
|
Text {
|
|
text: value;
|
|
color: item-area.has-hover ? DemoPalette.push-button-text-color : DemoPalette.text-primary;
|
|
font-size: DemoPalette.base-font-size;
|
|
}
|
|
}
|
|
|
|
item-area := TouchArea {
|
|
clicked => {
|
|
root.value = value;
|
|
root.selected(idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component CheckBox inherits Rectangle {
|
|
in property <string> text;
|
|
in-out property <bool> checked;
|
|
|
|
height: 32px;
|
|
|
|
HorizontalLayout {
|
|
spacing: 12px;
|
|
padding: 0;
|
|
SquareButton {
|
|
clicked => { root.checked = !root.checked; }
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: root.checked ? @image-url("images/check.svg") : @image-url("");
|
|
}
|
|
|
|
Text {
|
|
text <=> root.text;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: center;
|
|
color: DemoPalette.control-foreground;
|
|
horizontal-stretch: 1;
|
|
}
|
|
}
|
|
|
|
TouchArea {
|
|
clicked => {
|
|
root.checked = !root.checked;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component PushButton inherits Rectangle {
|
|
in property <string> text <=> label.text;
|
|
in property <bool> primary: true;
|
|
out property <bool> pressed: touch-area.pressed;
|
|
out property <ButtonColors> colors: root.primary ? DemoPalette.primary-push-button-colors : DemoPalette.secondary-push-button-colors;
|
|
in-out property <image> icon <=> img.source;
|
|
|
|
callback clicked;
|
|
|
|
border-radius: 13.5px;
|
|
background: root.pressed ? root.colors.pressed : (touch-area.has-hover ? root.colors.hovered : root.colors.base);
|
|
|
|
height: 27px; // line-height in the design
|
|
horizontal-stretch: 1;
|
|
|
|
HorizontalLayout {
|
|
padding-top: 0px;
|
|
padding-bottom: 0px;
|
|
padding-left: parent.border-radius;
|
|
padding-right: parent.border-radius;
|
|
|
|
img := Image {
|
|
horizontal-stretch: 0;
|
|
colorize: DemoPalette.push-button-text-color;
|
|
image-fit: contain;
|
|
width: 17px;
|
|
}
|
|
|
|
label := Text {
|
|
font-weight: 900;
|
|
font-size: DemoPalette.base-font-size * 0.975;
|
|
color: DemoPalette.push-button-text-color;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
|
|
touch-area := TouchArea { clicked => { root.clicked() } }
|
|
}
|