diff --git a/src/main.rs b/src/main.rs index b95658d..c871e1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ use std::rc::Rc; -use slint::{Color, VecModel}; +use std::thread; +use std::time::Duration; +use slint::{Color, Timer, TimerMode, VecModel}; slint::include_modules!(); +/// Zet HSL (hue/saturation/lightness) om naar RGB (u8). +/// `hue` in graden (0-360), `sat` en `light` als fractie (0-1). fn hsl_to_rgb(hue: f32, sat: f32, light: f32) -> (u8, u8, u8) { let c = (1.0 - (2.0 * light - 1.0).abs()) * sat; let x = c * (1.0 - ((hue / 60.0) % 2.0 - 1.0).abs()); @@ -24,20 +28,54 @@ fn hsl_to_rgb(hue: f32, sat: f32, light: f32) -> (u8, u8, u8) { ) } +/// Maakt het demo-venster aan, genereert een regenboogpalet van 32 kleuren +/// en start een timer die de balken en counter elke 100ms één stap laat schuiven. fn main() -> Result<(), slint::PlatformError> { let demo = DemoWindow::new()?; - let colors: Vec = (0..38) + let n = 32; + let colors: Vec = (0..n) .map(|i| { - let hue = (i as f32 / 38.0) * 360.0; + let hue = (i as f32 / n as f32) * 360.0; let (r, g, b) = hsl_to_rgb(hue, 0.85, 0.55); Color::from_rgb_u8(r, g, b).into() }) .collect(); let model: Rc> = Rc::new(VecModel::from(colors)); - demo.set_bar_colors(model.into()); - demo.set_window_title("DEMO Slint".into()); + demo.set_bar_colors(model.clone().into()); + demo.set_window_title("Slint & Rust Demo".into()); + demo.on_exit(|| slint::quit_event_loop().unwrap()); + + let weak_demo = demo.as_weak(); + let timer = Timer::default(); + timer.start(TimerMode::Repeated, std::time::Duration::from_millis(100), move || { + if let Some(demo) = weak_demo.upgrade() { + let first = model.remove(0); + model.push(first); + let c = demo.get_counter() + 1; + demo.set_counter(if c >= n { 0 } else { c }); + } + }); + + // ─── Voorbeeld: Arduino-achtige loop in een achtergrond-thread ─── + // Gebruik dit patroon als je zelf een loop nodig hebt (bv. sensoren uitlezen). + // De thread draait los van de UI, dus je moet `invoke_from_event_loop` + // gebruiken om het venster veilig te updaten. + // + // let weak = demo.as_weak(); + // thread::spawn(move || { + // let mut i = 0; + // loop { + // i += 1; + // let demo = weak.upgrade().unwrap(); + // // `invoke_from_event_loop` stuurt een actie naar de event loop + // slint::invoke_from_event_loop(move || { + // demo.set_counter(i % 32); + // }).unwrap(); + // thread::sleep(Duration::from_millis(100)); + // } + // }); demo.run() } diff --git a/ui/demo.slint b/ui/demo.slint index 12bd9be..125fcfb 100644 --- a/ui/demo.slint +++ b/ui/demo.slint @@ -2,21 +2,62 @@ export component DemoWindow inherits Window { width: 1920px; height: 480px; + callback exit; in property <[brush]> bar-colors; in property window-title; + in property counter; VerticalLayout { Rectangle { height: 60px; background: #2d2d2d; - Text { - text: window-title; - color: #ffffff; - font-size: 28px; - font-weight: 700; - horizontal-alignment: center; - vertical-alignment: center; + HorizontalLayout { + padding-right: 12px; + + HorizontalLayout { + horizontal-stretch: 1; + alignment: center; + + Text { + text: window-title+" ("; + color: #ffffff; + font-size: 28px; + font-weight: 700; + vertical-alignment: center; + } + + Text { + text: counter+")"; + color: #ffffff; + font-size: 28px; + font-weight: 700; + vertical-alignment: center; + } + } + + VerticalLayout { + alignment: center; + + Rectangle { + width: 70px; + height: 40px; + background: touch-area.has-hover ? #4a4a4a : #3a3a3a; + border-radius: 4px; + + exit-text := Text { + text: "Exit"; + color: touch-area.has-hover ? #000000 : #ffffff; + font-weight: 600; + horizontal-alignment: center; + vertical-alignment: center; + } + + touch-area := TouchArea { + clicked => { exit(); } + } + } + } } } @@ -25,7 +66,7 @@ export component DemoWindow inherits Window { spacing: 0px; for color in bar-colors: Rectangle { - width: 50px; + width: 60px; background: color; } }