ferroui_base/utilities/
i_weak_event_subscriber.rs1use super::weak_event::WeakEventArgs;
2use super::HandlerList;
3use crate::reactive::{Disposable, IDisposable};
4use std::any::Any;
5use std::rc::{Rc, Weak};
6
7pub trait IWeakEventSubscriber<A: WeakEventArgs + ?Sized> {
13 fn on_event(&self, sender: Option<&dyn Any>, ev: &dyn Any, e: &A::Args<'_>);
14}
15
16pub type WeakEventSubscriberHandler<A> =
19 dyn for<'s, 'v, 'r, 'a> Fn(Option<&'s dyn Any>, &'v dyn Any, &'r <A as WeakEventArgs>::Args<'a>);
20
21pub struct WeakEventSubscriber<A: WeakEventArgs + ?Sized> {
24 this: Weak<WeakEventSubscriber<A>>,
25 event: HandlerList<WeakEventSubscriberHandler<A>>,
26}
27
28impl<A: WeakEventArgs + ?Sized> WeakEventSubscriber<A> {
29 pub fn new() -> Rc<Self> {
30 Rc::new_cyclic(|this| Self { this: this.clone(), event: HandlerList::new() })
31 }
32
33 pub fn event<F>(&self, handler: F) -> Rc<dyn IDisposable>
36 where
37 F: for<'s, 'v, 'r, 'a> Fn(Option<&'s dyn Any>, &'v dyn Any, &'r A::Args<'a>) + 'static,
38 {
39 let token = self.event.add(Rc::new(handler));
40 let weak = self.this.clone();
41 Disposable::create(move || {
42 if let Some(this) = weak.upgrade() {
43 this.event.remove(token);
44 }
45 })
46 }
47}
48
49impl<A: WeakEventArgs + ?Sized> IWeakEventSubscriber<A> for WeakEventSubscriber<A> {
50 fn on_event(&self, sender: Option<&dyn Any>, ev: &dyn Any, e: &A::Args<'_>) {
51 if self.event.is_empty() {
52 return;
53 }
54 for (_, handler) in self.event.snapshot().iter() {
55 handler(sender, ev, e);
56 }
57 }
58}
59
60pub struct TargetWeakEventSubscriber<TTarget, A: WeakEventArgs + ?Sized> {
63 target: TTarget,
64 dispatch_func: Box<TargetDispatchFunc<TTarget, A>>,
65}
66
67type TargetDispatchFunc<TTarget, A> =
68 dyn for<'t, 's, 'v, 'r, 'a> Fn(&'t TTarget, Option<&'s dyn Any>, &'v dyn Any, &'r <A as WeakEventArgs>::Args<'a>);
69
70impl<TTarget, A: WeakEventArgs + ?Sized> TargetWeakEventSubscriber<TTarget, A> {
71 pub fn new<F>(target: TTarget, dispatch_func: F) -> Self
72 where
73 F: for<'t, 's, 'v, 'r, 'a> Fn(&'t TTarget, Option<&'s dyn Any>, &'v dyn Any, &'r A::Args<'a>) + 'static,
74 {
75 Self { target, dispatch_func: Box::new(dispatch_func) }
76 }
77}
78
79impl<TTarget, A: WeakEventArgs + ?Sized> IWeakEventSubscriber<A> for TargetWeakEventSubscriber<TTarget, A> {
80 fn on_event(&self, sender: Option<&dyn Any>, ev: &dyn Any, e: &A::Args<'_>) {
81 (self.dispatch_func)(&self.target, sender, ev, e);
82 }
83}