zng/
handler.rs

1//! Event handler API.
2//!
3//! A handler is a closure that takes a *context* and *arguments*, the context can be [`WIDGET`] or the app. The [`Handler<A>`]
4//! type supports both synchronous and asynchronous handlers. The handler is not usually instantiated directly, macros are provided
5//! for declaring handlers.
6//!
7//! The handler macros are [`hn!`], [`hn_once!`], [`async_hn!`], [`async_hn_once!`].
8//! These macros are built on top of the primitive macros [`clmv!`], [`async_clmv_fn!`] and [`async_clmv_fn_once!`] to
9//! provide a very easy way to *clone-move* captured variables into the handler.
10//!
11//! ```
12//! use zng::prelude::*;
13//! # fn example() {
14//!
15//! let last_clicked = var(Txt::from(""));
16//! # let _ =
17//! Stack!(
18//!     top_to_bottom,
19//!     5,
20//!     ui_vec![
21//!         Button! {
22//!             child = Text!("hn!");
23//!             on_click = hn!(last_clicked, |_| {
24//!                 last_clicked.set("hn!");
25//!             });
26//!         },
27//!         Button! {
28//!             child = Text!("hn_once!");
29//!             on_click = hn_once!(last_clicked, |_| {
30//!                 last_clicked.set("hn_once!");
31//!             });
32//!         },
33//!         {
34//!             let enabled = var(true);
35//!             Button! {
36//!                 child = Text!("async_hn!");
37//!                 on_click = async_hn!(last_clicked, enabled, |_| {
38//!                     last_clicked.set("async_hn!");
39//!                     enabled.set(false);
40//!                     task::deadline(1.secs()).await;
41//!                     enabled.set(true);
42//!                 });
43//!                 widget::enabled;
44//!             }
45//!         },
46//!         Text!(last_clicked),
47//!     ]
48//! )
49//! # ; }
50//! ```
51//!
52//! # App Context
53//!
54//! When a handler is not set in a widget the [`APP_HANDLER`] contextual service is available, it can be used to unsubscribe
55//! the event from within.
56//!
57//! ```
58//! # use zng::prelude::*;
59//! # use zng::focus::FOCUS_CHANGED_EVENT;
60//! # fn example() {
61//! FOCUS_CHANGED_EVENT
62//!     .on_pre_event(hn!(|args| {
63//!         println!("focused: {:?}", args.new_focus);
64//!         if args.new_focus.is_none() {
65//!             zng::handler::APP_HANDLER.unsubscribe();
66//!         }
67//!     }))
68//!     .perm();
69//! # }
70//! ```
71//!
72//! In the example above the event subscription is made `perm`, but inside the handler `unsubscribe` is called when a
73//! condition is met, causing the handler to be dropped. This is a common pattern for app level event handlers that
74//! can manage their own subscription.
75//!
76//! The [`APP_HANDLER`] will also be available after each `await` point in async handlers, after an async task unsubscribes
77//! all running handler tasks will run to the end and no new tasks will be started.
78//!
79//! # Args Type Inference
80//!
81//! The [`Handler<A>`] type is an alias for `Box<dyn FnMut(&A + Clone + 'static) ...>` by necessity as this is the only way to have a type where
82//! the closure args is inferred. Unfortunately this has some limitations, documentation shows the raw box type, the `A` bounds is not enforced
83//! on type declaration too.
84//!
85//! These limitations enable type inference for the arguments of [`hn!`] and [`async_hn!`] set directly on a property, reducing the need to
86//! track down exact event args types, unfortunately as of this release the [`hn_once!`] and [`async_hn_once!`] handlers will still need
87//! and explicit args type if the handler uses the arg.
88//!
89//! [`WIDGET`]: crate::widget::WIDGET
90//! [`clmv!`]: crate::clmv
91//! [`async_clmv_fn!`]: crate::async_clmv_fn
92//! [`async_clmv_fn_once!`]: crate::async_clmv_fn_once
93//!
94//! # Full API
95//!
96//! See [`zng_app::handler`] for the full handler API.
97
98pub use zng_app::handler::{APP_HANDLER, AppWeakHandle, ArcHandler, Handler, HandlerExt, async_hn, async_hn_once, hn, hn_once};