diff --git a/bike-lights/core/src/lib.rs b/bike-lights/core/src/lib.rs index 5c4ed49..d9b3c06 100644 --- a/bike-lights/core/src/lib.rs +++ b/bike-lights/core/src/lib.rs @@ -7,31 +7,30 @@ mod types; pub use types::{DashboardPattern, Pattern, RGB}; pub trait UI { + fn check_event(&self) -> Option; fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern); } pub trait Animation { - fn tick(&self, frame: Duration) -> (DashboardPattern, Pattern); + fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern); } pub struct DefaultAnimation {} impl Animation for DefaultAnimation { - fn tick(&self, _: Duration) -> (DashboardPattern, Pattern) { + fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern) { (PRIDE_DASHBOARD, PRIDE) } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Event { Brake, BrakeRelease, LeftBlinker, - LeftBlinkerRelease, NextPattern, PreviousPattern, RightBlinker, - RightBlinkerRelease, } #[derive(Clone)] @@ -63,8 +62,12 @@ impl App { } } - pub fn tick(&mut self, frame: Duration) { - let (dashboard, lights) = self.current_animation.tick(frame); + pub fn tick(&mut self, time: std::time::Instant) { + match self.ui.check_event() { + Some(event) => println!("event received: {:?}", event), + None => (), + }; + let (dashboard, lights) = self.current_animation.tick(time); self.dashboard_lights = dashboard.clone(); self.lights = lights.clone(); self.ui.update_lights(dashboard, lights); diff --git a/bike-lights/simulator/src/main.rs b/bike-lights/simulator/src/main.rs index e959e68..be422e2 100644 --- a/bike-lights/simulator/src/main.rs +++ b/bike-lights/simulator/src/main.rs @@ -1,8 +1,13 @@ use adw::prelude::*; use glib::{Object, Sender}; use gtk::subclass::prelude::*; -use lights_core::{App, DashboardPattern, Pattern, RGB, UI}; -use std::{cell::RefCell, env, rc::Rc}; +use lights_core::{App, DashboardPattern, Event, Pattern, RGB, UI}; +use std::{ + cell::RefCell, + env, + rc::Rc, + sync::mpsc::{Receiver, TryRecvError}, +}; const WIDTH: i32 = 640; const HEIGHT: i32 = 480; @@ -202,18 +207,26 @@ impl BikeLights { } struct GTKUI { - tx: Rc>>>, + tx: Sender, + rx: Receiver, } impl UI for GTKUI { + fn check_event(&self) -> Option { + match self.rx.try_recv() { + Ok(event) => Some(event), + Err(TryRecvError::Empty) => None, + Err(TryRecvError::Disconnected) => None, + } + } + fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) { - if let Some(tx) = self.tx.borrow().as_ref() { - tx.send(Update { + self.tx + .send(Update { dashboard: dashboard_lights, lights, }) .unwrap(); - } } } @@ -223,14 +236,17 @@ fn main() { .build(); adw_app.connect_activate(move |adw_app| { - let (tx, rx) = gtk::glib::MainContext::channel::(gtk::glib::Priority::DEFAULT); + let (update_tx, update_rx) = + gtk::glib::MainContext::channel::(gtk::glib::Priority::DEFAULT); + let (event_tx, event_rx) = std::sync::mpsc::channel(); std::thread::spawn(move || { let mut bike_app = App::new(Box::new(GTKUI { - tx: Rc::new(RefCell::new(Some(tx))), + tx: update_tx, + rx: event_rx, })); loop { - bike_app.tick(std::time::Duration::from_millis(0)); + bike_app.tick(std::time::Instant::now()); std::thread::sleep(std::time::Duration::from_millis(100)); } }); @@ -254,6 +270,27 @@ fn main() { let brake_button = gtk::Button::builder().label("Brakes").build(); let right_button = gtk::Button::builder().label("R").build(); + left_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::LeftBlinker); + } + }); + + brake_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::Brake); + } + }); + + right_button.connect_clicked({ + let event_tx = event_tx.clone(); + move |_| { + let _ = event_tx.send(Event::RightBlinker); + } + }); + controls.append(&left_button); controls.append(&brake_button); controls.append(&right_button); @@ -273,7 +310,7 @@ fn main() { layout.append(&dashboard_lights); layout.append(&bike_lights); - rx.attach(None, { + update_rx.attach(None, { let dashboard_lights = dashboard_lights.clone(); let bike_lights = bike_lights.clone(); move |Update { dashboard, lights }| {