diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 5ebf3d8..a15a528 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -2,13 +2,24 @@ use std::sync::Arc; use osui::prelude::*; +pub struct KeyPress; + +impl Event for KeyPress { + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + fn main() { - let mut cx = Context::new(app); + let cx = Context::new(app); cx.refresh(); std::thread::spawn({ let cx = cx.clone(); - move || {} + move || loop { + crossterm::event::read().unwrap(); + cx.event(&KeyPress); + } }); loop { @@ -20,5 +31,12 @@ fn main() { fn app(cx: &Arc) -> Vec { let count = use_state(0); + cx.on_event({ + let count = count.clone(); + move |_cx, _event: &KeyPress| { + *count.get() += 1; + } + }); + vec![Node::String(Arc::new(move || format!("{count}")))] } diff --git a/src/component.rs b/src/component.rs index 9134446..a7e30af 100644 --- a/src/component.rs +++ b/src/component.rs @@ -1,19 +1,38 @@ -use std::sync::{Arc, Mutex}; +use std::{ + any::{Any, TypeId}, + collections::HashMap, + sync::{Arc, Mutex}, +}; use crate::Node; -pub type Component = Arc) -> Vec>; +pub trait Event { + fn as_any(&self) -> &dyn Any; +} + +impl<'a> dyn Event + 'a { + pub fn get(&self) -> Option<&T> { + self.as_any().downcast_ref() + } +} + +pub type Component = Arc) -> Vec + Send + Sync>; +pub type EventHandler = Arc, &dyn Event) + Send + Sync>>; pub struct Context { component: Mutex, nodes: Mutex>, + event_handlers: Mutex>>, } impl Context { - pub fn new) -> Vec + 'static>(component: F) -> Arc { + pub fn new) -> Vec + Send + Sync + 'static>( + component: F, + ) -> Arc { Arc::new(Self { component: Mutex::new(Arc::new(component)), nodes: Mutex::new(Vec::new()), + event_handlers: Mutex::new(HashMap::new()), }) } @@ -25,4 +44,30 @@ impl Context { pub fn get_nodes(self: &Arc) -> Vec { self.nodes.lock().unwrap().clone() } + + pub fn on_event, &T) + Send + Sync + 'static>( + self: &Arc, + handler: F, + ) { + self.event_handlers + .lock() + .unwrap() + .entry(TypeId::of::()) + .or_insert_with(|| Vec::new()) + .push(Arc::new(Mutex::new( + move |ctx: &Arc, event: &dyn Event| { + if let Some(e) = event.get::() { + (handler)(ctx, e); + } + }, + ))); + } + + pub fn event(self: &Arc, event: &E) { + if let Some(v) = self.event_handlers.lock().unwrap().get(&TypeId::of::()) { + for i in v { + (i.lock().unwrap())(&self.clone(), event); + } + } + } } diff --git a/src/lib.rs b/src/lib.rs index 0384e0f..357c3ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ pub mod prelude { #[derive(Clone)] pub enum Node { - String(Arc String>), + String(Arc String + Send + Sync>), Component(component::Component), }