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}