150 lines
3.4 KiB
Rust
150 lines
3.4 KiB
Rust
|
use {
|
||
|
crate::core::View,
|
||
|
std::{
|
||
|
ops::Deref,
|
||
|
sync::{Arc, Weak, RwLock}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*\
|
||
|
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
Observer
|
||
|
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
\*/
|
||
|
pub trait Observer<V: View + ?Sized> : Send + Sync {
|
||
|
fn reset(&self, view: Option<Arc<V>>) {}
|
||
|
fn notify(&self, msg: &V::Msg);
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
impl<V: View + ?Sized, O: Observer<V>> Observer<V> for RwLock<O> {
|
||
|
fn notify(&self, msg: &V::Msg) {
|
||
|
self.read().unwrap().notify(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<V: View + ?Sized, O: Observer<V>> Observer<V> for Arc<O> {
|
||
|
fn notify(&self, msg: &V::Msg) {
|
||
|
self.deref().notify(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub trait ObserverExt<V: View + ?Sized> : Observer<V> {
|
||
|
fn notify_each(&self, it: impl IntoIterator<Item = V::Msg>);
|
||
|
}
|
||
|
|
||
|
impl<V: View + ?Sized, T: Observer<V>> ObserverExt<V> for T {
|
||
|
fn notify_each(&self, it: impl IntoIterator<Item = V::Msg>) {
|
||
|
for msg in it {
|
||
|
self.notify(&msg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*\
|
||
|
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
Broadcast
|
||
|
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
\*/
|
||
|
|
||
|
pub struct ObserverBroadcast<V: View + ?Sized> {
|
||
|
observers: Vec<Weak<dyn Observer<V>>>
|
||
|
}
|
||
|
|
||
|
impl<V: View + ?Sized> ObserverBroadcast<V> {
|
||
|
pub fn new() -> Self {
|
||
|
ObserverBroadcast {
|
||
|
observers: Vec::new()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn add_observer(&mut self, obs: Weak<dyn Observer<V>>) {
|
||
|
self.cleanup();
|
||
|
self.observers.push(obs);
|
||
|
}
|
||
|
|
||
|
fn cleanup(&mut self) {
|
||
|
self.observers.retain(|o| o.strong_count() > 0);
|
||
|
}
|
||
|
|
||
|
fn iter(&self) -> impl Iterator<Item = Arc<dyn Observer<V>>> + '_ {
|
||
|
self.observers.iter().filter_map(|o| o.upgrade())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V> {
|
||
|
fn reset(&self, view: Option<Arc<V>>) {
|
||
|
for o in self.iter() {
|
||
|
o.reset(view.clone());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn notify(&self, msg: &V::Msg) {
|
||
|
for o in self.iter() {
|
||
|
o.notify(&msg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub struct NotifyFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(&V::Msg) + Send + Sync {
|
||
|
f: F,
|
||
|
_phantom: std::marker::PhantomData<V>
|
||
|
}
|
||
|
|
||
|
impl<V, F> NotifyFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(&V::Msg) + Send + Sync {
|
||
|
pub fn new(f: F) -> Self {
|
||
|
NotifyFnObserver {
|
||
|
f,
|
||
|
_phantom: std::marker::PhantomData
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<V, F> Observer<V> for NotifyFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(&V::Msg) + Send + Sync {
|
||
|
fn notify(&self, msg: &V::Msg) {
|
||
|
(self.f)(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub struct ResetFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(Option<Arc<V>>) + Send + Sync {
|
||
|
f: F,
|
||
|
_phantom: std::marker::PhantomData<V>
|
||
|
}
|
||
|
|
||
|
impl<V, F> ResetFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(Option<Arc<V>>) + Send + Sync {
|
||
|
pub fn new(f: F) -> Self {
|
||
|
ResetFnObserver {
|
||
|
f,
|
||
|
_phantom: std::marker::PhantomData
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<V, F> Observer<V> for ResetFnObserver<V, F>
|
||
|
where V: View + ?Sized,
|
||
|
F: Fn(Option<Arc<V>>) + Send + Sync {
|
||
|
fn notify(&self, msg: &V::Msg) {}
|
||
|
fn reset(&self, view: Option<Arc<V>>) {
|
||
|
(self.f)(view);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|