util: add generic event listener framework
This commit is contained in:
parent
07b55e42c9
commit
dbb9bd2299
2 changed files with 70 additions and 0 deletions
69
src/utils/event_listener.rs
Normal file
69
src/utils/event_listener.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
use {
|
||||
crate::utils::linkedlist::{LinkedList, LinkedListIter, LinkedNode},
|
||||
std::{
|
||||
cell::Cell,
|
||||
rc::{Rc, Weak},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct EventSource<T: ?Sized> {
|
||||
listeners: LinkedList<Weak<T>>,
|
||||
on_attach: Cell<Option<Box<dyn FnOnce()>>>,
|
||||
}
|
||||
|
||||
pub struct EventListener<T: ?Sized> {
|
||||
link: LinkedNode<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Default for EventSource<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
listeners: Default::default(),
|
||||
on_attach: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> EventSource<T> {
|
||||
pub fn iter(&self) -> EventSourceIter<T> {
|
||||
EventSourceIter {
|
||||
iter: self.listeners.iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventSourceIter<T: ?Sized> {
|
||||
iter: LinkedListIter<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Iterator for EventSourceIter<T> {
|
||||
type Item = Rc<T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
for weak in self.iter.by_ref() {
|
||||
if let Some(t) = weak.upgrade() {
|
||||
return Some(t);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> EventListener<T> {
|
||||
pub fn new(t: Weak<T>) -> Self {
|
||||
Self {
|
||||
link: LinkedNode::detached(t),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attach(&self, source: &EventSource<T>) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue