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