diff --git a/src/utils.rs b/src/utils.rs index 91463c6a..d2afdf17 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -14,6 +14,7 @@ pub mod copyhashmap; pub mod debug_fn; pub mod double_click_state; pub mod errorfmt; +pub mod event_listener; pub mod fdcloser; pub mod gfx_api_ext; pub mod hash_map_ext; diff --git a/src/utils/event_listener.rs b/src/utils/event_listener.rs new file mode 100644 index 00000000..aef88ff2 --- /dev/null +++ b/src/utils/event_listener.rs @@ -0,0 +1,69 @@ +use { + crate::utils::linkedlist::{LinkedList, LinkedListIter, LinkedNode}, + std::{ + cell::Cell, + rc::{Rc, Weak}, + }, +}; + +pub struct EventSource { + listeners: LinkedList>, + on_attach: Cell>>, +} + +pub struct EventListener { + link: LinkedNode>, +} + +impl Default for EventSource { + fn default() -> Self { + Self { + listeners: Default::default(), + on_attach: Default::default(), + } + } +} + +impl EventSource { + pub fn iter(&self) -> EventSourceIter { + EventSourceIter { + iter: self.listeners.iter(), + } + } +} + +pub struct EventSourceIter { + iter: LinkedListIter>, +} + +impl Iterator for EventSourceIter { + type Item = Rc; + + fn next(&mut self) -> Option { + for weak in self.iter.by_ref() { + if let Some(t) = weak.upgrade() { + return Some(t); + } + } + None + } +} + +impl EventListener { + pub fn new(t: Weak) -> Self { + Self { + link: LinkedNode::detached(t), + } + } + + pub fn attach(&self, source: &EventSource) { + source.listeners.add_last_existing(&self.link); + if let Some(on_attach) = source.on_attach.take() { + on_attach(); + } + } + + pub fn detach(&self) { + self.link.detach(); + } +}