stack.rs

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