1use std::ops::Range;
2
3use crate::{
4 geometry::{rect::RectF, vector::Vector2F},
5 json::{self, json, ToJson},
6 AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View,
7 ViewContext,
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.
12pub struct Stack<V: View> {
13 children: Vec<AnyElement<V>>,
14}
15
16impl<V: View> Default for Stack<V> {
17 fn default() -> Self {
18 Self {
19 children: Vec::new(),
20 }
21 }
22}
23
24impl<V: View> Stack<V> {
25 pub fn new() -> Self {
26 Self::default()
27 }
28}
29
30impl<V: View> Element<V> for Stack<V> {
31 type LayoutState = ();
32 type PaintState = ();
33
34 fn layout(
35 &mut self,
36 mut constraint: SizeConstraint,
37 view: &mut V,
38 cx: &mut LayoutContext<V>,
39 ) -> (Vector2F, Self::LayoutState) {
40 let mut size = constraint.min;
41 let mut children = self.children.iter_mut();
42 if let Some(bottom_child) = children.next() {
43 size = bottom_child.layout(constraint, view, cx);
44 constraint = SizeConstraint::strict(size);
45 }
46
47 for child in children {
48 child.layout(constraint, view, cx);
49 }
50
51 (size, ())
52 }
53
54 fn paint(
55 &mut self,
56 scene: &mut SceneBuilder,
57 bounds: RectF,
58 visible_bounds: RectF,
59 _: &mut Self::LayoutState,
60 view: &mut V,
61 cx: &mut PaintContext<V>,
62 ) -> Self::PaintState {
63 for child in &mut self.children {
64 scene.paint_layer(None, |scene| {
65 child.paint(scene, bounds.origin(), visible_bounds, view, cx);
66 });
67 }
68 }
69
70 fn rect_for_text_range(
71 &self,
72 range_utf16: Range<usize>,
73 _: RectF,
74 _: RectF,
75 _: &Self::LayoutState,
76 _: &Self::PaintState,
77 view: &V,
78 cx: &ViewContext<V>,
79 ) -> Option<RectF> {
80 self.children
81 .iter()
82 .rev()
83 .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
84 }
85
86 fn debug(
87 &self,
88 bounds: RectF,
89 _: &Self::LayoutState,
90 _: &Self::PaintState,
91 view: &V,
92 cx: &ViewContext<V>,
93 ) -> json::Value {
94 json!({
95 "type": "Stack",
96 "bounds": bounds.to_json(),
97 "children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<json::Value>>()
98 })
99 }
100}
101
102impl<V: View> Extend<AnyElement<V>> for Stack<V> {
103 fn extend<T: IntoIterator<Item = AnyElement<V>>>(&mut self, children: T) {
104 self.children.extend(children)
105 }
106}