1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { DemoPalette, Page } from "common.slint";
5import { HomePage } from "./home_page.slint";
6import { InkLevel, InkPage } from "./ink_page.slint";
7import { SettingsPage, PrinterSettings } from "./settings_page.slint";
8import { PrinterQueue } from "./printer_queue.slint";
9
10// re-export for the native code
11export { PrinterQueue, PrinterSettings }
12
13import "./fonts/NotoSans-Regular.ttf";
14import "./fonts/NotoSans-Bold.ttf";
15
16component SideBarIcon inherits Rectangle {
17 in-out property <bool> active;
18 in-out property <image> icon <=> i.source;
19 in-out property <brush> icon-colorize <=> i.colorize;
20
21 callback activate;
22 width: DemoPalette.side-bar-width;
23 height: 72px;
24
25 Rectangle {
26 x: DemoPalette.side-bar-margin;
27 GridLayout {
28 padding: 0px;
29 @children
30 }
31
32 i := Image {
33 colorize: root.active ? DemoPalette.active-page-icon-color : DemoPalette.inactive-page-icon-color;
34 animate colorize { duration: 125ms; }
35 }
36 }
37
38 TouchArea {
39 clicked => { root.activate(); }
40 }
41}
42
43export component MainWindow inherits Window {
44 /// Note that this property is overwritten in the .cpp and .rs code.
45 /// The data is only in this file so it looks good in the viewer
46 in property <[InkLevel]> ink-levels: [
47 {color: #0ff, level: 60%},
48 {color: #ff0, level: 80%},
49 {color: #f0f, level: 70%},
50 {color: #000, level: 30%},
51 ];
52 in-out property <int> active-page: 0;
53 in-out property <bool> dark-mode <=> DemoPalette.dark-mode;
54
55 callback quit();
56
57 min-width: 772px;
58 min-height: 504px;
59 title: @tr("Slint printer demo");
60 background: DemoPalette.primary;
61 default-font-family: "Noto Sans";
62 default-font-size: DemoPalette.base-font-size;
63
64 HorizontalLayout {
65 padding: 10px;
66 padding-left: 67px;
67
68 main-view := Rectangle {
69 height: 100%;
70 border-radius: 30px;
71 background: DemoPalette.background;
72
73 Rectangle {
74 clip: true;
75 x: main-view.border-radius / 2;
76 y: main-view.border-radius / 2;
77 width: main-view.width - main-view.border-radius;
78 height: main-view.height - main-view.border-radius;
79
80 function calcPageY(pageNumber: int) -> length {
81 if (root.active-page == pageNumber) {
82 return 0;
83 }
84 return root.active-page < pageNumber ? - self.height / 2 : parent.height / 2;
85 }
86
87 property <duration> page-animation-duration: 250ms;
88
89 home-page := HomePage {
90 property <int> pageNumber: 0;
91 y: calcPageY(0);
92 opacity: root.active-page == 0 ? 1 : 0;
93 animate y {
94 duration: page-animation-duration;
95 easing: ease-out-quad;
96 }
97 animate opacity {
98 duration: page-animation-duration;
99 easing: ease-out-quad;
100 }
101 }
102
103 SettingsPage {
104 property <int> pageNumber: 1;
105 y: calcPageY(1);
106 opacity: root.active-page == pageNumber ? 1 : 0;
107 animate y {
108 duration: page-animation-duration;
109 easing: ease-out-quad;
110 }
111 animate opacity {
112 duration: page-animation-duration;
113 easing: ease-out-quad;
114 }
115 }
116
117 InkPage {
118 property <int> pageNumber: 2;
119 y: calcPageY(pageNumber);
120 opacity: root.active-page == pageNumber ? 1 : 0;
121 ink-levels <=> root.ink-levels;
122 page-visible: root.active-page == pageNumber;
123 animate y {
124 duration: page-animation-duration;
125 easing: ease-out-quad;
126 }
127 animate opacity {
128 duration: page-animation-duration;
129 easing: ease-out-quad;
130 }
131 }
132 }
133 }
134 }
135
136 sidebar := Rectangle {
137 function icon-y(index: int) -> length {
138 return 100px // top padding
139 + index * 72px;
140 }
141 x: 0px;
142 width: DemoPalette.side-bar-width;
143
144 Image {
145 x: parent.width - self.width + 1px; // workaround pixel gap
146 y: sidebar.icon-y(root.active-page) - self.width / 2;
147 source: @image-url("images/page_selection.svg");
148 colorize: DemoPalette.background;
149 animate y { duration: 125ms; }
150 }
151
152 VerticalLayout {
153 y: 82px;
154
155 for page-icon[idx] in [
156 @image-url("images/home.svg"),
157 @image-url("images/settings.svg"),
158 @image-url("images/ink.svg"),
159 ]: SideBarIcon {
160 activate => {
161 root.active-page = idx;
162 }
163 icon: page-icon;
164 active: root.active-page == idx;
165 }
166 }
167
168 Rectangle {
169 y: sidebar.icon-y(3) + 17px;
170 x: DemoPalette.side-bar-margin + 8px;
171 background: DemoPalette.background;
172 height: 2px;
173 width: 37px;
174 }
175
176 SideBarIcon {
177 activate => {
178 DemoPalette.dark-mode = !DemoPalette.dark-mode;
179 }
180
181 icon: DemoPalette.dark-mode ? @image-url("images/moon_full.svg") : @image-url("images/moon.svg");
182 icon-colorize: DemoPalette.dark-mode ? #F1FF98 : DemoPalette.inactive-page-icon-color;
183
184 y: sidebar.icon-y(4) - 17px;
185 }
186 }
187}
188