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::{AppWeakHandle, Handler, HandlerExt as _},
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::APP_HANDLER::unsubscribe).
222    ///
223    /// # Examples
224    ///
225    /// ```
226    /// # use zng_app::event::*;
227    /// # use zng_app::APP;
228    /// # use zng_app::handler::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(hn!(|args| {
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 [`Handler<A>`], there are multiple flavors of handlers, including
241    /// async handlers that allow calling `.await`. The handler closures can be declared using [`hn!`], [`async_hn!`],
242    /// [`hn_once!`] and [`async_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    /// [`hn!`]: crate::handler::hn!
251    /// [`async_hn!`]: crate::handler::async_hn!
252    /// [`hn_once!`]: crate::handler::hn_once!
253    /// [`async_hn_once!`]: crate::handler::async_hn_once!
254    pub fn on_pre_event(&self, handler: Handler<A>) -> EventHandle {
255        self.on_event_impl(handler, true)
256    }
257
258    /// Creates an event handler.
259    ///
260    /// The event `handler` is called for every update that has not stopped [`propagation`](AnyEventArgs::propagation).
261    /// The handler is called after all [`on_pre_event`](Self::on_pre_event) all widget handlers and all [`on_event`](Self::on_event)
262    /// handlers registered before this one.
263    ///
264    /// Returns an [`EventHandle`] that can be dropped to unsubscribe, you can also unsubscribe from inside the handler by calling
265    /// [`unsubscribe`](crate::handler::APP_HANDLER::unsubscribe) in the third parameter of [`hn!`] or [`async_hn!`].
266    ///
267    /// # Examples
268    ///
269    /// ```
270    /// # use zng_app::event::*;
271    /// # use zng_app::APP;
272    /// # use zng_app::handler::hn;
273    /// # event_args! { pub struct FocusChangedArgs { pub new_focus: bool, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) {} } }
274    /// # event! { pub static FOCUS_CHANGED_EVENT: FocusChangedArgs; }
275    /// # let _scope = APP.minimal();
276    /// let handle = FOCUS_CHANGED_EVENT.on_event(hn!(|args| {
277    ///     println!("focused: {:?}", args.new_focus);
278    /// }));
279    /// ```
280    /// The example listens to all `FOCUS_CHANGED_EVENT` events, independent of widget context, after the UI was notified.
281    ///
282    /// # Handlers
283    ///
284    /// the event handler can be any [`Handler<A>`], there are multiple flavors of handlers, including
285    /// async handlers that allow calling `.await`. The handler closures can be declared using [`hn!`], [`async_hn!`],
286    /// [`hn_once!`] and [`async_hn_once!`].
287    ///
288    /// ## Async
289    ///
290    /// Note that for async handlers only the code before the first `.await` is called in the *preview* moment, code after runs in
291    /// subsequent event updates, after the event has already propagated, so stopping [`propagation`](AnyEventArgs::propagation)
292    /// only causes the desired effect before the first `.await`.
293    ///
294    /// [`hn!`]: crate::handler::hn!
295    /// [`async_hn!`]: crate::handler::async_hn!
296    /// [`hn_once!`]: crate::handler::hn_once!
297    /// [`async_hn_once!`]: crate::handler::async_hn_once!
298    pub fn on_event(&self, handler: Handler<A>) -> EventHandle {
299        self.on_event_impl(handler, false)
300    }
301
302    fn on_event_impl(&self, handler: Handler<A>, is_preview: bool) -> EventHandle {
303        let handler = handler.into_arc();
304        let (inner_handle_owner, inner_handle) = zng_handle::Handle::new(());
305        self.as_any().hook(move |update| {
306            if inner_handle_owner.is_dropped() {
307                return false;
308            }
309
310            let handle = inner_handle.downgrade();
311            update.push_once_action(
312                Box::new(clmv!(handler, |update| {
313                    let args = update.args().as_any().downcast_ref::<A>().unwrap();
314                    if !args.propagation().is_stopped() {
315                        handler.app_event(handle.clone_boxed(), is_preview, args);
316                    }
317                })),
318                is_preview,
319            );
320
321            true
322        })
323    }
324
325    /// Creates a receiver channel for the event. The event updates are send on hook, before even preview handlers.
326    /// The receiver is unbounded, it will fill indefinitely if not drained. The receiver can be used in any thread,
327    /// including non-app threads.
328    ///
329    /// Drop the receiver to stop listening.
330    pub fn receiver(&self) -> EventReceiver<A>
331    where
332        A: Send,
333    {
334        let (sender, receiver) = flume::unbounded();
335
336        self.as_any()
337            .hook(move |update| sender.send(update.args().as_any().downcast_ref::<A>().unwrap().clone()).is_ok())
338            .perm();
339
340        EventReceiver { receiver, event: *self }
341    }
342
343    /// Creates a sender channel that can notify the event.
344    ///
345    /// Events can notify from any app thread, this sender can notify other threads too.
346    pub fn sender(&self) -> EventSender<A>
347    where
348        A: Send,
349    {
350        EVENTS_SV.write().sender(*self)
351    }
352
353    /// Returns `true` if any app level callback is registered for this event.
354    ///
355    /// This includes [`AnyEvent::hook`], [`Event::on_pre_event`], [`Event::on_event`] and [`Event::receiver`].
356    pub fn has_hooks(&self) -> bool {
357        self.as_any().has_hooks()
358    }
359}
360impl<A: EventArgs> Clone for Event<A> {
361    fn clone(&self) -> Self {
362        *self
363    }
364}
365impl<A: EventArgs> Copy for Event<A> {}
366impl<A: EventArgs> PartialEq for Event<A> {
367    fn eq(&self, other: &Self) -> bool {
368        self.local == other.local
369    }
370}
371impl<A: EventArgs> Eq for Event<A> {}
372
373/// Represents an [`Event`] without the args type.
374#[derive(Clone, Copy)]
375pub struct AnyEvent {
376    local: &'static AppLocal<EventData>,
377}
378impl fmt::Debug for AnyEvent {
379    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380        if f.alternate() {
381            write!(f, "AnyEvent({})", self.name())
382        } else {
383            write!(f, "{}", self.name())
384        }
385    }
386}
387impl AnyEvent {
388    /// Name of the event static item.
389    pub fn name(&self) -> &'static str {
390        self.local.read().name
391    }
392
393    /// Returns `true` if `self` is the type erased `event`.
394    pub fn is<A: EventArgs>(&self, event: &Event<A>) -> bool {
395        self == event
396    }
397
398    /// Returns `true` if the update is for this event.
399    pub fn has(&self, update: &EventUpdate) -> bool {
400        *self == update.event
401    }
402
403    /// Register a callback that is called just before an event begins notifying.
404    pub fn hook(&self, hook: impl Fn(&mut EventUpdate) -> bool + Send + Sync + 'static) -> EventHandle {
405        self.hook_impl(Box::new(hook))
406    }
407    fn hook_impl(&self, hook: Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>) -> EventHandle {
408        let (handle, hook) = EventHandle::new(hook);
409        self.local.write().hooks.push(hook);
410        handle
411    }
412
413    /// Register the widget to receive targeted events from this event.
414    ///
415    /// Widgets only receive events if they are in the delivery list generated by the event args and are
416    /// subscribers to the event. App extensions receive all events.
417    pub fn subscribe(&self, widget_id: WidgetId) -> EventHandle {
418        self.local
419            .write()
420            .widget_subs
421            .entry(widget_id)
422            .or_insert_with(EventHandle::new_none)
423            .clone()
424    }
425
426    /// Returns `true` if the widget is subscribed to this event.
427    pub fn is_subscriber(&self, widget_id: WidgetId) -> bool {
428        self.local.read().widget_subs.contains_key(&widget_id)
429    }
430
431    /// Returns `true` if at least one widget is subscribed to this event.
432    pub fn has_subscribers(&self) -> bool {
433        !self.local.read().widget_subs.is_empty()
434    }
435
436    /// Calls `visit` for each widget subscribed to this event.
437    ///
438    /// Note that trying to subscribe or add hook inside `visit` will deadlock. Inside `visit` you can notify the event and
439    /// generate event updates.
440    pub fn visit_subscribers<T>(&self, mut visit: impl FnMut(WidgetId) -> ControlFlow<T>) -> Option<T> {
441        for sub in self.local.read().widget_subs.keys() {
442            match visit(*sub) {
443                ControlFlow::Continue(_) => continue,
444                ControlFlow::Break(r) => return Some(r),
445            }
446        }
447        None
448    }
449
450    /// Returns `true` if any app level callback is registered for this event.
451    ///
452    /// This includes [`AnyEvent::hook`], [`Event::on_pre_event`], [`Event::on_event`] and [`Event::receiver`].
453    pub fn has_hooks(&self) -> bool {
454        !self.local.read().hooks.is_empty()
455    }
456
457    pub(crate) fn on_update(&self, update: &mut EventUpdate) {
458        let mut hooks = mem::take(&mut self.local.write().hooks);
459        hooks.retain(|h| h.call(update));
460
461        let mut write = self.local.write();
462        hooks.append(&mut write.hooks);
463        write.hooks = hooks;
464    }
465}
466impl PartialEq for AnyEvent {
467    fn eq(&self, other: &Self) -> bool {
468        self.local == other.local
469    }
470}
471impl Eq for AnyEvent {}
472impl std::hash::Hash for AnyEvent {
473    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
474        std::hash::Hash::hash(self.local, state)
475    }
476}
477impl<A: EventArgs> PartialEq<AnyEvent> for Event<A> {
478    fn eq(&self, other: &AnyEvent) -> bool {
479        self.local == other.local
480    }
481}
482impl<A: EventArgs> PartialEq<Event<A>> for AnyEvent {
483    fn eq(&self, other: &Event<A>) -> bool {
484        self.local == other.local
485    }
486}
487
488impl UpdateSubscribers for AnyEvent {
489    fn contains(&self, widget_id: WidgetId) -> bool {
490        if let Some(mut write) = self.local.try_write() {
491            match write.widget_subs.entry(widget_id) {
492                IdEntry::Occupied(e) => {
493                    let t = e.get().retain();
494                    if !t {
495                        let _ = e.remove();
496                    }
497                    t
498                }
499                IdEntry::Vacant(_) => false,
500            }
501        } else {
502            // fallback without cleanup
503            match self.local.read().widget_subs.get(&widget_id) {
504                Some(e) => e.retain(),
505                None => false,
506            }
507        }
508    }
509
510    fn to_set(&self) -> IdSet<WidgetId> {
511        self.local.read().widget_subs.keys().copied().collect()
512    }
513}
514
515/// Represents a collection of event handles.
516#[must_use = "the event subscriptions or handlers are dropped if the handle is dropped"]
517#[derive(Clone, Default)]
518pub struct EventHandles(Vec<EventHandle>);
519impl EventHandles {
520    /// Empty collection.
521    pub const fn dummy() -> Self {
522        EventHandles(vec![])
523    }
524
525    /// Returns `true` if empty or all handles are dummy.
526    pub fn is_dummy(&self) -> bool {
527        self.0.is_empty() || self.0.iter().all(EventHandle::is_dummy)
528    }
529
530    /// Drop all handles without stopping their behavior.
531    pub fn perm(self) {
532        for handle in self.0 {
533            handle.perm()
534        }
535    }
536
537    /// Add `other` handle to the collection.
538    pub fn push(&mut self, other: EventHandle) -> &mut Self {
539        if !other.is_dummy() {
540            self.0.push(other);
541        }
542        self
543    }
544
545    /// Drop all handles.
546    pub fn clear(&mut self) {
547        self.0.clear();
548    }
549}
550impl FromIterator<EventHandle> for EventHandles {
551    fn from_iter<T: IntoIterator<Item = EventHandle>>(iter: T) -> Self {
552        EventHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
553    }
554}
555impl<const N: usize> From<[EventHandle; N]> for EventHandles {
556    fn from(handles: [EventHandle; N]) -> Self {
557        handles.into_iter().filter(|h| !h.is_dummy()).collect()
558    }
559}
560impl Extend<EventHandle> for EventHandles {
561    fn extend<T: IntoIterator<Item = EventHandle>>(&mut self, iter: T) {
562        for handle in iter {
563            self.push(handle);
564        }
565    }
566}
567impl IntoIterator for EventHandles {
568    type Item = EventHandle;
569
570    type IntoIter = std::vec::IntoIter<EventHandle>;
571
572    fn into_iter(self) -> Self::IntoIter {
573        self.0.into_iter()
574    }
575}
576
577struct EventHandleData {
578    perm: AtomicBool,
579    hook: Option<Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>>,
580}
581
582/// Represents an event widget subscription, handler callback or hook.
583#[derive(Clone)]
584#[must_use = "the event subscription or handler is dropped if the handle is dropped"]
585pub struct EventHandle(Option<Arc<EventHandleData>>);
586impl PartialEq for EventHandle {
587    fn eq(&self, other: &Self) -> bool {
588        match (&self.0, &other.0) {
589            (None, None) => true,
590            (None, Some(_)) | (Some(_), None) => false,
591            (Some(a), Some(b)) => Arc::ptr_eq(a, b),
592        }
593    }
594}
595impl Eq for EventHandle {}
596impl std::hash::Hash for EventHandle {
597    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
598        let i = match &self.0 {
599            Some(rc) => Arc::as_ptr(rc) as usize,
600            None => 0,
601        };
602        state.write_usize(i);
603    }
604}
605impl fmt::Debug for EventHandle {
606    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
607        let i = match &self.0 {
608            Some(rc) => Arc::as_ptr(rc) as usize,
609            None => 0,
610        };
611        f.debug_tuple("EventHandle").field(&i).finish()
612    }
613}
614/// Dummy
615impl Default for EventHandle {
616    fn default() -> Self {
617        Self::dummy()
618    }
619}
620impl EventHandle {
621    fn new(hook: Box<dyn Fn(&mut EventUpdate) -> bool + Send + Sync>) -> (Self, EventHook) {
622        let rc = Arc::new(EventHandleData {
623            perm: AtomicBool::new(false),
624            hook: Some(hook),
625        });
626        (Self(Some(rc.clone())), EventHook(rc))
627    }
628
629    fn new_none() -> Self {
630        Self(Some(Arc::new(EventHandleData {
631            perm: AtomicBool::new(false),
632            hook: None,
633        })))
634    }
635
636    /// Handle to no event.
637    pub fn dummy() -> Self {
638        EventHandle(None)
639    }
640
641    /// If the handle is not actually registered in an event.
642    pub fn is_dummy(&self) -> bool {
643        self.0.is_none()
644    }
645
646    /// Drop the handle without un-registering it, the resource it represents will remain registered in the event for the duration of
647    /// the process.
648    pub fn perm(self) {
649        if let Some(rc) = self.0 {
650            rc.perm.store(true, Ordering::Relaxed);
651        }
652    }
653
654    /// Create an [`EventHandles`] collection with `self` and `other`.
655    pub fn with(self, other: Self) -> EventHandles {
656        [self, other].into()
657    }
658
659    fn retain(&self) -> bool {
660        let rc = self.0.as_ref().unwrap();
661        Arc::strong_count(rc) > 1 || rc.perm.load(Ordering::Relaxed)
662    }
663}
664
665struct EventHook(Arc<EventHandleData>);
666impl EventHook {
667    /// Callback, returns `true` if the handle must be retained.
668    fn call(&self, update: &mut EventUpdate) -> bool {
669        (Arc::strong_count(&self.0) > 1 || self.0.perm.load(Ordering::Relaxed)) && (self.0.hook.as_ref().unwrap())(update)
670    }
671}