element.rs

  1use crate::{
  2    BorrowWindow, Bounds, ElementId, FocusHandle, FocusListeners, LayoutId, Pixels, Point,
  3    StyleRefinement, ViewContext,
  4};
  5use derive_more::{Deref, DerefMut};
  6pub(crate) use smallvec::SmallVec;
  7use std::mem;
  8
  9pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
 10    type ViewState: 'static + Send + Sync;
 11    type ElementState: 'static + Send + Sync;
 12
 13    fn id(&self) -> Option<ElementId>;
 14
 15    fn initialize(
 16        &mut self,
 17        view_state: &mut Self::ViewState,
 18        element_state: Option<Self::ElementState>,
 19        cx: &mut ViewContext<Self::ViewState>,
 20    ) -> Self::ElementState;
 21
 22    fn layout(
 23        &mut self,
 24        view_state: &mut Self::ViewState,
 25        element_state: &mut Self::ElementState,
 26        cx: &mut ViewContext<Self::ViewState>,
 27    ) -> LayoutId;
 28
 29    fn paint(
 30        &mut self,
 31        bounds: Bounds<Pixels>,
 32        view_state: &mut Self::ViewState,
 33        element_state: &mut Self::ElementState,
 34        cx: &mut ViewContext<Self::ViewState>,
 35    );
 36}
 37
 38#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
 39pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
 40
 41pub trait ElementIdentity: 'static + Send + Sync {
 42    fn id(&self) -> Option<ElementId>;
 43}
 44
 45pub struct Identified(pub(crate) ElementId);
 46
 47impl ElementIdentity for Identified {
 48    fn id(&self) -> Option<ElementId> {
 49        Some(self.0.clone())
 50    }
 51}
 52
 53pub struct Anonymous;
 54
 55impl ElementIdentity for Anonymous {
 56    fn id(&self) -> Option<ElementId> {
 57        None
 58    }
 59}
 60
 61pub trait ElementFocusability<V: 'static + Send + Sync>: 'static + Send + Sync {
 62    fn as_focusable(&self) -> Option<&Focusable<V>>;
 63
 64    fn initialize<R>(
 65        &self,
 66        cx: &mut ViewContext<V>,
 67        f: impl FnOnce(&mut ViewContext<V>) -> R,
 68    ) -> R {
 69        if let Some(focusable) = self.as_focusable() {
 70            for listener in focusable.focus_listeners.iter().cloned() {
 71                cx.on_focus_changed(move |view, event, cx| listener(view, event, cx));
 72            }
 73            cx.with_focus(focusable.focus_handle.clone(), |cx| f(cx))
 74        } else {
 75            f(cx)
 76        }
 77    }
 78}
 79
 80pub struct Focusable<V: 'static + Send + Sync> {
 81    pub focus_handle: FocusHandle,
 82    pub focus_listeners: FocusListeners<V>,
 83    pub focus_style: StyleRefinement,
 84    pub focus_in_style: StyleRefinement,
 85    pub in_focus_style: StyleRefinement,
 86}
 87
 88impl<V> ElementFocusability<V> for Focusable<V>
 89where
 90    V: 'static + Send + Sync,
 91{
 92    fn as_focusable(&self) -> Option<&Focusable<V>> {
 93        Some(self)
 94    }
 95}
 96
 97impl<V> From<FocusHandle> for Focusable<V>
 98where
 99    V: 'static + Send + Sync,
