Skip to main content

agg_gui/widgets/
conditional.rs

1//! Conditional — show/hide a single child based on an external Cell<bool>.
2
3use std::cell::Cell;
4use std::rc::Rc;
5
6use crate::draw_ctx::DrawCtx;
7use crate::event::{Event, EventResult};
8use crate::geometry::{Rect, Size};
9use crate::layout_props::{HAnchor, Insets, VAnchor, WidgetBase};
10use crate::widget::Widget;
11
12/// Wrap a single child widget; show or hide it based on a shared boolean.
13///
14/// Mirrors the React-style `{cond && <Child/>}` pattern but without
15/// rebuilding the child on every toggle — the child keeps its state
16/// across show/hide cycles.  When hidden, layout returns `(0, 0)` and
17/// `is_visible` returns `false`, so paint / event dispatch skip the
18/// subtree.  Containers like `FlexColumn` honour `is_visible` to skip
19/// gap/margin allotted to hidden slots.
20pub struct Conditional {
21    bounds: Rect,
22    children: Vec<Box<dyn Widget>>, // 0 or 1 element
23    base: WidgetBase,
24    visible: Rc<Cell<bool>>,
25}
26
27impl Conditional {
28    pub fn new(visible: Rc<Cell<bool>>, child: Box<dyn Widget>) -> Self {
29        Self {
30            bounds: Rect::default(),
31            children: vec![child],
32            base: WidgetBase::new(),
33            visible,
34        }
35    }
36
37    pub fn visibility_cell(&self) -> Rc<Cell<bool>> {
38        Rc::clone(&self.visible)
39    }
40
41    pub fn with_margin(mut self, m: Insets) -> Self {
42        self.base.margin = m;
43        self
44    }
45    pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
46        self.base.h_anchor = h;
47        self
48    }
49    pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
50        self.base.v_anchor = v;
51        self
52    }
53}
54
55impl Widget for Conditional {
56    fn type_name(&self) -> &'static str {
57        "Conditional"
58    }
59    fn bounds(&self) -> Rect {
60        self.bounds
61    }
62    fn set_bounds(&mut self, b: Rect) {
63        self.bounds = b;
64    }
65    fn children(&self) -> &[Box<dyn Widget>] {
66        &self.children
67    }
68    fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
69        &mut self.children
70    }
71
72    fn margin(&self) -> Insets {
73        self.base.margin
74    }
75    fn widget_base(&self) -> Option<&WidgetBase> {
76        Some(&self.base)
77    }
78    fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
79        Some(&mut self.base)
80    }
81    fn h_anchor(&self) -> HAnchor {
82        self.base.h_anchor
83    }
84    fn v_anchor(&self) -> VAnchor {
85        self.base.v_anchor
86    }
87
88    fn layout(&mut self, available: Size) -> Size {
89        if !self.visible.get() {
90            self.bounds = Rect::new(0.0, 0.0, 0.0, 0.0);
91            return Size::new(0.0, 0.0);
92        }
93        if let Some(child) = self.children.first_mut() {
94            let s = child.layout(available);
95            child.set_bounds(Rect::new(0.0, 0.0, s.width, s.height));
96            self.bounds = Rect::new(0.0, 0.0, s.width, s.height);
97            return s;
98        }
99        Size::new(0.0, 0.0)
100    }
101
102    fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
103
104    fn is_visible(&self) -> bool {
105        self.visible.get()
106    }
107
108    fn on_event(&mut self, _e: &Event) -> EventResult {
109        EventResult::Ignored
110    }
111}