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