1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { DemoPalette, PushButton } from "./common.slint";
5
6enum JobStatus {
7 Waiting,
8 Printing
9}
10
11export struct PrinterQueueItem {
12 status: JobStatus,
13 progress: int,
14 title: string,
15 owner: string,
16 pages: int,
17 size: string, // number instead and format in .slint?
18 submission-date: string
19}
20
21export global PrinterQueue {
22 in property <[PrinterQueueItem]> printer-queue: [
23 { status: JobStatus.Printing, progress: 63, title: "Slint-Demo.jpeg", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
24 { status: JobStatus.Waiting, title: "Adressliste.docx", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
25 { status: JobStatus.Waiting, title: "210106-FinalPresentation.pdf", owner: "info@slint.dev", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" },
26 ];
27
28 callback start-job(string);
29 callback cancel-job(int);
30 callback pause-job(int);
31
32 public pure function statusString(status: JobStatus) -> string {
33 if (status == JobStatus.Printing) {
34 "PRINTING"
35 } else if (status == JobStatus.Waiting) {
36 "WAITING..."
37 } else {
38 "Unknown job status"
39 }
40 }
41}
42
43component PrintQueueDetailsLabel inherits Text {
44 font-weight: 500;
45 color: DemoPalette.control-foreground;
46 horizontal-stretch: 0;
47 font-size: DemoPalette.base-font-size * 0.9375;
48}
49
50component PrintQueueSeparator inherits Rectangle {
51 height: 1px;
52 border-width: 1px;
53 border-color: #BDC0D1;
54 horizontal-stretch: 2;
55}
56
57component PrintDetails inherits GridLayout {
58 in property <PrinterQueueItem> queue-item;
59
60 spacing: 3px;
61
62 Row {
63 PrintQueueDetailsLabel {
64 text: "Owner";
65 }
66
67 Text {
68 text: root.queue-item.owner;
69 color: DemoPalette.secondary-foreground-color;
70 overflow: elide;
71 horizontal-stretch: 1;
72 font-size: DemoPalette.base-font-size * 0.9375;
73 }
74 }
75
76 Row {
77 PrintQueueSeparator {
78 colspan: 2;
79 }
80 }
81
82 Row {
83 PrintQueueDetailsLabel {
84 text: "Pages";
85 }
86
87 Text {
88 text: root.queue-item.pages;
89 color: DemoPalette.secondary-foreground-color;
90 overflow: elide;
91 horizontal-stretch: 1;
92 font-size: DemoPalette.base-font-size * 0.9375;
93 }
94 }
95
96 Row {
97 PrintQueueSeparator {
98 colspan: 2;
99 }
100 }
101
102 Row {
103 PrintQueueDetailsLabel {
104 text: "Size";
105 }
106
107 Text {
108 text: root.queue-item.pages;
109 color: DemoPalette.secondary-foreground-color;
110 overflow: elide;
111 horizontal-stretch: 1;
112 font-size: DemoPalette.base-font-size * 0.9375;
113 }
114 }
115
116 Row {
117 PrintQueueSeparator {
118 colspan: 2;
119 }
120 }
121
122 Row {
123 PrintQueueDetailsLabel {
124 text: "Submitted";
125 }
126
127 Text {
128 text: root.queue-item.submission-date;
129 color: DemoPalette.secondary-foreground-color;
130 overflow: elide;
131 horizontal-stretch: 1;
132 font-size: DemoPalette.base-font-size * 0.9375;
133 }
134 }
135}
136
137component NarrowPrintQueueElement inherits Rectangle {
138 in property <PrinterQueueItem> queue-item;
139 in-out property <bool> expanded;
140
141 private property <float> expanded-opacity: 0;
142
143 callback cancel-job();
144
145 border-color: DemoPalette.control-outline-color;
146 border-radius: 6px;
147 border-width: 1px;
148 background: DemoPalette.printer-queue-item-background-color;
149 clip: true;
150 height: always-visible.min-height + layout.padding * 2;
151
152 states [
153 expanded when root.expanded : {
154 height: layout.min-height;
155 expanded-opacity: 1;
156 in {
157 animate height { duration: 200ms; easing: ease; }
158 animate expanded-opacity { duration: 200ms; }
159 }
160 out {
161 animate height { duration: 200ms; easing: ease; }
162 animate expanded-opacity { duration: 200ms; }
163 }
164 }
165 ]
166
167 TouchArea {
168 pointer-event(ev) => {
169 if (ev.kind == PointerEventKind.up) {
170 root.expanded = !root.expanded;
171 }
172 }
173 }
174
175 Rectangle {
176 height: 100%;
177 layout := VerticalLayout {
178 padding: root.border-radius;
179 spacing: 4px;
180 alignment: start;
181
182 always-visible := VerticalLayout {
183 padding: 0;
184 spacing: parent.spacing;
185
186 Text {
187 // TODO: text-transform: uppercase
188 text: {
189 if (root.queue-item.status == JobStatus.Printing) {
190 "\{root.queue-item.progress}% - \{PrinterQueue.statusString(root.queue-item.status)}"
191 } else {
192 PrinterQueue.statusString(root.queue-item.status)
193 }
194 }
195 color: DemoPalette.status-label-text-color;
196 font-size: DemoPalette.base-font-size * 0.75;
197 font-weight: 800;
198 letter-spacing: 1.26px;
199 }
200
201 Text {
202 text: root.queue-item.title;
203 overflow: elide;
204 color: DemoPalette.text-foreground-color;
205 font-weight: 800;
206 font-size: DemoPalette.base-font-size * 1.125;
207 }
208 }
209
210 if (root.expanded || root.expanded-opacity > 0) : PrintDetails {
211 padding: 0px;
212 padding-bottom: root.border-radius / 2;
213 queue-item: root.queue-item;
214 opacity: root.expanded-opacity;
215 }
216
217 if (root.expanded || root.expanded-opacity > 0) : HorizontalLayout {
218 Rectangle {
219 horizontal-stretch: 0;
220 width: 10%;
221 }
222
223 PushButton {
224 clicked => { root.cancel-job(); }
225
226 opacity: root.expanded-opacity;
227 text: "Delete";
228 icon: @image-url("images/delete.svg");
229 }
230
231 Rectangle {
232 horizontal-stretch: 0;
233 width: 10%;
234 }
235 }
236 }
237 }
238}
239
240component NarrowPrinterQueueList inherits Flickable {
241 VerticalLayout {
242 alignment: start;
243 padding: 0px;
244 spacing: 6px;
245
246 for queue-item[idx] in PrinterQueue.printer-queue: NarrowPrintQueueElement {
247 cancel-job => {
248 PrinterQueue.cancel-job(idx)
249 }
250
251 width: root.width;
252 queue-item: queue-item;
253 }
254 }
255}
256
257export component PrinterQueueView inherits Rectangle {
258 border-radius: 18px;
259 background: DemoPalette.night-mode ? DemoPalette.printer-action-background-color : #F4F6FF;
260
261 VerticalLayout {
262 padding: 6px;
263 spacing: 6px;
264
265 queue-list := NarrowPrinterQueueList { }
266 }
267}
268