slint/examples/iot-dashboard/iot-dashboard.60
Simon Hausmann a7ce64657c Restore source compatibility for drop-shadow-blur
Let's keep source compatibility and define `drop-shadow-blur` to be a radius.
The CSS spec says that the standard deviation is half of the radius.

We just need to scale again and increase the shadow rect to make sure that no borders are visible.
2021-05-20 12:14:05 +02:00

458 lines
13 KiB
Text

/* LICENSE BEGIN
This file is part of the SixtyFPS Project -- https://sixtyfps.io
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
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 */
/*
The design from this file is inspired from the design in
https://github.com/peter-ha/qskinny/tree/iot-dashboard/examples/iot-dashboard
Original license:
/****************************************************************************
**
** Copyright 2021 Edelhirsch Software GmbH. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of the copyright holder nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
*/
struct Palette := {
menuBar : brush,
mainContent : brush,
box : brush,
lightDisplay : brush,
pieChart : brush,
roundButton : brush,
weekdayBox : brush,
text : brush,
shadow : brush,
}
global Skin := {
property<bool> day: true;
property<Palette> palette : day ? {
menuBar : #6D7BFB,
mainContent : #fbfbfb,
box : #ffffff,
lightDisplay : #ffffff,
pieChart : #ffffff,
roundButton : #f7f7f7,
weekdayBox : #f4f4f4,
text : #000,
shadow : #0001, // ### added alpha
} : {
menuBar : #2937A7,
mainContent : #040404,
box : #000000,
lightDisplay : #000000,
pieChart : #000000,
roundButton : #0a0a0a,
weekdayBox : #0c0c0c,
text : #fff,
shadow : #fff1, // ### added alpha
};
property<float> f: 1.5; // FIXME: why do the font looks completely different with the same size on the QML demo
// From Skin::initHints in Skin.cpp
property <length> DefaultFont: 12pt * f;
property <length> TinyFont: 9pt * f;
property <length> SmallFont: 10pt * f;
property <length> MediumFont: 13pt * f;
property <length> LargeFont: 20pt * f;
property <length> HugeFont: 27pt * f; // (also, bold)
property <length> TitleFont: 10pt * f; // (also, bold)
}
export Clock := VerticalLayout {
property <string> time <=> time_label.text;
Text {
text: "Current time";
font_size: Skin.TitleFont;
font_weight: 700;
}
time_label := Text {
// FIXME: actual time
text: "10:02:45";
font_size: Skin.HugeFont;
font_weight: 700;
color: #6776FF;
}
}
PieChartPainted := Rectangle {
property <brush> brush <=> p.stroke;
property <float> progress;
back := Path {
width: 100%;
height: 100%;
stroke-width: parent.width / 6;
stroke: #aaaaaa40;
MoveTo {
x: 50;
y: 0;
}
ArcTo {
radius-x: 50;
radius-y: 50;
x: 50;
y: 100;
sweep: true;
large_arc: true;
}
MoveTo { x: 50; y: 100; }
ArcTo {
radius-x: 50;
radius-y: 50;
x: 50;
y: 0;
sweep: true;
large_arc: true;
}
// FIXME: would be nice if there was another way to define the bounding box of the path
MoveTo {
x: 0;
y: 0;
}
MoveTo {
x: 100;
y: 100;
}
}
p := Path {
width: 100%;
height: 100%;
stroke-width: parent.width / 6;
MoveTo {
x: 50;
y: 0;
}
ArcTo {
radius-x: 50;
radius-y: 50;
y: 50 - 50*cos(-progress * 360deg);
x: 50 - 50*sin(-progress * 360deg);
sweep: true;
large-arc: progress > 0.5;
}
// FIXME: would be nice if there was another way to define the bounding box of the path
MoveTo {
x: 0;
y: 0;
}
MoveTo {
x: 100;
y: 100;
}
}
}
// From TopBar.cpp
export TopBar := HorizontalLayout {
padding: 5px;
spacing: 0px;
for item in [
{ string: "Living Room", progress: 25, value: 175, color: #ff3122, gradient: @linear-gradient(0deg, #FF5C00, #FF3122) },
{ string: "Bedroom", progress: 45, value: 205, color: #6776ff, gradient: @linear-gradient(0deg, #6776FF, #6100FF) },
{ string: "Bathroom", progress: 15, value: 115, color: #f99055, gradient: @linear-gradient(0deg, #FFCE50, #FF3122) },
{ string: "Kitchen", progress: 86, value: 289, color: #6776ff, gradient: @linear-gradient(0deg, #6776FF, #6100FF) },
] : VerticalLayout {
padding: 0px;
spacing: 0px;
Text {
font_size: Skin.SmallFont;
text: item.string;
}
HorizontalLayout {
PieChartPainted {
brush: item.gradient;
progress: item.progress / 100;
Text {
width: 100%;
height: 100%;
vertical_alignment: center;
horizontal_alignment: center;
text: item.progress + "%";
color: item.color;
font_size: Skin.TinyFont;
}
}
VerticalLayout {
Text { text: item.value; }
Text { text: "kwH"; }
}
Rectangle {}
}
}
@children
}
// From Box.cpp
Box := Rectangle {
property <string> title;
background: Skin.palette.box;
drop-shadow-offset-x: 6px;
drop-shadow-offset-y: 6px;
drop-shadow-blur: 6px;
drop-shadow-color: Skin.palette.shadow;
VerticalLayout {
if (root.title != "") : Text {
text <=> root.title;
font_size: Skin.TitleFont;
}
padding: 15px;
@children
}
}
// From RoundedIcon.cpp
RoundedIcon := Rectangle {
property <bool> isBright;
property <bool> isSmall;
property <image> iconName <=> m_graphicLabel.source;
background: isBright ? @linear-gradient(180deg, #ff7d34, #ff3122) : @linear-gradient(180deg, #6776FF, #6100FF);
border-radius: 6px;
height: isSmall ? 60px : 68px;
width: isSmall ? 60px : 68px;
m_graphicLabel := Image {
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
}
}
//from Usage.cpp
UsageSpacer := Text {
text: "_____";
font_size: Skin.SmallFont;
color: #dddddd;
horizontal_stretch: 2;
}
export Usage := Box {
title: "Usage";
HorizontalLayout {
Text { text: "Usage Today"; font_size: Skin.SmallFont; }
UsageSpacer { }
Text { text: "0,5 kwH"; font_size: Skin.SmallFont; }
}
HorizontalLayout {
Text { text: "Usage this month"; font_size: Skin.SmallFont; }
UsageSpacer { }
Text { text: "60 kwH"; font_size: Skin.SmallFont; }
}
HorizontalLayout {
Text { text: "Total working hours"; font_size: Skin.SmallFont; }
UsageSpacer { }
Text { text: "125 hrs"; font_size: Skin.SmallFont; }
}
}
// From UpAndDownButton.cpp
RoundButton := Image { //### QskPushButton
property <bool> is_up; // ### QskAspect
Image {
source: is_up ? @image-url("images/up.svg") : @image-url("images/down.svg");
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
}
}
UpAndDownButton := Rectangle {
// FIXME: this is actually on the RoundButton
border-radius: 30px;
width: 45px;
background: Skin.palette.roundButton;
VerticalLayout {
RoundButton { is_up: true; }
RoundButton { is_up: false; }
}
}
// From BoxWithButtons.cpp
ButtonValueLabel := Text {
property <string> value <=> text;
font_size: Skin.HugeFont;
font_weight: 700;
color: #929cb2;
}
TitleAndValueBox := VerticalLayout { horizontal-stretch: 100; }
BoxWithButtons := Box {
property <image> iconFile <=> ri.iconName; //### in original, this is derived from title
property <string> value <=> val.value;
property <bool> isBright <=> ri.isBright;
property <string> title_ <=> titleLabel.text;
HorizontalLayout {
padding: 8px;
spacing: 20px;
VerticalLayout { // FIXME: there is no such layout in the original, we should so without it
alignment: center;
ri := RoundedIcon { }
}
TitleAndValueBox {
titleLabel := Text {
font_size: Skin.TitleFont;
font_weight: 700;
}
val := ButtonValueLabel { }
}
UpAndDownButton { }
}
}
export IndoorTemperature := BoxWithButtons {
title_: "Indoor Temperature";
iconFile: @image-url("images/indoor-temperature.png");
value: "+24";
isBright: true;
}
export Humidity := BoxWithButtons {
property <string> humidity_percent <=> value;
title_: "Humidity";
iconFile: @image-url("images/humidity.png");
value: "30%";
isBright: false;
}
// from MyDevices.cpp
Device := VerticalLayout {
property <string> name <=> t.text;
property <image> iconName <=> ri.iconName; // ### based on the name in the original
property <bool> isBright <=> ri.isBright;
HorizontalLayout { // ### FIXME: this latour is not in the original
alignment: center;
ri := RoundedIcon {
opacity: 0.15;
}
}
t := Text {
font_size: Skin.TinyFont;
horizontal_alignment: center;
}
}
export MyDevices := Box {
title: "My devices";
GridLayout {
spacing: 15px;
Row {
Device{
name: "Lamps";
iconName: @image-url("images/lamps.png");
isBright: true;
}
Device{
name: "Music System";
iconName: @image-url("images/music-system.png");
isBright: false;
}
}
Row {
Device{
name: "AC";
iconName: @image-url("images/ac.png");
isBright: false;
}
Device{
name: "Router";
iconName: @image-url("images/router.png");
isBright: true;
}
}
}
}
// ## FIXME
export UsageDiagram := Box {
Rectangle {}
}
// From LightIntensity.cpp
// ## FIXME
export LightIntensity := Box {
title: "Light intensity";
Rectangle {}
}
// From MenuBar.cpp
MenuItem := Rectangle {
property <image> icon <=> i.source;
property<string> name <=> t.text;
property<bool> active;
background: active ? rgba(100%, 100%, 100%, 14%) : ma.has_hover ? rgba(100%, 100%, 100%, 9%) : transparent;
ma := TouchArea {}
HorizontalLayout {
alignment: start;
padding: 8px;
padding-left: 30px;
padding-right: 30px;
i := Image { }
t := Text { color: white; }
}
}
// From MenuBar.cpp
export MenuBar := Rectangle {
background: Skin.palette.menuBar;
property<int> active: 0;
minimum-width: 140px;
VerticalLayout {
padding-left: 0px;
padding-top: 35px;
padding-right: 0px;
padding-bottom: 12px;
spacing: 8px;
Image {
source: @image-url("images/main-icon.png");
}
//### In the original, the icon is derived from the name
for entry[idx] in [
{ name: "Dashboard", icon: @image-url("images/dashboard.png") },
{ name: "Rooms", icon: @image-url("images/rooms.png") },
{ name: "Devices", icon: @image-url("images/devices.png") },
{ name: "Statistics", icon: @image-url("images/statistics.png") },
{ name: "Storage", icon: @image-url("images/storage.png") },
{ name: "Members", icon: @image-url("images/members.png") },
] : MenuItem {
name: entry.name;
icon: entry.icon;
active: root.active == idx;
}
Rectangle {}
MenuItem { name: "Logout"; icon: @image-url("images/logout.png"); }
}
}