element.rs

  1use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, ViewContext};
  2use derive_more::{Deref, DerefMut};
  3pub(crate) use smallvec::SmallVec;
  4use std::{any::Any, mem};
  5
  6pub trait Element: IntoAnyElement<Self::ViewState> {
  7    type ViewState: 'static;
  8    type ElementState: 'static;
  9
 10    fn id(&self) -> Option<ElementId>;
 11
 12    fn initialize(
 13        &mut self,
 14        view_state: &mut Self::ViewState,
 15        element_state: Option<Self::ElementState>,
 16        cx: &mut ViewContext<Self::ViewState>,
 17    ) -> Self::ElementState;
 18    // where
 19    //     Self::ViewState: Any + Send + Sync;
 20
 21    fn layout(
 22        &mut self,
 23        view_state: &mut Self::ViewState,
 24        element_state: &mut Self::ElementState,
 25        cx: &mut ViewContext<Self::ViewState>,
 26    ) -> LayoutId;
 27    // where
 28    //     Self::ViewState: Any + Send + Sync;
 29
 30    fn paint(
 31        &mut self,
 32        bounds: Bounds<Pixels>,
 33        view_state: &mut Self::ViewState,
 34        element_state: &mut Self::ElementState,
 35        cx: &mut ViewContext<Self::ViewState>,
 36    );
 37
 38    // where
 39    //     Self::ViewState: Any + Send + Sync;
 40}
 41
 42#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
 43pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
 44
 45pub trait ParentElement: Element {
 46    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
 47
 48    fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
 49    where
 50        Self: Sized,
 51    {
 52        self.children_mut().push(child.into_any());
 53        self
 54    }
 55
 56    fn children(
 57        mut self,
 58        iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
 59    ) -> Self
 60    where
 61        Self: Sized,
 62    {
 63        self.children_mut()
 64            .extend(iter.into_iter().map(|item| item.into_any()));
 65        self
 66    }
 67}
 68
 69trait ElementObject<V> {
 70    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
 71    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
 72    fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
 73}
 74
 75struct RenderedElement<E: Element> {
 76    element: E,
 77    phase: ElementRenderPhase<E::ElementState>,
 78}
 79
 80#[derive(Default)]
 81enum ElementRenderPhase<V> {
 82    #[default]
 83    Start,
 84    Initialized {
 85        frame_state: Option<V>,
 86    },
 87    LayoutRequested {
 88        layout_id: LayoutId,
 89        frame_state: Option<V>,
 90    },
 91    Painted,
 92}
 93
 94/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
 95/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
 96/// improved usability.
 97impl<E: Element> RenderedElement<E> {
 98    fn new(element: E) -> Self {
 99        RenderedElement {
100            element,
101            phase: ElementRenderPhase::Start,
102        }
103    }
104}
105
106impl<E> ElementObject<E::ViewState> for RenderedElement<E>
107where
108    E: Element,
109    // E::ViewState: Any + Send + Sync,
110    E::ElementState: Any + Send + Sync,
111{
112    fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
113        let frame_state = if let Some(id) = self.element.id() {
114            cx.with_element_state(id, |element_state, cx| {
115                let element_state = self.element.initialize(view_state, element_state, cx);
116                ((), element_state)
117            });
118            None
119        } else {
120            let frame_state = self.element.initialize(view_state, None, cx);
121            Some(frame_state)
122        };
123
124        self.phase = ElementRenderPhase::Initialized { frame_state };
125    }
126
127    fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
128        let layout_id;
129        let mut frame_state;
130        match mem::take(&mut self.phase) {
131            ElementRenderPhase::Initialized {
132                frame_state: initial_frame_state,
133            } => {
134                frame_state = initial_frame_state;
135                if let Some(id) = self.element.id() {
136                    layout_id = cx.with_element_state(id, |element_state, cx| {
137                        let mut element_state = element_state.unwrap();
138                        let layout_id = self.element.layout(state, &mut element_state, cx);
139                        (layout_id, element_state)
140                    });
141                } else {
142                    layout_id = self
143                        .element
144                        .layout(state, frame_state.as_mut().unwrap(), cx);
145                }
146            }
147            _ => panic!("must call initialize before layout"),
148        };
149
150        self.phase = ElementRenderPhase::LayoutRequested {
151            layout_id,
152            frame_state,
153        };
154        layout_id
155    }
156
157    fn paint(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
158        self.phase = match mem::take(&mut self.phase) {
159            ElementRenderPhase::LayoutRequested {
160                layout_id,
161                mut frame_state,
162            } => {
163                let bounds = cx.layout_bounds(layout_id);
164                if let Some(id) = self.element.id() {
165                    cx.with_element_state(id, |element_state, cx| {
166                        let mut element_state = element_state.unwrap();
167                        self.element
168                            .paint(bounds, view_state, &mut element_state, cx);
169                        ((), element_state)
170                    });
171                } else {
172                    self.element
173                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
174                }
175                ElementRenderPhase::Painted
176            }
177
178            _ => panic!("must call layout before paint"),
179        };
180    }
181}
182
183pub struct AnyElement<V>(Box<dyn ElementObject<V> + Send + Sync>);
184
185impl<V> AnyElement<V> {
186    pub fn new<E>(element: E) -> Self
187    where
188        E: 'static + Send + Sync,
189        E: Element<ViewState = V>,
190        E::ElementState: Any + Send + Sync,
191    {
192        AnyElement(Box::new(RenderedElement::new(element)))
193    }
194
195    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
196        self.0.initialize(view_state, cx);
197    }
198
199    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
200        self.0.layout(view_state, cx)
201    }
202
203    pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
204        self.0.paint(view_state, cx)
205    }
206}
207
208pub trait IntoAnyElement<V> {
209    fn into_any(self) -> AnyElement<V>;
210}
211
212impl<V> IntoAnyElement<V> for AnyElement<V> {
213    fn into_any(self) -> AnyElement<V> {
214        self
215    }
216}