zng_wgt/
visibility_props.rs1use crate::prelude::*;
2
3use zng_app::widget::info;
4
5#[property(CONTEXT, default(true))]
19pub fn visibility(child: impl IntoUiNode, visibility: impl IntoVar<Visibility>) -> 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 IntoUiNode, state: impl IntoVar<bool>, expected: Visibility) -> 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 IntoUiNode, state: impl IntoVar<bool>) -> UiNode {
111 visibility_eq_state(child, state, Visibility::Visible)
112}
113#[property(CONTEXT)]
115pub fn is_hidden(child: impl IntoUiNode, state: impl IntoVar<bool>) -> UiNode {
116 visibility_eq_state(child, state, Visibility::Hidden)
117}
118#[property(CONTEXT)]
120pub fn is_collapsed(child: impl IntoUiNode, state: impl IntoVar<bool>) -> UiNode {
121 visibility_eq_state(child, state, Visibility::Collapsed)
122}
123
124#[property(CONTEXT, default(true))]
154pub fn auto_hide(child: impl IntoUiNode, enabled: impl IntoVar<bool>) -> UiNode {
155 let enabled = enabled.into_var();
156
157 match_node(child, move |_, op| match op {
158 UiNodeOp::Init => {
159 WIDGET.sub_var(&enabled);
160 }
161 UiNodeOp::Update { .. } => {
162 if let Some(new) = enabled.get_new()
163 && WIDGET.bounds().can_auto_hide() != new
164 {
165 WIDGET.layout().render();
166 }
167 }
168 UiNodeOp::Layout { wl, .. } => {
169 wl.allow_auto_hide(enabled.get());
170 }
171 _ => {}
172 })
173}
174
175event_property! {
176 pub fn transform_changed {
178 event: info::TRANSFORM_CHANGED_EVENT,
179 args: info::TransformChangedArgs,
180 }
181
182 pub fn move {
184 event: info::TRANSFORM_CHANGED_EVENT,
185 args: info::TransformChangedArgs,
186 filter: |a| a.offset(WIDGET.id()).unwrap_or_default() != PxVector::zero(),
187 }
188
189 pub fn visibility_changed {
191 event: info::VISIBILITY_CHANGED_EVENT,
192 args: info::VisibilityChangedArgs,
193 }
194
195 pub fn collapse {
197 event: info::VISIBILITY_CHANGED_EVENT,
198 args: info::VisibilityChangedArgs,
199 filter: |a| a.is_collapse(WIDGET.id()),
200 }
201
202 pub fn hide {
204 event: info::VISIBILITY_CHANGED_EVENT,
205 args: info::VisibilityChangedArgs,
206 filter: |a| a.is_hide(WIDGET.id()),
207 }
208
209 pub fn show {
213 event: info::VISIBILITY_CHANGED_EVENT,
214 args: info::VisibilityChangedArgs,
215 filter: |a| a.is_show(WIDGET.id()),
216 }
217}