mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-04 01:20:37 +00:00

These are showing off use-cases for Slint, but they're not examples showing individual Slint features. Also removed the old printerdemo while at it.
405 lines
11 KiB
Text
405 lines
11 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { DemoPalette, PushButton } from "./common.slint";
|
|
|
|
export struct PrinterQueueItem {
|
|
status: string,
|
|
progress: int,
|
|
title: string,
|
|
owner: string,
|
|
pages: int,
|
|
size: string, // number instead and format in .slint?
|
|
submission-date: string
|
|
}
|
|
|
|
export global PrinterQueue {
|
|
in property <[PrinterQueueItem]> printer-queue: [
|
|
{ status: "printing", progress: 63, title: "210106-FinalPresentation.pdf", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
|
|
{ status: "waiting", title: "Adressliste.docx", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
|
|
{ status: "waiting", title: "Salaries.pdf", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
|
|
];
|
|
|
|
public pure function statusString(status: string) -> string {
|
|
if (status == "printing") {
|
|
@tr("PRINTING")
|
|
} else if (status == "waiting") {
|
|
@tr("WAITING...")
|
|
} else {
|
|
@tr("Unknown job status")
|
|
}
|
|
}
|
|
|
|
callback start-job(string);
|
|
callback cancel-job(int);
|
|
callback pause-job(int);
|
|
}
|
|
|
|
|
|
component PrintQueueDetailsLabel inherits Text {
|
|
font-weight: 500;
|
|
color: DemoPalette.control-foreground;
|
|
horizontal-stretch: 0;
|
|
font-size: DemoPalette.base-font-size * 0.9375;
|
|
}
|
|
|
|
component PrintQueueSeparator inherits Rectangle {
|
|
height: 1px;
|
|
border-width: 1px;
|
|
border-color: #BDC0D1;
|
|
horizontal-stretch: 2;
|
|
}
|
|
|
|
component PrintDetails inherits GridLayout {
|
|
in property <PrinterQueueItem> queue-item;
|
|
|
|
spacing: 3px;
|
|
|
|
Row {
|
|
PrintQueueDetailsLabel {
|
|
text: @tr("Job Owner");
|
|
}
|
|
|
|
Text {
|
|
text: root.queue-item.owner;
|
|
color: DemoPalette.secondary-foreground-color;
|
|
overflow: elide;
|
|
horizontal-stretch: 1;
|
|
font-size: DemoPalette.base-font-size * 0.9375;
|
|
}
|
|
}
|
|
Row {
|
|
PrintQueueSeparator {
|
|
colspan: 2;
|
|
}
|
|
}
|
|
|
|
Row {
|
|
PrintQueueDetailsLabel {
|
|
text: @tr("Pages");
|
|
}
|
|
|
|
Text {
|
|
text: root.queue-item.pages;
|
|
color: DemoPalette.secondary-foreground-color;
|
|
overflow: elide;
|
|
horizontal-stretch: 1;
|
|
font-size: DemoPalette.base-font-size * 0.9375;
|
|
}
|
|
}
|
|
|
|
Row {
|
|
PrintQueueSeparator {
|
|
colspan: 2;
|
|
}
|
|
}
|
|
|
|
Row {
|
|
PrintQueueDetailsLabel {
|
|
text: @tr("Size");
|
|
}
|
|
|
|
Text {
|
|
text: root.queue-item.pages;
|
|
color: DemoPalette.secondary-foreground-color;
|
|
overflow: elide;
|
|
horizontal-stretch: 1;
|
|
font-size: DemoPalette.base-font-size * 0.9375;
|
|
}
|
|
}
|
|
|
|
Row {
|
|
PrintQueueSeparator {
|
|
colspan: 2;
|
|
}
|
|
}
|
|
|
|
Row {
|
|
PrintQueueDetailsLabel {
|
|
text: @tr("Submitted");
|
|
}
|
|
|
|
Text {
|
|
text: root.queue-item.submission-date;
|
|
color: DemoPalette.secondary-foreground-color;
|
|
overflow: elide;
|
|
horizontal-stretch: 1;
|
|
font-size: DemoPalette.base-font-size * 0.9375;
|
|
}
|
|
}
|
|
}
|
|
|
|
component NarrowPrintQueueElement inherits Rectangle {
|
|
in property <PrinterQueueItem> queue-item;
|
|
in-out property <bool> expanded;
|
|
|
|
callback show-job-details();
|
|
|
|
private property <float> expanded-opacity: 0;
|
|
|
|
border-color: DemoPalette.secondary;
|
|
border-radius: 14px;
|
|
border-width: 2px;
|
|
background: DemoPalette.background;
|
|
clip: true;
|
|
height: always-visible.min-height + layout.padding * 2;
|
|
|
|
states [
|
|
expanded when root.expanded : {
|
|
height: layout.min-height;
|
|
expanded-opacity: 1;
|
|
|
|
in {
|
|
animate height { duration: 200ms; easing: ease; }
|
|
animate expanded-opacity { duration: 200ms; }
|
|
}
|
|
out {
|
|
animate height { duration: 200ms; easing: ease; }
|
|
animate expanded-opacity { duration: 200ms; }
|
|
}
|
|
}
|
|
]
|
|
|
|
TouchArea {
|
|
clicked => {
|
|
root.expanded = !root.expanded;
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
height: 100%;
|
|
layout := VerticalLayout {
|
|
padding: root.border-radius;
|
|
spacing: 4px;
|
|
alignment: start;
|
|
|
|
always-visible := VerticalLayout {
|
|
padding: 0;
|
|
spacing: parent.spacing;
|
|
|
|
Text {
|
|
// TODO: text-transform: uppercase
|
|
text: {
|
|
if (root.queue-item.progress > 0) {
|
|
@tr("{}% - {}",root.queue-item.progress, PrinterQueue.statusString(root.queue-item.status))
|
|
} else {
|
|
PrinterQueue.statusString(root.queue-item.status)
|
|
}
|
|
}
|
|
color: DemoPalette.text-secondary;
|
|
font-size: DemoPalette.base-font-size * 0.75;
|
|
font-weight: 800;
|
|
letter-spacing: 1.56px;
|
|
}
|
|
|
|
Text {
|
|
text: root.queue-item.title;
|
|
overflow: elide;
|
|
color: DemoPalette.text-primary;
|
|
font-weight: 800;
|
|
font-size: DemoPalette.base-font-size * 1.125;
|
|
}
|
|
}
|
|
|
|
if (root.expanded || root.expanded-opacity > 0) : PrintDetails {
|
|
padding: 0px;
|
|
padding-bottom: root.border-radius / 2;
|
|
queue-item: root.queue-item;
|
|
opacity: root.expanded-opacity;
|
|
}
|
|
|
|
if (root.expanded || root.expanded-opacity > 0) : HorizontalLayout {
|
|
Rectangle {
|
|
horizontal-stretch: 0;
|
|
width: 10%;
|
|
}
|
|
|
|
PushButton {
|
|
clicked => {
|
|
root.show-job-details();
|
|
}
|
|
opacity: root.expanded-opacity;
|
|
text: @tr("More ");
|
|
}
|
|
|
|
Rectangle {
|
|
horizontal-stretch: 0;
|
|
width: 10%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
component NarrowPrinterQueueList inherits Flickable {
|
|
callback show-job-details(int);
|
|
|
|
VerticalLayout {
|
|
alignment: start;
|
|
padding: 0px;
|
|
spacing: 13.5px;
|
|
|
|
for queue-item[idx] in PrinterQueue.printer-queue: NarrowPrintQueueElement {
|
|
show-job-details => {
|
|
root.show-job-details(idx)
|
|
}
|
|
|
|
width: root.width;
|
|
queue-item: queue-item;
|
|
}
|
|
}
|
|
}
|
|
|
|
component ProgressBar inherits Rectangle {
|
|
in property <int> progress;
|
|
|
|
// FIXME: The intermediate rectangle is needed to allow the surrounding
|
|
// layout to freely resize the progress bar without affecting the design-intended
|
|
// height of 6px. The alternative of specifying a `max-height: 6px` will unfortunately
|
|
// also affect the width calculation and make it vanish altogether.
|
|
Rectangle {
|
|
y: parent.height / 2 - 3px;
|
|
height: 6px;
|
|
|
|
border-radius: 3px;
|
|
background: DemoPalette.neutral-box;
|
|
|
|
Rectangle {
|
|
x:0;
|
|
width: max(6px, root.progress * parent.width / 100);
|
|
border-radius: parent.border-radius;
|
|
background: DemoPalette.control-foreground;
|
|
}
|
|
}
|
|
}
|
|
|
|
component WidePrintQueueElement inherits Rectangle {
|
|
in property <PrinterQueueItem> queue-item;
|
|
|
|
callback cancel-job();
|
|
callback pause-job();
|
|
|
|
border-color: DemoPalette.neutral-box;
|
|
border-radius: 14px;
|
|
border-width: 2px;
|
|
background: DemoPalette.background;
|
|
|
|
GridLayout {
|
|
padding: parent.border-radius;
|
|
spacing: 3px;
|
|
|
|
HorizontalLayout {
|
|
width: 48%;
|
|
Text {
|
|
// TODO: text-transform: uppercase
|
|
text: {
|
|
if (root.queue-item.progress > 0) {
|
|
@tr("{}% - {}",root.queue-item.progress, PrinterQueue.statusString(root.queue-item.status))
|
|
} else {
|
|
PrinterQueue.statusString(root.queue-item.status)
|
|
}
|
|
}
|
|
color: DemoPalette.text-secondary;
|
|
font-size: DemoPalette.base-font-size * 0.75;
|
|
font-weight: 700;
|
|
letter-spacing: 1.56px;
|
|
horizontal-stretch: 1;
|
|
}
|
|
|
|
ProgressBar {
|
|
// Each progress bar should have the same size
|
|
// In principle it should be the smaller size which would fit next to the text foe each entry
|
|
// But since it is too hard to compute, just hardcode that for now
|
|
width: 50%; // 164px;
|
|
progress: root.queue-item.progress;
|
|
}
|
|
}
|
|
|
|
Text {
|
|
col: 0;
|
|
row: 1;
|
|
text: root.queue-item.title;
|
|
color: DemoPalette.text-primary;
|
|
overflow: elide;
|
|
font-weight: 700;
|
|
font-size: DemoPalette.base-font-size * 1.125;
|
|
horizontal-stretch: 1;
|
|
}
|
|
|
|
HorizontalLayout {
|
|
col: 0;
|
|
row: 3;
|
|
spacing: 14px;
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 0;
|
|
|
|
PushButton {
|
|
clicked => { root.pause-job(); }
|
|
|
|
text: @tr("Pause");
|
|
icon: @image-url("images/pause.svg");
|
|
}
|
|
|
|
PushButton {
|
|
clicked => { root.cancel-job(); }
|
|
primary: false;
|
|
text: @tr("Delete");
|
|
icon: @image-url("images/delete.svg");
|
|
}
|
|
}
|
|
|
|
PrintDetails {
|
|
row: 0;
|
|
col: 2;
|
|
rowspan: 4;
|
|
width: 40%;
|
|
padding: 0px;
|
|
padding-bottom: root.border-radius / 2;
|
|
queue-item: root.queue-item;
|
|
horizontal-stretch: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export component WidePrinterQueueList inherits Flickable {
|
|
VerticalLayout {
|
|
alignment: start;
|
|
padding: 0px;
|
|
spacing: 13.5px;
|
|
|
|
for queue-item[idx] in PrinterQueue.printer-queue: WidePrintQueueElement {
|
|
cancel-job => { PrinterQueue.cancel-job(idx) }
|
|
pause-job => { PrinterQueue.pause-job(idx) }
|
|
|
|
queue-item: queue-item;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component PrinterQueueView inherits Rectangle {
|
|
callback show-job-details(int);
|
|
|
|
border-radius: 27px;
|
|
background: DemoPalette.background.darker(20%);
|
|
|
|
VerticalLayout {
|
|
padding: 16px;
|
|
spacing: 16px;
|
|
|
|
Text {
|
|
text: @tr("Printing Queue");
|
|
color: DemoPalette.text-primary;
|
|
font-size: DemoPalette.base-font-size * 1.5;
|
|
font-weight: 700;
|
|
}
|
|
|
|
queue-list := NarrowPrinterQueueList {
|
|
show-job-details(idx) => {
|
|
root.show-job-details(idx)
|
|
}
|
|
|
|
width: root.width - 2*parent.padding; // FIXME why do we need this? bug in layout?
|
|
}
|
|
}
|
|
}
|