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