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};