1use crate::{
2 BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners, KeyDownEvent,
3 KeyListener, KeyMatch, LayoutId, MouseClickEvent, MouseClickListener, MouseDownEvent,
4 MouseDownListener, MouseMoveEvent, MouseMoveListener, MouseUpEvent, MouseUpListener, Pixels,
5 Point, ScrollWheelEvent, ScrollWheelListener, Style, StyleRefinement, ViewContext,
6 WindowContext,
7};
8use derive_more::{Deref, DerefMut};
9use parking_lot::Mutex;
10use refineable::Refineable;
11pub(crate) use smallvec::SmallVec;
12use std::{any::TypeId, mem, sync::Arc};
13
14pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
15 type ViewState: 'static + Send + Sync;
16 type ElementState: 'static + Send + Sync;
17
18 fn id(&self) -> Option<ElementId>;
19
20 fn initialize(
21 &mut self,
22 view_state: &mut Self::ViewState,
23 element_state: Option<Self::ElementState>,
24 cx: &mut ViewContext<Self::ViewState>,
25 ) -> Self::ElementState;
26
27 fn layout(
28 &mut self,
29 view_state: &mut Self::ViewState,
30 element_state: &mut Self::ElementState,
31 cx: &mut ViewContext<Self::ViewState>,
32 ) -> LayoutId;
33
34 fn paint(
35 &mut self,
36 bounds: Bounds<Pixels>,
37 view_state: &mut Self::ViewState,
38 element_state: &mut Self::ElementState,
39 cx: &mut ViewContext<Self::ViewState>,
40 );
41}
42
43#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
44pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
45
46pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync {
47 fn as_stateless(&self) -> &StatelessInteractivity<V>;
48 fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V>;
49 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
50 fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
51
52 fn paint(
53 &mut self,
54 bounds: Bounds<Pixels>,
55 pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
56 cx: &mut ViewContext<V>,
57 ) {
58 let stateless = self.as_stateless();
59 for listener in stateless.mouse_down_listeners.iter().cloned() {
60 cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
61 listener(state, event, &bounds, phase, cx);
62 })
63 }
64
65 for listener in stateless.mouse_up_listeners.iter().cloned() {
66 cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
67 listener(state, event, &bounds, phase, cx);
68 })
69 }
70
71 for listener in stateless.mouse_move_listeners.iter().cloned() {
72 cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
73 listener(state, event, &bounds, phase, cx);
74 })
75 }
76
77 for listener in stateless.scroll_wheel_listeners.iter().cloned() {
78 cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
79 listener(state, event, &bounds, phase, cx);
80 })
81 }
82
83 if let Some(stateful) = self.as_stateful() {
84 let click_listeners = stateful.mouse_click_listeners.clone();
85
86 let mouse_down = pending_click.lock().clone();
87 if let Some(mouse_down) = mouse_down {
88 cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
89 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
90 let mouse_click = MouseClickEvent {
91 down: mouse_down.clone(),
92 up: event.clone(),
93 };
94 for listener in &click_listeners {
95 listener(state, &mouse_click, cx);
96 }
97 }
98
99 *pending_click.lock() = None;
100 });
101 } else {
102 cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
103 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
104 *pending_click.lock() = Some(event.clone());
105 }
106 });
107 };
108 }
109 }
110
111 fn initialize<R>(
112 &mut self,
113 cx: &mut ViewContext<V>,
114 f: impl FnOnce(&mut ViewContext<V>) -> R,
115 ) -> R {
116 if let Some(stateful) = self.as_stateful_mut() {
117 cx.with_element_id(stateful.id.clone(), |global_id, cx| {
118 stateful.key_listeners.push((
119 TypeId::of::<KeyDownEvent>(),
120 Arc::new(move |_, key_down, context, phase, cx| {
121 if phase == DispatchPhase::Bubble {
122 let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
123 if let KeyMatch::Some(action) =
124 cx.match_keystroke(&global_id, &key_down.keystroke, context)
125 {
126 return Some(action);
127 }
128 }
129
130 None
131 }),
132 ));
133 let result = stateful.stateless.initialize(cx, f);
134 stateful.key_listeners.pop();
135 result
136 })
137 } else {
138 cx.with_key_listeners(&self.as_stateless().key_listeners, f)
139 }
140 }
141}
142
143#[derive(Deref, DerefMut)]
144pub struct StatefulInteractivity<V: 'static + Send + Sync> {
145 pub id: ElementId,
146 #[deref]
147 #[deref_mut]
148 stateless: StatelessInteractivity<V>,
149 pub mouse_click_listeners: SmallVec<[MouseClickListener<V>; 2]>,
150}
151
152impl<V> ElementInteractivity<V> for StatefulInteractivity<V>
153where
154 V: 'static + Send + Sync,
155{
156 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
157 Some(self)
158 }
159
160 fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
161 Some(self)
162 }
163
164 fn as_stateless(&self) -> &StatelessInteractivity<V> {
165 &self.stateless
166 }
167
168 fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
169 &mut self.stateless
170 }
171}
172
173impl<V> From<ElementId> for StatefulInteractivity<V>
174where
175 V: 'static + Send + Sync,
176{
177 fn from(id: ElementId) -> Self {
178 Self {
179 id,
180 stateless: StatelessInteractivity::default(),
181 mouse_click_listeners: SmallVec::new(),
182 }
183 }
184}
185
186pub struct StatelessInteractivity<V> {
187 pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
188 pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
189 pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
190 pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
191 pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
192}
193
194impl<V> Default for StatelessInteractivity<V> {
195 fn default() -> Self {
196 Self {
197 mouse_down_listeners: SmallVec::new(),
198 mouse_up_listeners: SmallVec::new(),
199 mouse_move_listeners: SmallVec::new(),
200 scroll_wheel_listeners: SmallVec::new(),
201 key_listeners: SmallVec::new(),
202 }
203 }
204}
205
206impl<V> ElementInteractivity<V> for StatelessInteractivity<V>
207where
208 V: 'static + Send + Sync,
209{
210 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
211 None
212 }
213
214 fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
215 None
216 }
217
218 fn as_stateless(&self) -> &StatelessInteractivity<V> {
219 self
220 }
221
222 fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
223 self
224 }
225}
226
227pub trait ElementFocusability<V: 'static + Send + Sync>: 'static + Send + Sync {
228 fn as_focusable(&self) -> Option<&Focusable<V>>;
229
230 fn initialize<R>(
231 &self,
232 cx: &mut ViewContext<V>,
233 f: impl FnOnce(&mut ViewContext<V>) -> R,
234 ) -> R {
235 if let Some(focusable) = self.as_focusable() {
236 for listener in focusable.focus_listeners.iter().cloned() {
237 cx.on_focus_changed(move |view, event, cx| listener(view, event, cx));
238 }
239 cx.with_focus(focusable.focus_handle.clone(), |cx| f(cx))
240 } else {
241 f(cx)
242 }
243 }
244
245 fn refine_style(&self, style: &mut Style, cx: &WindowContext) {
246 if let Some(focusable) = self.as_focusable() {
247 if focusable.focus_handle.contains_focused(cx) {
248 style.refine(&focusable.focus_in_style);
249 }
250
251 if focusable.focus_handle.within_focused(cx) {
252 style.refine(&focusable.in_focus_style);
253 }
254
255 if focusable.focus_handle.is_focused(cx) {
256 style.refine(&focusable.focus_style);
257 }
258 }
259 }
260
261 fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
262 if let Some(focusable) = self.as_focusable() {
263 let focus_handle = focusable.focus_handle.clone();
264 cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
265 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
266 if !cx.default_prevented() {
267 cx.focus(&focus_handle);
268 cx.prevent_default();
269 }
270 }
271 })
272 }
273 }
274}
275
276pub struct Focusable<V: 'static + Send + Sync> {
277 pub focus_handle: FocusHandle,
278 pub focus_listeners: FocusListeners<V>,
279 pub focus_style: StyleRefinement,
280 pub focus_in_style: StyleRefinement,
281 pub in_focus_style: StyleRefinement,
282}
283
284impl<V> ElementFocusability<V> for Focusable<V>
285where
286 V: 'static + Send + Sync,
287{
288 fn as_focusable(&self) -> Option<&Focusable<V>> {
289 Some(self)
290 }
291}
292
293impl<V> From<FocusHandle> for Focusable<V>
294where
295 V: 'static + Send + Sync,
296{
297 fn from(value: FocusHandle) -> Self {
298 Self {
299 focus_handle: value,
300 focus_listeners: FocusListeners::default(),
301 focus_style: StyleRefinement::default(),
302 focus_in_style: StyleRefinement::default(),
303 in_focus_style: StyleRefinement::default(),
304 }
305 }
306}
307
308pub struct NonFocusable;
309
310impl<V> ElementFocusability<V> for NonFocusable
311where
312 V: 'static + Send + Sync,
313{
314 fn as_focusable(&self) -> Option<&Focusable<V>> {
315 None
316 }
317}
318
319pub trait ParentElement: Element {
320 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
321
322 fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
323 where
324 Self: Sized,
325 {
326 self.children_mut().push(child.into_any());
327 self
328 }
329
330 fn children(
331 mut self,
332 iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
333 ) -> Self
334 where
335 Self: Sized,
336 {
337 self.children_mut()
338 .extend(iter.into_iter().map(|item| item.into_any()));
339 self
340 }
341}
342
343trait ElementObject<V>: 'static + Send + Sync {
344 fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
345 fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
346 fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
347}
348
349struct RenderedElement<E: Element> {
350 element: E,
351 phase: ElementRenderPhase<E::ElementState>,
352}
353
354#[derive(Default)]
355enum ElementRenderPhase<V> {
356 #[default]
357 Start,
358 Initialized {
359 frame_state: Option<V>,
360 },
361 LayoutRequested {
362 layout_id: LayoutId,
363 frame_state: Option<V>,
364 },
365 Painted,
366}
367
368/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
369/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
370/// improved usability.
371impl<E: Element> RenderedElement<E> {
372 fn new(element: E) -> Self {
373 RenderedElement {
374 element,
375 phase: ElementRenderPhase::Start,
376 }
377 }
378}
379
380impl<E> ElementObject<E::ViewState> for RenderedElement<E>
381where
382 E: Element,
383{
384 fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
385 let frame_state = if let Some(id) = self.element.id() {
386 cx.with_element_state(id, |element_state, cx| {
387 let element_state = self.element.initialize(view_state, element_state, cx);
388 ((), element_state)
389 });
390 None
391 } else {
392 let frame_state = self.element.initialize(view_state, None, cx);
393 Some(frame_state)
394 };
395
396 self.phase = ElementRenderPhase::Initialized { frame_state };
397 }
398
399 fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
400 let layout_id;
401 let mut frame_state;
402 match mem::take(&mut self.phase) {
403 ElementRenderPhase::Initialized {
404 frame_state: initial_frame_state,
405 } => {
406 frame_state = initial_frame_state;
407 if let Some(id) = self.element.id() {
408 layout_id = cx.with_element_state(id, |element_state, cx| {
409 let mut element_state = element_state.unwrap();
410 let layout_id = self.element.layout(state, &mut element_state, cx);
411 (layout_id, element_state)
412 });
413 } else {
414 layout_id = self
415 .element
416 .layout(state, frame_state.as_mut().unwrap(), cx);
417 }
418 }
419 _ => panic!("must call initialize before layout"),
420 };
421
422 self.phase = ElementRenderPhase::LayoutRequested {
423 layout_id,
424 frame_state,
425 };
426 layout_id
427 }
428
429 fn paint(
430 &mut self,
431 view_state: &mut E::ViewState,
432 offset: Option<Point<Pixels>>,
433 cx: &mut ViewContext<E::ViewState>,
434 ) {
435 self.phase = match mem::take(&mut self.phase) {
436 ElementRenderPhase::LayoutRequested {
437 layout_id,
438 mut frame_state,
439 } => {
440 let mut bounds = cx.layout_bounds(layout_id);
441 offset.map(|offset| bounds.origin += offset);
442 if let Some(id) = self.element.id() {
443 cx.with_element_state(id, |element_state, cx| {
444 let mut element_state = element_state.unwrap();
445 self.element
446 .paint(bounds, view_state, &mut element_state, cx);
447 ((), element_state)
448 });
449 } else {
450 self.element
451 .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
452 }
453 ElementRenderPhase::Painted
454 }
455
456 _ => panic!("must call layout before paint"),
457 };
458 }
459}
460
461pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
462
463impl<V: 'static + Send + Sync> AnyElement<V> {
464 pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
465 AnyElement(Box::new(RenderedElement::new(element)))
466 }
467
468 pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
469 self.0.initialize(view_state, cx);
470 }
471
472 pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
473 self.0.layout(view_state, cx)
474 }
475
476 pub fn paint(
477 &mut self,
478 view_state: &mut V,
479 offset: Option<Point<Pixels>>,
480 cx: &mut ViewContext<V>,
481 ) {
482 self.0.paint(view_state, offset, cx)
483 }
484}
485
486pub trait IntoAnyElement<V> {
487 fn into_any(self) -> AnyElement<V>;
488}
489
490impl<V> IntoAnyElement<V> for AnyElement<V> {
491 fn into_any(self) -> AnyElement<V> {
492 self
493 }
494}