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