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