zng_app/
handler.rs

1//! Handler types and macros.
2
3use std::any::Any;
4use std::marker::PhantomData;
5use std::time::Duration;
6use std::{mem, thread};
7
8#[doc(hidden)]
9pub use zng_clone_move::*;
10
11use zng_handle::{Handle, WeakHandle};
12use zng_task::{self as task, UiTask};
13
14use crate::INSTANT;
15
16/// Represents a handler in a widget context.
17///
18/// There are different flavors of handlers, you can use macros to declare then.
19/// See [`hn!`], [`hn_once!`] or [`async_hn!`], [`async_hn_once!`] to start.
20#[diagnostic::on_unimplemented(
21    note = "use `hn!(|args: &{A}| {{ }})` to declare a widget handler from a `FnMut` closure",
22    note = "use `hn_once!`, `async_hn!` or `async_hn_once!` for other closure types"
23)]
24pub trait WidgetHandler<A: Clone + 'static>: Any + Send {
25    /// Called every time the handler's event happens in the widget context.
26    ///
27    /// Returns `true` when the event handler is async and it has not finished handling the event.
28    ///
29    /// [`update`]: WidgetHandler::update
30    /// [`info`]: crate::widget::node::UiNode::info
31    fn event(&mut self, args: &A) -> bool;
32
33    /// Called every widget update.
34    ///
35    /// Returns `false` when all pending async tasks are completed. Note that event properties
36    /// will call this method every update even if it is returning `false`.
37    ///
38    /// [`update`]: WidgetHandler::update
39    fn update(&mut self) -> bool {
40        false
41    }
42
43    /// Box the handler.
44    ///
45    /// The type `Box<dyn WidgetHandler<A>>` implements `WidgetHandler<A>` and just returns itself
46    /// in this method, avoiding double boxing.
47    fn boxed(self) -> Box<dyn WidgetHandler<A>>
48    where
49        Self: Sized,
50    {
51        Box::new(self)
52    }
53}
54impl<A: Clone + 'static> WidgetHandler<A> for Box<dyn WidgetHandler<A>> {
55    #[inline(always)]
56    fn event(&mut self, args: &A) -> bool {
57        self.as_mut().event(args)
58    }
59
60    #[inline(always)]
61    fn update(&mut self) -> bool {
62        self.as_mut().update()
63    }
64
65    #[inline(always)]
66    fn boxed(self) -> Box<dyn WidgetHandler<A>>
67    where
68        Self: Sized,
69    {
70        self
71    }
72}
73
74#[doc(hidden)]
75pub struct FnMutWidgetHandler<H> {
76    handler: H,
77}
78impl<A, H> WidgetHandler<A> for FnMutWidgetHandler<H>
79where
80    A: Clone + 'static,
81    H: FnMut(&A) + Send + 'static,
82{
83    #[inline(always)]
84    fn event(&mut self, args: &A) -> bool {
85        (self.handler)(args);
86        false
87    }
88}
89
90#[doc(hidden)]
91pub fn hn<A, H>(handler: H) -> FnMutWidgetHandler<H>
92where
93    A: Clone + 'static,
94    H: FnMut(&A) + Send + 'static,
95{
96    FnMutWidgetHandler { handler }
97}
98
99///<span data-del-macro-root></span> Declare a mutable *clone-move* event handler.
100///
101/// The macro input is a closure with optional *clone-move* variables, internally it uses [`clmv!`] so
102/// the input is the same syntax.
103///
104/// # Examples
105///
106/// The example declares an event handler for the `on_click` property.
107///
108/// ```
109/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
110/// # use zng_app::handler::hn;
111/// # let _scope = zng_app::APP.minimal();
112/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
113/// # let
114/// on_click = hn!(|_| {
115///     println!("Clicked!");
116/// });
117/// # on_click }
118/// ```
119///
120/// The closure input is `&ClickArgs` for this property. Note that
121/// if you want to use the event args you must annotate the input type, the context type is inferred.
122///
123/// ```
124/// # #[derive(Clone)] pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize }
125/// # use zng_app::handler::hn;
126/// # let _scope = zng_app::APP.minimal();
127/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
128/// # let
129/// on_click = hn!(|args: &ClickArgs| {
130///     println!("Clicked {}!", args.click_count);
131/// });
132/// # on_click }
133/// ```
134///
135/// Internally the [`clmv!`] macro is used so you can *clone-move* variables into the handler.
136///
137/// ```
138/// # #[derive(Clone)] pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize }
139/// # use zng_txt::formatx;
140/// # use zng_var::{var, Var};
141/// # use zng_app::handler::hn;
142/// # let _scope = zng_app::APP.minimal();
143/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
144/// let foo = var(0);
145///
146/// // ..
147///
148/// # let
149/// on_click = hn!(foo, |args: &ClickArgs| {
150///     foo.set(args.click_count);
151/// });
152///
153/// // can still use after:
154/// let bar = foo.map(|c| formatx!("click_count: {c}"));
155///
156/// # on_click }
157/// ```
158///
159/// In the example above only a clone of `foo` is moved into the handler. Note that handlers always capture by move, if `foo` was not
160/// listed in the *clone-move* section it would not be available after the handler is created. See [`clmv!`] for details.
161///
162/// [`clmv!`]: zng_clone_move::clmv
163#[macro_export]
164macro_rules! hn {
165    ($($tt:tt)+) => {
166        $crate::handler::hn($crate::handler::clmv!{ $($tt)+ })
167    }
168}
169#[doc(inline)]
170pub use crate::hn;
171use crate::{AppControlFlow, HeadlessApp};
172
173#[doc(hidden)]
174pub struct FnOnceWidgetHandler<H> {
175    handler: Option<H>,
176}
177impl<A, H> WidgetHandler<A> for FnOnceWidgetHandler<H>
178where
179    A: Clone + 'static,
180    H: FnOnce(&A) + Send + 'static,
181{
182    #[inline(always)]
183    fn event(&mut self, args: &A) -> bool {
184        if let Some(handler) = self.handler.take() {
185            handler(args);
186        }
187        false
188    }
189}
190#[doc(hidden)]
191pub fn hn_once<A, H>(handler: H) -> FnOnceWidgetHandler<H>
192where
193    A: Clone + 'static,
194    H: FnOnce(&A) + Send + 'static,
195{
196    FnOnceWidgetHandler { handler: Some(handler) }
197}
198
199///<span data-del-macro-root></span> Declare a *clone-move* event handler that is only called once.
200///
201/// The macro input is a closure with optional *clone-move* variables, internally it uses [`clmv!`] so
202/// the input is the same syntax.
203///
204/// # Examples
205///
206/// The example captures `data` by move and then destroys it in the first call, this cannot be done using [`hn!`] because
207/// the `data` needs to be available for all event calls. In this case the closure is only called once, subsequent events
208/// are ignored by the handler.
209///
210/// ```
211/// # use zng_app::handler::hn_once;
212/// # let _scope = zng_app::APP.minimal();
213/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<()> {
214/// let data = vec![1, 2, 3];
215/// # let
216/// on_click = hn_once!(|_| {
217///     for i in data {
218///         print!("{i}, ");
219///     }
220/// });
221/// # on_click }
222/// ```
223///
224/// Other then declaring a `FnOnce` this macro behaves like [`hn!`], so the same considerations apply. You can *clone-move* variables,
225/// the type of the input is the event arguments and must be annotated.
226///
227/// ```
228/// # use zng_app::handler::hn_once;
229/// # let _scope = zng_app::APP.minimal();
230/// # #[derive(Clone)]
231/// # pub struct ClickArgs { click_count: usize }
232/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
233/// let data = vec![1, 2, 3];
234/// # let
235/// on_click = hn_once!(data, |args: &ClickArgs| {
236///     drop(data);
237/// });
238///
239/// println!("{data:?}");
240/// # on_click }
241/// ```
242///
243/// [`clmv!`]: zng_clone_move::clmv
244#[macro_export]
245macro_rules! hn_once {
246    ($($tt:tt)+) => {
247        $crate::handler::hn_once($crate::handler::clmv! { $($tt)+ })
248    }
249}
250#[doc(inline)]
251pub use crate::hn_once;
252
253#[doc(hidden)]
254pub struct AsyncFnMutWidgetHandler<H> {
255    handler: H,
256    tasks: Vec<UiTask<()>>,
257}
258impl<A, F, H> WidgetHandler<A> for AsyncFnMutWidgetHandler<H>
259where
260    A: Clone + 'static,
261    F: Future<Output = ()> + Send + 'static,
262    H: FnMut(A) -> F + Send + 'static,
263{
264    fn event(&mut self, args: &A) -> bool {
265        let handler = &mut self.handler;
266        let mut task = UiTask::new(Some(WIDGET.id()), handler(args.clone()));
267        let need_update = task.update().is_none();
268        if need_update {
269            self.tasks.push(task);
270        }
271        need_update
272    }
273
274    fn update(&mut self) -> bool {
275        self.tasks.retain_mut(|t| t.update().is_none());
276        !self.tasks.is_empty()
277    }
278}
279#[doc(hidden)]
280pub fn async_hn<A, F, H>(handler: H) -> AsyncFnMutWidgetHandler<H>
281where
282    A: Clone + 'static,
283    F: Future<Output = ()> + Send + 'static,
284    H: FnMut(A) -> F + Send + 'static,
285{
286    AsyncFnMutWidgetHandler { handler, tasks: vec![] }
287}
288
289///<span data-del-macro-root></span> Declare an async *clone-move* event handler.
290///
291/// The macro input is a closure with optional *clone-move* variables, internally it uses [`async_clmv_fn!`] so
292/// the input is the same syntax.
293///
294/// # Examples
295///
296/// The example declares an async event handler for the `on_click` property.
297///
298/// ```
299/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
300/// # use zng_app::handler::async_hn;
301/// # use zng_task as task;
302/// # let _scope = zng_app::APP.minimal();
303/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
304/// # let
305/// on_click = async_hn!(|_| {
306///     println!("Clicked!");
307///
308///     task::run(async {
309///         println!("In other thread!");
310///     })
311///     .await;
312///
313///     println!("Back in UI thread, in a widget update.");
314/// });
315/// # on_click }
316/// ```
317///
318/// The closure input is `ClickArgs` for this property. Note that
319/// if you want to use the event args you must annotate the input type.
320///
321/// ```
322/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
323/// # use zng_app::handler::async_hn;
324/// # use zng_app::widget::WIDGET;
325/// # let _scope = zng_app::APP.minimal();
326/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
327/// # let
328/// on_click = async_hn!(|args: ClickArgs| {
329///     println!("Clicked {} {} times!", WIDGET.id(), args.click_count);
330/// });
331/// # on_click }
332/// ```
333///
334/// Internally the [`async_clmv_fn!`] macro is used so you can *clone-move* variables into the handler.
335///
336/// ```
337/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
338/// # use zng_app::handler::async_hn;
339/// # use zng_var::{var, Var};
340/// # use zng_task as task;
341/// # use zng_txt::formatx;
342/// # let _scope = zng_app::APP.minimal();
343/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
344/// let enabled = var(true);
345///
346/// // ..
347///
348/// # let
349/// on_click = async_hn!(enabled, |args: ClickArgs| {
350///     enabled.set(false);
351///
352///     task::run(async move {
353///         println!("do something {}", args.click_count);
354///     })
355///     .await;
356///
357///     enabled.set(true);
358/// });
359///
360/// // can still use after:
361/// # let
362/// text = enabled.map(|&e| if e { "Click Me!" } else { "Busy.." });
363/// enabled;
364///
365/// # on_click }
366/// ```
367///
368/// In the example above only a clone of `enabled` is moved into the handler. Note that handlers always capture by move, if `enabled` was not
369/// listed in the *clone-move* section it would not be available after the handler is created. See [`async_clmv_fn!`] for details.
370///
371/// The example also demonstrates a common pattern with async handlers, most events are only raised when the widget is enabled, so you can
372/// disable the widget while the async task is running. This way you don't block the UI running a task but the user cannot spawn a second
373/// task while the first is still running.
374///
375/// ## Futures and Clone-Move
376///
377/// You want to always *clone-move* captures for async handlers, because they then automatically get cloned again for each event. This
378/// needs to happen because you can have more then one *handler task* running at the same type, and both want access to the captured variables.
379///
380/// This second cloning can be avoided by using the [`async_hn_once!`] macro instead, but only if you expect a single event.
381///
382/// Note that this means you are declaring a normal closure that returns a `'static` future, not an async closure, see [`async_clmv_fn!`].
383///
384/// [`async_clmv_fn!`]: zng_clone_move::async_clmv_fn
385#[macro_export]
386macro_rules! async_hn {
387    ($($tt:tt)+) => {
388        $crate::handler::async_hn($crate::handler::async_clmv_fn! { $($tt)+ })
389    }
390}
391#[doc(inline)]
392pub use crate::async_hn;
393
394enum AsyncFnOnceWhState<H> {
395    NotCalled(H),
396    Pending(UiTask<()>),
397    Done,
398}
399#[doc(hidden)]
400pub struct AsyncFnOnceWidgetHandler<H> {
401    state: AsyncFnOnceWhState<H>,
402}
403impl<A, F, H> WidgetHandler<A> for AsyncFnOnceWidgetHandler<H>
404where
405    A: Clone + 'static,
406    F: Future<Output = ()> + Send + 'static,
407    H: FnOnce(A) -> F + Send + 'static,
408{
409    fn event(&mut self, args: &A) -> bool {
410        match mem::replace(&mut self.state, AsyncFnOnceWhState::Done) {
411            AsyncFnOnceWhState::NotCalled(handler) => {
412                let mut task = UiTask::new(Some(WIDGET.id()), handler(args.clone()));
413                let is_pending = task.update().is_none();
414                if is_pending {
415                    self.state = AsyncFnOnceWhState::Pending(task);
416                }
417                is_pending
418            }
419            AsyncFnOnceWhState::Pending(t) => {
420                self.state = AsyncFnOnceWhState::Pending(t);
421                false
422            }
423            AsyncFnOnceWhState::Done => false,
424        }
425    }
426
427    fn update(&mut self) -> bool {
428        let mut is_pending = false;
429        if let AsyncFnOnceWhState::Pending(t) = &mut self.state {
430            is_pending = t.update().is_none();
431            if !is_pending {
432                self.state = AsyncFnOnceWhState::Done;
433            }
434        }
435        is_pending
436    }
437}
438#[doc(hidden)]
439pub fn async_hn_once<A, F, H>(handler: H) -> AsyncFnOnceWidgetHandler<H>
440where
441    A: Clone + 'static,
442    F: Future<Output = ()> + Send + 'static,
443    H: FnOnce(A) -> F + Send + 'static,
444{
445    AsyncFnOnceWidgetHandler {
446        state: AsyncFnOnceWhState::NotCalled(handler),
447    }
448}
449
450///<span data-del-macro-root></span> Declare an async *clone-move* event handler that is only called once.
451///
452/// The macro input is a closure with optional *clone-move* variables, internally it uses [`async_clmv_fn_once!`] so
453/// the input is the same syntax.
454///
455/// # Examples
456///
457/// The example captures `data` by move and then moves it again to another thread. This is not something you can do using [`async_hn!`]
458/// because that handler expects to be called many times. We expect `on_open` to only be called once, so we can don't need to capture by
459/// *clone-move* here just to use `data`.
460///
461/// ```
462/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
463/// # use zng_app::handler::async_hn_once;
464/// # use zng_task as task;
465/// # let _scope = zng_app::APP.minimal();
466/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
467/// let data = vec![1, 2, 3];
468/// # let
469/// on_open = async_hn_once!(|_| {
470///     task::run(async move {
471///         for i in data {
472///             print!("{i}, ");
473///         }
474///     })
475///     .await;
476///
477///     println!("Done!");
478/// });
479/// # on_open }
480/// ```
481///
482/// You can still *clone-move* to have access to the variable after creating the handler, in this case the `data` will be cloned into the handler
483/// but will just be moved to the other thread, avoiding a needless clone.
484///
485/// ```
486/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
487/// # use zng_app::handler::async_hn_once;
488/// # use zng_task as task;
489/// # let _scope = zng_app::APP.minimal();
490/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
491/// let data = vec![1, 2, 3];
492/// # let
493/// on_open = async_hn_once!(data, |_| {
494///     task::run(async move {
495///         for i in data {
496///             print!("{i}, ");
497///         }
498///     })
499///     .await;
500///
501///     println!("Done!");
502/// });
503/// println!("{data:?}");
504/// # on_open }
505/// ```
506///
507/// [`async_clmv_fn_once!`]: zng_clone_move::async_clmv_fn_once
508#[macro_export]
509macro_rules! async_hn_once {
510    ($($tt:tt)+) => {
511        $crate::handler::async_hn_once($crate::handler::async_clmv_fn_once! { $($tt)+ })
512    }
513}
514#[doc(inline)]
515pub use crate::async_hn_once;
516
517/// Represents a weak handle to an [`AppHandler`] subscription.
518pub trait AppWeakHandle: Send {
519    /// Dynamic clone.
520    fn clone_boxed(&self) -> Box<dyn AppWeakHandle>;
521
522    /// Unsubscribes the [`AppHandler`].
523    ///
524    /// This stops the handler from being called again and causes it to be dropped in a future app update.
525    fn unsubscribe(&self);
526}
527impl<D: Send + Sync + 'static> AppWeakHandle for WeakHandle<D> {
528    fn clone_boxed(&self) -> Box<dyn AppWeakHandle> {
529        Box::new(self.clone())
530    }
531
532    fn unsubscribe(&self) {
533        if let Some(handle) = self.upgrade() {
534            handle.force_drop();
535        }
536    }
537}
538
539/// Arguments for a call of [`AppHandler::event`].
540#[non_exhaustive]
541pub struct AppHandlerArgs<'a> {
542    /// Handle to the [`AppHandler`] subscription.
543    pub handle: &'a dyn AppWeakHandle,
544    /// If the handler is invoked in a *preview* context.
545    pub is_preview: bool,
546}
547
548/// Represents an event handler in the app context.
549///
550/// There are different flavors of handlers, you can use macros to declare then.
551/// See [`app_hn!`], [`app_hn_once!`] or [`async_app_hn!`], [`async_app_hn_once!`] to start.
552#[diagnostic::on_unimplemented(
553    note = "use `app_hn!(|args: &{A}, _| {{ }})` to declare an app handler closure",
554    note = "use `app_hn_once!`, `async_app_hn!` or `async_app_hn_once!` for other closure types"
555)]
556pub trait AppHandler<A: Clone + 'static>: Any + Send {
557    /// Called every time the event happens.
558    ///
559    /// The `handler_args` can be used to unsubscribe the handler. Async handlers are expected to schedule
560    /// their tasks to run somewhere in the app, usually in the [`UPDATES.on_update`]. The `handle` is
561    /// **not** expected to cancel running async tasks, only to drop `self` before the next event happens.
562    ///
563    /// [`UPDATES.on_update`]: crate::update::UPDATES::on_update
564    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs);
565
566    /// Boxes the handler.
567    ///
568    /// The type `Box<dyn AppHandler<A>>` implements `AppHandler<A>` and just returns itself
569    /// in this method, avoiding double boxing.
570    fn boxed(self) -> Box<dyn AppHandler<A>>
571    where
572        Self: Sized,
573    {
574        Box::new(self)
575    }
576}
577impl<A: Clone + 'static> AppHandler<A> for Box<dyn AppHandler<A>> {
578    #[inline(always)]
579    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
580        self.as_mut().event(args, handler_args)
581    }
582
583    #[inline(always)]
584    fn boxed(self) -> Box<dyn AppHandler<A>> {
585        self
586    }
587}
588
589#[doc(hidden)]
590pub struct FnMutAppHandler<H> {
591    handler: H,
592}
593impl<A, H> AppHandler<A> for FnMutAppHandler<H>
594where
595    A: Clone + 'static,
596    H: FnMut(&A, &dyn AppWeakHandle) + Send + 'static,
597{
598    #[inline(always)]
599    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
600        (self.handler)(args, handler_args.handle);
601    }
602}
603#[doc(hidden)]
604pub fn app_hn<A, H>(handler: H) -> FnMutAppHandler<H>
605where
606    A: Clone + 'static,
607    H: FnMut(&A, &dyn AppWeakHandle) + Send + 'static,
608{
609    FnMutAppHandler { handler }
610}
611
612///<span data-del-macro-root></span> Declare a mutable *clone-move* app event handler.
613///
614/// The macro input is a closure with optional *clone-move* variables, internally it uses [`clmv!`] so
615/// the input is the same syntax.
616///
617/// # Examples
618///
619/// The example declares an event handler for the `CLICK_EVENT`.
620///
621/// ```
622/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
623/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
624/// # use zng_app::handler::app_hn;
625/// # let _scope = zng_app::APP.minimal();
626/// # fn assert_type() {
627/// CLICK_EVENT
628///     .on_event(app_hn!(|_, _| {
629///         println!("Clicked Somewhere!");
630///     }))
631///     .perm();
632/// # }
633/// ```
634///
635/// The closure input is `&A, &dyn AppWeakHandle` with `&A` equaling `&ClickArgs` for this event. Note that
636/// if you want to use the event args you must annotate the input type, the context and handle type is inferred.
637///
638/// The handle can be used to unsubscribe the event handler, if [`unsubscribe`](AppWeakHandle::unsubscribe) is called the handler
639/// will be dropped some time before the next event update.
640///
641/// ```
642/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
643/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
644/// # use zng_app::handler::app_hn;
645/// # let _scope = zng_app::APP.minimal();
646/// # fn assert_type() {
647/// CLICK_EVENT
648///     .on_event(app_hn!(|args: &ClickArgs, handle| {
649///         println!("Clicked {}!", args.target);
650///         handle.unsubscribe();
651///     }))
652///     .perm();
653/// # }
654/// ```
655///
656/// Internally the [`clmv!`] macro is used so you can *clone-move* variables into the handler.
657///
658/// ```
659/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
660/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
661/// # use zng_txt::{formatx, ToTxt};
662/// # use zng_var::{var, Var};
663/// # use zng_app::handler::app_hn;
664/// # let _scope = zng_app::APP.minimal();
665/// # fn assert_type() {
666/// let foo = var("".to_txt());
667///
668/// CLICK_EVENT
669///     .on_event(app_hn!(foo, |args: &ClickArgs, _| {
670///         foo.set(args.target.to_txt());
671///     }))
672///     .perm();
673///
674/// // can still use after:
675/// let bar = foo.map(|c| formatx!("last click: {c}"));
676///
677/// # }
678/// ```
679///
680/// In the example above only a clone of `foo` is moved into the handler. Note that handlers always capture by move, if `foo` was not
681/// listed in the *clone-move* section it would not be available after the handler is created. See [`clmv!`] for details.
682///
683/// [`clmv!`]: zng_clone_move::clmv
684#[macro_export]
685macro_rules! app_hn {
686    ($($tt:tt)+) => {
687        $crate::handler::app_hn($crate::handler::clmv!{ $($tt)+ })
688    }
689}
690#[doc(inline)]
691pub use crate::app_hn;
692
693#[doc(hidden)]
694pub struct FnOnceAppHandler<H> {
695    handler: Option<H>,
696}
697impl<A, H> AppHandler<A> for FnOnceAppHandler<H>
698where
699    A: Clone + 'static,
700    H: FnOnce(&A) + Send + 'static,
701{
702    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
703        if let Some(handler) = self.handler.take() {
704            handler(args);
705            handler_args.handle.unsubscribe();
706        } else {
707            tracing::error!("`app_hn_once!` called after requesting unsubscribe");
708        }
709    }
710}
711#[doc(hidden)]
712pub fn app_hn_once<A, H>(handler: H) -> FnOnceAppHandler<H>
713where
714    A: Clone + 'static,
715    H: FnOnce(&A) + Send + 'static,
716{
717    FnOnceAppHandler { handler: Some(handler) }
718}
719
720///<span data-del-macro-root></span> Declare a *clone-move* app event handler that is only called once.
721///
722/// The macro input is a closure with optional *clone-move* variables, internally it uses [`clmv!`] so
723/// the input is the same syntax.
724///
725/// # Examples
726///
727/// The example captures `data` by move and then destroys it in the first call, this cannot be done using [`app_hn!`] because
728/// the `data` needs to be available for all event calls. In this case the closure is only called once, subsequent events
729/// are ignored by the handler and it automatically requests unsubscribe.
730///
731/// ```
732/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
733/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
734/// # use zng_app::handler::app_hn_once;
735/// # let _scope = zng_app::APP.minimal();
736/// # fn assert_type() {
737/// let data = vec![1, 2, 3];
738///
739/// CLICK_EVENT
740///     .on_event(app_hn_once!(|_| {
741///         for i in data {
742///             print!("{i}, ");
743///         }
744///     }))
745///     .perm();
746/// # }
747/// ```
748///
749/// Other then declaring a `FnOnce` this macro behaves like [`app_hn!`], so the same considerations apply. You can *clone-move* variables,
750/// the type of the input is the event arguments and must be annotated.
751///
752/// ```
753/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
754/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
755/// # use zng_app::handler::app_hn_once;
756/// # let _scope = zng_app::APP.minimal();
757/// # fn assert_type() {
758/// let data = vec![1, 2, 3];
759///
760/// CLICK_EVENT
761///     .on_event(app_hn_once!(data, |args: &ClickArgs| {
762///         drop(data);
763///     }))
764///     .perm();
765///
766/// println!("{data:?}");
767/// # }
768/// ```
769///
770/// [`clmv!`]: zng_clone_move::clmv
771#[macro_export]
772macro_rules! app_hn_once {
773    ($($tt:tt)+) => {
774        $crate::handler::app_hn_once($crate::handler::clmv! { $($tt)+ })
775    }
776}
777#[doc(inline)]
778pub use crate::app_hn_once;
779
780#[doc(hidden)]
781pub struct AsyncFnMutAppHandler<H> {
782    handler: H,
783}
784impl<A, F, H> AppHandler<A> for AsyncFnMutAppHandler<H>
785where
786    A: Clone + 'static,
787    F: Future<Output = ()> + Send + 'static,
788    H: FnMut(A, Box<dyn AppWeakHandle>) -> F + Send + 'static,
789{
790    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
791        let handler = &mut self.handler;
792        let mut task = UiTask::new(None, handler(args.clone(), handler_args.handle.clone_boxed()));
793        if task.update().is_none() {
794            if handler_args.is_preview {
795                UPDATES
796                    .on_pre_update(app_hn!(|_, handle| {
797                        if task.update().is_some() {
798                            handle.unsubscribe();
799                        }
800                    }))
801                    .perm();
802            } else {
803                UPDATES
804                    .on_update(app_hn!(|_, handle| {
805                        if task.update().is_some() {
806                            handle.unsubscribe();
807                        }
808                    }))
809                    .perm();
810            }
811        }
812    }
813}
814#[doc(hidden)]
815pub fn async_app_hn<A, F, H>(handler: H) -> AsyncFnMutAppHandler<H>
816where
817    A: Clone + 'static,
818    F: Future<Output = ()> + Send + 'static,
819    H: FnMut(A, Box<dyn AppWeakHandle>) -> F + Send + 'static,
820{
821    AsyncFnMutAppHandler { handler }
822}
823
824///<span data-del-macro-root></span> Declare an async *clone-move* app event handler.
825///
826/// The macro input is a closure with optional *clone-move* variables, internally it uses [`async_clmv_fn!`] so
827/// the input is the same syntax.
828///
829/// The handler generates a future for each event, the future is polled immediately if it does not finish it is scheduled
830/// to update in [`on_pre_update`](crate::update::UPDATES::on_pre_update) or [`on_update`](crate::update::UPDATES::on_update) depending
831/// on if the handler was assigned to a *preview* event or not.
832///
833/// Note that this means [`propagation`](crate::event::AnyEventArgs::propagation) can only be meaningfully stopped before the
834/// first `.await`, after, the event has already propagated.
835///
836/// # Examples
837///
838/// The example declares an async event handler for the `CLICK_EVENT`.
839///
840/// ```
841/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
842/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
843/// # use zng_app::handler::async_app_hn;
844/// # use zng_task as task;
845/// # let _scope = zng_app::APP.minimal();
846/// # fn assert_type() {
847/// CLICK_EVENT
848///     .on_event(async_app_hn!(|_, _| {
849///         println!("Clicked Somewhere!");
850///
851///         task::run(async {
852///             println!("In other thread!");
853///         })
854///         .await;
855///
856///         println!("Back in UI thread, in an app update.");
857///     }))
858///     .perm();
859/// # }
860/// ```
861///
862/// The closure input is `A, Box<dyn AppWeakHandle>` for all handlers and `A` is `ClickArgs` for this example. Note that
863/// if you want to use the event args you must annotate the input type, the context and handle types are inferred.
864///
865/// The handle can be used to unsubscribe the event handler, if [`unsubscribe`](AppWeakHandle::unsubscribe) is called the handler
866/// will be dropped some time before the next event update. Running tasks are not canceled by unsubscribing, the only way to *cancel*
867/// then is by returning early inside the async blocks.
868///
869/// ```
870/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
871/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
872/// # use zng_app::handler::async_app_hn;
873/// # use zng_task as task;
874/// # let _scope = zng_app::APP.minimal();
875/// # fn assert_type() {
876/// CLICK_EVENT
877///     .on_event(async_app_hn!(|args: ClickArgs, handle| {
878///         println!("Clicked {}!", args.target);
879///         task::run(async move {
880///             handle.unsubscribe();
881///         });
882///     }))
883///     .perm();
884/// # }
885/// ```
886///
887/// Internally the [`async_clmv_fn!`] macro is used so you can *clone-move* variables into the handler.
888///
889/// ```
890/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
891/// # zng_app::event::event! { pub static CLICK_EVENT: ClickArgs; }
892/// # use zng_app::handler::async_app_hn;
893/// # use zng_var::{var, Var};
894/// # use zng_task as task;
895/// # use zng_txt::{formatx, ToTxt};
896/// #
897/// # let _scope = zng_app::APP.minimal();
898/// # fn assert_type() {
899/// let status = var("pending..".to_txt());
900///
901/// CLICK_EVENT
902///     .on_event(async_app_hn!(status, |args: ClickArgs, _| {
903///         status.set(formatx!("processing {}..", args.target));
904///
905///         task::run(async move {
906///             println!("do something slow");
907///         })
908///         .await;
909///
910///         status.set(formatx!("finished {}", args.target));
911///     }))
912///     .perm();
913///
914/// // can still use after:
915/// let text = status;
916///
917/// # }
918/// ```
919///
920/// In the example above only a clone of `status` is moved into the handler. Note that handlers always capture by move, if `status` was not
921/// listed in the *clone-move* section it would not be available after the handler is created. See [`async_clmv_fn!`] for details.
922///
923/// ## Futures and Clone-Move
924///
925/// You may want to always *clone-move* captures for async handlers, because they then automatically get cloned again for each event. This
926/// needs to happen because you can have more then one *handler task* running at the same type, and both want access to the captured variables.
927///
928/// This second cloning can be avoided by using the [`async_hn_once!`] macro instead, but only if you expect a single event.
929///
930/// [`async_clmv_fn!`]: zng_clone_move::async_clmv_fn
931#[macro_export]
932macro_rules! async_app_hn {
933    ($($tt:tt)+) => {
934        $crate::handler::async_app_hn($crate::handler::async_clmv_fn! { $($tt)+ })
935    }
936}
937#[doc(inline)]
938pub use crate::async_app_hn;
939
940#[doc(hidden)]
941pub struct AsyncFnOnceAppHandler<H> {
942    handler: Option<H>,
943}
944
945impl<A, F, H> AppHandler<A> for AsyncFnOnceAppHandler<H>
946where
947    A: Clone + 'static,
948    F: Future<Output = ()> + Send + 'static,
949    H: FnOnce(A) -> F + Send + 'static,
950{
951    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
952        if let Some(handler) = self.handler.take() {
953            handler_args.handle.unsubscribe();
954
955            let mut task = UiTask::new(None, handler(args.clone()));
956            if task.update().is_none() {
957                if handler_args.is_preview {
958                    UPDATES
959                        .on_pre_update(app_hn!(|_, handle| {
960                            if task.update().is_some() {
961                                handle.unsubscribe();
962                            }
963                        }))
964                        .perm();
965                } else {
966                    UPDATES
967                        .on_update(app_hn!(|_, handle| {
968                            if task.update().is_some() {
969                                handle.unsubscribe();
970                            }
971                        }))
972                        .perm();
973                }
974            }
975        } else {
976            tracing::error!("`async_app_hn_once!` called after requesting unsubscribe");
977        }
978    }
979}
980#[doc(hidden)]
981pub fn async_app_hn_once<A, F, H>(handler: H) -> AsyncFnOnceAppHandler<H>
982where
983    A: Clone + 'static,
984    F: Future<Output = ()> + Send + 'static,
985    H: FnOnce(A) -> F + Send + 'static,
986{
987    AsyncFnOnceAppHandler { handler: Some(handler) }
988}
989
990///<span data-del-macro-root></span> Declare an async *clone-move* app event handler that is only called once.
991///
992/// The macro input is a closure with optional *clone-move* variables, internally it uses [`async_clmv_fn_once!`] so
993/// the input is the same syntax.
994///
995/// # Examples
996///
997/// The example captures `data` by move and then moves it again to another thread. This is not something you can do using [`async_app_hn!`]
998/// because that handler expects to be called many times. We want to handle `CLICK_EVENT` once in this example, so we can don't need
999/// to capture by *clone-move* just to use `data`.
1000///
1001/// ```
1002/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
1003/// # use zng_app::handler::async_hn_once;
1004/// # use zng_task as task;
1005/// # let _scope = zng_app::APP.minimal();
1006/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
1007/// let data = vec![1, 2, 3];
1008/// # let
1009/// on_open = async_hn_once!(|_| {
1010///     task::run(async move {
1011///         for i in data {
1012///             print!("{i}, ");
1013///         }
1014///     })
1015///     .await;
1016///
1017///     println!("Done!");
1018/// });
1019/// # on_open }
1020/// ```
1021///
1022/// You can still *clone-move* to have access to the variable after creating the handler, in this case the `data` will be cloned into the handler
1023/// but will just be moved to the other thread, avoiding a needless clone.
1024///
1025/// ```
1026/// # zng_app::event::event_args! { pub struct ClickArgs { pub target: zng_txt::Txt, pub click_count: usize, .. fn delivery_list(&self, _l: &mut UpdateDeliveryList) { } } }
1027/// # use zng_app::handler::async_hn_once;
1028/// # use zng_task as task;
1029/// # let _scope = zng_app::APP.minimal();
1030/// # fn assert_type() -> impl zng_app::handler::WidgetHandler<ClickArgs> {
1031/// let data = vec![1, 2, 3];
1032/// # let
1033/// on_open = async_hn_once!(data, |_| {
1034///     task::run(async move {
1035///         for i in data {
1036///             print!("{i}, ");
1037///         }
1038///     })
1039///     .await;
1040///
1041///     println!("Done!");
1042/// });
1043/// println!("{data:?}");
1044/// # on_open }
1045/// ```
1046///
1047/// [`async_clmv_fn_once!`]: zng_clone_move::async_clmv_fn_once
1048#[macro_export]
1049macro_rules! async_app_hn_once {
1050    ($($tt:tt)+) => {
1051        $crate::handler::async_app_hn_once($crate::handler::async_clmv_fn_once! { $($tt)+ })
1052    }
1053}
1054#[doc(inline)]
1055pub use crate::async_app_hn_once;
1056use crate::update::UPDATES;
1057use crate::widget::{UiTaskWidget, WIDGET};
1058
1059/// Widget handler wrapper that filters the events, only delegating to `self` when `filter` returns `true`.
1060pub struct FilterWidgetHandler<A, H, F> {
1061    _args: PhantomData<fn() -> A>,
1062    handler: H,
1063    filter: F,
1064}
1065impl<A, H, F> FilterWidgetHandler<A, H, F>
1066where
1067    A: Clone + 'static,
1068    H: WidgetHandler<A>,
1069    F: FnMut(&A) -> bool + Send + 'static,
1070{
1071    /// New filter handler.
1072    pub fn new(handler: H, filter: F) -> Self {
1073        Self {
1074            handler,
1075            filter,
1076            _args: PhantomData,
1077        }
1078    }
1079}
1080impl<A, H, F> WidgetHandler<A> for FilterWidgetHandler<A, H, F>
1081where
1082    A: Clone + 'static,
1083    H: WidgetHandler<A>,
1084    F: FnMut(&A) -> bool + Send + 'static,
1085{
1086    #[inline(always)]
1087    fn event(&mut self, args: &A) -> bool {
1088        if (self.filter)(args) { self.handler.event(args) } else { false }
1089    }
1090
1091    #[inline(always)]
1092    fn update(&mut self) -> bool {
1093        self.handler.update()
1094    }
1095}
1096
1097/// App handler wrapper that filters the events, only delegating to `self` when `filter` returns `true`.
1098pub struct FilterAppHandler<A, H, F> {
1099    _args: PhantomData<fn() -> A>,
1100    handler: H,
1101    filter: F,
1102}
1103impl<A, H, F> FilterAppHandler<A, H, F>
1104where
1105    A: Clone + 'static,
1106    H: AppHandler<A>,
1107    F: FnMut(&A) -> bool + Send + 'static,
1108{
1109    /// New filter handler.
1110    pub fn new(handler: H, filter: F) -> Self {
1111        Self {
1112            handler,
1113            filter,
1114            _args: PhantomData,
1115        }
1116    }
1117}
1118impl<A, H, F> AppHandler<A> for FilterAppHandler<A, H, F>
1119where
1120    A: Clone + 'static,
1121    H: AppHandler<A>,
1122    F: FnMut(&A) -> bool + Send + 'static,
1123{
1124    #[inline(always)]
1125    fn event(&mut self, args: &A, handler_args: &AppHandlerArgs) {
1126        if (self.filter)(args) {
1127            self.handler.event(args, handler_args);
1128        }
1129    }
1130}
1131
1132impl HeadlessApp {
1133    /// Calls an [`AppHandler<A>`] once and blocks until the update tasks started during the call complete.
1134    ///
1135    /// This function *spins* until all update tasks are completed. Timers or send events can
1136    /// be received during execution but the loop does not sleep, it just spins requesting an update
1137    /// for each pass.
1138    pub fn block_on<A>(&mut self, handler: &mut dyn AppHandler<A>, args: &A, timeout: Duration) -> Result<(), String>
1139    where
1140        A: Clone + 'static,
1141    {
1142        self.block_on_multi(vec![handler], args, timeout)
1143    }
1144
1145    /// Calls multiple [`AppHandler<A>`] once each and blocks until all update tasks are complete.
1146    ///
1147    /// This function *spins* until all update tasks are completed. Timers or send events can
1148    /// be received during execution but the loop does not sleep, it just spins requesting an update
1149    /// for each pass.
1150    pub fn block_on_multi<A>(&mut self, handlers: Vec<&mut dyn AppHandler<A>>, args: &A, timeout: Duration) -> Result<(), String>
1151    where
1152        A: Clone + 'static,
1153    {
1154        let (pre_len, pos_len) = UPDATES.handler_lens();
1155
1156        let handler_args = AppHandlerArgs {
1157            handle: &Handle::dummy(()).downgrade(),
1158            is_preview: false,
1159        };
1160        for handler in handlers {
1161            handler.event(args, &handler_args);
1162        }
1163
1164        let mut pending = UPDATES.new_update_handlers(pre_len, pos_len);
1165
1166        if !pending.is_empty() {
1167            let start_time = INSTANT.now();
1168            while {
1169                pending.retain(|h| h());
1170                !pending.is_empty()
1171            } {
1172                UPDATES.update(None);
1173                let flow = self.update(false);
1174                if INSTANT.now().duration_since(start_time) >= timeout {
1175                    return Err(format!(
1176                        "block_on reached timeout of {timeout:?} before the handler task could finish",
1177                    ));
1178                }
1179
1180                match flow {
1181                    AppControlFlow::Poll => continue,
1182                    AppControlFlow::Wait => {
1183                        thread::yield_now();
1184                        continue;
1185                    }
1186                    AppControlFlow::Exit => return Ok(()),
1187                }
1188            }
1189        }
1190
1191        Ok(())
1192    }
1193
1194    /// Polls a `future` and updates the app repeatedly until it completes or the `timeout` is reached.
1195    pub fn block_on_fut<F: Future>(&mut self, future: F, timeout: Duration) -> Result<F::Output, String> {
1196        let future = task::with_deadline(future, timeout);
1197        let mut future = std::pin::pin!(future);
1198
1199        let waker = UPDATES.waker(None);
1200        let mut cx = std::task::Context::from_waker(&waker);
1201
1202        loop {
1203            let mut fut_poll = future.as_mut().poll(&mut cx);
1204            let flow = self.update_observe(
1205                || {
1206                    if fut_poll.is_pending() {
1207                        fut_poll = future.as_mut().poll(&mut cx);
1208                    }
1209                },
1210                true,
1211            );
1212
1213            match fut_poll {
1214                std::task::Poll::Ready(r) => match r {
1215                    Ok(r) => return Ok(r),
1216                    Err(e) => return Err(e.to_string()),
1217                },
1218                std::task::Poll::Pending => {}
1219            }
1220
1221            match flow {
1222                AppControlFlow::Poll => continue,
1223                AppControlFlow::Wait => {
1224                    thread::yield_now();
1225                    continue;
1226                }
1227                AppControlFlow::Exit => return Err("app exited".to_owned()),
1228            }
1229        }
1230    }
1231
1232    /// Calls the `handler` once and [`block_on`] it with a 60 seconds timeout using the minimal headless app.
1233    ///
1234    /// [`block_on`]: Self::block_on
1235    #[track_caller]
1236    #[cfg(any(test, doc, feature = "test_util"))]
1237    pub fn doc_test<A, H>(args: A, mut handler: H)
1238    where
1239        A: Clone + 'static,
1240        H: AppHandler<A>,
1241    {
1242        let mut app = crate::APP.minimal().run_headless(false);
1243        app.block_on(&mut handler, &args, DOC_TEST_BLOCK_ON_TIMEOUT).unwrap();
1244    }
1245
1246    /// Calls the `handlers` once each and [`block_on_multi`] with a 60 seconds timeout.
1247    ///
1248    /// [`block_on_multi`]: Self::block_on_multi
1249    #[track_caller]
1250    #[cfg(any(test, doc, feature = "test_util"))]
1251    pub fn doc_test_multi<A>(args: A, mut handlers: Vec<Box<dyn AppHandler<A>>>)
1252    where
1253        A: Clone + 'static,
1254    {
1255        let mut app = crate::APP.minimal().run_headless(false);
1256        app.block_on_multi(handlers.iter_mut().map(|h| h.as_mut()).collect(), &args, DOC_TEST_BLOCK_ON_TIMEOUT)
1257            .unwrap()
1258    }
1259}
1260
1261#[cfg(any(test, doc, feature = "test_util"))]
1262const DOC_TEST_BLOCK_ON_TIMEOUT: Duration = Duration::from_secs(60);