Skip to main content

ferroui_dialogs/internal/
child_fitter.rs

1use ferroui_base::input::InputElementImpl;
2use ferroui_base::interactivity::InteractiveImpl;
3use ferroui_base::layout::{Layoutable, LayoutableImpl, LayoutableImplExt};
4use ferroui_base::{ferro_class, ferro_class_info, ferro_impl_classes, instantiate, FerroObjectImpl, Ref, Size, StyledElementImpl, VisualImpl};
5use ferroui_controls::{ControlImpl, Decorator};
6
7/// A decorator that asks for no space and measures its child with the
8/// space it is arranged in.
9#[repr(C)]
10pub struct ChildFitter {
11    base: Decorator,
12}
13
14ferro_class!(ChildFitter: Decorator);
15ferro_impl_classes!(ChildFitter: StyledElementImpl, VisualImpl, InteractiveImpl, InputElementImpl, ControlImpl);
16ferro_class_info!(ChildFitter { new: ChildFitter::new });
17
18impl FerroObjectImpl for ChildFitter {}
19
20impl LayoutableImpl for ChildFitter {
21    fn measure_override(_this: &Self, _available_size: Size) -> Size {
22        Size::new(0.0, 0.0)
23    }
24
25    fn arrange_override(this: &Self, final_size: Size) -> Size {
26        if let Some(child) = this.child() {
27            Layoutable::measure(&child, final_size);
28        }
29        Self::parent_arrange_override(this, final_size);
30        final_size
31    }
32}
33
34impl ChildFitter {
35    pub fn construct() -> Self {
36        Self { base: Decorator::construct() }
37    }
38
39    pub fn new() -> Ref<Self> {
40        instantiate(Self::construct())
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    // Not from upstream: the upstream project has no tests.
47    use super::*;
48    use ferroui_controls::Border;
49
50    #[test]
51    fn measures_to_nothing_and_measures_the_child_with_the_arranged_size() {
52        let fitter = ChildFitter::new();
53        let child = Border::new();
54        child.set_width(150.0);
55        fitter.set_child(child.clone());
56
57        fitter.measure(Size::new(500.0, 500.0));
58        assert_eq!(Size::new(0.0, 0.0), fitter.desired_size());
59
60        fitter.arrange(ferroui_base::Rect::new(0.0, 0.0, 200.0, 100.0));
61        assert_eq!(Size::new(150.0, 0.0), child.desired_size());
62        assert_eq!(Size::new(200.0, 100.0), fitter.bounds().size());
63    }
64}