Function zng::widget::node::with_context_var

source ·
pub fn with_context_var<T>(
    child: impl UiNode,
    context_var: ContextVar<T>,
    value: impl IntoVar<T>,
) -> impl UiNode
where T: VarValue,
Expand description

Helper for declaring properties that sets a context var.

The generated UiNode delegates each method to child inside a call to ContextVar::with_context.

§Examples

A simple context property declaration:

context_var! {
    pub static FOO_VAR: u32 = 0u32;
}

/// Sets the [`FOO_VAR`] in the widgets and its content.
#[property(CONTEXT, default(FOO_VAR))]
pub fn foo(child: impl UiNode, value: impl IntoVar<u32>) -> impl UiNode {
    with_context_var(child, FOO_VAR, value)
}

When set in a widget, the value is accessible in all inner nodes of the widget, using FOO_VAR.get, and if value is set to a variable the FOO_VAR will also reflect its is_new and read_only. If the value var is not read-only inner nodes can modify it using FOO_VAR.set or FOO_VAR.modify.

Also note that the property default is set to the same FOO_VAR, this causes the property to pass-through the outer context value, as if it was not set.

Tip: You can use a merge_var! to merge a new value to the previous context value:

#[derive(Debug, Clone, Default, PartialEq)]
pub struct Config {
    pub foo: bool,
    pub bar: bool,
}

context_var! {
    pub static CONFIG_VAR: Config = Config::default();
}

/// Sets the *foo* config.
#[property(CONTEXT, default(false))]
pub fn foo(child: impl UiNode, value: impl IntoVar<bool>) -> impl UiNode {
    with_context_var(child, CONFIG_VAR, merge_var!(CONFIG_VAR, value.into_var(), |c, &v| {
        let mut c = c.clone();
        c.foo = v;
        c
    }))
}

/// Sets the *bar* config.
#[property(CONTEXT, default(false))]
pub fn bar(child: impl UiNode, value: impl IntoVar<bool>) -> impl UiNode {
    with_context_var(child, CONFIG_VAR, merge_var!(CONFIG_VAR, value.into_var(), |c, &v| {
        let mut c = c.clone();
        c.bar = v;
        c
    }))
}

When set in a widget, the merge_var! will read the context value of the parent properties, modify a clone of the value and the result will be accessible to the inner properties, the widget user can then set with the composed value in steps and the final consumer of the composed value only need to monitor to a single context variable.