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}