1use crate::{
2 AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext,
3};
4use derive_more::{Deref, DerefMut};
5pub(crate) use smallvec::SmallVec;
6use std::{any::Any, mem};
7
8pub trait Element<V: 'static> {
9 type ElementState: 'static;
10
11 fn id(&self) -> Option<ElementId>;
12
13 /// Called to initialize this element for the current frame. If this
14 /// element had state in a previous frame, it will be passed in for the 3rd argument.
15 fn initialize(
16 &mut self,
17 view_state: &mut V,
18 element_state: Option<Self::ElementState>,
19 cx: &mut ViewContext<V>,
20 ) -> Self::ElementState;
21
22 fn layout(
23 &mut self,
24 view_state: &mut V,
25 element_state: &mut Self::ElementState,
26 cx: &mut ViewContext<V>,
27 ) -> LayoutId;
28
29 fn prepaint(
30 &mut self,
31 bounds: Bounds<Pixels>,
32 view_state: &mut V,
33 element_state: &mut Self::ElementState,
34 cx: &mut ViewContext<V>,
35 );
36
37 fn paint(
38 &mut self,
39 bounds: Bounds<Pixels>,
40 view_state: &mut V,
41 element_state: &mut Self::ElementState,
42 cx: &mut ViewContext<V>,
43 );
44}
45
46#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
47pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
48
49pub trait ParentElement<V: 'static> {
50 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
51
52 fn child(mut self, child: impl Component<V>) -> Self
53 where
54 Self: Sized,
55 {
56 self.children_mut().push(child.render());
57 self
58 }
59
60 fn children(mut self, iter: impl IntoIterator<Item = impl Component<V>>) -> Self
61 where
62 Self: Sized,
63 {
64 self.children_mut()
65 .extend(iter.into_iter().map(|item| item.render()));
66 self
67 }
68}
69
70trait ElementObject<V> {
71 fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
72 fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
73 fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
74 fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
75 fn measure(
76 &mut self,
77 available_space: Size<AvailableSpace>,
78 view_state: &mut V,
79 cx: &mut ViewContext<V>,
80 ) -> Size<Pixels>;
81 fn draw(
82 &mut self,
83 origin: Point<Pixels>,
84 available_space: Size<AvailableSpace>,
85 view_state: &mut V,
86 cx: &mut ViewContext<V>,
87 );
88}
89
90struct RenderedElement<V: 'static, E: Element<V>> {
91 element: E,
92 phase: ElementRenderPhase<E::ElementState>,
93}
94
95#[derive(Default)]
96enum ElementRenderPhase<V> {
97 #[default]
98 Start,
99 Initialized {
100 frame_state: Option<V>,
101 },
102 LayoutRequested {
103 layout_id: LayoutId,
104 frame_state: Option<V>,
105 },
106 LayoutComputed {
107 layout_id: LayoutId,
108 available_space: Size<AvailableSpace>,
109 frame_state: Option<V>,
110 },
111 Painted,
112}
113
114/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
115/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
116/// improved usability.
117impl<V, E: Element<V>> RenderedElement<V, E> {
118 fn new(element: E) -> Self {
119 RenderedElement {
120 element,
121 phase: ElementRenderPhase::Start,
122 }
123 }
124}
125
126impl<V, E> ElementObject<V> for RenderedElement<V, E>
127where
128 E: Element<V>,
129 E::ElementState: 'static,
130{
131 fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
132 let frame_state = if let Some(id) = self.element.id() {
133 cx.with_element_state(id, |element_state, cx| {
134 let element_state = self.element.initialize(view_state, element_state, cx);
135 ((), element_state)
136 });
137 None
138 } else {
139 let frame_state = self.element.initialize(view_state, None, cx);
140 Some(frame_state)
141 };
142
143 self.phase = ElementRenderPhase::Initialized { frame_state };
144 }
145
146 fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
147 let layout_id;
148 let mut frame_state;
149 match mem::take(&mut self.phase) {
150 ElementRenderPhase::Initialized {
151 frame_state: initial_frame_state,
152 } => {
153 frame_state = initial_frame_state;
154 if let Some(id) = self.element.id() {
155 layout_id = cx.with_element_state(id, |element_state, cx| {
156 let mut element_state = element_state.unwrap();
157 let layout_id = self.element.layout(state, &mut element_state, cx);
158 (layout_id, element_state)
159 });
160 } else {
161 layout_id = self
162 .element
163 .layout(state, frame_state.as_mut().unwrap(), cx);
164 }
165 }
166 ElementRenderPhase::Start => panic!("must call initialize before layout"),
167 ElementRenderPhase::LayoutRequested { .. }
168 | ElementRenderPhase::LayoutComputed { .. }
169 | ElementRenderPhase::Painted => {
170 panic!("element rendered twice")
171 }
172 };
173
174 self.phase = ElementRenderPhase::LayoutRequested {
175 layout_id,
176 frame_state,
177 };
178 layout_id
179 }
180
181 fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
182 self.phase = match mem::take(&mut self.phase) {
183 ElementRenderPhase::LayoutRequested {
184 layout_id,
185 mut frame_state,
186 }
187 | ElementRenderPhase::LayoutComputed {
188 layout_id,
189 mut frame_state,
190 ..
191 } => {
192 let bounds = cx.layout_bounds(layout_id);
193 if let Some(id) = self.element.id() {
194 cx.with_element_state(id, |element_state, cx| {
195 let mut element_state = element_state.unwrap();
196 self.element
197 .paint(bounds, view_state, &mut element_state, cx);
198 ((), element_state)
199 });
200 } else {
201 self.element
202 .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
203 }
204 ElementRenderPhase::Painted
205 }
206
207 _ => panic!("must call layout before paint"),
208 };
209 }
210
211 fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
212 self.phase = match mem::take(&mut self.phase) {
213 ElementRenderPhase::LayoutRequested {
214 layout_id,
215 mut frame_state,
216 }
217 | ElementRenderPhase::LayoutComputed {
218 layout_id,
219 mut frame_state,
220 ..
221 } => {
222 let bounds = cx.layout_bounds(layout_id);
223 if let Some(id) = self.element.id() {
224 cx.with_element_state(id, |element_state, cx| {
225 let mut element_state = element_state.unwrap();
226 self.element
227 .prepaint(bounds, view_state, &mut element_state, cx);
228 ((), element_state)
229 });
230 } else {
231 self.element
232 .prepaint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
233 }
234 ElementRenderPhase::Painted
235 }
236
237 _ => panic!("must call layout before paint"),
238 };
239 }
240
241 fn measure(
242 &mut self,
243 available_space: Size<AvailableSpace>,
244 view_state: &mut V,
245 cx: &mut ViewContext<V>,
246 ) -> Size<Pixels> {
247 if matches!(&self.phase, ElementRenderPhase::Start) {
248 self.initialize(view_state, cx);
249 }
250
251 if matches!(&self.phase, ElementRenderPhase::Initialized { .. }) {
252 self.layout(view_state, cx);
253 }
254
255 let layout_id = match &mut self.phase {
256 ElementRenderPhase::LayoutRequested {
257 layout_id,
258 frame_state,
259 } => {
260 cx.compute_layout(*layout_id, available_space);
261 let layout_id = *layout_id;
262 self.phase = ElementRenderPhase::LayoutComputed {
263 layout_id,
264 available_space,
265 frame_state: frame_state.take(),
266 };
267 layout_id
268 }
269 ElementRenderPhase::LayoutComputed {
270 layout_id,
271 available_space: prev_available_space,
272 ..
273 } => {
274 if available_space != *prev_available_space {
275 cx.compute_layout(*layout_id, available_space);
276 *prev_available_space = available_space;
277 }
278 *layout_id
279 }
280 _ => panic!("cannot measure after painting"),
281 };
282
283 cx.layout_bounds(layout_id).size
284 }
285
286 fn draw(
287 &mut self,
288 mut origin: Point<Pixels>,
289 available_space: Size<AvailableSpace>,
290 view_state: &mut V,
291 cx: &mut ViewContext<V>,
292 ) {
293 self.measure(available_space, view_state, cx);
294 // Ignore the element offset when drawing this element, as the origin is already specified
295 // in absolute terms.
296 origin -= cx.element_offset();
297 cx.with_element_offset(Some(origin), |cx| self.paint(view_state, cx))
298 }
299}
300
301pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
302
303impl<V> AnyElement<V> {
304 pub fn new<E>(element: E) -> Self
305 where
306 V: 'static,
307 E: 'static + Element<V>,
308 E::ElementState: Any,
309 {
310 AnyElement(Box::new(RenderedElement::new(element)))
311 }
312
313 pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
314 self.0.initialize(view_state, cx);
315 }
316
317 pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
318 self.0.layout(view_state, cx)
319 }
320
321 pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
322 self.0.paint(view_state, cx)
323 }
324
325 pub fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
326 self.0.prepaint(view_state, cx)
327 }
328
329 /// Initializes this element and performs layout within the given available space to determine its size.
330 pub fn measure(
331 &mut self,
332 available_space: Size<AvailableSpace>,
333 view_state: &mut V,
334 cx: &mut ViewContext<V>,
335 ) -> Size<Pixels> {
336 self.0.measure(available_space, view_state, cx)
337 }
338
339 /// Initializes this element and performs layout in the available space, then paints it at the given origin.
340 pub fn draw(
341 &mut self,
342 origin: Point<Pixels>,
343 available_space: Size<AvailableSpace>,
344 view_state: &mut V,
345 cx: &mut ViewContext<V>,
346 ) {
347 self.0.draw(origin, available_space, view_state, cx)
348 }
349}
350
351pub trait Component<V> {
352 fn render(self) -> AnyElement<V>;
353
354 fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
355 where
356 Self: Sized,
357 U: Component<V>,
358 {
359 f(self)
360 }
361
362 fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
363 where
364 Self: Sized,
365 {
366 self.map(|this| if condition { then(this) } else { this })
367 }
368
369 fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self
370 where
371 Self: Sized,
372 {
373 self.map(|this| {
374 if let Some(value) = option {
375 then(this, value)
376 } else {
377 this
378 }
379 })
380 }
381}
382
383impl<V> Component<V> for AnyElement<V> {
384 fn render(self) -> AnyElement<V> {
385 self
386 }
387}
388
389impl<V, E, F> Element<V> for Option<F>
390where
391 V: 'static,
392 E: 'static + Component<V>,
393 F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
394{
395 type ElementState = AnyElement<V>;
396
397 fn id(&self) -> Option<ElementId> {
398 None
399 }
400
401 fn initialize(
402 &mut self,
403 view_state: &mut V,
404 _rendered_element: Option<Self::ElementState>,
405 cx: &mut ViewContext<V>,
406 ) -> Self::ElementState {
407 let render = self.take().unwrap();
408 let mut rendered_element = (render)(view_state, cx).render();
409 rendered_element.initialize(view_state, cx);
410 rendered_element
411 }
412
413 fn layout(
414 &mut self,
415 view_state: &mut V,
416 rendered_element: &mut Self::ElementState,
417 cx: &mut ViewContext<V>,
418 ) -> LayoutId {
419 rendered_element.layout(view_state, cx)
420 }
421
422 fn prepaint(
423 &mut self,
424 _bounds: Bounds<Pixels>,
425 view_state: &mut V,
426 rendered_element: &mut Self::ElementState,
427 cx: &mut ViewContext<V>,
428 ) {
429 rendered_element.prepaint(view_state, cx)
430 }
431
432 fn paint(
433 &mut self,
434 _bounds: Bounds<Pixels>,
435 view_state: &mut V,
436 rendered_element: &mut Self::ElementState,
437 cx: &mut ViewContext<V>,
438 ) {
439 rendered_element.paint(view_state, cx)
440 }
441}
442
443impl<V, E, F> Component<V> for Option<F>
444where
445 V: 'static,
446 E: 'static + Component<V>,
447 F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
448{
449 fn render(self) -> AnyElement<V> {
450 AnyElement::new(self)
451 }
452}
453
454impl<V, E, F> Component<V> for F
455where
456 V: 'static,
457 E: 'static + Component<V>,
458 F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
459{
460 fn render(self) -> AnyElement<V> {
461 AnyElement::new(Some(self))
462 }
463}