Skip to main content

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 IntoUiNode, clip: impl IntoVar<bool>) -> 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 { .. } if clip.is_new() => {
20            WIDGET.layout().render();
21        }
22        UiNodeOp::Layout { wl, final_size } => {
23            let bounds = child.layout(wl);
24
25            if clip.get() {
26                let c = BORDER.border_radius();
27                if c != corners {
28                    corners = c;
29                    WIDGET.render();
30                }
31            }
32
33            *final_size = bounds;
34        }
35        UiNodeOp::Render { frame } => {
36            if clip.get() {
37                frame.push_clips(
38                    |c| {
39                        let wgt_bounds = WIDGET.bounds();
40                        let bounds = PxRect::from_size(wgt_bounds.inner_size());
41
42                        if corners != PxCornerRadius::zero() {
43                            c.push_clip_rounded_rect(bounds, corners, false, true);
44                        } else {
45                            c.push_clip_rect(bounds, false, true);
46                        }
47
48                        if let Some(inline) = wgt_bounds.inline() {
49                            for r in inline.negative_space().iter() {
50                                c.push_clip_rect(*r, true, true);
51                            }
52                        };
53                    },
54                    |f| child.render(f),
55                );
56            } else {
57                child.render(frame);
58            }
59        }
60        _ => {}
61    })
62}