Function zng_app::widget::node::match_node

source ·
pub fn match_node<C: UiNode>(
    child: C,
    closure: impl FnMut(&mut MatchNodeChild<BoxedUiNode>, UiNodeOp<'_>) + Send + 'static,
) -> impl UiNode
Expand description

Creates a node that is implemented as a closure that matches over UiNodeOp and delegates to another child node.

The closure node can delegate to child, when the closure itself does not delegate, the child methods are called after the closure returns. See MatchNodeChild for more details.

This is a convenient way of declaring anonymous nodes, such as those that implement a property function. By leveraging closure captures, state can be easily declared and used, without the verbosity of declaring a struct.

§Examples

The example declares a property node that implements multiple UI node operations.

#[property(LAYOUT)]
pub fn count_layout(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
    let enabled = enabled.into_var();
    let mut layout_count = 0;

    match_node(child, move |child, op| match op {
        UiNodeOp::Init => {
            WIDGET.sub_var(&enabled);
        }
        UiNodeOp::Update { .. } => {
            if let Some(true) = enabled.get_new() {
                println!("layout count reset");
                layout_count = 0;
            }
        }
        UiNodeOp::Measure { wm, desired_size } => {
            let s = child.measure(wm);
            *desired_size = LAYOUT.constraints().fill_size_or(s);
        }
        UiNodeOp::Layout { wl, final_size } => {
            if enabled.get() {
                layout_count += 1;
                println!("layout {layout_count}");
            }
            let s = child.layout(wl);
            *final_size = LAYOUT.constraints().fill_size_or(s);
        }
        _ => {}
    })
}

§See Also

See also match_node_list that delegates to multiple children, match_node_leaf that declares a leaf node (no child) and match_widget that can extend a widget node.

Note that the child type is changed to BoxedUiNode when build with the feature = "dyn_node", if you want to access the child directly using MatchNodeChild::child you can use match_node_typed instead.