From f401d4a99501f0e4afbed73233be2a55ee209e8b Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 28 Jun 2025 03:51:13 +0200 Subject: [PATCH] better structure --- src/element/input.rs | 6 ++-- src/events.rs | 64 ++++++++++++++++--------------------- src/extensions/keypress.rs | 10 +++--- src/extensions/mod.rs | 14 ++++---- src/extensions/tick_rate.rs | 10 +++--- src/lib.rs | 19 ++++++----- src/macros.rs | 5 +++ src/main.rs | 42 +++++++++++++----------- src/state.rs | 8 ++--- 9 files changed, 93 insertions(+), 85 deletions(-) diff --git a/src/element/input.rs b/src/element/input.rs index ec927b6..b085104 100644 --- a/src/element/input.rs +++ b/src/element/input.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crossterm::event::KeyEvent; use crate::{ @@ -13,7 +15,7 @@ impl Input { } impl Element for Input { - fn init(&mut self, events: &mut crate::events::EventManager) { + fn init(&mut self, events: &Arc) { event_handler!(Self, self, events, on_keypress); } @@ -39,7 +41,7 @@ impl Element for Input { } impl KeyPressEventHandler for Input { - fn on_keypress(&mut self, events: &mut EventManager, event: Box) { + fn on_keypress(&mut self, events: &Arc, event: Box) { match event.code { crossterm::event::KeyCode::Char(c) => { self.0.insert(self.1, c); diff --git a/src/events.rs b/src/events.rs index 052f00e..1138089 100644 --- a/src/events.rs +++ b/src/events.rs @@ -12,59 +12,51 @@ pub trait Event { fn as_any(self: Box) -> Box; } -#[derive(Clone)] -pub struct EventHandlerFn(pub Arc)>>); - -impl std::fmt::Debug for EventHandlerFn { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "FnMut()") - } -} - pub struct EventManager { - handlers: HashMap>, - states: Option>, + handlers: + Mutex, Box)>>>>>, + states: Mutex>>, } impl EventManager { - pub fn new() -> EventManager { - EventManager { - handlers: HashMap::new(), - states: None, - } + pub fn new() -> Arc { + Arc::new(EventManager { + handlers: Mutex::new(HashMap::new()), + states: Mutex::new(None), + }) } - pub fn on) + 'static>( - &mut self, + pub fn on, Box) + 'static>( + self: &Arc, mut f: F, ) { - let states = self.states.clone(); - let wrapper = Arc::new(Mutex::new( - move |e: &mut EventManager, evt: Box| { - if let Ok(concrete) = evt.as_any().downcast::() { - f(e, concrete); - if let Some(states) = &states { - states.clone().flush(); - } - } - }, - )) as Arc)>>; - + let states = self.states.lock().unwrap().clone(); self.handlers + .lock() + .unwrap() .entry(TypeId::of::()) .or_insert_with(Vec::new) - .push(EventHandlerFn(wrapper)); + .push(Arc::new(Mutex::new( + move |e: &Arc, evt: Box| { + if let Ok(concrete) = evt.as_any().downcast::() { + f(&e, concrete); + if let Some(states) = &states { + states.clone().flush(); + } + } + }, + ))); } - pub fn dispatch(&mut self, evt: E) { + pub fn dispatch(self: &Arc, evt: E) { let tid = evt.type_id(); - if let Some(handlers) = self.handlers.get_mut(&tid) { + if let Some(handlers) = self.handlers.lock().unwrap().get_mut(&tid) { // Clone handlers to avoid borrowing self during call let handler_clones: Vec<_> = handlers.iter().cloned().collect(); for h in handler_clones { - let mut ha = h.0.lock().unwrap(); + let mut ha = h.lock().unwrap(); (ha)(self, Box::new(evt.clone())); } } @@ -74,7 +66,7 @@ impl EventManager { } } - pub fn set_state_manager(&mut self, states: Arc) { - self.states = Some(states); + pub fn set_state_manager(self: &Arc, states: Arc) { + *self.states.lock().unwrap() = Some(states); } } diff --git a/src/extensions/keypress.rs b/src/extensions/keypress.rs index 16be086..0eb7d17 100644 --- a/src/extensions/keypress.rs +++ b/src/extensions/keypress.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crossterm::event::KeyEvent; use crate::{ @@ -13,13 +15,13 @@ impl Event for KeyEvent { } pub trait KeyPressEventHandler { - fn on_keypress(&mut self, events: &mut EventManager, event: Box); + fn on_keypress(&mut self, events: &Arc, event: Box); } pub struct KeyPressExtension; impl Extension for KeyPressExtension { - fn init(&mut self, _: &mut Screen, events: &mut EventManager) { + fn init(&mut self, _: &mut Screen, events: &Arc) { crossterm::terminal::enable_raw_mode().unwrap(); crate::utils::clear().unwrap(); crate::utils::hide_cursor().unwrap(); @@ -31,9 +33,9 @@ impl Extension for KeyPressExtension { }); } - fn tick_start(&mut self, _: &mut Screen, _: &mut EventManager) {} + fn tick_start(&mut self, _: &mut Screen, _: &Arc) {} - fn tick_end(&mut self, _: &mut Screen, events: &mut EventManager) { + fn tick_end(&mut self, _: &mut Screen, events: &Arc) { if crossterm::event::poll(std::time::Duration::from_millis(13)).unwrap() { match crossterm::event::read().unwrap() { crossterm::event::Event::Key(e) => { diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 1e7b187..9e09980 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -1,30 +1,32 @@ pub mod keypress; pub mod tick_rate; +use std::sync::Arc; + use crate::{events::EventManager, Screen}; pub trait Extension { - fn init(&mut self, screen: &mut Screen, events: &mut EventManager); - fn tick_start(&mut self, screen: &mut Screen, events: &mut EventManager); - fn tick_end(&mut self, screen: &mut Screen, events: &mut EventManager); + fn init(&mut self, screen: &mut Screen, events: &Arc); + fn tick_start(&mut self, screen: &mut Screen, events: &Arc); + fn tick_end(&mut self, screen: &mut Screen, events: &Arc); } pub struct ExtensionManager(Vec>); impl Extension for ExtensionManager { - fn init(&mut self, screen: &mut Screen, events: &mut EventManager) { + fn init(&mut self, screen: &mut Screen, events: &Arc) { for ext in &mut self.0 { ext.init(screen, events); } } - fn tick_start(&mut self, screen: &mut Screen, events: &mut EventManager) { + fn tick_start(&mut self, screen: &mut Screen, events: &Arc) { for ext in &mut self.0 { ext.tick_start(screen, events); } } - fn tick_end(&mut self, screen: &mut Screen, events: &mut EventManager) { + fn tick_end(&mut self, screen: &mut Screen, events: &Arc) { for ext in &mut self.0 { ext.tick_end(screen, events); } diff --git a/src/extensions/tick_rate.rs b/src/extensions/tick_rate.rs index 63f97d1..7f624bc 100644 --- a/src/extensions/tick_rate.rs +++ b/src/extensions/tick_rate.rs @@ -1,13 +1,15 @@ -use crate::extensions::Extension; +use std::sync::Arc; + +use crate::{events::EventManager, extensions::Extension}; pub struct TickRate(pub u8); impl Extension for TickRate { - fn init(&mut self, _: &mut crate::Screen, _: &mut crate::events::EventManager) {} + fn init(&mut self, _: &mut crate::Screen, _: &Arc) {} - fn tick_end(&mut self, _: &mut crate::Screen, _: &mut crate::events::EventManager) { + fn tick_end(&mut self, _: &mut crate::Screen, _: &Arc) { std::thread::sleep(std::time::Duration::from_millis(1000 / self.0 as u64)); } - fn tick_start(&mut self, _: &mut crate::Screen, _: &mut crate::events::EventManager) {} + fn tick_start(&mut self, _: &mut crate::Screen, _: &Arc) {} } diff --git a/src/lib.rs b/src/lib.rs index 4598d67..a67f12d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use std::{ any::{Any, TypeId}, collections::HashMap, + sync::Arc, }; use crate::{ @@ -23,7 +24,7 @@ pub trait Element { #[allow(unused)] fn render(&mut self, scope: &mut RenderScope) {} #[allow(unused)] - fn init(&mut self, events: &mut EventManager) {} + fn init(&mut self, events: &Arc) {} fn as_any(&self) -> &dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any; } @@ -61,12 +62,14 @@ impl Widget { pub struct Screen { pub elements: Vec, + pub events: Arc, } impl Screen { pub fn new() -> Screen { Screen { elements: Vec::new(), + events: EventManager::new(), } } @@ -76,22 +79,18 @@ impl Screen { self.elements.last_mut().unwrap() } - pub fn run( - &mut self, - events: &mut EventManager, - extensions: &mut ExtensionManager, - ) -> std::io::Result<()> { + pub fn run(&mut self, extensions: &mut ExtensionManager) -> std::io::Result<()> { let mut scope = RenderScope::new(); for elem in &mut self.elements { elem.component(Transform::new()); - elem.0.init(events); + elem.0.init(&self.events); } - extensions.init(self, events); + extensions.init(self, &self.events.clone()); loop { - extensions.tick_start(self, events); + extensions.tick_start(self, &self.events.clone()); utils::clear().unwrap(); for elem in &mut self.elements { @@ -108,7 +107,7 @@ impl Screen { scope.draw(); } - extensions.tick_end(self, events); + extensions.tick_end(self, &self.events.clone()); } } } diff --git a/src/macros.rs b/src/macros.rs index 9dc8b22..083462a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -122,3 +122,8 @@ macro_rules! event_handler { $events.on(move |es, e| unsafe { (*self_ref).$method(es, e) }); }}; } + +#[macro_export] +macro_rules! rsx { + () => {}; +} diff --git a/src/main.rs b/src/main.rs index d30269f..169fb6d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,27 +3,31 @@ use std::sync::Arc; use crossterm::event::KeyEvent; use osui::{ element::rect::Rect, - events::{Close, EventManager}, - extensions::{keypress::KeyPressExtension, tick_rate::TickRate, ExtensionManager}, + events::Close, + extensions::{keypress::KeyPressExtension, ExtensionManager}, state::StateManager, style::Transform, Screen, }; fn main() { - let states = StateManager::new(app); - app(states); + init(&StateManager::new(init)); } -fn app(states: Arc) { +fn init(states: &Arc) { let mut screen = Screen::new(); - let mut extensions = ExtensionManager::new(); - let mut events = EventManager::new(); + screen.events.set_state_manager(states.clone()); - extensions.add(TickRate(50)); + let mut extensions = ExtensionManager::new(); extensions.add(KeyPressExtension); - events.set_state_manager(states.clone()); + app(states, &mut screen); + + screen.run(&mut extensions).unwrap(); +} + +fn app(states: &Arc, screen: &mut Screen) { + screen.events.set_state_manager(states.clone()); let count = states.use_state(0); @@ -35,14 +39,14 @@ fn app(states: Arc) { .draw(format!("Count: {}", count.get())) .component(Transform::center()); - events.on(move |events, event: Box| match event.code { - crossterm::event::KeyCode::Enter => { - count.set(count.get() + 1); - } - _ => { - events.dispatch(Close); - } - }); - - screen.run(&mut events, &mut extensions).unwrap(); + screen + .events + .on(move |events, event: Box| match event.code { + crossterm::event::KeyCode::Enter => { + count.set(count.get() + 1); + } + _ => { + events.dispatch(Close); + } + }); } diff --git a/src/state.rs b/src/state.rs index 27bd17c..1d1b4c2 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,7 +8,7 @@ use std::{ /// ---------- public API ---------- pub struct StateManager { - recall: fn(Arc), + recall: Box)>, store: Mutex>>, cursor: Mutex, dirty: Mutex, @@ -21,9 +21,9 @@ pub struct State { } impl StateManager { - pub fn new(recall: fn(Arc)) -> Arc { + pub fn new) + 'static>(recall: F) -> Arc { Arc::new(Self { - recall, + recall: Box::new(recall), store: Mutex::new(HashMap::new()), cursor: Mutex::new(0), dirty: Mutex::new(false), @@ -49,7 +49,7 @@ impl StateManager { } } - pub fn flush(self: Arc) { + pub fn flush(self: &Arc) { let mut d = self.dirty.lock().unwrap(); if *d { *d = false;