1use crate::{
35 A11ySubtreeBuilder, App, ArenaBox, AvailableSpace, Bounds, Context, DispatchNodeId, ElementId,
36 FocusHandle, InspectorElementId, LayoutId, Pixels, Point, Size, Style, Window,
37 util::FluentBuilder, window::with_element_arena,
38};
39use derive_more::{Deref, DerefMut};
40use std::{
41 any::Any,
42 fmt::{self, Debug, Display},
43 mem, panic,
44 sync::Arc,
45};
46
47pub trait Element: 'static + IntoElement {
52 type RequestLayoutState: 'static;
55
56 type PrepaintState: 'static;
59
60 fn id(&self) -> Option<ElementId>;
66
67 fn source_location(&self) -> Option<&'static panic::Location<'static>>;
70
71 fn request_layout(
74 &mut self,
75 id: Option<&GlobalElementId>,
76 inspector_id: Option<&InspectorElementId>,
77 window: &mut Window,
78 cx: &mut App,
79 ) -> (LayoutId, Self::RequestLayoutState);
80
81 fn prepaint(
84 &mut self,
85 id: Option<&GlobalElementId>,
86 inspector_id: Option<&InspectorElementId>,
87 bounds: Bounds<Pixels>,
88 request_layout: &mut Self::RequestLayoutState,
89 window: &mut Window,
90 cx: &mut App,
91 ) -> Self::PrepaintState;
92
93 fn paint(
96 &mut self,
97 id: Option<&GlobalElementId>,
98 inspector_id: Option<&InspectorElementId>,
99 bounds: Bounds<Pixels>,
100 request_layout: &mut Self::RequestLayoutState,
101 prepaint: &mut Self::PrepaintState,
102 window: &mut Window,
103 cx: &mut App,
104 );
105
106 fn a11y_role(&self) -> Option<accesskit::Role> {
113 None
114 }
115
116 fn write_a11y_info(&self, _node: &mut accesskit::Node) {}
121
122 fn a11y_synthetic_children(
132 &mut self,
133 _prepaint: &mut Self::PrepaintState,
134 _builder: &mut A11ySubtreeBuilder,
135 ) {
136 }
137
138 fn into_any(self) -> AnyElement {
140 AnyElement::new(self)
141 }
142}
143
144pub trait IntoElement: Sized {
146 type Element: Element;
149
150 fn into_element(self) -> Self::Element;
152
153 fn into_any_element(self) -> AnyElement {
155 self.into_element().into_any()
156 }
157}
158
159impl<T: IntoElement> FluentBuilder for T {}
160
161pub trait Render: 'static + Sized {
164 fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement;
166}
167
168impl Render for Empty {
169 fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
170 Empty
171 }
172}
173
174pub trait RenderOnce: 'static {
180 fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement;
184}
185
186pub trait ParentElementTyped {
188 type Child;
190
191 fn extend(&mut self, elements: impl IntoIterator<Item = Self::Child>);
193
194 fn child(mut self, child: Self::Child) -> Self
196 where
197 Self: Sized,
198 {
199 self.extend(std::iter::once(child));
200 self
201 }
202
203 fn children(mut self, children: impl IntoIterator<Item = Self::Child>) -> Self
205 where
206 Self: Sized,
207 {
208 self.extend(children);
209 self
210 }
211}
212
213pub trait ParentElement {
216 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>);
218
219 fn child(mut self, child: impl IntoElement) -> Self
221 where
222 Self: Sized,
223 {
224 self.extend(std::iter::once(child.into_element().into_any()));
225 self
226 }
227
228 fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self
230 where
231 Self: Sized,
232 {
233 self.extend(children.into_iter().map(|child| child.into_any_element()));
234 self
235 }
236}
237
238#[derive(Deref, DerefMut, Clone, Default, Debug, Eq, PartialEq, Hash)]
240pub struct GlobalElementId(pub(crate) Arc<[ElementId]>);
241
242impl Display for GlobalElementId {
243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 for (i, element_id) in self.0.iter().enumerate() {
245 if i > 0 {
246 write!(f, ".")?;
247 }
248 write!(f, "{}", element_id)?;
249 }
250 Ok(())
251 }
252}
253
254impl GlobalElementId {
255 pub(crate) fn accesskit_node_id(&self) -> accesskit::NodeId {
256 use std::hash::{Hash, Hasher};
257 let mut hasher = std::hash::DefaultHasher::default();
258 self.hash(&mut hasher);
259 accesskit::NodeId(hasher.finish())
260 }
261}
262
263trait ElementObject {
264 fn inner_element(&mut self) -> &mut dyn Any;
265
266 fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId;
267
268 fn prepaint(&mut self, window: &mut Window, cx: &mut App);
269
270 fn paint(&mut self, window: &mut Window, cx: &mut App);
271
272 fn layout_as_root(
273 &mut self,
274 available_space: Size<AvailableSpace>,
275 window: &mut Window,
276 cx: &mut App,
277 ) -> Size<Pixels>;
278}
279
280pub struct Drawable<E: Element> {
282 pub element: E,
284 phase: ElementDrawPhase<E::RequestLayoutState, E::PrepaintState>,
285}
286
287#[derive(Default)]
288enum ElementDrawPhase<RequestLayoutState, PrepaintState> {
289 #[default]
290 Start,
291 RequestLayout {
292 layout_id: LayoutId,
293 global_id: Option<GlobalElementId>,
294 inspector_id: Option<InspectorElementId>,
295 request_layout: RequestLayoutState,
296 },
297 LayoutComputed {
298 layout_id: LayoutId,
299 global_id: Option<GlobalElementId>,
300 inspector_id: Option<InspectorElementId>,
301 available_space: Size<AvailableSpace>,
302 request_layout: RequestLayoutState,
303 },
304 Prepaint {
305 node_id: DispatchNodeId,
306 global_id: Option<GlobalElementId>,
307 inspector_id: Option<InspectorElementId>,
308 bounds: Bounds<Pixels>,
309 request_layout: RequestLayoutState,
310 prepaint: PrepaintState,
311 },
312 Painted,
313}
314
315impl<E: Element> Drawable<E> {
317 pub(crate) fn new(element: E) -> Self {
318 Drawable {
319 element,
320 phase: ElementDrawPhase::Start,
321 }
322 }
323
324 fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
325 match mem::take(&mut self.phase) {
326 ElementDrawPhase::Start => {
327 let global_id = self.element.id().map(|element_id| {
328 window.element_id_stack.push(element_id);
329 GlobalElementId(Arc::from(&*window.element_id_stack))
330 });
331
332 let inspector_id;
333 #[cfg(any(feature = "inspector", debug_assertions))]
334 {
335 inspector_id = self.element.source_location().map(|source| {
336 let path = crate::InspectorElementPath {
337 global_id: GlobalElementId(Arc::from(&*window.element_id_stack)),
338 source_location: source,
339 };
340 window.build_inspector_element_id(path)
341 });
342 }
343 #[cfg(not(any(feature = "inspector", debug_assertions)))]
344 {
345 inspector_id = None;
346 }
347
348 let (layout_id, request_layout) = self.element.request_layout(
349 global_id.as_ref(),
350 inspector_id.as_ref(),
351 window,
352 cx,
353 );
354
355 if global_id.is_some() {
356 window.element_id_stack.pop();
357 }
358
359 self.phase = ElementDrawPhase::RequestLayout {
360 layout_id,
361 global_id,
362 inspector_id,
363 request_layout,
364 };
365 layout_id
366 }
367 _ => panic!("must call request_layout only once"),
368 }
369 }
370
371 pub(crate) fn prepaint(&mut self, window: &mut Window, cx: &mut App) {
372 match mem::take(&mut self.phase) {
373 ElementDrawPhase::RequestLayout {
374 layout_id,
375 global_id,
376 inspector_id,
377 mut request_layout,
378 }
379 | ElementDrawPhase::LayoutComputed {
380 layout_id,
381 global_id,
382 inspector_id,
383 mut request_layout,
384 ..
385 } => {
386 if let Some(element_id) = self.element.id() {
387 window.element_id_stack.push(element_id);
388 debug_assert_eq!(&*global_id.as_ref().unwrap().0, &*window.element_id_stack);
389 }
390
391 let bounds = window.layout_bounds(layout_id);
392 let mut pushed_a11y_node = false;
393 if window.a11y.is_active() {
394 if let Some(global_id) = global_id.as_ref() {
395 if let Some(role) = self.element.a11y_role() {
396 let node_id = global_id.accesskit_node_id();
397 let mut node = accesskit::Node::new(role);
398 let scale = window.scale_factor();
399 node.set_bounds(accesskit::Rect {
400 x0: (bounds.origin.x.0 * scale) as f64,
401 y0: (bounds.origin.y.0 * scale) as f64,
402 x1: ((bounds.origin.x.0 + bounds.size.width.0) * scale) as f64,
403 y1: ((bounds.origin.y.0 + bounds.size.height.0) * scale) as f64,
404 });
405 self.element.write_a11y_info(&mut node);
406 window.a11y.node_bounds.insert(node_id, bounds);
407 pushed_a11y_node = window.a11y.nodes.push(node_id, node);
408 #[cfg(debug_assertions)]
409 if pushed_a11y_node {
410 let view = window
411 .a11y
412 .view_type_names
413 .get(&window.current_view())
414 .copied();
415 let source_location = self.element.source_location();
416 window.a11y.nodes.record_node_info(
417 node_id,
418 crate::window::a11y::debug::NodeDebugInfo {
419 synthetic: false,
420 view,
421 element_id: global_id.0.last().map(|id| format!("{id:?}")),
422 source_location,
423 },
424 );
425 }
426 }
427 }
428 }
429
430 let node_id = window.next_frame.dispatch_tree.push_node();
431 let mut prepaint = self.element.prepaint(
432 global_id.as_ref(),
433 inspector_id.as_ref(),
434 bounds,
435 &mut request_layout,
436 window,
437 cx,
438 );
439 window.next_frame.dispatch_tree.pop_node();
440
441 if pushed_a11y_node {
442 if let Some(global_id) = global_id.as_ref() {
443 #[cfg(debug_assertions)]
444 let creator = crate::window::a11y::debug::NodeCreator {
445 view: window
446 .a11y
447 .view_type_names
448 .get(&window.current_view())
449 .copied(),
450 element_id: global_id.0.last().map(|id| format!("{id:?}")),
451 source_location: self.element.source_location(),
452 };
453 let mut builder = A11ySubtreeBuilder::new(
454 global_id.accesskit_node_id(),
455 &mut window.a11y.nodes,
456 );
457 #[cfg(debug_assertions)]
458 {
459 builder = builder.with_creator(creator);
460 }
461 self.element
462 .a11y_synthetic_children(&mut prepaint, &mut builder);
463 }
464 window.a11y.nodes.pop();
465 }
466
467 if global_id.is_some() {
468 window.element_id_stack.pop();
469 }
470
471 self.phase = ElementDrawPhase::Prepaint {
472 node_id,
473 global_id,
474 inspector_id,
475 bounds,
476 request_layout,
477 prepaint,
478 };
479 }
480 _ => panic!("must call request_layout before prepaint"),
481 }
482 }
483
484 pub(crate) fn paint(
485 &mut self,
486 window: &mut Window,
487 cx: &mut App,
488 ) -> (E::RequestLayoutState, E::PrepaintState) {
489 match mem::take(&mut self.phase) {
490 ElementDrawPhase::Prepaint {
491 node_id,
492 global_id,
493 inspector_id,
494 bounds,
495 mut request_layout,
496 mut prepaint,
497 ..
498 } => {
499 if let Some(element_id) = self.element.id() {
500 window.element_id_stack.push(element_id);
501 debug_assert_eq!(&*global_id.as_ref().unwrap().0, &*window.element_id_stack);
502 }
503
504 window.next_frame.dispatch_tree.set_active_node(node_id);
505 self.element.paint(
506 global_id.as_ref(),
507 inspector_id.as_ref(),
508 bounds,
509 &mut request_layout,
510 &mut prepaint,
511 window,
512 cx,
513 );
514
515 if global_id.is_some() {
516 window.element_id_stack.pop();
517 }
518
519 self.phase = ElementDrawPhase::Painted;
520 (request_layout, prepaint)
521 }
522 _ => panic!("must call prepaint before paint"),
523 }
524 }
525
526 pub(crate) fn layout_as_root(
527 &mut self,
528 available_space: Size<AvailableSpace>,
529 window: &mut Window,
530 cx: &mut App,
531 ) -> Size<Pixels> {
532 if matches!(&self.phase, ElementDrawPhase::Start) {
533 self.request_layout(window, cx);
534 }
535
536 let layout_id = match mem::take(&mut self.phase) {
537 ElementDrawPhase::RequestLayout {
538 layout_id,
539 global_id,
540 inspector_id,
541 request_layout,
542 } => {
543 window.compute_layout(layout_id, available_space, cx);
544 self.phase = ElementDrawPhase::LayoutComputed {
545 layout_id,
546 global_id,
547 inspector_id,
548 available_space,
549 request_layout,
550 };
551 layout_id
552 }
553 ElementDrawPhase::LayoutComputed {
554 layout_id,
555 global_id,
556 inspector_id,
557 available_space: prev_available_space,
558 request_layout,
559 } => {
560 if available_space != prev_available_space {
561 window.compute_layout(layout_id, available_space, cx);
562 }
563 self.phase = ElementDrawPhase::LayoutComputed {
564 layout_id,
565 global_id,
566 inspector_id,
567 available_space,
568 request_layout,
569 };
570 layout_id
571 }
572 _ => panic!("cannot measure after painting"),
573 };
574
575 window.layout_bounds(layout_id).size
576 }
577}
578
579impl<E> ElementObject for Drawable<E>
580where
581 E: Element,
582 E::RequestLayoutState: 'static,
583{
584 fn inner_element(&mut self) -> &mut dyn Any {
585 &mut self.element
586 }
587
588 #[inline]
589 fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
590 Drawable::request_layout(self, window, cx)
591 }
592
593 #[inline]
594 fn prepaint(&mut self, window: &mut Window, cx: &mut App) {
595 Drawable::prepaint(self, window, cx);
596 }
597
598 #[inline]
599 fn paint(&mut self, window: &mut Window, cx: &mut App) {
600 Drawable::paint(self, window, cx);
601 }
602
603 #[inline]
604 fn layout_as_root(
605 &mut self,
606 available_space: Size<AvailableSpace>,
607 window: &mut Window,
608 cx: &mut App,
609 ) -> Size<Pixels> {
610 Drawable::layout_as_root(self, available_space, window, cx)
611 }
612}
613
614pub struct AnyElement(ArenaBox<dyn ElementObject>);
616
617impl AnyElement {
618 pub(crate) fn new<E>(element: E) -> Self
619 where
620 E: 'static + Element,
621 E::RequestLayoutState: Any,
622 {
623 let element = with_element_arena(|arena| arena.alloc(|| Drawable::new(element)))
624 .map(|element| element as &mut dyn ElementObject);
625 AnyElement(element)
626 }
627
628 pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
630 self.0.inner_element().downcast_mut::<T>()
631 }
632
633 pub fn request_layout(&mut self, window: &mut Window, cx: &mut App) -> LayoutId {
636 self.0.request_layout(window, cx)
637 }
638
639 pub fn prepaint(&mut self, window: &mut Window, cx: &mut App) -> Option<FocusHandle> {
642 let focus_assigned = window.next_frame.focus.is_some();
643
644 self.0.prepaint(window, cx);
645
646 if !focus_assigned && let Some(focus_id) = window.next_frame.focus {
647 return FocusHandle::for_id(focus_id, &cx.focus_handles);
648 }
649
650 None
651 }
652
653 pub fn paint(&mut self, window: &mut Window, cx: &mut App) {
655 self.0.paint(window, cx);
656 }
657
658 pub fn layout_as_root(
660 &mut self,
661 available_space: Size<AvailableSpace>,
662 window: &mut Window,
663 cx: &mut App,
664 ) -> Size<Pixels> {
665 self.0.layout_as_root(available_space, window, cx)
666 }
667
668 pub fn prepaint_at(
671 &mut self,
672 origin: Point<Pixels>,
673 window: &mut Window,
674 cx: &mut App,
675 ) -> Option<FocusHandle> {
676 window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx))
677 }
678
679 pub fn prepaint_as_root(
682 &mut self,
683 origin: Point<Pixels>,
684 available_space: Size<AvailableSpace>,
685 window: &mut Window,
686 cx: &mut App,
687 ) -> Option<FocusHandle> {
688 self.layout_as_root(available_space, window, cx);
689 window.with_absolute_element_offset(origin, |window| self.prepaint(window, cx))
690 }
691}
692
693impl Element for AnyElement {
694 type RequestLayoutState = ();
695 type PrepaintState = ();
696
697 fn id(&self) -> Option<ElementId> {
698 None
699 }
700
701 fn source_location(&self) -> Option<&'static panic::Location<'static>> {
702 None
703 }
704
705 fn request_layout(
706 &mut self,
707 _: Option<&GlobalElementId>,
708 _inspector_id: Option<&InspectorElementId>,
709 window: &mut Window,
710 cx: &mut App,
711 ) -> (LayoutId, Self::RequestLayoutState) {
712 let layout_id = self.request_layout(window, cx);
713 (layout_id, ())
714 }
715
716 fn prepaint(
717 &mut self,
718 _: Option<&GlobalElementId>,
719 _inspector_id: Option<&InspectorElementId>,
720 _: Bounds<Pixels>,
721 _: &mut Self::RequestLayoutState,
722 window: &mut Window,
723 cx: &mut App,
724 ) {
725 self.prepaint(window, cx);
726 }
727
728 fn paint(
729 &mut self,
730 _: Option<&GlobalElementId>,
731 _inspector_id: Option<&InspectorElementId>,
732 _: Bounds<Pixels>,
733 _: &mut Self::RequestLayoutState,
734 _: &mut Self::PrepaintState,
735 window: &mut Window,
736 cx: &mut App,
737 ) {
738 self.paint(window, cx);
739 }
740}
741
742impl IntoElement for AnyElement {
743 type Element = Self;
744
745 fn into_element(self) -> Self::Element {
746 self
747 }
748
749 fn into_any_element(self) -> AnyElement {
750 self
751 }
752}
753
754pub struct Empty;
756
757impl IntoElement for Empty {
758 type Element = Self;
759
760 fn into_element(self) -> Self::Element {
761 self
762 }
763}
764
765impl Element for Empty {
766 type RequestLayoutState = ();
767 type PrepaintState = ();
768
769 fn id(&self) -> Option<ElementId> {
770 None
771 }
772
773 fn source_location(&self) -> Option<&'static panic::Location<'static>> {
774 None
775 }
776
777 fn request_layout(
778 &mut self,
779 _id: Option<&GlobalElementId>,
780 _inspector_id: Option<&InspectorElementId>,
781 window: &mut Window,
782 cx: &mut App,
783 ) -> (LayoutId, Self::RequestLayoutState) {
784 (
785 window.request_layout(
786 Style {
787 display: crate::Display::None,
788 ..Default::default()
789 },
790 None,
791 cx,
792 ),
793 (),
794 )
795 }
796
797 fn prepaint(
798 &mut self,
799 _id: Option<&GlobalElementId>,
800 _inspector_id: Option<&InspectorElementId>,
801 _bounds: Bounds<Pixels>,
802 _state: &mut Self::RequestLayoutState,
803 _window: &mut Window,
804 _cx: &mut App,
805 ) {
806 }
807
808 fn paint(
809 &mut self,
810 _id: Option<&GlobalElementId>,
811 _inspector_id: Option<&InspectorElementId>,
812 _bounds: Bounds<Pixels>,
813 _request_layout: &mut Self::RequestLayoutState,
814 _prepaint: &mut Self::PrepaintState,
815 _window: &mut Window,
816 _cx: &mut App,
817 ) {
818 }
819}