1786023101
122
Cargo.lock
generated
@@ -127,6 +127,12 @@ version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
|
||||
|
||||
[[package]]
|
||||
name = "as-raw-xcb-connection"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
|
||||
|
||||
[[package]]
|
||||
name = "as-slice"
|
||||
version = "0.2.1"
|
||||
@@ -697,6 +703,7 @@ dependencies = [
|
||||
"objc2 0.5.2",
|
||||
"objc2-app-kit 0.2.2",
|
||||
"objc2-foundation 0.2.2",
|
||||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -809,6 +816,15 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf"
|
||||
dependencies = [
|
||||
"dtor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cursor-icon"
|
||||
version = "1.2.0"
|
||||
@@ -1016,6 +1032,12 @@ dependencies = [
|
||||
"linux-raw-sys 0.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtor"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.17.0"
|
||||
@@ -1488,6 +1510,16 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
|
||||
dependencies = [
|
||||
"rustix 1.1.4",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.24"
|
||||
@@ -1570,6 +1602,7 @@ dependencies = [
|
||||
"cgl",
|
||||
"dispatch2",
|
||||
"glutin_egl_sys",
|
||||
"glutin_glx_sys",
|
||||
"glutin_wgl_sys",
|
||||
"libloading",
|
||||
"objc2 0.6.4",
|
||||
@@ -1579,6 +1612,19 @@ dependencies = [
|
||||
"once_cell",
|
||||
"raw-window-handle",
|
||||
"windows-sys 0.52.0",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin-winit"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"glutin",
|
||||
"raw-window-handle",
|
||||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1591,6 +1637,16 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_glx_sys"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.6.1"
|
||||
@@ -1746,6 +1802,8 @@ dependencies = [
|
||||
"copypasta",
|
||||
"derive_more",
|
||||
"futures",
|
||||
"glutin",
|
||||
"glutin-winit",
|
||||
"i-slint-common",
|
||||
"i-slint-core",
|
||||
"i-slint-core-macros",
|
||||
@@ -4281,7 +4339,9 @@ version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3"
|
||||
dependencies = [
|
||||
"as-raw-xcb-connection",
|
||||
"bytemuck",
|
||||
"fastrand",
|
||||
"js-sys",
|
||||
"ndk",
|
||||
"objc2 0.6.4",
|
||||
@@ -4291,10 +4351,13 @@ dependencies = [
|
||||
"objc2-quartz-core 0.3.2",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.5.18",
|
||||
"rustix 1.1.4",
|
||||
"tiny-xlib",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4554,6 +4617,19 @@ dependencies = [
|
||||
"strict-num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-xlib"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a90a0ca3ee6a69f2ad28fd11621a4c3f03b371f366be500b64df260c4ffbafb4"
|
||||
dependencies = [
|
||||
"as-raw-xcb-connection",
|
||||
"ctor",
|
||||
"libloading",
|
||||
"pkg-config",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.3"
|
||||
@@ -5317,6 +5393,7 @@ dependencies = [
|
||||
"atomic-waker",
|
||||
"bitflags 2.13.1",
|
||||
"block2 0.5.1",
|
||||
"bytemuck",
|
||||
"calloop 0.13.0",
|
||||
"cfg_aliases",
|
||||
"concurrent-queue",
|
||||
@@ -5332,6 +5409,7 @@ dependencies = [
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-ui-kit 0.2.2",
|
||||
"orbclient",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.4.1",
|
||||
@@ -5344,6 +5422,8 @@ dependencies = [
|
||||
"web-sys",
|
||||
"web-time",
|
||||
"windows-sys 0.52.0",
|
||||
"x11-dl",
|
||||
"x11rb",
|
||||
"xkbcommon-dl",
|
||||
]
|
||||
|
||||
@@ -5390,6 +5470,48 @@ dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
|
||||
dependencies = [
|
||||
"as-raw-xcb-connection",
|
||||
"gethostname",
|
||||
"libc",
|
||||
"libloading",
|
||||
"once_cell",
|
||||
"rustix 1.1.4",
|
||||
"x11rb-protocol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb-protocol"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.6.1"
|
||||
|
||||
@@ -11,5 +11,8 @@ framebuffer = "0.3.1"
|
||||
linfb = { version = "0.2.1", default-features = false }
|
||||
slint = { version = "1.17.1", default-features = false, features = ["std", "compat-1-2", "libm", "renderer-software", "unsafe-single-threaded"] }
|
||||
|
||||
[features]
|
||||
dev = ["slint/backend-winit-x11"]
|
||||
|
||||
[build-dependencies]
|
||||
slint-build = "1.17.1"
|
||||
|
||||
19
src/main.rs
@@ -1,20 +1,21 @@
|
||||
mod rgba;
|
||||
#[cfg(not(feature = "dev"))]
|
||||
mod trekstor;
|
||||
|
||||
use crate::trekstor::Trekstor;
|
||||
|
||||
slint::include_modules!();
|
||||
|
||||
fn main() -> Result<(), slint::PlatformError> {
|
||||
slint::platform::set_platform(Box::new(Trekstor::new())).expect("set platform");
|
||||
#[cfg(not(feature = "dev"))]
|
||||
slint::platform::set_platform(Box::new(crate::trekstor::Trekstor::new()))
|
||||
.expect("set platform");
|
||||
|
||||
let ui = AppWindow::new()?;
|
||||
let ui = MainWindow::new()?;
|
||||
|
||||
let ui_handle = ui.as_weak();
|
||||
ui.on_request_increase_value(move || {
|
||||
let ui = ui_handle.unwrap();
|
||||
ui.set_counter(ui.get_counter() + 1);
|
||||
});
|
||||
// let ui_handle = ui.as_weak();
|
||||
// ui.on_request_increase_value(move || {
|
||||
// let ui = ui_handle.unwrap();
|
||||
// ui.set_counter(ui.get_counter() + 1);
|
||||
// });
|
||||
|
||||
ui.run()
|
||||
}
|
||||
|
||||
BIN
ui/images/blue-hint.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
ui/images/dial-frame.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
ui/images/dial-trim.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
ui/images/indicator.png
Normal file
|
After Width: | Height: | Size: 268 B |
BIN
ui/images/light-hole.png
Normal file
|
After Width: | Height: | Size: 338 B |
BIN
ui/images/light.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
ui/images/metal-dial.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
ui/images/metal-lights.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
ui/images/slint-logo-square-dark.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
162
ui/main.slint
@@ -1,50 +1,130 @@
|
||||
import { Button, VerticalBox, HorizontalBox, CheckBox } from "std-widgets.slint";
|
||||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export component AppWindow inherits Window {
|
||||
default-font-size: 24px;
|
||||
in-out property<int> counter: 42;
|
||||
callback request-increase-value();
|
||||
HorizontalBox {
|
||||
VerticalBox {
|
||||
width: 50%;
|
||||
Text {
|
||||
text: "Counter: \{root.counter}";
|
||||
export global AppState {
|
||||
out property <int> totalLights: 35;
|
||||
property <angle> degreesFilledWithLights: 360deg - (startAngle - endAngle);
|
||||
out property <int> volume: (normalizeAngle(angle - startAngle) / degreesFilledWithLights) * (totalLights + 1);
|
||||
out property <angle> startAngle: 120deg;
|
||||
out property <angle> endAngle: 60deg;
|
||||
out property <angle> angleGap: startAngle - endAngle;
|
||||
in-out property <angle> angle: startAngle;
|
||||
out property <length> elementRadius: 185px;
|
||||
|
||||
pure public function normalizeAngle(angle: angle) -> angle {
|
||||
return (angle + 360deg).mod(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
export component Light {
|
||||
in property <int> index;
|
||||
property <angle> gap: (360deg - (AppState.startAngle - AppState.endAngle)) / AppState.totalLights;
|
||||
property <angle> angle: (index * gap) + AppState.startAngle;
|
||||
property <bool> lightOn: index <= AppState.volume;
|
||||
|
||||
x: AppState.elementRadius * angle.cos();
|
||||
y: AppState.elementRadius * angle.sin();
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
states [
|
||||
lightOn when root.lightOn: {
|
||||
blueLed.opacity: 0.6;
|
||||
in {
|
||||
animate blueLed.opacity {
|
||||
duration: 100ms;
|
||||
easing: ease-in-sine;
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Increase value";
|
||||
clicked => {
|
||||
root.request-increase-value();
|
||||
out {
|
||||
animate blueLed.opacity {
|
||||
duration: 600ms;
|
||||
easing: ease-out-sine;
|
||||
}
|
||||
}
|
||||
}
|
||||
VerticalBox {
|
||||
width: 50%;
|
||||
alignment: start;
|
||||
CheckBox {
|
||||
text: "Armory Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Bedroom Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Hallway Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Kitchen Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Living Room Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Shower Light";
|
||||
}
|
||||
CheckBox {
|
||||
text: "Utilities Light";
|
||||
enabled: false;
|
||||
}
|
||||
CheckBox {
|
||||
text: "WC Light";
|
||||
]
|
||||
|
||||
Image {
|
||||
source: @image-url("images/light-hole.png");
|
||||
}
|
||||
|
||||
blueLed := Image {
|
||||
source: @image-url("images/light.png");
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
export component MainWindow inherits Window {
|
||||
preferred-width: 500px;
|
||||
preferred-height: 500px;
|
||||
background: #1e1d27;
|
||||
|
||||
base := Image {
|
||||
source: @image-url("images/dial-frame.png");
|
||||
}
|
||||
|
||||
ta := TouchArea {
|
||||
property <length> centerX: self.width / 2;
|
||||
property <length> centerY: self.height / 2;
|
||||
property <length> relativeX: ta.mouse-x - centerX;
|
||||
property <length> relativeY: ta.mouse-y - centerY;
|
||||
property <angle> lastAngle;
|
||||
property <bool> hovering: Math.pow(relativeX / 1px, 2) + Math.pow(relativeY / 1px, 2) < metalKnob.width / 2px * metalKnob.height / 2px;
|
||||
property <bool> touching: false;
|
||||
width: base.width;
|
||||
height: base.height;
|
||||
|
||||
mouse-cursor: touching ? grabbing : hovering ? grab : default;
|
||||
|
||||
pointer-event(event) => {
|
||||
let newAngle = AppState.normalizeAngle(atan2(relativeY / 1px, relativeX / 1px));
|
||||
if event.kind == PointerEventKind.down {
|
||||
if hovering {
|
||||
touching = true;
|
||||
lastAngle = newAngle;
|
||||
}
|
||||
} else if event.kind == PointerEventKind.up {
|
||||
touching = false;
|
||||
} else if event.kind == PointerEventKind.move {
|
||||
if touching {
|
||||
let nextAngle = AppState.normalizeAngle(AppState.angle - lastAngle + newAngle);
|
||||
// Check if the new angle is within the start and end angles
|
||||
if nextAngle >= AppState.startAngle || nextAngle <= AppState.endAngle {
|
||||
AppState.angle = nextAngle;
|
||||
}
|
||||
lastAngle = newAngle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metalKnob := Image {
|
||||
source: @image-url("images/metal-dial.png");
|
||||
transform-rotation: AppState.angle;
|
||||
}
|
||||
|
||||
Image {
|
||||
source: @image-url("images/metal-lights.png");
|
||||
}
|
||||
|
||||
Image {
|
||||
source: @image-url("images/dial-trim.png");
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
x: parent.width / 2;
|
||||
y: parent.height / 2;
|
||||
|
||||
Image {
|
||||
property <float> r: 0.5;
|
||||
x: r * root.width / 2 * AppState.angle.cos();
|
||||
y: r * root.height / 2 * AppState.angle.sin();
|
||||
source: @image-url("images/indicator.png");
|
||||
}
|
||||
|
||||
for i in AppState.totalLights + 1: Light {
|
||||
index: i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||