1use crate::{
2 AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext,
3 WindowContext,
4};
5use derive_more::{Deref, DerefMut};
6pub(crate) use smallvec::SmallVec;
7use std::{any::Any, fmt::Debug};
8
9pub trait Render: 'static + Sized {
10 type Element: Element + 'static;
11
12 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
13}
14
15pub trait RenderOnce: Sized {
16 type Element: Element + 'static;
17
18 fn element_id(&self) -> Option<ElementId>;
19
20 fn render_once(self) -> Self::Element;
21
22 fn render_into_any(self) -> AnyElement {
23 self.render_once().into_any()
24 }
25
26 fn draw<T, R>(
27 self,
28 origin: Point<Pixels>,
29 available_space: Size<T>,
30 cx: &mut WindowContext,
31 f: impl FnOnce(&mut <Self::Element as Element>::State, &mut WindowContext) -> R,
32 ) -> R
33 where
34 T: Clone + Default + Debug + Into<AvailableSpace>,
35 {
36 let element = self.render_once();
37 let element_id = element.element_id();
38 let element = DrawableElement {
39 element: Some(element),
40 phase: ElementDrawPhase::Start,
41 };
42
43 let frame_state =
44 DrawableElement::draw(element, origin, available_space.map(Into::into), cx);
45
46 if let Some(mut frame_state) = frame_state {
47 f(&mut frame_state, cx)
48 } else {
49 cx.with_element_state(element_id.unwrap(), |element_state, cx| {
50 let mut element_state = element_state.unwrap();
51 let result = f(&mut element_state, cx);
52 (result, element_state)
53 })
54 }
55 }
56
57 fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
58 where
59 Self: Sized,
60 U: RenderOnce,
61 {
62 f(self)
63 }
64
65 fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
66 where
67 Self: Sized,
68 {
69 self.map(|this| if condition { then(this) } else { this })
70 }
71
72 fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self
73 where
74 Self: Sized,
75 {
76 self.map(|this| {
77 if let Some(value) = option {
78 then(this, value)
79 } else {
80 this
81 }
82 })
83 }
84}
85
86pub trait Element: 'static + RenderOnce {
87 type State: 'static;
88
89 fn layout(
90 &mut self,
91 state: Option<Self::State>,
92 cx: &mut WindowContext,
93 ) -> (LayoutId, Self::State);
94
95 fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext);
96
97 fn into_any(self) -> AnyElement {
98 AnyElement::new(self)
99 }
100}
101
102pub trait Component: 'static {
103 type Rendered: RenderOnce;
104
105 fn render(self, cx: &mut WindowContext) -> Self::Rendered;
106}
107
108pub struct CompositeElement<C> {
109 component: Option<C>,
110}
111
112pub struct CompositeElementState<C: Component> {
113 rendered_element: Option<<C::Rendered as RenderOnce>::Element>,
114 rendered_element_state: <<C::Rendered as RenderOnce>::Element as Element>::State,
115}
116
117impl<C> CompositeElement<C> {
118 pub fn new(component: C) -> Self {
119 CompositeElement {
120 component: Some(component),
121 }
122 }
123}
124
125impl<C: Component> Element for CompositeElement<C> {
126 type State = CompositeElementState<C>;
127
128 fn layout(
129 &mut self,
130 state: Option<Self::State>,
131 cx: &mut WindowContext,
132 ) -> (LayoutId, Self::State) {
133 let mut element = self.component.take().unwrap().render(cx).render_once();
134 let (layout_id, state) = element.layout(state.map(|s| s.rendered_element_state), cx);
135 let state = CompositeElementState {
136 rendered_element: Some(element),
137 rendered_element_state: state,
138 };
139 (layout_id, state)
140 }
141
142 fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
143 state
144 .rendered_element
145 .take()
146 .unwrap()
147 .paint(bounds, &mut state.rendered_element_state, cx);
148 }
149}
150
151impl<C: Component> RenderOnce for CompositeElement<C> {
152 type Element = Self;
153
154 fn element_id(&self) -> Option<ElementId> {
155 None
156 }
157
158 fn render_once(self) -> Self::Element {
159 self
160 }
161}
162
163#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
164pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
165
166pub trait ParentElement {
167 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
168
169 fn child(mut self, child: impl RenderOnce) -> Self
170 where
171 Self: Sized,
172 {
173 self.children_mut().push(child.render_once().into_any());
174 self
175 }
176
177 fn children(mut self, children: impl IntoIterator<Item = impl RenderOnce>) -> Self
178 where
179 Self: Sized,
180 {
181 self.children_mut().extend(
182 children
183 .into_iter()
184 .map(|child| child.render_once().into_any()),
185 );
186 self
187 }
188}
189
190trait ElementObject {
191 fn element_id(&self) -> Option<ElementId>;
192
193 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId;
194
195 fn paint(&mut self, cx: &mut WindowContext);
196
197 fn measure(
198 &mut self,
199 available_space: Size<AvailableSpace>,
200 cx: &mut WindowContext,
201 ) -> Size<Pixels>;
202
203 fn draw(
204 &mut self,
205 origin: Point<Pixels>,
206 available_space: Size<AvailableSpace>,
207 cx: &mut WindowContext,
208 );
209}
210
211pub struct DrawableElement<E: Element> {
212 element: Option<E>,
213 phase: ElementDrawPhase<E::State>,
214}
215
216#[derive(Default)]
217enum ElementDrawPhase<S> {
218 #[default]
219 Start,
220 LayoutRequested {
221 layout_id: LayoutId,
222 frame_state: Option<S>,
223 },
224 LayoutComputed {
225 layout_id: LayoutId,
226 available_space: Size<AvailableSpace>,
227 frame_state: Option<S>,
228 },
229}
230
231/// A wrapper around an implementer of [Element] that allows it to be drawn in a window.
232impl<E: Element> DrawableElement<E> {
233 fn new(element: E) -> Self {
234 DrawableElement {
235 element: Some(element),
236 phase: ElementDrawPhase::Start,
237 }
238 }
239
240 fn element_id(&self) -> Option<ElementId> {
241 self.element.as_ref()?.element_id()
242 }
243
244 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
245 let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id()
246 {
247 let layout_id = cx.with_element_state(id, |element_state, cx| {
248 self.element.as_mut().unwrap().layout(element_state, cx)
249 });
250 (layout_id, None)
251 } else {
252 let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(None, cx);
253 (layout_id, Some(frame_state))
254 };
255
256 self.phase = ElementDrawPhase::LayoutRequested {
257 layout_id,
258 frame_state,
259 };
260 layout_id
261 }
262
263 fn paint(mut self, cx: &mut WindowContext) -> Option<E::State> {
264 match self.phase {
265 ElementDrawPhase::LayoutRequested {
266 layout_id,
267 frame_state,
268 }
269 | ElementDrawPhase::LayoutComputed {
270 layout_id,
271 frame_state,
272 ..
273 } => {
274 let bounds = cx.layout_bounds(layout_id);
275
276 if let Some(mut frame_state) = frame_state {
277 self.element
278 .take()
279 .unwrap()
280 .paint(bounds, &mut frame_state, cx);
281 Some(frame_state)
282 } else {
283 let element_id = self
284 .element
285 .as_ref()
286 .unwrap()
287 .element_id()
288 .expect("if we don't have frame state, we should have element state");
289 cx.with_element_state(element_id, |element_state, cx| {
290 let mut element_state = element_state.unwrap();
291 self.element
292 .take()
293 .unwrap()
294 .paint(bounds, &mut element_state, cx);
295 ((), element_state)
296 });
297 None
298 }
299 }
300
301 _ => panic!("must call layout before paint"),
302 }
303 }
304
305 fn measure(
306 &mut self,
307 available_space: Size<AvailableSpace>,
308 cx: &mut WindowContext,
309 ) -> Size<Pixels> {
310 if matches!(&self.phase, ElementDrawPhase::Start) {
311 self.layout(cx);
312 }
313
314 let layout_id = match &mut self.phase {
315 ElementDrawPhase::LayoutRequested {
316 layout_id,
317 frame_state,
318 } => {
319 cx.compute_layout(*layout_id, available_space);
320 let layout_id = *layout_id;
321 self.phase = ElementDrawPhase::LayoutComputed {
322 layout_id,
323 available_space,
324 frame_state: frame_state.take(),
325 };
326 layout_id
327 }
328 ElementDrawPhase::LayoutComputed {
329 layout_id,
330 available_space: prev_available_space,
331 ..
332 } => {
333 if available_space != *prev_available_space {
334 cx.compute_layout(*layout_id, available_space);
335 *prev_available_space = available_space;
336 }
337 *layout_id
338 }
339 _ => panic!("cannot measure after painting"),
340 };
341
342 cx.layout_bounds(layout_id).size
343 }
344
345 fn draw(
346 mut self,
347 origin: Point<Pixels>,
348 available_space: Size<AvailableSpace>,
349 cx: &mut WindowContext,
350 ) -> Option<E::State> {
351 self.measure(available_space, cx);
352 cx.with_absolute_element_offset(origin, |cx| self.paint(cx))
353 }
354}
355
356// impl<V: 'static, E: Element> Element for DrawableElement<V, E> {
357// type State = <E::Element as Element>::State;
358
359// fn layout(
360// &mut self,
361// element_state: Option<Self::State>,
362// cx: &mut WindowContext,
363// ) -> (LayoutId, Self::State) {
364
365// }
366
367// fn paint(
368// self,
369// bounds: Bounds<Pixels>,
370// element_state: &mut Self::State,
371// cx: &mut WindowContext,
372// ) {
373// todo!()
374// }
375// }
376
377// impl<V: 'static, E: 'static + Element> RenderOnce for DrawableElement<V, E> {
378// type Element = Self;
379
380// fn element_id(&self) -> Option<ElementId> {
381// self.element.as_ref()?.element_id()
382// }
383
384// fn render_once(self) -> Self::Element {
385// self
386// }
387// }
388
389impl<E> ElementObject for Option<DrawableElement<E>>
390where
391 E: Element,
392 E::State: 'static,
393{
394 fn element_id(&self) -> Option<ElementId> {
395 self.as_ref().unwrap().element_id()
396 }
397
398 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
399 DrawableElement::layout(self.as_mut().unwrap(), cx)
400 }
401
402 fn paint(&mut self, cx: &mut WindowContext) {
403 DrawableElement::paint(self.take().unwrap(), cx);
404 }
405
406 fn measure(
407 &mut self,
408 available_space: Size<AvailableSpace>,
409 cx: &mut WindowContext,
410 ) -> Size<Pixels> {
411 DrawableElement::measure(self.as_mut().unwrap(), available_space, cx)
412 }
413
414 fn draw(
415 &mut self,
416 origin: Point<Pixels>,
417 available_space: Size<AvailableSpace>,
418 cx: &mut WindowContext,
419 ) {
420 DrawableElement::draw(self.take().unwrap(), origin, available_space, cx);
421 }
422}
423
424pub struct AnyElement(Box<dyn ElementObject>);
425
426impl AnyElement {
427 pub fn new<E>(element: E) -> Self
428 where
429 E: 'static + Element,
430 E::State: Any,
431 {
432 AnyElement(Box::new(Some(DrawableElement::new(element))) as Box<dyn ElementObject>)
433 }
434
435 pub fn element_id(&self) -> Option<ElementId> {
436 self.0.element_id()
437 }
438
439 pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
440 self.0.layout(cx)
441 }
442
443 pub fn paint(mut self, cx: &mut WindowContext) {
444 self.0.paint(cx)
445 }
446
447 /// Initializes this element and performs layout within the given available space to determine its size.
448 pub fn measure(
449 &mut self,
450 available_space: Size<AvailableSpace>,
451 cx: &mut WindowContext,
452 ) -> Size<Pixels> {
453 self.0.measure(available_space, cx)
454 }
455
456 /// Initializes this element and performs layout in the available space, then paints it at the given origin.
457 pub fn draw(
458 mut self,
459 origin: Point<Pixels>,
460 available_space: Size<AvailableSpace>,
461 cx: &mut WindowContext,
462 ) {
463 self.0.draw(origin, available_space, cx)
464 }
465
466 /// Converts this `AnyElement` into a trait object that can be stored and manipulated.
467 pub fn into_any(self) -> AnyElement {
468 AnyElement::new(self)
469 }
470}
471
472impl Element for AnyElement {
473 type State = ();
474
475 fn layout(
476 &mut self,
477 _: Option<Self::State>,
478 cx: &mut WindowContext,
479 ) -> (LayoutId, Self::State) {
480 let layout_id = self.layout(cx);
481 (layout_id, ())
482 }
483
484 fn paint(self, _: Bounds<Pixels>, _: &mut Self::State, cx: &mut WindowContext) {
485 self.paint(cx);
486 }
487}
488
489impl RenderOnce for AnyElement {
490 type Element = Self;
491
492 fn element_id(&self) -> Option<ElementId> {
493 AnyElement::element_id(self)
494 }
495
496 fn render_once(self) -> Self::Element {
497 self
498 }
499}
500
501// impl<V, E, F> Element for Option<F>
502// where
503// V: 'static,
504// E: Element,
505// F: FnOnce(&mut V, &mut WindowContext<'_, V>) -> E + 'static,
506// {
507// type State = Option<AnyElement>;
508
509// fn element_id(&self) -> Option<ElementId> {
510// None
511// }
512
513// fn layout(
514// &mut self,
515// _: Option<Self::State>,
516// cx: &mut WindowContext,
517// ) -> (LayoutId, Self::State) {
518// let render = self.take().unwrap();
519// let mut element = (render)(view_state, cx).into_any();
520// let layout_id = element.layout(view_state, cx);
521// (layout_id, Some(element))
522// }
523
524// fn paint(
525// self,
526// _bounds: Bounds<Pixels>,
527// rendered_element: &mut Self::State,
528// cx: &mut WindowContext,
529// ) {
530// rendered_element.take().unwrap().paint(view_state, cx);
531// }
532// }
533
534// impl<V, E, F> RenderOnce for Option<F>
535// where
536// V: 'static,
537// E: Element,
538// F: FnOnce(&mut V, &mut WindowContext) -> E + 'static,
539// {
540// type Element = Self;
541
542// fn render(self) -> Self::Element {
543// self
544// }
545// }