199 lines
6.5 KiB
Plaintext
199 lines
6.5 KiB
Plaintext
import { Palette, HorizontalBox, VerticalBox } from "std-widgets.slint";
|
|
import { Icons } from "material/ui/icons/icons.slint";
|
|
import {
|
|
ListTile,
|
|
Vertical,
|
|
ElevatedButton,
|
|
SegmentedButton,
|
|
MaterialPalette,
|
|
FilledButton,
|
|
MaterialText,
|
|
MaterialTypography,
|
|
MaterialStyleMetrics,
|
|
} from "material/material.slint";
|
|
|
|
export struct WeatherData {
|
|
icon-index: int,
|
|
label: string,
|
|
temperature: float,
|
|
temperature_unit: string,
|
|
}
|
|
|
|
export struct ThermostatData {
|
|
id: string,
|
|
name: string,
|
|
current: float,
|
|
temperature: float,
|
|
unit: string,
|
|
target: int,
|
|
remainder: int,
|
|
state: string,
|
|
available: bool,
|
|
}
|
|
|
|
export component Climate inherits Rectangle {
|
|
in property <WeatherData> weather;
|
|
in property <[ThermostatData]> thermostats;
|
|
in property <bool> is-night;
|
|
|
|
in property <string> next-event-date;
|
|
in property <string> next-event-time;
|
|
in property <string> next-event-summary;
|
|
|
|
property <int> icon-index: weather.icon-index == 1 && is-night ? 2 : weather.icon-index;
|
|
|
|
callback set_temperature(string, float);
|
|
callback toggle_thermostat(string);
|
|
|
|
property <[image]> icons: [
|
|
@image-url("icons/sun.svg"),
|
|
@image-url("icons/cloud-sun.svg"),
|
|
@image-url("icons/cloud-moon.svg"),
|
|
@image-url("icons/cloud.svg"),
|
|
@image-url("icons/cloud-rain.svg"),
|
|
@image-url("icons/cloud-rain-wind.svg"),
|
|
@image-url("icons/cloud-lightning.svg"),
|
|
@image-url("icons/snowflake.svg"),
|
|
@image-url("icons/cloud-fog.svg"),
|
|
@image-url("icons/moon.svg"),
|
|
];
|
|
|
|
VerticalLayout {
|
|
spacing: MaterialStyleMetrics.spacing_16;
|
|
HorizontalLayout {
|
|
Vertical {
|
|
ListTile {
|
|
avatar_icon: Icons.event_upcoming;
|
|
avatar_foreground: Palette.foreground;
|
|
text: next-event-date;
|
|
supporting-text: next-event-summary;
|
|
height: 72px;
|
|
enabled: false;
|
|
VerticalLayout {
|
|
alignment: center;
|
|
horizontal_stretch: 1;
|
|
MaterialText {
|
|
text: next-event-time;
|
|
color: MaterialPalette.on_surface;
|
|
overflow: elide;
|
|
horizontal-alignment: right;
|
|
style: MaterialTypography.title_medium;
|
|
}
|
|
|
|
MaterialText {
|
|
text: "";
|
|
overflow: elide;
|
|
horizontal-alignment: right;
|
|
style: MaterialTypography.body_medium;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Vertical {
|
|
Text {
|
|
text: "\{weather.temperature}\{weather.temperature-unit}";
|
|
font-size: 36px;
|
|
font-weight: 700;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: right;
|
|
}
|
|
|
|
Text {
|
|
text: weather.label;
|
|
font-size: 24px;
|
|
font-weight: 500;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: right;
|
|
}
|
|
}
|
|
|
|
Image {
|
|
colorize: Palette.foreground;
|
|
width: 120px;
|
|
height: 105px;
|
|
source: icons[icon-index];
|
|
image-fit: contain;
|
|
}
|
|
}
|
|
|
|
for thermostat[index] in thermostats: ListTile {
|
|
avatar_icon: Icons.thermostat;
|
|
avatar_foreground: Palette.foreground;
|
|
text: thermostat.name;
|
|
supporting-text: thermostat.available ? thermostat.state : "UNAVAILABLE";
|
|
height: 72px;
|
|
enabled: false;
|
|
|
|
ElevatedButton {
|
|
icon: Icons.remove;
|
|
clicked => { root.set_temperature(thermostat.id, thermostat.temperature - 0.5) }
|
|
}
|
|
|
|
Rectangle {
|
|
width: 80px;
|
|
VerticalLayout {
|
|
HorizontalLayout {
|
|
Text {
|
|
text: thermostat.target;
|
|
font-size: 40px;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: right;
|
|
font-weight: 700;
|
|
height: 40px;
|
|
}
|
|
|
|
VerticalLayout {
|
|
padding-top: 2px;
|
|
Text {
|
|
text: thermostat.unit;
|
|
font-size: 14px;
|
|
horizontal-alignment: left;
|
|
vertical-alignment: top;
|
|
font-weight: 500;
|
|
height: 18px;
|
|
}
|
|
|
|
Text {
|
|
text: ".\{thermostat.remainder}";
|
|
// color: MaterialPalette.primary;
|
|
font-size: 14px;
|
|
horizontal-alignment: left;
|
|
vertical-alignment: bottom;
|
|
font-weight: 500;
|
|
height: 18px;
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
text: "\{thermostat.current} \{thermostat.unit}";
|
|
color: MaterialPalette.secondary;
|
|
font-size: 12px;
|
|
vertical-alignment: top;
|
|
horizontal-alignment: center;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
|
|
ElevatedButton {
|
|
icon: Icons.add;
|
|
clicked => { root.set_temperature(thermostat.id, thermostat.temperature + 0.5) }
|
|
}
|
|
|
|
if thermostat.state == "OFF": ElevatedButton {
|
|
icon: Icons.mode_heat_off;
|
|
clicked => { root.toggle_thermostat(thermostat.id) }
|
|
}
|
|
|
|
if thermostat.state == "HEAT": FilledButton {
|
|
icon: Icons.mode_heat;
|
|
clicked => { root.toggle_thermostat(thermostat.id) }
|
|
}
|
|
}
|
|
|
|
Rectangle { }
|
|
}
|
|
}
|