zng_wgt/
clip_props.rs

1use crate::prelude::*;
2
3/// Clips the widget child to the area of the widget when set to `true`.
4///
5/// Any content rendered outside the widget inner bounds is clipped, hit-test shapes are also clipped. The clip is
6/// rectangular and can have rounded corners if [`corner_radius`] is set. If the widget is inlined during layout the first
7/// row advance and last row trail are also clipped.
8///
9/// [`corner_radius`]: fn@crate::corner_radius
10#[property(FILL, default(false))]
11pub fn clip_to_bounds(child: impl UiNode, clip: impl IntoVar<bool>) -> impl UiNode {
12    let clip = clip.into_var();
13    let mut corners = PxCornerRadius::zero();
14
15    match_node(child, move |child, op| match op {
16        UiNodeOp::Init => {
17            WIDGET.layout().render();
18        }
19        UiNodeOp::Update { .. } => {
20            if clip.is_new() {
21                WIDGET.layout().render();
22            }
23        }
24        UiNodeOp::Layout { wl, final_size } => {
25            let bounds = child.layout(wl);
26
27            if clip.get() {
28                let c = BORDER.border_radius();
29                if c != corners {
30                    corners = c;
31                    WIDGET.render();
32                }
33            }
34
35            *final_size = bounds;
36        }
37        UiNodeOp::Render { frame } => {
38            if clip.get() {
39                frame.push_clips(
40                    |c| {
41                        let wgt_bounds = WIDGET.bounds();
42                        let bounds = PxRect::from_size(wgt_bounds.inner_size());
43
44                        if corners != PxCornerRadius::zero() {
45                            c.push_clip_rounded_rect(bounds, corners, false, true);
46                        } else {
47                            c.push_clip_rect(bounds, false, true);
48                        }
49
50                        if let Some(inline) = wgt_bounds.inline() {
51                            for r in inline.negative_space().iter() {
52                                c.push_clip_rect(*r, true, true);
53                            }
54                        };
55                    },
56                    |f| child.render(f),
57                );
58            } else {
59                child.render(frame);
60            }
61        }
62        _ => {}
63    })
64}