1use crate::{
2 AnyElement, AppContext, BorrowWindow, Bounds, Element, ElementId, IdentifiedElement,
3 IntoAnyElement, LayoutId, Pixels, SharedString, Style, StyleCascade, Styled, ViewContext,
4};
5use collections::HashMap;
6use refineable::Refineable;
7use smallvec::SmallVec;
8
9#[derive(Default)]
10struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
11
12pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
13 cx.default_global::<GroupBounds>()
14 .0
15 .get(name)
16 .and_then(|bounds_stack| bounds_stack.last().cloned())
17}
18
19pub trait LayoutNode<V: 'static + Send + Sync, K: ElementKind> {
20 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
21 fn group_mut(&mut self) -> &mut Option<SharedString>;
22
23 fn child(mut self, child: impl IntoAnyElement<V>) -> Self
24 where
25 Self: Sized,
26 {
27 self.children_mut().push(child.into_any());
28 self
29 }
30
31 fn children<C, E>(mut self, children: C) -> Self
32 where
33 C: IntoIterator<Item = E>,
34 E: IntoAnyElement<V>,
35 Self: Sized,
36 {
37 for child in children {
38 self.children_mut().push(child.into_any());
39 }
40 self
41 }
42}
43
44pub trait ElementKind: 'static + Send + Sync {
45 fn id(&self) -> Option<ElementId>;
46}
47
48pub struct IdentifiedElementKind(ElementId);
49pub struct AnonymousElementKind;
50
51impl ElementKind for IdentifiedElementKind {
52 fn id(&self) -> Option<ElementId> {
53 Some(self.0.clone())
54 }
55}
56
57impl ElementKind for AnonymousElementKind {
58 fn id(&self) -> Option<ElementId> {
59 None
60 }
61}
62
63pub struct LayoutNodeElement<V: 'static + Send + Sync, K: ElementKind> {
64 style_cascade: StyleCascade,
65 computed_style: Option<Style>,
66 children: SmallVec<[AnyElement<V>; 2]>,
67 kind: K,
68 group: Option<SharedString>,
69}
70
71impl<V: 'static + Send + Sync> LayoutNodeElement<V, AnonymousElementKind> {
72 pub fn identify(self, id: impl Into<ElementId>) -> LayoutNodeElement<V, IdentifiedElementKind> {
73 LayoutNodeElement {
74 style_cascade: self.style_cascade,
75 computed_style: self.computed_style,
76 children: self.children,
77 kind: IdentifiedElementKind(id.into()),
78 group: self.group,
79 }
80 }
81}
82
83impl<V: 'static + Send + Sync, E: ElementKind> LayoutNodeElement<V, E> {
84 pub fn set_group(&mut self, group: impl Into<SharedString>) {
85 self.group = Some(group.into());
86 }
87
88 fn with_element_id<R>(
89 &mut self,
90 cx: &mut ViewContext<V>,
91 f: impl FnOnce(&mut Self, &mut ViewContext<V>) -> R,
92 ) -> R {
93 if let Some(id) = self.id() {
94 cx.with_element_id(id, |cx| f(self, cx))
95 } else {
96 f(self, cx)
97 }
98 }
99}
100
101impl<V: 'static + Send + Sync, K: ElementKind> Styled for LayoutNodeElement<V, K> {
102 fn style_cascade(&mut self) -> &mut StyleCascade {
103 &mut self.style_cascade
104 }
105
106 fn computed_style(&mut self) -> &Style {
107 self.computed_style
108 .get_or_insert_with(|| Style::default().refined(self.style_cascade.merged()))
109 }
110}
111
112impl<V: 'static + Send + Sync> IdentifiedElement for LayoutNodeElement<V, IdentifiedElementKind> {
113 fn id(&self) -> ElementId {
114 self.kind.0.clone()
115 }
116}
117
118impl<V, K> IntoAnyElement<V> for LayoutNodeElement<V, K>
119where
120 V: 'static + Send + Sync,
121 K: ElementKind,
122{
123 fn into_any(self) -> AnyElement<V> {
124 AnyElement::new(self)
125 }
126}
127
128impl<V: 'static + Send + Sync, K: ElementKind> Element for LayoutNodeElement<V, K> {
129 type ViewState = V;
130 type ElementState = ();
131
132 fn id(&self) -> Option<ElementId> {
133 self.kind.id()
134 }
135
136 fn layout(
137 &mut self,
138 state: &mut Self::ViewState,
139 _: Option<Self::ElementState>,
140 cx: &mut ViewContext<Self::ViewState>,
141 ) -> (LayoutId, Self::ElementState) {
142 self.with_element_id(cx, |this, cx| {
143 let layout_ids = this
144 .children
145 .iter_mut()
146 .map(|child| child.layout(state, cx))
147 .collect::<Vec<_>>();
148
149 let style = this.computed_style();
150 let layout_id = cx.request_layout(style, layout_ids);
151 (layout_id, ())
152 })
153 }
154
155 fn paint(
156 &mut self,
157 bounds: Bounds<Pixels>,
158 state: &mut Self::ViewState,
159 _: &mut Self::ElementState,
160 cx: &mut ViewContext<Self::ViewState>,
161 ) {
162 self.with_element_id(cx, |this, cx| {
163 if let Some(group) = this.group.clone() {
164 cx.default_global::<GroupBounds>()
165 .0
166 .entry(group)
167 .or_default()
168 .push(bounds);
169 }
170
171 let style = this.computed_style().clone();
172 let z_index = style.z_index.unwrap_or(0);
173 cx.stack(z_index, |cx| style.paint(bounds, cx));
174
175 // todo!("implement overflow")
176 // let overflow = &style.overflow;
177
178 style.apply_text_style(cx, |cx| {
179 cx.stack(z_index + 1, |cx| {
180 style.apply_overflow(bounds, cx, |cx| {
181 for child in &mut this.children {
182 child.paint(state, None, cx);
183 }
184 })
185 })
186 });
187
188 if let Some(group) = this.group.as_ref() {
189 cx.default_global::<GroupBounds>()
190 .0
191 .get_mut(group)
192 .unwrap()
193 .pop();
194 }
195 })
196 }
197}
198
199impl<V: 'static + Send + Sync, K: ElementKind> LayoutNode<V, K> for LayoutNodeElement<V, K> {
200 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
201 &mut self.children
202 }
203
204 fn group_mut(&mut self) -> &mut Option<SharedString> {
205 &mut self.group
206 }
207}