zng_app/
event.rs

1//! App event and commands API.
2
3use std::{
4    any::Any,
5    fmt,
6    marker::PhantomData,
7    mem,
8    ops::{ControlFlow, Deref},
9    sync::{
10        Arc,
11        atomic::{AtomicBool, Ordering},
12    },
13};
14
15mod args;
16pub use args::*;
17
18mod command;
19pub use command::*;
20
21mod events;
22pub use events::*;
23
24use crate::{
25    AppEventSender,
26    handler::{AppWeakHandle, Handler, HandlerExt as _},
27    update::{EventUpdate, UpdateDeliveryList, UpdateSubscribers, UpdatesTrace},
28    widget::WidgetId,
29};
30use parking_lot::Mutex;
31use zng_app_context::AppLocal;
32use zng_clone_move::clmv;
33use zng_task::channel::{self, ChannelError};
34use zng_unique_id::{IdEntry, IdMap, IdSet};
35
36///<span data-del-macro-root></span> Declares new [`Event<A>`] static items.
37///
38/// Event static items represent external, app or widget events. You can also use [`command!`]
39/// to declare events specialized for commanding widgets and services.
40///
41/// [`AppExtension`]: crate::AppExtension
42///
43/// # Conventions
44///
45/// Command events have the `_EVENT` suffix, for example an event representing a click is called `CLICK_EVENT`.
46///
47/// # Properties
48///
49/// If the event targets widgets you can use `event_property!` to declare properties that setup event handlers for the event.
50///
51/// # Examples
52///
53/// The example defines two events with the same arguments type.
54///
55/// ```
56/// # use zng_app::event::*;
57/// # event_args! { pub struct ClickArgs { .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
58/// event! {
59///     /// Event docs.
60///     pub static CLICK_EVENT: ClickArgs;
61///
62///     /// Other event docs.
63///     pub static DOUBLE_CLICK_EVENT: ClickArgs;
64/// }
65/// ```
66#[macro_export]
67macro_rules! event_macro {
68    ($(
69        $(#[$attr:meta])*
70        $vis:vis static $EVENT:ident: $Args:path;
71    )+) => {
72        $(
73            $(#[$attr])*
74            $vis static $EVENT: $crate::event::Event<$Args> = {
75                $crate::event::app_local! {
76                    static LOCAL: $crate::event::EventData = const { $crate::event::EventData::new(std::stringify!($EVENT)) };
77                }
78                $crate::event::Event::new(&LOCAL)
79            };
80        )+
81    }
82}
83#[doc(inline)]
84pub use crate::event_macro as event;
85
86#[doc(hidden)]
87pub struct EventData {
88    name: &'static str,
89    widget_subs: IdMap<WidgetId, EventHandle>,
90    hooks: Vec<EventHook>,
91}
92impl EventData {
93    #[doc(hidden)]
94    pub const fn new(name: &'static str) -> Self {
95        EventData {
96            name,
97            widget_subs: IdMap::new(),
98            hooks: vec![],
99        }
100    }
101}
102
103/// Represents an event.
104///
105/// Use the [`event!`] macro to declare events.
106pub struct Event<A: EventArgs> {
107    local: &'static AppLocal<EventData>,
108    _args: PhantomData<fn(A)>,
109}
110impl<A: EventArgs> fmt::Debug for Event<A> {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        if f.alternate() {
113            write!(f, "Event({})", self.name())
114        } else {
115            write!(f, "{}", self.name())
116        }
117    }
118}
119impl<A: EventArgs> Event<A> {
120    #[doc(hidden)]
121    pub const fn new(local: &'static AppLocal<EventData>) -> Self {
122        Event { local, _args: PhantomData }
123    }
124
125    /// Gets the event without the args type.
126    pub fn as_any(&self) -> AnyEvent {
127        AnyEvent { local: self.local }
128    }
129
130    /// Register the widget to receive targeted events from this event.
131    ///
132    /// Widgets only receive events if they are in the delivery list generated by the event args and are
133    /// subscribers to the event. App extensions receive all events.
134    pub fn subscribe(&self, widget_id: WidgetId) -> EventHandle {
135        self.as_any().subscribe(widget_id)
136    }
137
138    /// Returns `true` if the widget is subscribed to this event.
139    pub fn is_subscriber(&self, widget_id: WidgetId) -> bool {
140        self.as_any().is_subscriber(widget_id)
141    }
142
143    /// Returns `true` if at least one widget is subscribed to this event.
144    pub fn has_subscribers(&self) -> bool {
145        self.as_any().has_subscribers()
146    }
147
148    /// Calls `visit` for each widget subscribed to this event.
149    ///
150    /// Note that trying to subscribe or add hook inside `visit` will deadlock. Inside `visit` you can notify the event and
151    /// generate event updates.
152    pub fn visit_subscribers<T>(&self, visit: impl FnMut(WidgetId) -> ControlFlow<T>) -> Option<T> {
153        self.as_any().visit_subscribers(visit)
154    }
155
156    /// Name of the event static item.
157    pub fn name(&self) -> &'static str {
158        self.local.read().name
159    }
160
161    /// Returns `true` if the update is for this event.
162    pub fn has(&self, update: &EventUpdate) -> bool {
163        *self == update.event
164    }
165
166    /// Get the event update args if the update is for this event.
167    pub fn on<'a>(&self, update: &'a EventUpdate) -> Option<&'a A> {
168        if *self == update.event {
169            update.args.as_any().downcast_ref()
170        } else {
171            None
172        }
173    }
174
175    /// Get the event update args if the update is for this event and propagation is not stopped.
176    pub fn on_unhandled<'a>(&self, update: &'a EventUpdate) -> Option<&'a A> {
177        self.on(update).filter(|a| !a.propagation().is_stopped())
178    }
179
180    /// Calls `handler` if the update is for this event and propagation is not stopped, after the handler is called propagation is stopped.
181    pub fn handle<R>(&self, update: &EventUpdate, handler: impl FnOnce(&A) -> R) -> Option<R> {
182        if let Some(args) = self.on(update) {
183            args.handle(handler)
184        } else {
185            None
186        }
187    }
188
189    /// Create an event update for this event with delivery list filtered by the event subscribers.
190    pub fn new_update(&self, args: A) -> EventUpdate {
191        self.new_update_custom(args, UpdateDeliveryList::new(Box::new(self.as_any())))
192    }
193
194    /// Create and event update for this event with a custom delivery list.
195    pub fn new_update_custom(&self, args: A, mut delivery_list: UpdateDeliveryList) -> EventUpdate {
196        args.delivery_list(&mut delivery_list);
197        EventUpdate {
198            event: self.as_any(),
199            delivery_list,
200            args: Box::new(args),
201            pre_actions: Mutex::new(vec![]),
202            pos_actions: Mutex::new(vec![]),
203        }
204    }
205
206    /// Schedule an event update.
207    pub fn notify(&self, args: A) {
208        let update = self.new_update(args);
209        EVENTS.notify(update);
210    }
211
212    /// Creates a preview event handler.
213    ///
214    /// The event `handler` is called for every update that has not stopped [`propagation`](AnyEventArgs::propagation).
215    /// The handler is called before widget handlers and [`on_event`](Self::on_event) handlers. The handler is called
216    /// after all previous registered preview handlers.
217    ///
218    /// Returns an [`EventHandle`] that can be dropped to unsubscribe, you can also unsubscribe from inside the handler by calling
219    /// [`unsubscribe`](crate::handler::APP_HANDLER::unsubscribe).
220    ///
221    /// # Examples
222    ///
223    /// ```
224    /// # use zng_app::event::*;
225    /// # use zng_app::APP;
226    /// # use zng_app::handler::hn;
227    /// # event_args! { pub struct FocusChangedArgs { pub new_focus: bool, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) {} } }
228    /// # event! { pub static FOCUS_CHANGED_EVENT: FocusChangedArgs; }
229    /// # let _scope = APP.minimal();
230    /// let handle = FOCUS_CHANGED_EVENT.on_pre_event(hn!(|args| {
231    ///     println!("focused: {:?}", args.new_focus);
232    /// }));
233    /// ```
234    /// The example listens to all `FOCUS_CHANGED_EVENT` events, independent of widget context and before all UI handlers.
235    ///
236    /// # Handlers
237    ///
238    /// the event handler can be any [`Handler<A>`], there are multiple flavors of handlers, including
239    /// async handlers that allow calling `.await`. The handler closures can be declared using [`hn!`], [`async_hn!`],
240    /// [`hn_once!`] and [`async_hn_once!`].
241    ///
242    /// ## Async
243    ///
244    /// Note that for async handlers only the code before the first `.await` is called in the *preview* moment, code after runs in
245    /// subsequent event updates, after the event has already propagated, so stopping [`propagation`](AnyEventArgs::propagation)
246    /// only causes the desired effect before the first `.await`.
247    ///
248    /// [`hn!`]: crate::handler::hn!
249    /// [`async_hn!`]: crate::handler::async_hn!
250    /// [`hn_once!`]: crate::handler::hn_once!
251    /// [`async_hn_once!`]: crate::handler::async_hn_once!
252    pub fn on_pre_event(&self, handler: Handler<A>) -> EventHandle {
253        self.on_event_impl(handler, true)
254    }
255
256    /// Creates an event handler.
257    ///
258    /// The event `handler` is called for every update that has not stopped [`propagation`](AnyEventArgs::propagation).
259    /// The handler is called after all [`on_pre_event`](Self::on_pre_event) all widget handlers and all [`on_event`](Self::on_event)
260    /// handlers registered before this one.
261    ///
262    /// Returns an [`EventHandle`] that can be dropped to unsubscribe, you can also unsubscribe from inside the handler by calling
263    /// [`unsubscribe`](crate::handler::APP_HANDLER::unsubscribe) in the third parameter of [`hn!`] or [`async_hn!`].
264    ///
265    /// # Examples
266    ///
267    /// ```
268    /// # use zng_app::event::*;
269    /// # use zng_app::APP;
270    /// # use zng_app::handler::hn;
271    /// # event_args! { pub struct FocusChangedArgs { pub new_focus: bool, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) {} } }
272    /// # event! { pub static FOCUS_CHANGED_EVENT: FocusChangedArgs; }
273    /// # let _scope = APP.minimal();
274    /// let handle = FOCUS_CHANGED_EVENT.on_event(hn!(|args| {
275    ///     println!("focused: {:?}", args.new_focus);
276    /// }));
277    /// ```
278    /// The example listens to all `FOCUS_CHANGED_EVENT` events, independent of widget context, after the UI was notified.
279    ///
280    /// # Handlers
281    ///
282    /// the event handler can be any [`Handler<A>`], there are multiple flavors of handlers, including
283    /// async handlers that allow calling `.await`. The handler closures can be declared using [`hn!`], [`async_hn!`],
284    /// [`hn_once!`] and [`async_hn_once!`].
285    ///
286    /// ## Async
287    ///
288    /// Note that for async handlers only the code before the first `.await` is called in the *preview* moment, code after runs in
289    /// subsequent event updates, after the event has already propagated, so stopping [`propagation`](AnyEventArgs::propagation)
290    /// only causes the desired effect before the first `.await`.
291    ///
292    /// [`hn!`]: crate::handler::hn!
293    /// [`async_hn!`]: crate::handler::async_hn!
294    /// [`hn_once!`]: crate::handler::hn_once!
295    /// [`async_hn_once!`]: crate::handler::async_hn_once!
296    pub fn on_event(&self, handler: Handler<A>) -> EventHandle {
297        self.on_event_impl(handler, false)
298    }
299
300    fn on_event_impl(&self, handler: Handler<A>, is_preview: bool) -> EventHandle {
301        let handler = handler.into_arc();
302        let (inner_handle_owner, inner_handle) = zng_handle::Handle::new(());
303        self.as_any().hook(move |update| {
304            if inner_handle_owner.is_dropped() {
305                return false;
306            }
307
308            let handle = inner_handle.downgrade();
309            update.push_once_action(
310                Box::new(clmv!(handler, |update| {
311                    let args = update.args().as_any().downcast_ref::<A>().unwrap();
312                    if !args.propagation().is_stopped() {
313                        handler.app_event(handle.clone_boxed(), is_preview, args);
314                    }
315                })),
316                is_preview,
317            );
318
319            true
320        })
321    }
322
323    /// Creates a receiver channel for the event. The event updates are send on hook, before even preview handlers.
324    /// The receiver is unbounded, it will fill indefinitely if not drained. The receiver can be used in any thread,
325    /// including non-app threads.
326    ///
327    /// Drop the receiver to stop listening.
328    pub fn receiver(&self) -> channel::Receiver<A>
329    where
330        A: Send,
331    {
332        let (sender, receiver) = channel::unbounded();
333
334        self.as_any()
335            .hook(move |update| {
336                sender
337                    .send_blocking(update.args().as_any().downcast_ref::<A>().unwrap().clone())
338                    .is_ok()
339            })
340            .perm();
341
342        receiver
343    }
344
345    /// Creates a sender channel that can notify the event.
346    ///
347    /// Events can notify from any app thread, this sender can notify other threads too.
348    pub fn sender(&self) -> EventSender<A>
349    where
350        A: Send,
351    {
352        EVENTS_SV.write().sender(*self)
353    }
354
355    /// Returns `true` if any app level callback is registered for this event.
356    ///
357    /// This includes [`AnyEvent::hook`], [`Event::on_pre_event`], [`Event::on_event`] and [`Event::receiver`].
358    pub fn has_hooks(&self) -> bool {
359        self.as_any().has_hooks()
360    }
361}
362impl<A: EventArgs> Clone for Event<A> {
363    fn clone(&self) -> Self {
364        *self
365    }
366}
367impl<A: EventArgs> Copy for Event<A> {}
368impl<A: EventArgs> PartialEq for Event<A> {
369    fn eq(&self, other: &Self) -> bool {
370        self.local == other.local
371    }
372}
373impl<A: EventArgs> Eq for Event<A> {}
374
375/// Represents an [`Event`] without the args type.
376#[derive(Clone, Copy)]
377pub struct AnyEvent {
378    local: &'static AppLocal<EventData>,
379}
380impl fmt::Debug for AnyEvent {
381    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
382        if f.alternate() {
383            write!(f, "AnyEvent({})", self.name())
384        } else {
385            write!(f, "{}", self.name())
386        }
387    }
388}
389impl AnyEvent {
390    /// Name of the event static item.
391    pub fn name(&self) -> &'static str {
392        self.local.read().name
393    }
394
395    /// Returns `true` if `self` is the type erased `event`.
396    pub fn is<A: EventArgs>(&self, event: &Event<A>) -> bool {
397        self == event
398    }
399
400    /// Returns `true` if the update is for this event.
401    pub fn has(&self, update: &EventUpdate) -> bool {
402        *self == update.event
403    }
404
405    /// Register a callback that is called just before an event begins notifying.
406    pub fn hook(&self, hook: impl Fn(&mut EventUpdate) -> bool + Send + Sync + 'static) -> EventHandle {
407        self.hook_impl(Box::new(hook))
408    }
409    fn hook_impl(&self, hook: Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>) -> EventHandle {
410        let (handle, hook) = EventHandle::new(hook);
411        self.local.write().hooks.push(hook);
412        handle
413    }
414
415    /// Register the widget to receive targeted events from this event.
416    ///
417    /// Widgets only receive events if they are in the delivery list generated by the event args and are
418    /// subscribers to the event. App extensions receive all events.
419    pub fn subscribe(&self, widget_id: WidgetId) -> EventHandle {
420        self.local
421            .write()
422            .widget_subs
423            .entry(widget_id)
424            .or_insert_with(EventHandle::new_none)
425            .clone()
426    }
427
428    /// Returns `true` if the widget is subscribed to this event.
429    pub fn is_subscriber(&self, widget_id: WidgetId) -> bool {
430        self.local.read().widget_subs.contains_key(&widget_id)
431    }
432
433    /// Returns `true` if at least one widget is subscribed to this event.
434    pub fn has_subscribers(&self) -> bool {
435        !self.local.read().widget_subs.is_empty()
436    }
437
438    /// Calls `visit` for each widget subscribed to this event.
439    ///
440    /// Note that trying to subscribe or add hook inside `visit` will deadlock. Inside `visit` you can notify the event and
441    /// generate event updates.
442    pub fn visit_subscribers<T>(&self, mut visit: impl FnMut(WidgetId) -> ControlFlow<T>) -> Option<T> {
443        for sub in self.local.read().widget_subs.keys() {
444            match visit(*sub) {
445                ControlFlow::Continue(_) => continue,
446                ControlFlow::Break(r) => return Some(r),
447            }
448        }
449        None
450    }
451
452    /// Returns `true` if any app level callback is registered for this event.
453    ///
454    /// This includes [`AnyEvent::hook`], [`Event::on_pre_event`], [`Event::on_event`] and [`Event::receiver`].
455    pub fn has_hooks(&self) -> bool {
456        !self.local.read().hooks.is_empty()
457    }
458
459    pub(crate) fn on_update(&self, update: &mut EventUpdate) {
460        let mut hooks = mem::take(&mut self.local.write().hooks);
461        hooks.retain(|h| h.call(update));
462
463        let mut write = self.local.write();
464        hooks.append(&mut write.hooks);
465        write.hooks = hooks;
466    }
467}
468impl PartialEq for AnyEvent {
469    fn eq(&self, other: &Self) -> bool {
470        self.local == other.local
471    }
472}
473impl Eq for AnyEvent {}
474impl std::hash::Hash for AnyEvent {
475    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
476        std::hash::Hash::hash(self.local, state)
477    }
478}
479impl<A: EventArgs> PartialEq<AnyEvent> for Event<A> {
480    fn eq(&self, other: &AnyEvent) -> bool {
481        self.local == other.local
482    }
483}
484impl<A: EventArgs> PartialEq<Event<A>> for AnyEvent {
485    fn eq(&self, other: &Event<A>) -> bool {
486        self.local == other.local
487    }
488}
489
490impl UpdateSubscribers for AnyEvent {
491    fn contains(&self, widget_id: WidgetId) -> bool {
492        if let Some(mut write) = self.local.try_write() {
493            match write.widget_subs.entry(widget_id) {
494                IdEntry::Occupied(e) => {
495                    let t = e.get().retain();
496                    if !t {
497                        let _ = e.remove();
498                    }
499                    t
500                }
501                IdEntry::Vacant(_) => false,
502            }
503        } else {
504            // fallback without cleanup
505            match self.local.read().widget_subs.get(&widget_id) {
506                Some(e) => e.retain(),
507                None => false,
508            }
509        }
510    }
511
512    fn to_set(&self) -> IdSet<WidgetId> {
513        self.local.read().widget_subs.keys().copied().collect()
514    }
515}
516
517/// Represents a collection of event handles.
518#[must_use = "the event subscriptions or handlers are dropped if the handle is dropped"]
519#[derive(Clone, Default)]
520pub struct EventHandles(Vec<EventHandle>);
521impl EventHandles {
522    /// Empty collection.
523    pub const fn dummy() -> Self {
524        EventHandles(vec![])
525    }
526
527    /// Returns `true` if empty or all handles are dummy.
528    pub fn is_dummy(&self) -> bool {
529        self.0.is_empty() || self.0.iter().all(EventHandle::is_dummy)
530    }
531
532    /// Drop all handles without stopping their behavior.
533    pub fn perm(self) {
534        for handle in self.0 {
535            handle.perm()
536        }
537    }
538
539    /// Add `other` handle to the collection.
540    pub fn push(&mut self, other: EventHandle) -> &mut Self {
541        if !other.is_dummy() {
542            self.0.push(other);
543        }
544        self
545    }
546
547    /// Drop all handles.
548    pub fn clear(&mut self) {
549        self.0.clear();
550    }
551}
552impl FromIterator<EventHandle> for EventHandles {
553    fn from_iter<T: IntoIterator<Item = EventHandle>>(iter: T) -> Self {
554        EventHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
555    }
556}
557impl<const N: usize> From<[EventHandle; N]> for EventHandles {
558    fn from(handles: [EventHandle; N]) -> Self {
559        handles.into_iter().filter(|h| !h.is_dummy()).collect()
560    }
561}
562impl Extend<EventHandle> for EventHandles {
563    fn extend<T: IntoIterator<Item = EventHandle>>(&mut self, iter: T) {
564        for handle in iter {
565            self.push(handle);
566        }
567    }
568}
569impl IntoIterator for EventHandles {
570    type Item = EventHandle;
571
572    type IntoIter = std::vec::IntoIter<EventHandle>;
573
574    fn into_iter(self) -> Self::IntoIter {
575        self.0.into_iter()
576    }
577}
578
579struct EventHandleData {
580    perm: AtomicBool,
581    hook: Option<Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>>,
582}
583
584/// Represents an event widget subscription, handler callback or hook.
585#[derive(Clone)]
586#[must_use = "the event subscription or handler is dropped if the handle is dropped"]
587pub struct EventHandle(Option<Arc<EventHandleData>>);
588impl PartialEq for EventHandle {
589    fn eq(&self, other: &Self) -> bool {
590        match (&self.0, &other.0) {
591            (None, None) => true,
592            (None, Some(_)) | (Some(_), None) => false,
593            (Some(a), Some(b)) => Arc::ptr_eq(a, b),
594        }
595    }
596}
597impl Eq for EventHandle {}
598impl std::hash::Hash for EventHandle {
599    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
600        let i = match &self.0 {
601            Some(rc) => Arc::as_ptr(rc) as usize,
602            None => 0,
603        };
604        state.write_usize(i);
605    }
606}
607impl fmt::Debug for EventHandle {
608    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609        let i = match &self.0 {
610            Some(rc) => Arc::as_ptr(rc) as usize,
611            None => 0,
612        };
613        f.debug_tuple("EventHandle").field(&i).finish()
614    }
615}
616/// Dummy
617impl Default for EventHandle {
618    fn default() -> Self {
619        Self::dummy()
620    }
621}
622impl EventHandle {
623    fn new(hook: Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>) -> (Self, EventHook) {
624        let rc = Arc::new(EventHandleData {
625            perm: AtomicBool::new(false),
626            hook: Some(hook),
627        });
628        (Self(Some(rc.clone())), EventHook(rc))
629    }
630
631    fn new_none() -> Self {
632        Self(Some(Arc::new(EventHandleData {
633            perm: AtomicBool::new(false),
634            hook: None,
635        })))
636    }
637
638    /// Handle to no event.
639    pub fn dummy() -> Self {
640        EventHandle(None)
641    }
642
643    /// If the handle is not actually registered in an event.
644    pub fn is_dummy(&self) -> bool {
645        self.0.is_none()
646    }
647
648    /// Drop the handle without un-registering it, the resource it represents will remain registered in the event for the duration of
649    /// the process.
650    pub fn perm(self) {
651        if let Some(rc) = self.0 {
652            rc.perm.store(true, Ordering::Relaxed);
653        }
654    }
655
656    /// Create an [`EventHandles`] collection with `self` and `other`.
657    pub fn with(self, other: Self) -> EventHandles {
658        [self, other].into()
659    }
660
661    fn retain(&self) -> bool {
662        let rc = self.0.as_ref().unwrap();
663        Arc::strong_count(rc) > 1 || rc.perm.load(Ordering::Relaxed)
664    }
665}
666
667struct EventHook(Arc<EventHandleData>);
668impl EventHook {
669    /// Callback, returns `true` if the handle must be retained.
670    fn call(&self, update: &mut EventUpdate) -> bool {
671        (Arc::strong_count(&self.0) > 1 || self.0.perm.load(Ordering::Relaxed)) && (self.0.hook.as_ref().unwrap())(update)
672    }
673}
674
675pub(crate) struct EventUpdateMsg {
676    args: Box<dyn FnOnce() -> EventUpdate + Send>,
677}
678impl EventUpdateMsg {
679    pub(crate) fn get(self) -> EventUpdate {
680        (self.args)()
681    }
682}
683impl fmt::Debug for EventUpdateMsg {
684    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685        f.debug_struct("EventUpdateMsg").finish_non_exhaustive()
686    }
687}
688
689/// An event update sender that can be used from any thread and without access to [`EVENTS`].
690///
691/// Use [`Event::sender`] to create a sender.
692pub struct EventSender<A>
693where
694    A: EventArgs + Send,
695{
696    pub(super) sender: AppEventSender,
697    pub(super) event: Event<A>,
698}
699impl<A> Clone for EventSender<A>
700where
701    A: EventArgs + Send,
702{
703    fn clone(&self) -> Self {
704        EventSender {
705            sender: self.sender.clone(),
706            event: self.event,
707        }
708    }
709}
710impl<A> fmt::Debug for EventSender<A>
711where
712    A: EventArgs + Send,
713{
714    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
715        write!(f, "EventSender({:?})", &self.event)
716    }
717}
718impl<A> EventSender<A>
719where
720    A: EventArgs + Send,
721{
722    /// Send an event update.
723    pub fn send(&self, args: A) -> Result<(), ChannelError> {
724        UpdatesTrace::log_event(self.event.as_any());
725
726        let event = self.event;
727        let msg = EventUpdateMsg {
728            args: Box::new(move || event.new_update(args)),
729        };
730
731        self.sender.send_event(msg)
732    }
733
734    /// Event that receives from this sender.
735    pub fn event(&self) -> Event<A> {
736        self.event
737    }
738}