1786023101

This commit is contained in:
2026-08-06 15:31:41 +02:00
parent 345a487f18
commit 4b30c6b4f6
13 changed files with 256 additions and 50 deletions

122
Cargo.lock generated
View File

@@ -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"

View File

@@ -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"

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
ui/images/dial-frame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
ui/images/dial-trim.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
ui/images/indicator.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

BIN
ui/images/light-hole.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

BIN
ui/images/light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
ui/images/metal-dial.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
ui/images/metal-lights.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -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;
}
}
}