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