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