element.rs

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