Skip to main content

rosace_widgets/tree/
stack.rs

1use rosace_core::types::Size;
2use super::{Widget, LayoutCtx, PaintCtx, BoxedWidget, avail_w, avail_h};
3
4/// Z-axis overlay — all children drawn at the same position (back-to-front).
5pub struct Stack {
6    children: Vec<BoxedWidget>,
7    fit: StackFit,
8}
9
10/// How a Stack sizes itself relative to its children.
11#[derive(Debug, Clone, Copy, Default)]
12pub enum StackFit {
13    /// Size to the largest child.
14    #[default]
15    Loose,
16    /// Expand to fill all available space.
17    Expand,
18}
19
20impl Stack {
21    pub fn new() -> Self { Self { children: Vec::new(), fit: StackFit::Loose } }
22    pub fn fit(mut self, f: StackFit) -> Self { self.fit = f; self }
23    pub fn child(mut self, w: impl Widget + 'static) -> Self {
24        self.children.push(Box::new(w)); self
25    }
26}
27
28impl Default for Stack {
29    fn default() -> Self { Self::new() }
30}
31
32impl Widget for Stack {
33    fn layout(&self, ctx: &LayoutCtx) -> Size {
34        let constraints = ctx.constraints;
35        match self.fit {
36            StackFit::Expand => Size {
37                width: avail_w(constraints),
38                height: avail_h(constraints),
39            },
40            StackFit::Loose => {
41                let mut max_w = 0.0_f32;
42                let mut max_h = 0.0_f32;
43                for child in &self.children {
44                    let s = child.layout(ctx);
45                    max_w = max_w.max(s.width);
46                    max_h = max_h.max(s.height);
47                }
48                Size { width: max_w, height: max_h }
49            }
50        }
51    }
52
53    fn paint(&self, ctx: &mut PaintCtx) {
54        for child in &self.children {
55            child.paint(&mut ctx.child(ctx.rect));
56        }
57    }
58}