Module handler

Module handler 

Source
Expand description

Event handler API.

A handler is a closure that takes a context and arguments, the context can be WIDGET or the app. The Handler<A> type supports both synchronous and asynchronous handlers. The handler is not usually instantiated directly, macros are provided for declaring handlers.

The handler macros are hn!, hn_once!, async_hn!, async_hn_once!. These macros are built on top of the primitive macros clmv!, async_clmv_fn! and async_clmv_fn_once! to provide a very easy way to clone-move captured variables into the handler.

use zng::prelude::*;

let last_clicked = var(Txt::from(""));
Stack!(
    top_to_bottom,
    5,
    ui_vec![
        Button! {
            child = Text!("hn!");
            on_click = hn!(last_clicked, |_| {
                last_clicked.set("hn!");
            });
        },
        Button! {
            child = Text!("hn_once!");
            on_click = hn_once!(last_clicked, |_| {
                last_clicked.set("hn_once!");
            });
        },
        {
            let enabled = var(true);
            Button! {
                child = Text!("async_hn!");
                on_click = async_hn!(last_clicked, enabled, |_| {
                    last_clicked.set("async_hn!");
                    enabled.set(false);
                    task::deadline(1.secs()).await;
                    enabled.set(true);
                });
                widget::enabled;
            }
        },
        Text!(last_clicked),
    ]
)

§App Context

When a handler is not set in a widget the APP_HANDLER contextual service is available, it can be used to unsubscribe the event from within.

FOCUS_CHANGED_EVENT
    .on_pre_event(hn!(|args| {
        println!("focused: {:?}", args.new_focus);
        if args.new_focus.is_none() {
            zng::handler::APP_HANDLER.unsubscribe();
        }
    }))
    .perm();

In the example above the event subscription is made perm, but inside the handler unsubscribe is called when a condition is met, causing the handler to be dropped. This is a common pattern for app level event handlers that can manage their own subscription.

The APP_HANDLER will also be available after each await point in async handlers, after an async task unsubscribes all running handler tasks will run to the end and no new tasks will be started.

§Args Type Inference

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 the closure args is inferred. Unfortunately this has some limitations, documentation shows the raw box type, the A bounds is not enforced on type declaration too.

These limitations enable type inference for the arguments of hn! and async_hn! set directly on a property, reducing the need to track down exact event args types, unfortunately as of this release the hn_once! and async_hn_once! handlers will still need and explicit args type if the handler uses the arg.

§Full API

See zng_app::handler for the full handler API.

Macros§

async_hn
Declare an async clone-move event handler.
async_hn_once
Declare an async clone-move event handler that is only called once.
hn
Declare a mutable clone-move event handler.
hn_once
Declare a clone-move event handler that is only called once.

Structs§

APP_HANDLER
Service available in app scoped Handler<A> calls.
ArcHandler
Represents a cloneable handler.

Traits§

AppWeakHandle
Represents a weak handle to a Handler subscription in the app context.
HandlerExt
Extension methods for Handler<A>.

Type Aliases§

Handler
Represents a handler in a widget context.