From 3cacd42421523eb42494876e3e3e01fd48e98c71 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 27 Jun 2025 12:22:59 -0500 Subject: [PATCH] event handler on events --- src/element/input.rs | 32 +++++++------------------------- src/events.rs | 30 +++++++++++++++++++++--------- src/extensions/keypress.rs | 4 ++-- src/macros.rs | 2 +- src/main.rs | 24 +++++++----------------- 5 files changed, 38 insertions(+), 54 deletions(-) diff --git a/src/element/input.rs b/src/element/input.rs index 7482552..82fedfe 100644 --- a/src/element/input.rs +++ b/src/element/input.rs @@ -1,20 +1,14 @@ -use std::sync::{Arc, Mutex}; - use crossterm::event::KeyEvent; use crate::{ event, event_handler, events::EventManager, extensions::keypress::KeyPressEventHandler, Element, }; -pub struct Input(String, usize, Arc>); +pub struct Input(String, usize); impl Input { pub fn new() -> Input { - Input(String::new(), 0, Arc::new(Mutex::new(EventManager::new()))) - } - - pub fn get_event(&self) -> Arc> { - self.2.clone() + Input(String::new(), 0) } } @@ -45,42 +39,30 @@ impl Element for Input { } impl KeyPressEventHandler for Input { - fn on_keypress(&mut self, event: Box) { + fn on_keypress(&mut self, events: &mut EventManager, event: Box) { match event.code { crossterm::event::KeyCode::Char(c) => { self.0.insert(self.1, c); self.1 += 1; - self.2 - .lock() - .unwrap() - .dispatch(InputUpdateEvent(self.0.clone())); + events.dispatch(InputUpdateEvent(self.0.clone())); } crossterm::event::KeyCode::Backspace => { if self.1 > 0 { self.0.remove(self.1 - 1); self.1 -= 1; - self.2 - .lock() - .unwrap() - .dispatch(InputUpdateEvent(self.0.clone())); + events.dispatch(InputUpdateEvent(self.0.clone())); } } crossterm::event::KeyCode::Left => { if self.1 > 0 { self.1 -= 1; - self.2 - .lock() - .unwrap() - .dispatch(InputUpdateEvent(self.0.clone())); + events.dispatch(InputUpdateEvent(self.0.clone())); } } crossterm::event::KeyCode::Right => { if self.1 < self.0.len() { self.1 += 1; - self.2 - .lock() - .unwrap() - .dispatch(InputUpdateEvent(self.0.clone())); + events.dispatch(InputUpdateEvent(self.0.clone())); } } _ => {} diff --git a/src/events.rs b/src/events.rs index b8dbab1..7790d10 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,6 +1,7 @@ use std::{ any::{Any, TypeId}, collections::HashMap, + sync::{Arc, Mutex}, }; use crate::event; @@ -11,7 +12,8 @@ pub trait Event { fn as_any(self: Box) -> Box; } -pub struct EventHandlerFn(pub 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 { @@ -31,12 +33,17 @@ impl EventManager { } } - pub fn on) + 'static>(&mut self, mut f: F) { - let wrapper = Box::new(move |evt: Box| { - if let Ok(concrete) = evt.as_any().downcast::() { - f(concrete); - } - }) as Box)>; + pub fn on) + 'static>( + &mut self, + mut f: F, + ) { + let wrapper = Arc::new(Mutex::new( + move |e: &mut EventManager, evt: Box| { + if let Ok(concrete) = evt.as_any().downcast::() { + f(e, concrete); + } + }, + )) as Arc)>>; self.handlers .entry(TypeId::of::()) @@ -46,9 +53,14 @@ impl EventManager { pub fn dispatch(&mut self, evt: E) { let tid = evt.type_id(); + if let Some(handlers) = self.handlers.get_mut(&tid) { - for h in handlers { - (h.0)(Box::new(evt.clone())); + // 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(); + (ha)(self, Box::new(evt.clone())); } } diff --git a/src/extensions/keypress.rs b/src/extensions/keypress.rs index c76efd5..307c51f 100644 --- a/src/extensions/keypress.rs +++ b/src/extensions/keypress.rs @@ -13,7 +13,7 @@ impl Event for KeyEvent { } pub trait KeyPressEventHandler { - fn on_keypress(&mut self, event: Box); + fn on_keypress(&mut self, events: &mut EventManager, event: Box); } pub struct KeyPressExtension; @@ -24,7 +24,7 @@ impl Extension for KeyPressExtension { crate::utils::clear().unwrap(); crate::utils::hide_cursor().unwrap(); - events.on(|_: Box| { + events.on(|_, _: Box| { crossterm::terminal::disable_raw_mode().unwrap(); crate::utils::show_cursor().unwrap(); crate::utils::clear().unwrap(); diff --git a/src/macros.rs b/src/macros.rs index 2b1da6b..9dc8b22 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -119,6 +119,6 @@ macro_rules! component { macro_rules! event_handler { ($self_ty:ty, $self:ident, $events:ident, $method:ident) => {{ let self_ref = $self as *mut $self_ty; - $events.on(move |e| unsafe { (*self_ref).$method(e) }); + $events.on(move |es, e| unsafe { (*self_ref).$method(es, e) }); }}; } diff --git a/src/main.rs b/src/main.rs index 798ee70..07fa97f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use osui::{ element::input::{Input, InputUpdateEvent}, - events::EventManager, + events::{Close, EventManager}, extensions::{keypress::KeyPressExtension, ExtensionManager}, style::Transform, Screen, @@ -12,23 +12,13 @@ fn main() { let mut events = EventManager::new(); extensions.add(KeyPressExtension); - let widget = screen.draw(Input::new()).component(Transform::center()); + screen.draw(Input::new()).component(Transform::center()); - let input_event = widget - .0 - .as_any() - .downcast_ref::() - .unwrap() - .get_event(); - - input_event - .lock() - .unwrap() - .on(|event: Box| { - if event.0 == "quit" { - std::process::exit(0) - } - }); + events.on(|events, event: Box| { + if event.0 == "quit" { + events.dispatch(Close); + } + }); screen.run(&mut events, &mut extensions).unwrap(); }