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}