element.rs

  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// }