100{
101    fn from(value: FocusHandle) -> Self {
102        Self {
103            focus_handle: value,
104            focus_listeners: FocusListeners::default(),
105            focus_style: StyleRefinement::default(),
106            focus_in_style: StyleRefinement::default(),
107            in_focus_style: StyleRefinement::default(),
108        }
109    }
110}
111
112pub struct NonFocusable;
113
114impl<V> ElementFocusability<V> for NonFocusable
115where
116    V: 'static + Send + Sync,
117{
118    fn as_focusable(&self) -> Option<&Focusable<V>> {
119        None
120    }
121}
122
123pub trait ParentElement: Element {
124    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
125
126    fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
127    where
128        Self: Sized,
129    {
130        self.children_mut().push(child.into_any());
131        self
132    }
133
134    fn children(
135        mut self,
136        iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
137    ) -> Self
138    where
139        Self: Sized,
140    {
141        self.children_mut()
142            .extend(iter.into_iter().map(|item| item.into_any()));
143        self
144    }
145}
146
147trait ElementObject<V>: 'static + Send + Sync {
148    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
149    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
150    fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
151}
152
153struct RenderedElement<E: Element> {
154    element: E,
155    phase: ElementRenderPhase<E::ElementState>,
156}
157
158#[derive(Default)]
159enum ElementRenderPhase<V> {
160    #[default]
161    Start,
162    Initialized {
163        frame_state: Option<V>,
164    },
165    LayoutRequested {
166        layout_id: LayoutId,
167        frame_state: Option<V>,
168    },
169    Painted,
170}
171
172/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
173/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
174/// improved usability.
175impl<E: Element> RenderedElement<E> {
176    fn new(element: E) -> Self {
177        RenderedElement {
178            element,
179            phase: ElementRenderPhase::Start,
180        }
181    }
182}
183
184impl<E> ElementObject<E::ViewState> for RenderedElement<E>
185where
186    E: Element,
187{
188    fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
189        let frame_state = if let Some(id) = self.element.id() {
190            cx.with_element_state(id, |element_state, cx| {
191                let element_state = self.element.initialize(view_state, element_state, cx);
192                ((), element_state)
193            });
194            None
195        } else {
196            let frame_state = self.element.initialize(view_state, None, cx);
197            Some(frame_state)
198        };
199
200        self.phase = ElementRenderPhase::Initialized { frame_state };
201    }
202
203    fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
204        let layout_id;
205        let mut frame_state;
206        match mem::take(&mut self.phase) {
207            ElementRenderPhase::Initialized {
208                frame_state: initial_frame_state,
209            } => {
210                frame_state = initial_frame_state;
211                if let Some(id) = self.element.id() {
212                    layout_id = cx.with_element_state(id, |element_state, cx| {
213                        let mut element_state = element_state.unwrap();
214                        let layout_id = self.element.layout(state, &mut element_state, cx);
215                        (layout_id, element_state)
216                    });
217                } else {
218                    layout_id = self
219                        .element
220                        .layout(state, frame_state.as_mut().unwrap(), cx);
221                }
222            }
223            _ => panic!("must call initialize before layout"),
224        };
225
226        self.phase = ElementRenderPhase::LayoutRequested {
227            layout_id,
228            frame_state,
229        };
230        layout_id
231    }
232
233    fn paint(
234        &mut self,
235        view_state: &mut E::ViewState,
236        offset: Option<Point<Pixels>>,
237        cx: &mut ViewContext<E::ViewState>,
238    ) {
239        self.phase = match mem::take(&mut self.phase) {
240            ElementRenderPhase::LayoutRequested {
241                layout_id,
242                mut frame_state,
243            } => {
244                let mut bounds = cx.layout_bounds(layout_id);
245                offset.map(|offset| bounds.origin += offset);
246                if let Some(id) = self.element.id() {
247                    cx.with_element_state(id, |element_state, cx| {
248                        let mut element_state = element_state.unwrap();
249                        self.element
250                            .paint(bounds, view_state, &mut element_state, cx);
251                        ((), element_state)
252                    });
253                } else {
254                    self.element
255                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
256                }
257                ElementRenderPhase::Painted
258            }
259
260            _ => panic!("must call layout before paint"),
261        };
262    }
263}
264
265pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
266
267impl<V: 'static + Send + Sync> AnyElement<V> {
268    pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
269        AnyElement(Box::new(RenderedElement::new(element)))
270    }
271
272    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
273        self.0.initialize(view_state, cx);
274    }
275
276    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
277        self.0.layout(view_state, cx)
278    }
279
280    pub fn paint(
281        &mut self,
282        view_state: &mut V,
283        offset: Option<Point<Pixels>>,
284        cx: &mut ViewContext<V>,
285    ) {
286        self.0.paint(view_state, offset, cx)
287    }
288}
289
290pub trait IntoAnyElement<V> {
291    fn into_any(self) -> AnyElement<V>;
292}
293
294impl<V> IntoAnyElement<V> for AnyElement<V> {
295    fn into_any(self) -> AnyElement<V> {
296        self
297    }
298}