/* LICENSE BEGIN This file is part of the SixtyFPS Project -- https://sixtyfps.io Copyright (c) 2021 Olivier Goffart Copyright (c) 2021 Simon Hausmann SPDX-License-Identifier: GPL-3.0-only This file is also available under commercial licensing terms. Please contact info@sixtyfps.io for more information. LICENSE END */ import { DemoPalette, PushButton } from "./common.60"; export struct PrinterQueueItem := { status: string, // WAITING..., PRINTING progress: int, title: string, owner: string, pages: int, size: string, // number instead and format in .60? submission-date: string } export global PrinterQueue := { callback start-job(string); callback cancel-job(int); callback pause-job(int); property <[PrinterQueueItem]> printer-queue: [ { status: "PRINTING", progress: 63, title: "210106-FinalPresentation.pdf", owner: "simon.hausmann@sixtyfps.io", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" }, { status: "WAITING...", title: "Adressliste.docx", owner: "simon.hausmann@sixtyfps.io", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" }, { status: "WAITING...", title: "210106-FinalPresentation.pdf", owner: "simon.hausmann@sixtyfps.io", pages: 6, size: "143kb", submission-date: "11:41 25/01/21" }, ]; } PrintQueueDetailsLabel := Text { font-weight: 500; color: DemoPalette.control-foreground; horizontal-stretch: 0; font-size: DemoPalette.base-font-size * 0.9375; } PrintQueueSeparator := Rectangle { height: 1px; border-width: 1px; border-color: #BDC0D1; horizontal-stretch: 2; } PrintDetails := GridLayout { property queue-item; spacing: 3px; Row { PrintQueueDetailsLabel { text: "Owner"; } Text { text: 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: "Pages"; } Text { text: 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: "Size"; } Text { text: 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: "Submitted"; } Text { text: queue-item.submission-date; color: DemoPalette.secondary-foreground-color; overflow: elide; horizontal-stretch: 1; font-size: DemoPalette.base-font-size * 0.9375; } } } NarrowPrintQueueElement := Rectangle { property queue-item; callback show-job-details(); border-color: DemoPalette.control-outline-color; border-radius: 14px; border-width: 2px; background: DemoPalette.printer-queue-item-background-color; clip: true; property expanded; property expanded-opacity: 0; height: always-visible.min-height + layout.padding * 2; states [ expanded when expanded : { height: layout.min-height; expanded-opacity: 1; } ] transitions [ in expanded : { animate height { duration: 200ms; easing: ease; } animate expanded-opacity { duration: 200ms; } } out expanded : { animate height { duration: 200ms; easing: ease; } animate expanded-opacity { duration: 200ms; } } ] TouchArea { clicked => { expanded = !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 (queue-item.status == "PRINTING") { "\{queue-item.progress}% - \{queue-item.status}" } else { queue-item.status } } color: DemoPalette.status-label-text-color; font-size: DemoPalette.base-font-size * 0.75; font-weight: 800; letter-spacing: 1.56px; } Text { text: queue-item.title; overflow: elide; color: DemoPalette.text-foreground-color; font-weight: 800; font-size: DemoPalette.base-font-size * 1.125; } } if (expanded || expanded-opacity > 0) : PrintDetails { padding: 0px; padding-bottom: root.border-radius / 2; queue-item: root.queue-item; opacity: expanded-opacity; } if (expanded || expanded-opacity > 0) : HorizontalLayout { Rectangle { horizontal-stretch: 0; width: 10%; } PushButton { opacity: expanded-opacity; text: "More "; clicked => { root.show-job-details(); } } Rectangle { horizontal-stretch: 0; width: 10%; } } } } } NarrowPrinterQueueList := Flickable { callback show-job-details(int); VerticalLayout { alignment: start; padding: 0px; spacing: 13.5px; for queue-item[idx] in PrinterQueue.printer-queue: NarrowPrintQueueElement { width: root.width; queue-item: queue-item; show-job-details => { root.show-job-details(idx) } } } } ProgressBar := Rectangle { property 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 { width: max(6px, progress * parent.width / 100); border-radius: parent.border-radius; background: DemoPalette.control-foreground; } } } WidePrintQueueElement := Rectangle { callback cancel-job(); callback pause-job(); property queue-item; border-color: DemoPalette.neutral-box; border-radius: 14px; border-width: 2px; background: DemoPalette.printer-queue-item-background-color; GridLayout { padding: parent.border-radius; spacing: 3px; HorizontalLayout { width: 48%; Text { // TODO: text-transform: uppercase text: { if (queue-item.status == "PRINTING") { "\{queue-item.progress}% - \{queue-item.status}" } else { queue-item.status } } color: DemoPalette.status-label-text-color; 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: queue-item.progress; } } Text { col: 0; row: 1; text: queue-item.title; color: DemoPalette.text-foreground-color; 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 { text: "Pause"; icon: @image-url("images/pause.svg"); clicked => { pause-job(); } } PushButton { primary: false; text: "Delete"; icon: @image-url("images/delete.svg"); clicked => { cancel-job(); } } } 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 WidePrinterQueueList := Flickable { VerticalLayout { alignment: start; padding: 0px; spacing: 13.5px; for queue-item[idx] in PrinterQueue.printer-queue: WidePrintQueueElement { queue-item: queue-item; cancel-job => { PrinterQueue.cancel-job(idx) } pause-job => { PrinterQueue.pause-job(idx) } } } } export PrinterQueueView := Rectangle { callback show-job-details(int); border-radius: 27px; background: DemoPalette.night-mode ? DemoPalette.printer-action-background-color : #F4F6FF; VerticalLayout { padding: 16px; spacing: 16px; Text { text: "Printing-Queue"; color: DemoPalette.text-foreground-color; font-size: DemoPalette.base-font-size * 1.5; font-weight: 700; } queue-list := NarrowPrinterQueueList { width: root.width - 2*parent.padding; // FIXME why do we need this? bug in layout? show-job-details(idx) => { root.show-job-details(idx) } } } }