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