stack.rs

 1use std::ops::Range;
 2
 3use crate::{
 4    geometry::{rect::RectF, vector::Vector2F},
 5    json::{self, json, ToJson},
 6    presenter::MeasurementContext,
 7    DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
 8};
 9
10/// Element which renders it's children in a stack on top of each other.
11/// The first child determines the size of the others.
12#[derive(Default)]
13pub struct Stack {
14    children: Vec<ElementBox>,
15}
16
17impl Stack {
18    pub fn new() -> Self {
19        Self::default()
20    }
21}
22
23impl Element for Stack {
24    type LayoutState = ();
25    type PaintState = ();
26
27    fn layout(
28        &mut self,
29        mut constraint: SizeConstraint,
30        cx: &mut LayoutContext,
31    ) -> (Vector2F, Self::LayoutState) {
32        let mut size = constraint.min;
33        let mut children = self.children.iter_mut();
34        if let Some(bottom_child) = children.next() {
35            size = bottom_child.layout(constraint, cx);
36            constraint = SizeConstraint::strict(size);
37        }
38
39        for child in children {
40            child.layout(constraint, cx);
41        }
42
43        (size, ())
44    }
45
46    fn paint(
47        &mut self,
48        bounds: RectF,
49        visible_bounds: RectF,
50        _: &mut Self::LayoutState,
51        cx: &mut PaintContext,
52    ) -> Self::PaintState {
53        for child in &mut self.children {
54            cx.paint_layer(None, |cx| {
55                child.paint(bounds.origin(), visible_bounds, cx);
56            });
57        }
58    }
59
60    fn rect_for_text_range(
61        &self,
62        range_utf16: Range<usize>,
63        _: RectF,
64        _: RectF,
65        _: &Self::LayoutState,
66        _: &Self::PaintState,
67        cx: &MeasurementContext,
68    ) -> Option<RectF> {
69        self.children
70            .iter()
71            .rev()
72            .find_map(|child| child.rect_for_text_range(range_utf16.clone(), cx))
73    }
74
75    fn debug(
76        &self,
77        bounds: RectF,
78        _: &Self::LayoutState,
79        _: &Self::PaintState,
80        cx: &DebugContext,
81    ) -> json::Value {
82        json!({
83            "type": "Stack",
84            "bounds": bounds.to_json(),
85            "children": self.children.iter().map(|child| child.debug(cx)).collect::<Vec<json::Value>>()
86        })
87    }
88}
89
90impl Extend<ElementBox> for Stack {
91    fn extend<T: IntoIterator<Item = ElementBox>>(&mut self, children: T) {
92        self.children.extend(children)
93    }
94}