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