zng_wgt/
visibility_props.rs
1use crate::prelude::*;
2
3use zng_app::widget::info;
4
5#[property(CONTEXT, default(true))]
19pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> impl UiNode {
20 let visibility = visibility.into_var();
21 let mut prev_vis = Visibility::Visible;
22
23 match_node(child, move |child, op| match op {
24 UiNodeOp::Init => {
25 WIDGET.sub_var(&visibility);
26 prev_vis = visibility.get();
27 }
28 UiNodeOp::Update { .. } => {
29 if let Some(vis) = visibility.get_new() {
30 use Visibility::*;
31 match (prev_vis, vis) {
32 (Collapsed, Visible) | (Visible, Collapsed) => {
33 WIDGET.layout().render();
34 }
35 (Hidden, Visible) | (Visible, Hidden) => {
36 WIDGET.render();
37 }
38 (Collapsed, Hidden) | (Hidden, Collapsed) => {
39 WIDGET.layout();
40 }
41 _ => {}
42 }
43 prev_vis = vis;
44 }
45 }
46
47 UiNodeOp::Measure { wm, desired_size } => {
48 if Visibility::Collapsed != visibility.get() {
49 *desired_size = child.measure(wm);
50 } else {
51 child.delegated();
52 }
53 }
54 UiNodeOp::Layout { wl, final_size } => {
55 if Visibility::Collapsed != visibility.get() {
56 *final_size = child.layout(wl);
57 } else {
58 wl.collapse();
59 child.delegated();
60 }
61 }
62
63 UiNodeOp::Render { frame } => match visibility.get() {
64 Visibility::Visible => child.render(frame),
65 Visibility::Hidden => frame.hide(|frame| child.render(frame)),
66 Visibility::Collapsed => {
67 child.delegated();
68 #[cfg(debug_assertions)]
69 {
70 tracing::error!(
71 "collapsed {} rendered, to fix, layout the widget, or `WidgetLayout::collapse_child` the widget",
72 WIDGET.trace_id()
73 )
74 }
75 }
76 },
77 UiNodeOp::RenderUpdate { update } => match visibility.get() {
78 Visibility::Visible => child.render_update(update),
79 Visibility::Hidden => update.hidden(|update| child.render_update(update)),
80 Visibility::Collapsed => {
81 child.delegated();
82 #[cfg(debug_assertions)]
83 {
84 tracing::error!(
85 "collapsed {} render-updated, to fix, layout the widget, or `WidgetLayout::collapse_child` the widget",
86 WIDGET.trace_id()
87 )
88 }
89 }
90 },
91 _ => {}
92 })
93}
94
95fn visibility_eq_state(child: impl UiNode, state: impl IntoVar<bool>, expected: Visibility) -> impl UiNode {
96 event_state(
97 child,
98 state,
99 expected == Visibility::Visible,
100 info::VISIBILITY_CHANGED_EVENT,
101 move |a| {
102 let vis = a.tree.get(WIDGET.id()).map(|w| w.visibility()).unwrap_or(Visibility::Visible);
103
104 Some(vis == expected)
105 },
106 )
107}
108#[property(CONTEXT)]
110pub fn is_visible(child: impl UiNode, state: impl IntoVar<bool>) -> impl UiNode {
111 visibility_eq_state(child, state, Visibility::Visible)
112}
113#[property(CONTEXT)]
115pub fn is_hidden(child: impl UiNode, state: impl IntoVar<bool>) -> impl UiNode {
116 visibility_eq_state(child, state, Visibility::Hidden)
117}
118#[property(CONTEXT)]
120pub fn is_collapsed(child: impl UiNode, state: impl IntoVar<bool>) -> impl UiNode {
121 visibility_eq_state(child, state, Visibility::Collapsed)
122}
123
124#[property(CONTEXT, default(true))]
153pub fn auto_hide(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
154 let enabled = enabled.into_var();
155
156 match_node(child, move |_, op| match op {
157 UiNodeOp::Init => {
158 WIDGET.sub_var(&enabled);
159 }
160 UiNodeOp::Update { .. } => {
161 if let Some(new) = enabled.get_new() {
162 if WIDGET.bounds().can_auto_hide() != new {
163 WIDGET.layout().render();
164 }
165 }
166 }
167 UiNodeOp::Layout { wl, .. } => {
168 wl.allow_auto_hide(enabled.get());
169 }
170 _ => {}
171 })
172}
173
174event_property! {
175 pub fn transform_changed {
177 event: info::TRANSFORM_CHANGED_EVENT,
178 args: info::TransformChangedArgs,
179 }
180
181 pub fn move {
183 event: info::TRANSFORM_CHANGED_EVENT,
184 args: info::TransformChangedArgs,
185 filter: |a| a.offset(WIDGET.id()).unwrap_or_default() != PxVector::zero(),
186 }
187
188 pub fn visibility_changed {
190 event: info::VISIBILITY_CHANGED_EVENT,
191 args: info::VisibilityChangedArgs,
192 }
193
194 pub fn collapse {
196 event: info::VISIBILITY_CHANGED_EVENT,
197 args: info::VisibilityChangedArgs,
198 filter: |a| a.is_collapse(WIDGET.id()),
199 }
200
201 pub fn hide {
203 event: info::VISIBILITY_CHANGED_EVENT,
204 args: info::VisibilityChangedArgs,
205 filter: |a| a.is_hide(WIDGET.id()),
206 }
207
208 pub fn show {
212 event: info::VISIBILITY_CHANGED_EVENT,
213 args: info::VisibilityChangedArgs,
214 filter: |a| a.is_show(WIDGET.id()),
215 }
216}