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}