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