element.rs

  1use crate::{BorrowWindow, Bounds, ElementId, FocusHandle, LayoutId, Pixels, Point, 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(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>);
 37
 38pub trait ElementIdentity: 'static + Send + Sync {
 39    fn id(&self) -> Option<ElementId>;
 40}
 41
 42pub struct Identified(pub(crate) ElementId);
 43
 44impl ElementIdentity for Identified {
 45    fn id(&self) -> Option<ElementId> {
 46        Some(self.0.clone())
 47    }
 48}
 49
 50pub struct Anonymous;
 51
 52impl ElementIdentity for Anonymous {
 53    fn id(&self) -> Option<ElementId> {
 54        None
 55    }
 56}
 57
 58pub trait ElementFocusability: 'static + Send + Sync {
 59    fn focus_handle(&self) -> Option<&FocusHandle>;
 60}
 61
 62pub struct Focusable(FocusHandle);
 63
 64impl ElementFocusability for Focusable {
 65    fn focus_handle(&self) -> Option<&FocusHandle> {
 66        Some(&self.0)
 67    }
 68}
 69
 70impl From<FocusHandle> for Focusable {
 71    fn from(value: FocusHandle) -> Self {
 72        Self(value)
 73    }
 74}
 75
 76pub struct NonFocusable;
 77
 78impl ElementFocusability for NonFocusable {
 79    fn focus_handle(&self) -> Option<&FocusHandle> {
 80        None
 81    }
 82}
 83
 84pub trait ParentElement: Element {
 85    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
 86
 87    fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
 88    where
 89        Self: Sized,
 90    {
 91        self.children_mut().push(child.into_any());
 92        self
 93    }
 94
 95    fn children(
 96        mut self,
 97        iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
 98    ) -> Self
 99    where
100        Self: Sized,
101    {
102        self.children_mut()
103            .extend(iter.into_iter().map(|item| item.into_any()));
104        self
105    }
106}
107
108trait ElementObject<V>: 'static + Send + Sync {
109    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
110    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
111    fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
112}
113
114struct RenderedElement<E: Element> {
115    element: E,
116    phase: ElementRenderPhase<E::ElementState>,
117}
118
119#[derive(Default)]
120enum ElementRenderPhase<V> {
121    #[default]
122    Start,
123    Initialized {
124        frame_state: Option<V>,
125    },
126    LayoutRequested {
127        layout_id: LayoutId,
128        frame_state: Option<V>,
129    },
130    Painted,
131}
132
133/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
134/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
135/// improved usability.
136impl<E: Element> RenderedElement<E> {
137    fn new(element: E) -> Self {
138        RenderedElement {
139            element,
140            phase: ElementRenderPhase::Start,
141        }
142    }
143}
144
145impl<E> ElementObject<E::ViewState> for RenderedElement<E>
146where
147    E: Element,
148{
149    fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
150        let frame_state = if let Some(id) = self.element.id() {
151            cx.with_element_state(id, |element_state, cx| {
152                let element_state = self.element.initialize(view_state, element_state, cx);
153                ((), element_state)
154            });
155            None
156        } else {
157            let frame_state = self.element.initialize(view_state, None, cx);
158            Some(frame_state)
159        };
160
161        self.phase = ElementRenderPhase::Initialized { frame_state };
162    }
163
164    fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
165        let layout_id;
166        let mut frame_state;
167        match mem::take(&mut self.phase) {
168            ElementRenderPhase::Initialized {
169                frame_state: initial_frame_state,
170            } => {
171                frame_state = initial_frame_state;
172                if let Some(id) = self.element.id() {
173                    layout_id = cx.with_element_state(id, |element_state, cx| {
174                        let mut element_state = element_state.unwrap();
175                        let layout_id = self.element.layout(state, &mut element_state, cx);
176                        (layout_id, element_state)
177                    });
178                } else {
179                    layout_id = self
180                        .element
181                        .layout(state, frame_state.as_mut().unwrap(), cx);
182                }
183            }
184            _ => panic!("must call initialize before layout"),
185        };
186
187        self.phase = ElementRenderPhase::LayoutRequested {
188            layout_id,
189            frame_state,
190        };
191        layout_id
192    }
193
194    fn paint(
195        &mut self,
196        view_state: &mut E::ViewState,
197        offset: Option<Point<Pixels>>,
198        cx: &mut ViewContext<E::ViewState>,
199    ) {
200        self.phase = match mem::take(&mut self.phase) {
201            ElementRenderPhase::LayoutRequested {
202                layout_id,
203                mut frame_state,
204            } => {
205                let mut bounds = cx.layout_bounds(layout_id);
206                offset.map(|offset| bounds.origin += offset);
207                if let Some(id) = self.element.id() {
208                    cx.with_element_state(id, |element_state, cx| {
209                        let mut element_state = element_state.unwrap();
210                        self.element
211                            .paint(bounds, view_state, &mut element_state, cx);
212                        ((), element_state)
213                    });
214                } else {
215                    self.element
216                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
217                }
218                ElementRenderPhase::Painted
219            }
220
221            _ => panic!("must call layout before paint"),
222        };
223    }
224}
225
226pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
227
228impl<V: 'static + Send + Sync> AnyElement<V> {
229    pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
230        AnyElement(Box::new(RenderedElement::new(element)))
231    }
232
233    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
234        self.0.initialize(view_state, cx);
235    }
236
237    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
238        self.0.layout(view_state, cx)
239    }
240
241    pub fn paint(
242        &mut self,
243        view_state: &mut V,
244        offset: Option<Point<Pixels>>,
245        cx: &mut ViewContext<V>,
246    ) {
247        self.0.paint(view_state, offset, cx)
248    }
249}
250
251pub trait IntoAnyElement<V> {
252    fn into_any(self) -> AnyElement<V>;
253}
254
255impl<V> IntoAnyElement<V> for AnyElement<V> {
256    fn into_any(self) -> AnyElement<V> {
257        self
258    }
259}