1use std::any::{Any, TypeId};
10use std::cell::Cell;
11use std::fmt::{self, Debug, Display};
12use std::hash::{Hash, Hasher};
13use std::ops::Receiver;
14use std::rc::Rc;
15use std::time::Duration;
16
17use inset_animation::Curve;
18use inset_embedder::{Matrix4, Offset, Rect};
19use inset_foundation::{App, Handle, HandleId};
20use inset_services::MouseTrackerAnnotation;
21
22use crate::layer::{
23 AnyContainerLayer, AnyOffsetLayer, ErasedLayer, LayerHandle, OffsetLayer, OffsetLayerMixin,
24};
25use crate::painting_context::PaintingContext;
26use crate::pipeline_owner::PipelineOwner;
27
28thread_local! {
29 static DEBUG_ACTIVE_LAYOUT: Cell<Option<AnyRenderObject>> = const { Cell::new(None) };
30 static DEBUG_ACTIVE_PAINT: Cell<Option<AnyRenderObject>> = const { Cell::new(None) };
31 static DEBUG_CHECKING_INTRINSICS: Cell<bool> = const { Cell::new(false) };
32}
33
34pub fn debug_checking_intrinsics() -> bool {
40 DEBUG_CHECKING_INTRINSICS.get()
41}
42
43pub fn set_debug_checking_intrinsics(value: bool) {
45 DEBUG_CHECKING_INTRINSICS.set(value);
46}
47
48pub trait Constraints {
52 fn is_tight(&self) -> bool;
54
55 fn is_normalized(&self) -> bool;
57
58 fn debug_assert_is_valid(&self, is_applied_constraint: bool) -> bool {
63 let _ = is_applied_constraint;
64 debug_assert!(self.is_normalized());
65 self.is_normalized()
66 }
67}
68
69pub trait ParentData: Any + Debug + Display {
74 fn detach(&mut self) {}
76
77 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
84 let _ = id;
85 None
86 }
87
88 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
90 let _ = id;
91 None
92 }
93}
94
95impl dyn ParentData {
96 pub fn part<P: 'static>(&self) -> Option<&P> {
98 self.provide(TypeId::of::<P>())?.downcast_ref()
99 }
100
101 pub fn part_mut<P: 'static>(&mut self) -> Option<&mut P> {
103 self.provide_mut(TypeId::of::<P>())?.downcast_mut()
104 }
105}
106
107#[derive(Debug, Default)]
109pub struct EmptyParentData;
110
111impl ParentData for EmptyParentData {}
112
113impl Display for EmptyParentData {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 f.write_str("<none>")
116 }
117}
118
119pub struct RenderObjectData {
121 pub(crate) object_vtable: Option<&'static RenderObjectVTable>,
125 pub(crate) parent: Option<AnyRenderObject>,
126 pub(crate) owner: Option<Handle<PipelineOwner>>,
127 pub(crate) depth: i32,
128 pub(crate) parent_data: Option<Box<dyn ParentData>>,
129 pub(crate) needs_layout: bool,
130 pub(crate) needs_paint: bool,
131 pub(crate) needs_composited_layer_update: bool,
132 pub(crate) needs_compositing_bits_update: bool,
133 pub(crate) needs_compositing: bool,
134 pub(crate) was_repaint_boundary: bool,
135 pub(crate) layer: LayerHandle<AnyContainerLayer>,
137 pub(crate) is_relayout_boundary: Option<bool>,
138 pub(crate) doing_this_layout_with_callback: bool,
139 pub(crate) debug_doing_this_layout: bool,
140 pub(crate) debug_doing_this_resize: bool,
141 pub(crate) debug_doing_this_paint: bool,
142 pub(crate) debug_can_parent_use_size: Option<bool>,
143 pub(crate) debug_mutations_locked: bool,
144}
145
146impl RenderObjectData {
147 pub fn new() -> RenderObjectData {
149 RenderObjectData {
150 object_vtable: None,
151 parent: None,
152 owner: None,
153 depth: 0,
154 parent_data: None,
155 needs_layout: true,
156 needs_paint: true,
157 needs_composited_layer_update: false,
158 needs_compositing_bits_update: false,
159 needs_compositing: false,
160 was_repaint_boundary: false,
161 layer: LayerHandle::new(),
162 is_relayout_boundary: None,
163 doing_this_layout_with_callback: false,
164 debug_doing_this_layout: false,
165 debug_doing_this_resize: false,
166 debug_doing_this_paint: false,
167 debug_can_parent_use_size: None,
168 debug_mutations_locked: false,
169 }
170 }
171}
172
173impl Default for RenderObjectData {
174 fn default() -> RenderObjectData {
175 RenderObjectData::new()
176 }
177}
178
179pub struct RenderObjectWithChildData<C> {
181 pub(crate) child: Option<C>,
182}
183
184impl<C> RenderObjectWithChildData<C> {
185 pub const fn new() -> RenderObjectWithChildData<C> {
187 RenderObjectWithChildData { child: None }
188 }
189}
190
191impl<C> Default for RenderObjectWithChildData<C> {
192 fn default() -> RenderObjectWithChildData<C> {
193 RenderObjectWithChildData::new()
194 }
195}
196
197#[derive(Debug)]
199pub struct ContainerParentData<ChildType> {
200 pub(crate) previous_sibling: Option<ChildType>,
201 pub(crate) next_sibling: Option<ChildType>,
202}
203
204impl<ChildType> ContainerParentData<ChildType> {
205 pub const fn new() -> ContainerParentData<ChildType> {
207 ContainerParentData {
208 previous_sibling: None,
209 next_sibling: None,
210 }
211 }
212}
213
214impl<ChildType> Default for ContainerParentData<ChildType> {
215 fn default() -> ContainerParentData<ChildType> {
216 ContainerParentData::new()
217 }
218}
219
220pub trait ContainerParentDataMixin: ParentData {
229 type ChildType: Copy + PartialEq;
231
232 fn container_parent_data(&self) -> &ContainerParentData<Self::ChildType>;
234
235 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<Self::ChildType>;
237
238 fn previous_sibling(&self) -> Option<Self::ChildType> {
240 self.container_parent_data().previous_sibling
241 }
242
243 fn set_previous_sibling(&mut self, value: Option<Self::ChildType>) {
245 self.container_parent_data_mut().previous_sibling = value;
246 }
247
248 fn next_sibling(&self) -> Option<Self::ChildType> {
250 self.container_parent_data().next_sibling
251 }
252
253 fn set_next_sibling(&mut self, value: Option<Self::ChildType>) {
255 self.container_parent_data_mut().next_sibling = value;
256 }
257
258 fn detach(&mut self) {
262 debug_assert!(
263 self.previous_sibling().is_none(),
264 "Pointers to siblings must be nulled before detaching ParentData."
265 );
266 debug_assert!(
267 self.next_sibling().is_none(),
268 "Pointers to siblings must be nulled before detaching ParentData."
269 );
270 }
271}
272
273pub struct ContainerRenderObjectData<ChildType> {
276 pub(crate) child_count: usize,
277 pub(crate) first_child: Option<ChildType>,
278 pub(crate) last_child: Option<ChildType>,
279}
280
281impl<ChildType> ContainerRenderObjectData<ChildType> {
282 pub const fn new() -> ContainerRenderObjectData<ChildType> {
284 ContainerRenderObjectData {
285 child_count: 0,
286 first_child: None,
287 last_child: None,
288 }
289 }
290}
291
292impl<ChildType> Default for ContainerRenderObjectData<ChildType> {
293 fn default() -> ContainerRenderObjectData<ChildType> {
294 ContainerRenderObjectData::new()
295 }
296}
297
298pub trait ErasedRenderObject: Copy + PartialEq + Debug + 'static {
303 fn as_object(self) -> AnyRenderObject;
305
306 fn from_object(object: AnyRenderObject) -> Self;
312}
313
314pub trait RenderObjectWithChildMixin: RenderObject {
319 type ChildType: ErasedRenderObject;
321
322 fn child_data(
324 self: RenderHandle<Self>,
325 app: &App,
326 ) -> &RenderObjectWithChildData<Self::ChildType>;
327
328 fn child_data_mut(
330 self: RenderHandle<Self>,
331 app: &mut App,
332 ) -> &mut RenderObjectWithChildData<Self::ChildType>;
333
334 fn child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
336 self.child_data(app).child
337 }
338
339 fn set_child(self: RenderHandle<Self>, app: &mut App, value: Option<Self::ChildType>) {
341 if let Some(old) = self.child(app) {
342 self.as_render_object(app).drop_child(app, old.as_object());
343 }
344 self.child_data_mut(app).child = value;
345 if let Some(new) = value {
346 self.as_render_object(app).adopt_child(app, new.as_object());
347 }
348 }
349}
350
351pub trait ContainerRenderObjectMixin: RenderObject {
364 type ChildType: ErasedRenderObject;
366
367 type ParentDataType: ContainerParentDataMixin<ChildType = Self::ChildType> + 'static;
369
370 fn container_data(
372 self: RenderHandle<Self>,
373 app: &App,
374 ) -> &ContainerRenderObjectData<Self::ChildType>;
375
376 fn container_data_mut(
378 self: RenderHandle<Self>,
379 app: &mut App,
380 ) -> &mut ContainerRenderObjectData<Self::ChildType>;
381
382 fn child_count(self: RenderHandle<Self>, app: &App) -> usize {
384 self.container_data(app).child_count
385 }
386
387 fn insert(
392 self: RenderHandle<Self>,
393 app: &mut App,
394 child: Self::ChildType,
395 after: Option<Self::ChildType>,
396 ) {
397 ContainerRenderObjectBase::insert(self, app, child, after)
398 }
399
400 fn add(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
402 let last_child = self.last_child(app);
403 self.insert(app, child, last_child);
404 }
405
406 fn add_all(self: RenderHandle<Self>, app: &mut App, children: Option<Vec<Self::ChildType>>) {
408 for child in children.into_iter().flatten() {
409 self.add(app, child);
410 }
411 }
412
413 fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
417 ContainerRenderObjectBase::remove(self, app, child)
418 }
419
420 fn remove_all(self: RenderHandle<Self>, app: &mut App) {
424 ContainerRenderObjectBase::remove_all(self, app)
425 }
426
427 fn move_child(
433 self: RenderHandle<Self>,
434 app: &mut App,
435 child: Self::ChildType,
436 after: Option<Self::ChildType>,
437 ) {
438 ContainerRenderObjectBase::move_child(self, app, child, after)
439 }
440
441 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
443 let mut child = self.first_child(app);
444 while let Some(current) = child {
445 current.as_object().attach(app, owner);
446 child = current
447 .as_object()
448 .parent_data_of::<Self::ParentDataType>(app)
449 .next_sibling();
450 }
451 }
452
453 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
455 let mut child = self.first_child(app);
456 while let Some(current) = child {
457 current.as_object().detach(app);
458 child = current
459 .as_object()
460 .parent_data_of::<Self::ParentDataType>(app)
461 .next_sibling();
462 }
463 }
464
465 fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
467 let mut child = self.first_child(app);
468 while let Some(current) = child {
469 self.as_render_object(app)
470 .redepth_child(app, current.as_object());
471 child = current
472 .as_object()
473 .parent_data_of::<Self::ParentDataType>(app)
474 .next_sibling();
475 }
476 }
477
478 fn visit_children(
480 self: RenderHandle<Self>,
481 app: &App,
482 visitor: &mut dyn FnMut(AnyRenderObject),
483 ) {
484 let mut child = self.first_child(app);
485 while let Some(current) = child {
486 visitor(current.as_object());
487 child = current
488 .as_object()
489 .parent_data_of::<Self::ParentDataType>(app)
490 .next_sibling();
491 }
492 }
493
494 fn first_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
496 self.container_data(app).first_child
497 }
498
499 fn last_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
501 self.container_data(app).last_child
502 }
503
504 fn child_before(
506 self: RenderHandle<Self>,
507 app: &App,
508 child: Self::ChildType,
509 ) -> Option<Self::ChildType> {
510 debug_assert_eq!(
511 child.as_object().parent(app),
512 Some(self.as_render_object(app))
513 );
514 child
515 .as_object()
516 .parent_data_of::<Self::ParentDataType>(app)
517 .previous_sibling()
518 }
519
520 fn child_after(
522 self: RenderHandle<Self>,
523 app: &App,
524 child: Self::ChildType,
525 ) -> Option<Self::ChildType> {
526 debug_assert_eq!(
527 child.as_object().parent(app),
528 Some(self.as_render_object(app))
529 );
530 child
531 .as_object()
532 .parent_data_of::<Self::ParentDataType>(app)
533 .next_sibling()
534 }
535
536 fn children_as_list(self: RenderHandle<Self>, app: &App) -> Vec<Self::ChildType> {
540 let mut result = Vec::new();
541 let mut child = self.first_child(app);
542 while let Some(current) = child {
543 result.push(current);
544 child = current
545 .as_object()
546 .parent_data_of::<Self::ParentDataType>(app)
547 .next_sibling();
548 }
549 result
550 }
551}
552
553pub trait ContainerRenderObjectBase: ContainerRenderObjectMixin {
558 fn insert(
560 self: RenderHandle<Self>,
561 app: &mut App,
562 child: Self::ChildType,
563 after: Option<Self::ChildType>,
564 ) {
565 debug_assert!(
566 child.as_object() != self.as_render_object(app),
567 "A RenderObject cannot be inserted into itself."
568 );
569 debug_assert!(
570 after.is_none_or(|after| after.as_object() != self.as_render_object(app)),
571 "A RenderObject cannot simultaneously be both the parent and the sibling of another \
572 RenderObject."
573 );
574 debug_assert!(
575 after != Some(child),
576 "A RenderObject cannot be inserted after itself."
577 );
578 debug_assert!(Some(child) != self.first_child(app));
579 debug_assert!(Some(child) != self.last_child(app));
580 self.as_render_object(app)
581 .adopt_child(app, child.as_object());
582 debug_assert!(
583 child
584 .as_object()
585 .parent_data_is::<Self::ParentDataType>(app),
586 "A child has parent data that does not conform to this render object's \
587 ParentDataType. Override setup_parent_data to install it."
588 );
589 insert_into_child_list(self, app, child, after);
590 }
591
592 fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
594 remove_from_child_list(self, app, child);
595 self.as_render_object(app)
596 .drop_child(app, child.as_object());
597 }
598
599 fn remove_all(self: RenderHandle<Self>, app: &mut App) {
601 let mut child = self.first_child(app);
602 while let Some(current) = child {
603 let child_parent_data = current
604 .as_object()
605 .parent_data_of_mut::<Self::ParentDataType>(app);
606 let next = child_parent_data.next_sibling();
607 child_parent_data.set_previous_sibling(None);
608 child_parent_data.set_next_sibling(None);
609 self.as_render_object(app)
610 .drop_child(app, current.as_object());
611 child = next;
612 }
613 let container = self.container_data_mut(app);
614 container.first_child = None;
615 container.last_child = None;
616 container.child_count = 0;
617 }
618
619 fn move_child(
621 self: RenderHandle<Self>,
622 app: &mut App,
623 child: Self::ChildType,
624 after: Option<Self::ChildType>,
625 ) {
626 debug_assert!(child.as_object() != self.as_render_object(app));
627 debug_assert!(after.is_none_or(|after| after.as_object() != self.as_render_object(app)));
628 debug_assert!(after != Some(child));
629 debug_assert_eq!(
630 child.as_object().parent(app),
631 Some(self.as_render_object(app)),
632 "the child must already be a child of this render object"
633 );
634 if child
635 .as_object()
636 .parent_data_of::<Self::ParentDataType>(app)
637 .previous_sibling()
638 == after
639 {
640 return;
641 }
642 remove_from_child_list(self, app, child);
643 insert_into_child_list(self, app, child, after);
644 self.as_render_object(app).mark_needs_layout(app);
645 }
646}
647
648impl<T: ContainerRenderObjectMixin> ContainerRenderObjectBase for T {}
649
650fn debug_ultimate_previous_sibling_of<P>(
652 app: &App,
653 child: P::ChildType,
654 equals: Option<P::ChildType>,
655) -> bool
656where
657 P: ContainerParentDataMixin + 'static,
658 P::ChildType: ErasedRenderObject,
659{
660 let mut child = child;
661 while let Some(previous) = child
662 .as_object()
663 .parent_data_of::<P>(app)
664 .previous_sibling()
665 {
666 debug_assert!(previous != child);
667 child = previous;
668 }
669 Some(child) == equals
670}
671
672fn debug_ultimate_next_sibling_of<P>(
674 app: &App,
675 child: P::ChildType,
676 equals: Option<P::ChildType>,
677) -> bool
678where
679 P: ContainerParentDataMixin + 'static,
680 P::ChildType: ErasedRenderObject,
681{
682 let mut child = child;
683 while let Some(next) = child.as_object().parent_data_of::<P>(app).next_sibling() {
684 debug_assert!(next != child);
685 child = next;
686 }
687 Some(child) == equals
688}
689
690fn insert_into_child_list<T: ContainerRenderObjectMixin>(
692 this: RenderHandle<T>,
693 app: &mut App,
694 child: T::ChildType,
695 after: Option<T::ChildType>,
696) {
697 type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
698
699 debug_assert!(
700 child
701 .as_object()
702 .parent_data_of::<ParentDataOf<T>>(app)
703 .next_sibling()
704 .is_none()
705 );
706 debug_assert!(
707 child
708 .as_object()
709 .parent_data_of::<ParentDataOf<T>>(app)
710 .previous_sibling()
711 .is_none()
712 );
713 this.container_data_mut(app).child_count += 1;
714 let Some(after) = after else {
715 let first_child = this.first_child(app);
717 child
718 .as_object()
719 .parent_data_of_mut::<ParentDataOf<T>>(app)
720 .set_next_sibling(first_child);
721 if let Some(first_child) = first_child {
722 first_child
723 .as_object()
724 .parent_data_of_mut::<ParentDataOf<T>>(app)
725 .set_previous_sibling(Some(child));
726 }
727 let container = this.container_data_mut(app);
728 container.first_child = Some(child);
729 container.last_child.get_or_insert(child);
730 return;
731 };
732 debug_assert!(this.first_child(app).is_some());
733 debug_assert!(this.last_child(app).is_some());
734 debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
735 app,
736 after,
737 this.first_child(app)
738 ));
739 debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
740 app,
741 after,
742 this.last_child(app)
743 ));
744 let after_next_sibling = after
745 .as_object()
746 .parent_data_of::<ParentDataOf<T>>(app)
747 .next_sibling();
748 let Some(after_next_sibling) = after_next_sibling else {
749 debug_assert_eq!(Some(after), this.last_child(app));
751 child
752 .as_object()
753 .parent_data_of_mut::<ParentDataOf<T>>(app)
754 .set_previous_sibling(Some(after));
755 after
756 .as_object()
757 .parent_data_of_mut::<ParentDataOf<T>>(app)
758 .set_next_sibling(Some(child));
759 this.container_data_mut(app).last_child = Some(child);
760 return;
761 };
762 let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
765 child_parent_data.set_next_sibling(Some(after_next_sibling));
766 child_parent_data.set_previous_sibling(Some(after));
767 after
769 .as_object()
770 .parent_data_of_mut::<ParentDataOf<T>>(app)
771 .set_next_sibling(Some(child));
772 after_next_sibling
773 .as_object()
774 .parent_data_of_mut::<ParentDataOf<T>>(app)
775 .set_previous_sibling(Some(child));
776}
777
778fn remove_from_child_list<T: ContainerRenderObjectMixin>(
780 this: RenderHandle<T>,
781 app: &mut App,
782 child: T::ChildType,
783) {
784 type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
785
786 debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
787 app,
788 child,
789 this.first_child(app)
790 ));
791 debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
792 app,
793 child,
794 this.last_child(app)
795 ));
796 let child_parent_data = child.as_object().parent_data_of::<ParentDataOf<T>>(app);
797 let (previous_sibling, next_sibling) = (
798 child_parent_data.previous_sibling(),
799 child_parent_data.next_sibling(),
800 );
801 match previous_sibling {
802 None => {
803 debug_assert_eq!(this.first_child(app), Some(child));
804 this.container_data_mut(app).first_child = next_sibling;
805 }
806 Some(previous_sibling) => previous_sibling
807 .as_object()
808 .parent_data_of_mut::<ParentDataOf<T>>(app)
809 .set_next_sibling(next_sibling),
810 }
811 match next_sibling {
812 None => {
813 debug_assert_eq!(this.last_child(app), Some(child));
814 this.container_data_mut(app).last_child = previous_sibling;
815 }
816 Some(next_sibling) => next_sibling
817 .as_object()
818 .parent_data_of_mut::<ParentDataOf<T>>(app)
819 .set_previous_sibling(previous_sibling),
820 }
821 let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
822 child_parent_data.set_previous_sibling(None);
823 child_parent_data.set_next_sibling(None);
824 this.container_data_mut(app).child_count -= 1;
825}
826
827pub trait RenderObject: 'static + Sized {
834 fn render_object_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectData;
836
837 fn render_object_data_mut(self: RenderHandle<Self>, app: &mut App) -> &mut RenderObjectData;
839
840 fn as_render_object(self: RenderHandle<Self>, app: &App) -> AnyRenderObject {
843 let vtable = self
844 .render_object_data(app)
845 .object_vtable
846 .expect("a render object records its vtable when the protocol creates it");
847 AnyRenderObject::from_vtable(self.id(), vtable)
848 }
849
850 fn perform_layout(self: RenderHandle<Self>, app: &mut App);
855
856 fn perform_resize(self: RenderHandle<Self>, _app: &mut App) {
863 let _ = self;
864 panic!("RenderObject::perform_resize was called; override it when sized_by_parent is true")
865 }
866
867 fn visit_children(
869 self: RenderHandle<Self>,
870 app: &App,
871 visitor: &mut dyn FnMut(AnyRenderObject),
872 ) {
873 let _ = (self, app, visitor);
874 }
875
876 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
881 if child.parent_data(app).is_none() {
882 child.set_parent_data(app, EmptyParentData);
883 }
884 }
885
886 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
890 for child in collect_children(app, self) {
891 child.attach(app, owner);
892 }
893 }
894
895 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
898 for child in collect_children(app, self) {
899 child.detach(app);
900 }
901 }
902
903 fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
905 let depth = self.render_object_data(app).depth;
906 let owner = self.render_object_data(app).owner;
907 for child in collect_children(app, self) {
908 debug_assert_eq!(child.owner(app), owner);
909 child.redepth_below(app, depth);
910 }
911 }
912
913 fn sized_by_parent(self: RenderHandle<Self>, _app: &App) -> bool {
915 let _ = self;
916 false
917 }
918
919 fn apply_paint_transform(
935 self: RenderHandle<Self>,
936 app: &App,
937 child: AnyRenderObject,
938 transform: &mut Matrix4,
939 ) {
940 let _ = transform;
941 debug_assert!(child.parent(app).map(AnyRenderObject::id) == Some(self.id()));
942 }
943
944 fn is_repaint_boundary(self: RenderHandle<Self>, _app: &App) -> bool {
961 let _ = self;
962 false
963 }
964
965 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
975 let _ = self;
976 false
977 }
978
979 fn mouse_tracker_annotation(
983 self: RenderHandle<Self>,
984 _app: &App,
985 ) -> Option<MouseTrackerAnnotation> {
986 let _ = self;
987 None
988 }
989
990 fn update_composited_layer(
1011 self: RenderHandle<Self>,
1012 app: &mut App,
1013 old_layer: Option<AnyOffsetLayer>,
1014 ) -> AnyOffsetLayer {
1015 debug_assert!(self.is_repaint_boundary(app));
1016 old_layer.unwrap_or_else(|| OffsetLayer::new(app, Offset::ZERO).as_offset_layer())
1017 }
1018
1019 fn show_on_screen(
1038 self: RenderHandle<Self>,
1039 app: &mut App,
1040 descendant: Option<AnyRenderObject>,
1041 rect: Option<Rect>,
1042 duration: Duration,
1043 curve: Rc<dyn Curve>,
1044 ) {
1045 RenderObjectBase::show_on_screen(self, app, descendant, rect, duration, curve)
1046 }
1047
1048 fn interface(self: RenderHandle<Self>, id: TypeId) -> Option<Box<dyn Any>> {
1054 let _ = (self, id);
1055 None
1056 }
1057
1058 fn dispose(self: RenderHandle<Self>, app: &mut App) {
1072 RenderObjectBase::dispose(self, app);
1073 }
1074
1075 fn paint(
1081 self: RenderHandle<Self>,
1082 app: &mut App,
1083 context: &mut PaintingContext,
1084 offset: Offset,
1085 ) {
1086 let _ = (self, app, context, offset);
1087 }
1088}
1089
1090fn collect_children<T: RenderObject>(app: &App, this: RenderHandle<T>) -> Vec<AnyRenderObject> {
1091 let mut children = Vec::new();
1092 this.visit_children(app, &mut |child| children.push(child));
1093 children
1094}
1095
1096#[macro_export]
1098macro_rules! render_object_accessors {
1099 () => {
1100 fn render_object_data(
1101 self: $crate::RenderHandle<Self>,
1102 app: &::inset_foundation::App,
1103 ) -> &$crate::RenderObjectData {
1104 &self.get(app).render_object
1105 }
1106 fn render_object_data_mut(
1107 self: $crate::RenderHandle<Self>,
1108 app: &mut ::inset_foundation::App,
1109 ) -> &mut $crate::RenderObjectData {
1110 &mut self.get_mut(app).render_object
1111 }
1112 };
1113}
1114
1115pub struct RenderHandle<T>(Handle<T>);
1120
1121impl<T> Clone for RenderHandle<T> {
1122 fn clone(&self) -> RenderHandle<T> {
1123 *self
1124 }
1125}
1126
1127impl<T> Copy for RenderHandle<T> {}
1128
1129impl<T> Receiver for RenderHandle<T> {
1130 type Target = T;
1131}
1132
1133impl<T> PartialEq for RenderHandle<T> {
1134 fn eq(&self, other: &RenderHandle<T>) -> bool {
1135 self.0 == other.0
1136 }
1137}
1138
1139impl<T> Eq for RenderHandle<T> {}
1140
1141impl<T> Hash for RenderHandle<T> {
1142 fn hash<H: Hasher>(&self, state: &mut H) {
1143 self.0.hash(state);
1144 }
1145}
1146
1147impl<T> Debug for RenderHandle<T> {
1148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1149 write!(
1150 f,
1151 "RenderHandle<{}>({:?})",
1152 std::any::type_name::<T>(),
1153 self.0.id()
1154 )
1155 }
1156}
1157
1158impl<T: 'static> RenderHandle<T> {
1159 pub fn get(self, app: &App) -> &T {
1161 app.get(self.0)
1162 }
1163
1164 pub fn get_mut(self, app: &mut App) -> &mut T {
1166 app.get_mut(self.0)
1167 }
1168
1169 pub(crate) fn id(self) -> HandleId {
1170 self.0.id()
1171 }
1172
1173 pub fn handle(self) -> Handle<T> {
1175 self.0
1176 }
1177
1178 pub fn from_handle(handle: Handle<T>) -> RenderHandle<T> {
1180 RenderHandle(handle)
1181 }
1182}
1183
1184pub(crate) fn resolve<T: 'static>(id: HandleId) -> RenderHandle<T> {
1186 RenderHandle(Handle::from_id(id))
1187}
1188
1189pub(crate) fn create<T: 'static>(app: &mut App, object: T) -> RenderHandle<T> {
1190 RenderHandle(app.create(object))
1191}
1192
1193pub(crate) type ShowOnScreenFn =
1195 fn(&mut App, HandleId, Option<AnyRenderObject>, Option<Rect>, Duration, Rc<dyn Curve>);
1196
1197pub(crate) struct RenderObjectVTable {
1201 pub object_data: fn(&App, HandleId) -> &RenderObjectData,
1202 pub object_data_mut: fn(&mut App, HandleId) -> &mut RenderObjectData,
1203 pub visit_children: fn(&App, HandleId, &mut dyn FnMut(AnyRenderObject)),
1204 pub did_attach: fn(&mut App, HandleId, Handle<PipelineOwner>),
1205 pub did_detach: fn(&mut App, HandleId),
1206 pub redepth_children: fn(&mut App, HandleId),
1207 pub setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1208 pub sized_by_parent: fn(&App, HandleId) -> bool,
1209 pub perform_layout: fn(&mut App, HandleId),
1210 pub perform_resize: fn(&mut App, HandleId),
1211 pub mark_needs_layout: fn(&mut App, HandleId),
1212 pub paint_bounds: fn(&App, HandleId) -> Rect,
1213 pub apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1214 pub is_repaint_boundary: fn(&App, HandleId) -> bool,
1215 pub always_needs_compositing: fn(&App, HandleId) -> bool,
1216 pub mouse_tracker_annotation: fn(&App, HandleId) -> Option<MouseTrackerAnnotation>,
1217 pub update_composited_layer: fn(&mut App, HandleId, Option<AnyOffsetLayer>) -> AnyOffsetLayer,
1218 pub show_on_screen: ShowOnScreenFn,
1219 pub interface: fn(HandleId, TypeId) -> Option<Box<dyn Any>>,
1220 pub paint: fn(&mut App, HandleId, &mut PaintingContext, Offset),
1221 pub dispose: fn(&mut App, HandleId),
1222 pub as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1224 pub as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1225}
1226
1227impl RenderObjectVTable {
1228 pub(crate) const fn of<T: RenderObject>(
1232 setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1233 paint_bounds: fn(&App, HandleId) -> Rect,
1234 apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1235 perform_resize: fn(&mut App, HandleId),
1236 mark_needs_layout: fn(&mut App, HandleId),
1237 as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1238 as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1239 ) -> RenderObjectVTable {
1240 RenderObjectVTable {
1241 object_data: |app, id| T::render_object_data(resolve(id), app),
1242 object_data_mut: |app, id| T::render_object_data_mut(resolve(id), app),
1243 visit_children: |app, id, visitor| T::visit_children(resolve(id), app, visitor),
1244 did_attach: |app, id, owner| T::did_attach(resolve(id), app, owner),
1245 did_detach: |app, id| T::did_detach(resolve(id), app),
1246 redepth_children: |app, id| T::redepth_children(resolve(id), app),
1247 setup_parent_data,
1248 sized_by_parent: |app, id| T::sized_by_parent(resolve(id), app),
1249 perform_layout: |app, id| T::perform_layout(resolve(id), app),
1250 perform_resize,
1251 mark_needs_layout,
1252 paint_bounds,
1253 apply_paint_transform,
1254 is_repaint_boundary: |app, id| T::is_repaint_boundary(resolve(id), app),
1255 always_needs_compositing: |app, id| T::always_needs_compositing(resolve(id), app),
1256 mouse_tracker_annotation: |app, id| T::mouse_tracker_annotation(resolve(id), app),
1257 update_composited_layer: |app, id, old_layer| {
1258 T::update_composited_layer(resolve(id), app, old_layer)
1259 },
1260 show_on_screen: |app, id, descendant, rect, duration, curve| {
1261 T::show_on_screen(resolve(id), app, descendant, rect, duration, curve)
1262 },
1263 interface: |id, interface| T::interface(resolve(id), interface),
1264 paint: |app, id, context, offset| T::paint(resolve(id), app, context, offset),
1265 dispose: |app, id| T::dispose(resolve(id), app),
1266 as_box,
1267 as_sliver,
1268 }
1269 }
1270}
1271
1272#[derive(Clone, Copy)]
1277pub struct AnyRenderObject {
1278 id: HandleId,
1279 vtable: &'static RenderObjectVTable,
1280}
1281
1282impl PartialEq for AnyRenderObject {
1283 fn eq(&self, other: &AnyRenderObject) -> bool {
1284 self.id == other.id
1285 }
1286}
1287
1288impl Eq for AnyRenderObject {}
1289
1290impl Hash for AnyRenderObject {
1291 fn hash<H: Hasher>(&self, state: &mut H) {
1292 self.id.hash(state);
1293 }
1294}
1295
1296impl From<AnyRenderObject> for HandleId {
1297 fn from(object: AnyRenderObject) -> HandleId {
1298 object.id
1299 }
1300}
1301
1302impl Debug for AnyRenderObject {
1303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1304 write!(f, "AnyRenderObject({:?})", self.id)
1305 }
1306}
1307
1308impl AnyRenderObject {
1309 pub(crate) fn from_vtable(
1310 id: HandleId,
1311 vtable: &'static RenderObjectVTable,
1312 ) -> AnyRenderObject {
1313 AnyRenderObject { id, vtable }
1314 }
1315
1316 pub fn as_box(self) -> Option<crate::box_::AnyRenderBox> {
1318 self.vtable
1319 .as_box
1320 .map(|vtable| crate::box_::AnyRenderBox::from_vtable(self.id, vtable()))
1321 }
1322
1323 pub fn as_sliver(self) -> Option<crate::sliver::AnyRenderSliver> {
1325 self.vtable
1326 .as_sliver
1327 .map(|vtable| crate::sliver::AnyRenderSliver::from_vtable(self.id, vtable()))
1328 }
1329
1330 pub fn debug_active_layout() -> Option<AnyRenderObject> {
1334 DEBUG_ACTIVE_LAYOUT.get()
1335 }
1336
1337 pub(crate) fn set_debug_active_layout(node: Option<AnyRenderObject>) {
1338 DEBUG_ACTIVE_LAYOUT.set(node);
1339 }
1340
1341 pub fn debug_active_paint() -> Option<AnyRenderObject> {
1345 DEBUG_ACTIVE_PAINT.get()
1346 }
1347
1348 fn data(self, app: &App) -> &RenderObjectData {
1349 (self.vtable.object_data)(app, self.id)
1350 }
1351
1352 pub(crate) fn data_mut(self, app: &mut App) -> &mut RenderObjectData {
1353 (self.vtable.object_data_mut)(app, self.id)
1354 }
1355
1356 pub fn parent_data(self, app: &App) -> Option<&dyn ParentData> {
1358 self.data(app).parent_data.as_deref()
1359 }
1360
1361 pub fn parent_data_mut(self, app: &mut App) -> Option<&mut dyn ParentData> {
1363 self.data_mut(app).parent_data.as_deref_mut()
1364 }
1365
1366 pub fn parent_data_is<P: ParentData + 'static>(self, app: &App) -> bool {
1368 self.parent_data(app)
1369 .is_some_and(|data| (data as &dyn Any).is::<P>())
1370 }
1371
1372 pub fn parent_data_of<P: ParentData + 'static>(self, app: &App) -> &P {
1378 self.parent_data(app)
1379 .and_then(|data| (data as &dyn Any).downcast_ref::<P>())
1380 .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1381 }
1382
1383 pub fn parent_data_of_mut<P: ParentData + 'static>(self, app: &mut App) -> &mut P {
1385 self.parent_data_mut(app)
1386 .and_then(|data| (data as &mut dyn Any).downcast_mut::<P>())
1387 .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1388 }
1389
1390 pub fn set_parent_data(self, app: &mut App, parent_data: impl ParentData + 'static) {
1392 self.data_mut(app).parent_data = Some(Box::new(parent_data));
1393 }
1394
1395 fn clear_parent_data(self, app: &mut App) {
1396 self.data_mut(app).parent_data = None;
1397 }
1398
1399 pub fn parent(self, app: &App) -> Option<AnyRenderObject> {
1401 self.data(app).parent
1402 }
1403
1404 fn set_parent(self, app: &mut App, parent: Option<AnyRenderObject>) {
1405 self.data_mut(app).parent = parent;
1406 }
1407
1408 pub fn owner(self, app: &App) -> Option<Handle<PipelineOwner>> {
1410 self.data(app).owner
1411 }
1412
1413 pub fn attached(self, app: &App) -> bool {
1415 self.owner(app).is_some()
1416 }
1417
1418 pub fn depth(self, app: &App) -> i32 {
1420 self.data(app).depth
1421 }
1422
1423 fn set_depth(self, app: &mut App, depth: i32) {
1424 self.data_mut(app).depth = depth;
1425 }
1426
1427 pub(crate) fn needs_layout(self, app: &App) -> bool {
1428 self.data(app).needs_layout
1429 }
1430
1431 fn set_needs_layout(self, app: &mut App, value: bool) {
1432 self.data_mut(app).needs_layout = value;
1433 }
1434
1435 pub fn debug_needs_layout(self, app: &App) -> bool {
1439 if !cfg!(debug_assertions) {
1440 return false;
1441 }
1442 self.needs_layout(app)
1443 }
1444
1445 pub(crate) fn is_relayout_boundary(self, app: &App) -> Option<bool> {
1446 self.data(app).is_relayout_boundary
1447 }
1448
1449 fn set_is_relayout_boundary(self, app: &mut App, value: Option<bool>) {
1450 self.data_mut(app).is_relayout_boundary = value;
1451 }
1452
1453 fn doing_this_layout_with_callback(self, app: &App) -> bool {
1454 self.data(app).doing_this_layout_with_callback
1455 }
1456
1457 pub(crate) fn debug_doing_this_layout(self, app: &App) -> bool {
1458 self.data(app).debug_doing_this_layout
1459 }
1460
1461 fn set_debug_doing_this_layout(self, app: &mut App, value: bool) {
1462 self.data_mut(app).debug_doing_this_layout = value;
1463 }
1464
1465 pub(crate) fn debug_doing_this_resize(self, app: &App) -> bool {
1466 self.data(app).debug_doing_this_resize
1467 }
1468
1469 fn set_debug_doing_this_resize(self, app: &mut App, value: bool) {
1470 self.data_mut(app).debug_doing_this_resize = value;
1471 }
1472
1473 fn set_debug_can_parent_use_size(self, app: &mut App, value: Option<bool>) {
1474 self.data_mut(app).debug_can_parent_use_size = value;
1475 }
1476
1477 fn debug_mutations_locked(self, app: &App) -> bool {
1478 self.data(app).debug_mutations_locked
1479 }
1480
1481 fn set_debug_mutations_locked(self, app: &mut App, value: bool) {
1482 self.data_mut(app).debug_mutations_locked = value;
1483 }
1484
1485 fn sized_by_parent(self, app: &App) -> bool {
1486 (self.vtable.sized_by_parent)(app, self.id)
1487 }
1488
1489 pub fn visit_children(self, app: &App, visitor: &mut dyn FnMut(AnyRenderObject)) {
1491 (self.vtable.visit_children)(app, self.id, visitor)
1492 }
1493
1494 pub fn setup_parent_data(self, app: &mut App, child: AnyRenderObject) {
1496 (self.vtable.setup_parent_data)(app, self.id, child)
1497 }
1498
1499 pub fn redepth_child(self, app: &mut App, child: AnyRenderObject) {
1501 debug_assert_eq!(child.owner(app), self.owner(app));
1502 child.redepth_below(app, self.depth(app));
1503 }
1504
1505 pub(crate) fn redepth_below(self, app: &mut App, parent_depth: i32) {
1507 if self.depth(app) <= parent_depth {
1508 self.set_depth(app, parent_depth + 1);
1509 (self.vtable.redepth_children)(app, self.id);
1510 }
1511 }
1512
1513 pub fn adopt_child(self, app: &mut App, child: AnyRenderObject) {
1515 debug_assert!(child.parent(app).is_none());
1516 if cfg!(debug_assertions) {
1517 let mut node = Some(self);
1518 while let Some(current) = node {
1519 debug_assert_ne!(current, child, "adopt_child would create a cycle");
1520 node = current.parent(app);
1521 }
1522 }
1523 self.setup_parent_data(app, child);
1524 self.mark_needs_layout(app);
1525 self.mark_needs_compositing_bits_update(app);
1526 child.set_parent(app, Some(self));
1527 if self.attached(app) {
1528 child.attach(app, self.owner(app).expect("attached parent has an owner"));
1529 }
1530 self.redepth_child(app, child);
1531 }
1532
1533 pub fn drop_child(self, app: &mut App, child: AnyRenderObject) {
1535 debug_assert_eq!(child.parent(app), Some(self));
1536 debug_assert_eq!(child.attached(app), self.attached(app));
1537 debug_assert!(child.parent_data(app).is_some());
1538 if !child.is_relayout_boundary(app).unwrap_or(true) {
1539 child.set_is_relayout_boundary(app, None);
1540 }
1541 if let Some(parent_data) = child.parent_data_mut(app) {
1542 parent_data.detach();
1543 }
1544 child.clear_parent_data(app);
1545 child.set_parent(app, None);
1546 if self.attached(app) {
1547 child.detach(app);
1548 }
1549 self.mark_needs_layout(app);
1550 self.mark_needs_compositing_bits_update(app);
1551 }
1552
1553 pub fn attach(self, app: &mut App, owner: Handle<PipelineOwner>) {
1558 debug_assert!(
1559 !app.is_disposed(self.id),
1560 "attach on a disposed render object"
1561 );
1562 debug_assert!(self.owner(app).is_none());
1563 self.data_mut(app).owner = Some(owner);
1564 if self.needs_layout(app) && self.is_relayout_boundary(app).is_some() {
1565 self.set_needs_layout(app, false);
1566 self.mark_needs_layout(app);
1567 }
1568 if self.needs_compositing_bits_update(app) {
1569 self.set_needs_compositing_bits_update(app, false);
1570 self.mark_needs_compositing_bits_update(app);
1571 }
1572 if self.needs_paint(app) && self.layer(app).is_some() {
1573 self.set_needs_paint(app, false);
1574 self.mark_needs_paint(app);
1575 }
1576 (self.vtable.did_attach)(app, self.id, owner)
1577 }
1578
1579 pub fn detach(self, app: &mut App) {
1584 debug_assert!(self.owner(app).is_some());
1585 self.data_mut(app).owner = None;
1586 debug_assert!(
1587 self.parent(app).is_none()
1588 || self.attached(app)
1589 == self.parent(app).is_some_and(|parent| parent.attached(app))
1590 );
1591 (self.vtable.did_detach)(app, self.id)
1592 }
1593
1594 pub fn mark_needs_layout(self, app: &mut App) {
1599 debug_assert!(
1600 !app.is_disposed(self.id),
1601 "mark_needs_layout on a disposed render object"
1602 );
1603 (self.vtable.mark_needs_layout)(app, self.id)
1604 }
1605
1606 pub fn mark_parent_needs_layout(self, app: &mut App) {
1609 self.set_needs_layout(app, true);
1610 let parent = self
1611 .parent(app)
1612 .expect("mark_parent_needs_layout requires a parent");
1613 if !self.doing_this_layout_with_callback(app) {
1614 parent.mark_needs_layout(app);
1615 } else {
1616 debug_assert!(parent.debug_doing_this_layout(app));
1617 }
1618 debug_assert_eq!(Some(parent), self.parent(app));
1619 }
1620
1621 pub fn invoke_layout_callback(self, app: &mut App, callback: impl FnOnce(&mut App)) {
1637 debug_assert!(self.debug_mutations_locked(app));
1638 debug_assert!(self.debug_doing_this_layout(app));
1639 debug_assert!(!self.doing_this_layout_with_callback(app));
1640 self.data_mut(app).doing_this_layout_with_callback = true;
1641 let owner = self.owner(app).expect("a laying-out object is attached");
1642 owner.enable_mutations_to_dirty_subtrees(app, callback);
1643 self.data_mut(app).doing_this_layout_with_callback = false;
1644 }
1645
1646 pub fn mark_needs_layout_for_sized_by_parent_change(self, app: &mut App) {
1647 self.mark_needs_layout(app);
1648 self.mark_parent_needs_layout(app);
1649 }
1650
1651 pub fn schedule_initial_layout(self, app: &mut App) {
1653 debug_assert!(self.attached(app));
1654 debug_assert!(self.parent(app).is_none());
1655 debug_assert!(!self.owner(app).expect("attached").debug_doing_layout(app));
1656 debug_assert!(self.is_relayout_boundary(app).is_none());
1657 self.set_is_relayout_boundary(app, Some(true));
1658 if cfg!(debug_assertions) {
1659 self.set_debug_can_parent_use_size(app, Some(false));
1660 }
1661 let owner = self.owner(app).expect("attached");
1662 owner.add_node_needing_layout(app, self);
1663 }
1664
1665 pub(crate) fn layout_without_resize(self, app: &mut App) {
1666 debug_assert!(self.needs_layout(app));
1667 debug_assert!(self.is_relayout_boundary(app).unwrap_or(false));
1668 let perform_layout = self.vtable.perform_layout;
1669 let previous = if cfg!(debug_assertions) {
1670 debug_assert!(!self.doing_this_layout_with_callback(app));
1671 self.set_debug_mutations_locked(app, true);
1672 self.set_debug_doing_this_layout(app, true);
1673 let previous = AnyRenderObject::debug_active_layout();
1674 AnyRenderObject::set_debug_active_layout(Some(self));
1675 if crate::debug::debug_print_layouts() {
1676 eprintln!("Laying out (without resize) {self:?}");
1677 }
1678 previous
1679 } else {
1680 None
1681 };
1682 perform_layout(app, self.id);
1683 if cfg!(debug_assertions) {
1684 AnyRenderObject::set_debug_active_layout(previous);
1685 self.set_debug_doing_this_layout(app, false);
1686 self.set_debug_mutations_locked(app, false);
1687 }
1688 self.set_needs_layout(app, false);
1689 self.mark_needs_paint(app);
1690 }
1691
1692 pub(crate) fn run_layout(
1694 self,
1695 app: &mut App,
1696 parent_uses_size: bool,
1697 constraints_tight: bool,
1698 same_constraints: bool,
1699 store_constraints: impl FnOnce(&mut App),
1700 ) {
1701 debug_assert!(!self.debug_doing_this_resize(app));
1702 debug_assert!(!self.debug_doing_this_layout(app));
1703 if cfg!(debug_assertions) {
1704 self.set_debug_can_parent_use_size(app, Some(parent_uses_size));
1705 }
1706
1707 let sized_by_parent = self.sized_by_parent(app);
1708 self.set_is_relayout_boundary(
1709 app,
1710 Some(
1711 !parent_uses_size
1712 || sized_by_parent
1713 || constraints_tight
1714 || self.parent(app).is_none(),
1715 ),
1716 );
1717 if !self.needs_layout(app) && same_constraints {
1718 return;
1719 }
1720 store_constraints(app);
1721
1722 if sized_by_parent {
1723 if cfg!(debug_assertions) {
1724 self.set_debug_doing_this_resize(app, true);
1725 }
1726 (self.vtable.perform_resize)(app, self.id);
1727 if cfg!(debug_assertions) {
1728 self.set_debug_doing_this_resize(app, false);
1729 }
1730 }
1731
1732 let previous = if cfg!(debug_assertions) {
1733 debug_assert!(!self.doing_this_layout_with_callback(app));
1734 self.set_debug_mutations_locked(app, true);
1735 self.set_debug_doing_this_layout(app, true);
1736 let previous = AnyRenderObject::debug_active_layout();
1737 AnyRenderObject::set_debug_active_layout(Some(self));
1738 if crate::debug::debug_print_layouts() {
1739 eprintln!(
1740 "Laying out ({}) {self:?}",
1741 if sized_by_parent {
1742 "with separate resize"
1743 } else {
1744 "with resize allowed"
1745 }
1746 );
1747 }
1748 previous
1749 } else {
1750 None
1751 };
1752 (self.vtable.perform_layout)(app, self.id);
1753 if cfg!(debug_assertions) {
1754 AnyRenderObject::set_debug_active_layout(previous);
1755 self.set_debug_doing_this_layout(app, false);
1756 self.set_debug_mutations_locked(app, false);
1757 }
1758 self.set_needs_layout(app, false);
1759 self.mark_needs_paint(app);
1760 }
1761
1762 pub(crate) fn needs_paint(self, app: &App) -> bool {
1765 self.data(app).needs_paint
1766 }
1767
1768 fn set_needs_paint(self, app: &mut App, value: bool) {
1769 self.data_mut(app).needs_paint = value;
1770 }
1771
1772 pub fn debug_needs_paint(self, app: &App) -> bool {
1776 if !cfg!(debug_assertions) {
1777 return false;
1778 }
1779 self.needs_paint(app)
1780 }
1781
1782 pub(crate) fn needs_composited_layer_update(self, app: &App) -> bool {
1783 self.data(app).needs_composited_layer_update
1784 }
1785
1786 pub(crate) fn set_needs_composited_layer_update(self, app: &mut App, value: bool) {
1787 self.data_mut(app).needs_composited_layer_update = value;
1788 }
1789
1790 pub fn debug_needs_composited_layer_update(self, app: &App) -> bool {
1794 if !cfg!(debug_assertions) {
1795 return false;
1796 }
1797 self.needs_composited_layer_update(app)
1798 }
1799
1800 pub(crate) fn was_repaint_boundary(self, app: &App) -> bool {
1801 self.data(app).was_repaint_boundary
1802 }
1803
1804 pub fn id(self) -> HandleId {
1806 self.id
1807 }
1808
1809 pub fn downcast<T: RenderObject>(self, app: &App) -> Option<RenderHandle<T>> {
1811 app.handle::<T>(self.id).map(RenderHandle::from_handle)
1812 }
1813
1814 pub fn dispose(self, app: &mut App) {
1821 debug_assert!(!self.attached(app));
1822 (self.vtable.dispose)(app, self.id);
1823 app.destroy(self.id);
1824 }
1825
1826 pub fn is_repaint_boundary(self, app: &App) -> bool {
1828 (self.vtable.is_repaint_boundary)(app, self.id)
1829 }
1830
1831 pub fn paint_bounds(self, app: &App) -> Rect {
1833 (self.vtable.paint_bounds)(app, self.id)
1834 }
1835
1836 pub fn apply_paint_transform(self, app: &App, child: AnyRenderObject, transform: &mut Matrix4) {
1838 (self.vtable.apply_paint_transform)(app, self.id, child, transform)
1839 }
1840
1841 pub fn get_transform_to(self, app: &App, target: Option<AnyRenderObject>) -> Matrix4 {
1852 debug_assert!(self.attached(app));
1853 let mut from_path: Option<Vec<AnyRenderObject>> = None;
1859 let mut to_path: Option<Vec<AnyRenderObject>> = None;
1862
1863 let mut from = self;
1864 let mut to = target.unwrap_or_else(|| {
1865 self.owner(app)
1866 .and_then(|owner| owner.root_node(app))
1867 .expect("an attached render object has a root")
1868 });
1869
1870 while from != to {
1871 let from_depth = from.depth(app);
1872 let to_depth = to.depth(app);
1873
1874 if from_depth >= to_depth {
1875 let from_parent = from.parent(app).unwrap_or_else(|| {
1876 panic!("{target:?} and {self:?} are not in the same render tree.")
1877 });
1878 from_path
1879 .get_or_insert_with(|| vec![self])
1880 .push(from_parent);
1881 from = from_parent;
1882 }
1883 if from_depth <= to_depth {
1884 let to_parent = to.parent(app).unwrap_or_else(|| {
1885 panic!("{target:?} and {self:?} are not in the same render tree.")
1886 });
1887 debug_assert!(
1888 target.is_some(),
1889 "{self:?} has a depth that is less than or equal to the root node"
1890 );
1891 to_path
1892 .get_or_insert_with(|| vec![target.expect("checked above")])
1893 .push(to_parent);
1894 to = to_parent;
1895 }
1896 }
1897
1898 let mut from_transform: Option<Matrix4> = None;
1899 if let Some(from_path) = &from_path {
1900 debug_assert!(from_path.len() > 1);
1901 let mut transform = Matrix4::IDENTITY;
1902 let last_index = if target.is_none() {
1903 from_path.len() - 2
1904 } else {
1905 from_path.len() - 1
1906 };
1907 for index in (1..=last_index).rev() {
1908 from_path[index].apply_paint_transform(app, from_path[index - 1], &mut transform);
1909 }
1910 from_transform = Some(transform);
1911 }
1912 let Some(to_path) = to_path else {
1913 return from_transform.unwrap_or(Matrix4::IDENTITY);
1914 };
1915
1916 debug_assert!(to_path.len() > 1);
1917 let mut to_transform = Matrix4::IDENTITY;
1918 for index in (1..to_path.len()).rev() {
1919 to_path[index].apply_paint_transform(app, to_path[index - 1], &mut to_transform);
1920 }
1921 let Some(to_transform) = to_transform.invert() else {
1922 return zero_matrix();
1924 };
1925 match from_transform {
1926 Some(mut from_transform) => {
1927 multiply(&mut from_transform, &to_transform);
1928 from_transform
1929 }
1930 None => to_transform,
1931 }
1932 }
1933
1934 pub fn mouse_tracker_annotation(self, app: &App) -> Option<MouseTrackerAnnotation> {
1937 if !app.contains(self.id) {
1938 return None;
1939 }
1940 (self.vtable.mouse_tracker_annotation)(app, self.id)
1941 }
1942
1943 pub fn interface<I: 'static>(self) -> Option<I> {
1946 (self.vtable.interface)(self.id, TypeId::of::<I>())?
1947 .downcast()
1948 .ok()
1949 .map(|handle| *handle)
1950 }
1951
1952 pub fn show_on_screen(
1954 self,
1955 app: &mut App,
1956 descendant: Option<AnyRenderObject>,
1957 rect: Option<Rect>,
1958 duration: Duration,
1959 curve: Rc<dyn Curve>,
1960 ) {
1961 (self.vtable.show_on_screen)(app, self.id, descendant, rect, duration, curve)
1962 }
1963
1964 pub fn update_composited_layer(
1966 self,
1967 app: &mut App,
1968 old_layer: Option<AnyOffsetLayer>,
1969 ) -> AnyOffsetLayer {
1970 (self.vtable.update_composited_layer)(app, self.id, old_layer)
1971 }
1972
1973 pub fn always_needs_compositing(self, app: &App) -> bool {
1975 (self.vtable.always_needs_compositing)(app, self.id)
1976 }
1977
1978 pub fn layer(self, app: &App) -> Option<AnyContainerLayer> {
1996 debug_assert!(
1997 !self.is_repaint_boundary(app)
1998 || self.data(app).layer.layer().is_none()
1999 || self
2000 .data(app)
2001 .layer
2002 .layer()
2003 .is_some_and(|layer| layer.as_offset_layer().is_some())
2004 );
2005 self.data(app).layer.layer()
2006 }
2007
2008 pub fn set_layer(self, app: &mut App, new_layer: Option<AnyContainerLayer>) {
2011 debug_assert!(
2012 !self.is_repaint_boundary(app),
2013 "Attempted to set a layer to a repaint boundary render object.\n\
2014 The framework creates and assigns an OffsetLayer to a repaint \
2015 boundary automatically."
2016 );
2017 LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, new_layer);
2018 }
2019
2020 pub fn layer_as<T: 'static>(self, app: &App) -> Option<Handle<T>> {
2022 self.layer(app)
2023 .and_then(|layer| app.handle::<T>(layer.id()))
2024 }
2025
2026 pub fn debug_layer(self, app: &App) -> Option<AnyContainerLayer> {
2034 if !cfg!(debug_assertions) {
2035 return None;
2036 }
2037 self.data(app).layer.layer()
2038 }
2039
2040 pub(crate) fn needs_compositing_bits_update(self, app: &App) -> bool {
2041 self.data(app).needs_compositing_bits_update
2042 }
2043
2044 fn set_needs_compositing_bits_update(self, app: &mut App, value: bool) {
2045 self.data_mut(app).needs_compositing_bits_update = value;
2046 }
2047
2048 pub fn mark_needs_compositing_bits_update(self, app: &mut App) {
2065 debug_assert!(
2066 !app.is_disposed(self.id),
2067 "mark_needs_compositing_bits_update on a disposed render object"
2068 );
2069 if self.needs_compositing_bits_update(app) {
2070 return;
2071 }
2072 self.set_needs_compositing_bits_update(app, true);
2073 if let Some(parent) = self.parent(app) {
2074 if parent.needs_compositing_bits_update(app) {
2075 return;
2076 }
2077 if (!self.was_repaint_boundary(app) || !self.is_repaint_boundary(app))
2078 && !parent.is_repaint_boundary(app)
2079 {
2080 parent.mark_needs_compositing_bits_update(app);
2081 return;
2082 }
2083 }
2084 if let Some(owner) = self.owner(app) {
2086 owner.add_node_needing_compositing_bits_update(app, self);
2087 }
2088 }
2089
2090 pub fn needs_compositing(self, app: &App) -> bool {
2098 debug_assert!(
2099 !self.needs_compositing_bits_update(app),
2100 "make sure we don't use this bit when it is dirty"
2101 );
2102 self.data(app).needs_compositing
2103 }
2104
2105 pub(crate) fn update_compositing_bits(self, app: &mut App) {
2107 if !self.needs_compositing_bits_update(app) {
2108 return;
2109 }
2110 let old_needs_compositing = self.data(app).needs_compositing;
2111 self.data_mut(app).needs_compositing = false;
2112 let mut children = Vec::new();
2113 self.visit_children(app, &mut |child| children.push(child));
2114 for child in children {
2115 child.update_compositing_bits(app);
2116 if child.needs_compositing(app) {
2117 self.data_mut(app).needs_compositing = true;
2118 }
2119 }
2120 if self.is_repaint_boundary(app) || self.always_needs_compositing(app) {
2121 self.data_mut(app).needs_compositing = true;
2122 }
2123 if !self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2129 self.set_needs_paint(app, false);
2130 self.set_needs_composited_layer_update(app, false);
2131 if let Some(owner) = self.owner(app) {
2132 owner.remove_node_needing_paint(app, self);
2133 }
2134 self.set_needs_compositing_bits_update(app, false);
2135 self.mark_needs_paint(app);
2136 } else if old_needs_compositing != self.data(app).needs_compositing {
2137 self.set_needs_compositing_bits_update(app, false);
2138 self.mark_needs_paint(app);
2139 } else {
2140 self.set_needs_compositing_bits_update(app, false);
2141 }
2142 }
2143
2144 pub fn mark_needs_paint(self, app: &mut App) {
2151 debug_assert!(
2152 !app.is_disposed(self.id),
2153 "mark_needs_paint on a disposed render object"
2154 );
2155 debug_assert!(
2156 self.owner(app)
2157 .is_none_or(|owner| !owner.debug_doing_paint(app))
2158 );
2159 if self.needs_paint(app) {
2160 return;
2161 }
2162 self.set_needs_paint(app, true);
2163 if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2164 if crate::debug::debug_print_mark_needs_paint_stacks() {
2165 eprintln!("markNeedsPaint() called for {self:?}");
2166 }
2167 debug_assert!(
2168 self.layer(app)
2169 .is_some_and(|layer| layer.as_offset_layer().is_some())
2170 );
2171 if let Some(owner) = self.owner(app) {
2172 owner.add_node_needing_paint(app, self);
2173 owner.request_visual_update(app);
2174 }
2175 } else if let Some(parent) = self.parent(app) {
2176 parent.mark_needs_paint(app);
2177 } else {
2178 if crate::debug::debug_print_mark_needs_paint_stacks() {
2179 eprintln!("markNeedsPaint() called for {self:?} (root of render tree)");
2180 }
2181 if let Some(owner) = self.owner(app) {
2182 owner.request_visual_update(app);
2183 }
2184 }
2185 }
2186
2187 pub fn mark_needs_composited_layer_update(self, app: &mut App) {
2200 debug_assert!(
2201 !app.is_disposed(self.id),
2202 "mark_needs_composited_layer_update on a disposed render object"
2203 );
2204 debug_assert!(
2205 self.owner(app)
2206 .is_none_or(|owner| !owner.debug_doing_paint(app))
2207 );
2208 if self.needs_composited_layer_update(app) || self.needs_paint(app) {
2209 return;
2210 }
2211 self.set_needs_composited_layer_update(app, true);
2212 if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2213 debug_assert!(self.layer(app).is_some());
2214 if let Some(owner) = self.owner(app) {
2215 owner.add_node_needing_paint(app, self);
2216 owner.request_visual_update(app);
2217 }
2218 } else {
2219 self.mark_needs_paint(app);
2220 }
2221 }
2222
2223 pub(crate) fn skipped_painting_on_layer(self, app: &mut App) {
2226 debug_assert!(self.attached(app));
2227 debug_assert!(self.is_repaint_boundary(app));
2228 debug_assert!(self.needs_paint(app) || self.needs_composited_layer_update(app));
2229 debug_assert!(self.layer(app).is_some());
2230 debug_assert!(
2231 self.layer(app)
2232 .is_some_and(|layer| !layer.as_layer().attached(app))
2233 );
2234 let mut node = self.parent(app);
2235 while let Some(current) = node {
2236 if current.is_repaint_boundary(app) {
2237 match current.layer(app) {
2238 None => break,
2239 Some(layer) if layer.as_layer().attached(app) => break,
2240 Some(_) => current.set_needs_paint(app, true),
2241 }
2242 }
2243 node = current.parent(app);
2244 }
2245 }
2246
2247 pub fn schedule_initial_paint(self, app: &mut App, root_layer: AnyContainerLayer) {
2252 debug_assert!(root_layer.as_layer().attached(app));
2253 debug_assert!(self.attached(app));
2254 debug_assert!(self.parent(app).is_none());
2255 debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2256 debug_assert!(self.is_repaint_boundary(app));
2257 debug_assert!(self.layer(app).is_none());
2258 LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, Some(root_layer));
2259 debug_assert!(self.needs_paint(app));
2260 let owner = self.owner(app).expect("attached");
2261 owner.add_node_needing_paint(app, self);
2262 }
2263
2264 pub fn replace_root_layer(self, app: &mut App, root_layer: AnyOffsetLayer) {
2270 debug_assert!(
2271 !app.is_disposed(self.id),
2272 "replace_root_layer on a disposed render object"
2273 );
2274 debug_assert!(root_layer.as_layer().attached(app));
2275 debug_assert!(self.attached(app));
2276 debug_assert!(self.parent(app).is_none());
2277 debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2278 debug_assert!(self.is_repaint_boundary(app));
2279 debug_assert!(
2280 self.layer(app).is_some(),
2281 "use schedule_initial_paint the first time"
2282 );
2283 self.layer(app).expect("checked").as_layer().detach(app);
2284 LayerHandle::set_layer(
2285 app,
2286 |app| &mut self.data_mut(app).layer,
2287 Some(root_layer.as_container_layer()),
2288 );
2289 self.mark_needs_paint(app);
2290 }
2291
2292 pub(crate) fn paint_with_context(
2294 self,
2295 app: &mut App,
2296 context: &mut PaintingContext,
2297 offset: Offset,
2298 ) {
2299 debug_assert!(
2300 !self.data(app).debug_doing_this_paint,
2301 "Tried to paint a RenderObject reentrantly: {self:?}"
2302 );
2303 if self.needs_layout(app) {
2304 return;
2305 }
2306 debug_assert!(
2307 !self.needs_compositing_bits_update(app),
2308 "Tried to paint a RenderObject before its compositing bits were updated.\n\
2309 The following RenderObject was marked as having dirty compositing bits \
2310 at the time that it was painted: {self:?}\n\
2311 A RenderObject that still has dirty compositing bits cannot be painted \
2312 because this indicates that the tree has not yet been properly configured \
2313 for creating the layer tree.\n\
2314 This usually indicates an error in the Flutter framework itself."
2315 );
2316 let debug_last_active_paint = if cfg!(debug_assertions) {
2317 self.data_mut(app).debug_doing_this_paint = true;
2318 let previous = DEBUG_ACTIVE_PAINT.replace(Some(self));
2319 debug_assert!(!self.is_repaint_boundary(app) || self.layer(app).is_some());
2320 previous
2321 } else {
2322 None
2323 };
2324 self.set_needs_paint(app, false);
2325 self.set_needs_composited_layer_update(app, false);
2326 let is_repaint_boundary = self.is_repaint_boundary(app);
2327 self.data_mut(app).was_repaint_boundary = is_repaint_boundary;
2328 (self.vtable.paint)(app, self.id, context, offset);
2329 debug_assert!(!self.needs_layout(app));
2330 debug_assert!(!self.needs_paint(app));
2331 if cfg!(debug_assertions) {
2332 DEBUG_ACTIVE_PAINT.set(debug_last_active_paint);
2333 self.data_mut(app).debug_doing_this_paint = false;
2334 }
2335 }
2336}
2337
2338pub trait RenderObjectBase: RenderObject {
2343 fn dispose(self: RenderHandle<Self>, app: &mut App) {
2346 LayerHandle::set_layer(app, |app| &mut self.render_object_data_mut(app).layer, None);
2347 }
2348
2349 fn mark_needs_layout(self: RenderHandle<Self>, app: &mut App) {
2352 let this = self.as_render_object(app);
2353 if this.needs_layout(app) {
2354 return;
2355 }
2356 this.set_needs_layout(app, true);
2357 if let Some(owner) = this.owner(app)
2358 && this.is_relayout_boundary(app).unwrap_or(false)
2359 {
2360 if crate::debug::debug_print_mark_needs_layout_stacks() {
2361 eprintln!("markNeedsLayout() called for {this:?}");
2362 }
2363 owner.add_node_needing_layout(app, this);
2364 owner.request_visual_update(app);
2365 } else if this.parent(app).is_some() {
2366 this.mark_parent_needs_layout(app);
2367 }
2368 }
2369
2370 fn show_on_screen(
2372 self: RenderHandle<Self>,
2373 app: &mut App,
2374 descendant: Option<AnyRenderObject>,
2375 rect: Option<Rect>,
2376 duration: Duration,
2377 curve: Rc<dyn Curve>,
2378 ) {
2379 let this = self.as_render_object(app);
2380 if let Some(parent) = this.parent(app) {
2381 parent.show_on_screen(app, Some(descendant.unwrap_or(this)), rect, duration, curve);
2382 }
2383 }
2384}
2385
2386impl<T: RenderObject> RenderObjectBase for T {}
2387
2388pub(crate) fn zero_matrix() -> Matrix4 {
2390 Matrix4::from_flutter_array(&[0.0; 16])
2391}
2392
2393pub(crate) fn multiply(transform: &mut Matrix4, other: &Matrix4) {
2396 *transform = transform.then(other);
2397}
2398
2399pub(crate) fn translate(transform: &mut Matrix4, dx: f64, dy: f64) {
2401 multiply(transform, &Matrix4::translation(dx as f32, dy as f32));
2402}
2403
2404pub(crate) fn perspective_transform(transform: &Matrix4, point: [f64; 3]) -> [f64; 3] {
2407 let m = transform.to_flutter_array().map(f64::from);
2408 let [x, y, z] = point;
2409 let out = |row: usize| m[row] * x + m[4 + row] * y + m[8 + row] * z + m[12 + row];
2410 let w = out(3);
2411 [out(0) / w, out(1) / w, out(2) / w]
2412}
2413
2414#[derive(Debug)]
2416pub struct RenderObjectWithLayoutCallbackData {
2417 needs_rebuild: bool,
2421}
2422
2423impl Default for RenderObjectWithLayoutCallbackData {
2424 fn default() -> RenderObjectWithLayoutCallbackData {
2425 RenderObjectWithLayoutCallbackData {
2426 needs_rebuild: true,
2427 }
2428 }
2429}
2430
2431pub trait RenderObjectWithLayoutCallbackMixin: crate::box_::RenderBox {
2439 fn layout_callback_data(
2441 self: RenderHandle<Self>,
2442 app: &App,
2443 ) -> &RenderObjectWithLayoutCallbackData;
2444
2445 fn layout_callback_data_mut(
2447 self: RenderHandle<Self>,
2448 app: &mut App,
2449 ) -> &mut RenderObjectWithLayoutCallbackData;
2450
2451 fn layout_callback(self: RenderHandle<Self>, app: &mut App);
2455
2456 fn run_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2461 debug_assert!(self.as_object().debug_doing_this_layout(app));
2462 self.as_object()
2463 .invoke_layout_callback(app, |app| Self::layout_callback(self, app));
2464 self.layout_callback_data_mut(app).needs_rebuild = false;
2465 }
2466
2467 fn schedule_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2470 if self.layout_callback_data(app).needs_rebuild {
2471 debug_assert!(self.as_object().needs_layout(app));
2472 return;
2473 }
2474 self.layout_callback_data_mut(app).needs_rebuild = true;
2475 if let Some(owner) = self.as_object().owner(app) {
2480 owner.add_node_needing_layout(app, self.as_object());
2481 }
2482 self.as_object().mark_needs_layout(app);
2485 }
2486}
2487
2488#[cfg(test)]
2489mod tests {
2490 use std::cell::Cell;
2491 use std::rc::Rc;
2492
2493 use inset_foundation::{App, AppCell, Listener};
2494
2495 use super::*;
2496 use crate::box_::{BoxConstraints, RenderBox, RenderBoxData};
2497 use crate::pipeline_owner::PipelineOwner;
2498
2499 struct TestLeaf {
2500 render_object: RenderObjectData,
2501 render_box: RenderBoxData,
2502 layouts: Rc<Cell<u32>>,
2503 }
2504
2505 impl RenderObject for TestLeaf {
2506 render_object_accessors!();
2507
2508 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2509 let layouts = self.get(app).layouts.clone();
2510 layouts.set(layouts.get() + 1);
2511 let size = self.constraints(app).smallest();
2512 self.set_size(app, size);
2513 }
2514 }
2515
2516 impl RenderBox for TestLeaf {
2517 crate::render_box_accessors!();
2518 }
2519
2520 struct TestParent {
2521 render_object: RenderObjectData,
2522 render_box: RenderBoxData,
2523 child: Option<crate::AnyRenderBox>,
2524 layouts: Rc<Cell<u32>>,
2525 parent_uses_size: bool,
2526 lay_out_child: bool,
2527 }
2528
2529 impl RenderObject for TestParent {
2530 render_object_accessors!();
2531
2532 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2533 let layouts = self.get(app).layouts.clone();
2534 layouts.set(layouts.get() + 1);
2535 let child = self.get(app).child;
2536 let parent_uses_size = self.get(app).parent_uses_size;
2537 let lay_out_child = self.get(app).lay_out_child;
2538 let constraints = self.constraints(app);
2539 if let Some(child) = child
2540 && lay_out_child
2541 {
2542 child.layout(app, constraints, parent_uses_size);
2543 let _again = self.get(app).layouts.get();
2544 if parent_uses_size {
2545 self.set_size(app, child.size(app));
2546 return;
2547 }
2548 }
2549 self.set_size(app, constraints.smallest());
2550 }
2551
2552 fn visit_children(
2553 self: RenderHandle<Self>,
2554 app: &App,
2555 visitor: &mut dyn FnMut(AnyRenderObject),
2556 ) {
2557 if let Some(child) = self.get(app).child {
2558 visitor(child.as_object());
2559 }
2560 }
2561 }
2562
2563 impl RenderBox for TestParent {
2564 crate::render_box_accessors!();
2565 }
2566
2567 fn tight() -> BoxConstraints {
2568 BoxConstraints::tight_for_finite(100.0, 100.0)
2569 }
2570
2571 fn loose() -> BoxConstraints {
2572 BoxConstraints::new()
2573 }
2574
2575 fn leaf(layouts: Rc<Cell<u32>>) -> TestLeaf {
2576 TestLeaf {
2577 render_object: RenderObjectData::new(),
2578 render_box: RenderBoxData::new(),
2579 layouts,
2580 }
2581 }
2582
2583 fn parent(
2584 child: Option<crate::AnyRenderBox>,
2585 layouts: Rc<Cell<u32>>,
2586 parent_uses_size: bool,
2587 lay_out_child: bool,
2588 ) -> TestParent {
2589 TestParent {
2590 render_object: RenderObjectData::new(),
2591 render_box: RenderBoxData::new(),
2592 child,
2593 layouts,
2594 parent_uses_size,
2595 lay_out_child,
2596 }
2597 }
2598
2599 #[test]
2601 fn nodes_needing_layout_updated_with_layout_changes() {
2602 let cell = AppCell::new();
2603 let mut app = cell.borrow_mut();
2604 let owner = PipelineOwner::new(&mut app, None);
2605 let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2606 node.as_object().attach(&mut app, owner);
2607 assert!(owner.nodes_needing_layout(&app).is_empty());
2608
2609 node.layout(&mut app, tight(), false);
2610 node.as_object().mark_needs_layout(&mut app);
2611 assert!(owner.nodes_needing_layout(&app).contains(&node.as_object()));
2612
2613 owner.flush_layout(&mut app);
2614 assert!(owner.nodes_needing_layout(&app).is_empty());
2615 }
2616
2617 #[test]
2618 fn clean_layout_skips_perform_layout() {
2619 let cell = AppCell::new();
2620 let mut app = cell.borrow_mut();
2621 let layouts = Rc::new(Cell::new(0));
2622 let node = RenderHandle::new_box(&mut app, leaf(Rc::clone(&layouts)));
2623 node.layout(&mut app, tight(), false);
2624 assert_eq!(layouts.get(), 1);
2625 node.layout(&mut app, tight(), false);
2626 assert_eq!(layouts.get(), 1);
2627 node.as_object().mark_needs_layout(&mut app);
2628 node.layout(&mut app, tight(), false);
2629 assert_eq!(layouts.get(), 2);
2630 }
2631
2632 #[test]
2633 fn parent_uses_size_marks_parent() {
2634 let cell = AppCell::new();
2635 let mut app = cell.borrow_mut();
2636 let owner = PipelineOwner::new(&mut app, None);
2637 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2638 let parent = RenderHandle::new_box(
2639 &mut app,
2640 parent(Some(child.as_box()), Rc::new(Cell::new(0)), true, true),
2641 );
2642 parent.adopt_child(&mut app, child.as_object());
2643 parent.as_object().attach(&mut app, owner);
2644 parent.layout(&mut app, loose(), false);
2645 assert!(!parent.debug_needs_layout(&app));
2646 assert!(!child.debug_needs_layout(&app));
2647
2648 child.as_object().mark_needs_layout(&mut app);
2649 assert!(parent.debug_needs_layout(&app));
2650 assert!(
2651 owner
2652 .nodes_needing_layout(&app)
2653 .contains(&parent.as_object())
2654 );
2655 }
2656
2657 #[test]
2658 fn adopt_drop_attach_detach() {
2659 let cell = AppCell::new();
2660 let mut app = cell.borrow_mut();
2661 let owner = PipelineOwner::new(&mut app, None);
2662 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2663 let parent = RenderHandle::new_box(
2664 &mut app,
2665 parent(Some(child.as_box()), Rc::new(Cell::new(0)), false, true),
2666 );
2667 parent.adopt_child(&mut app, child.as_object());
2668 assert_eq!(child.parent(&app), Some(parent.as_object()));
2669 assert_eq!(
2670 child.as_object().depth(&app),
2671 parent.as_object().depth(&app) + 1
2672 );
2673 assert!(!child.attached(&app));
2674
2675 parent.as_object().attach(&mut app, owner);
2676 assert!(parent.attached(&app));
2677 assert!(child.attached(&app));
2678 assert_eq!(child.owner(&app), Some(owner));
2679
2680 parent.drop_child(&mut app, child.as_object());
2681 assert!(child.parent(&app).is_none());
2682 assert!(!child.attached(&app));
2683 assert!(parent.attached(&app));
2684 }
2685
2686 #[test]
2687 fn parent_reenters_itself_after_child_layout() {
2688 let cell = AppCell::new();
2689 let mut app = cell.borrow_mut();
2690 let layouts = Rc::new(Cell::new(0));
2691 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2692 let parent = RenderHandle::new_box(
2693 &mut app,
2694 parent(Some(child.as_box()), Rc::clone(&layouts), true, true),
2695 );
2696 parent.adopt_child(&mut app, child.as_object());
2697 parent.layout(&mut app, loose(), false);
2698 assert_eq!(layouts.get(), 1);
2699 assert_eq!(parent.size(&app), child.size(&app));
2700 }
2701
2702 #[test]
2703 fn flush_layout_orders_by_depth() {
2704 let cell = AppCell::new();
2705 let mut app = cell.borrow_mut();
2706 let owner = PipelineOwner::new(&mut app, None);
2707 let order = Rc::new(std::cell::RefCell::new(Vec::new()));
2708 let child_order = Rc::clone(&order);
2709 let parent_order = Rc::clone(&order);
2710
2711 struct OrderLeaf {
2712 render_object: RenderObjectData,
2713 render_box: RenderBoxData,
2714 name: &'static str,
2715 order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2716 }
2717 impl RenderObject for OrderLeaf {
2718 render_object_accessors!();
2719
2720 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2721 let name = self.get(app).name;
2722 self.get(app).order.borrow_mut().push(name);
2723 let size = self.constraints(app).smallest();
2724 self.set_size(app, size);
2725 }
2726 }
2727 impl RenderBox for OrderLeaf {
2728 crate::render_box_accessors!();
2729 }
2730
2731 struct OrderParent {
2732 render_object: RenderObjectData,
2733 render_box: RenderBoxData,
2734 name: &'static str,
2735 child: Option<crate::AnyRenderBox>,
2736 order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2737 }
2738 impl RenderObject for OrderParent {
2739 render_object_accessors!();
2740
2741 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2742 let name = self.get(app).name;
2743 self.get(app).order.borrow_mut().push(name);
2744 let size = self.constraints(app).smallest();
2745 self.set_size(app, size);
2746 }
2747 fn visit_children(
2748 self: RenderHandle<Self>,
2749 app: &App,
2750 visitor: &mut dyn FnMut(AnyRenderObject),
2751 ) {
2752 if let Some(child) = self.get(app).child {
2753 visitor(child.as_object());
2754 }
2755 }
2756 }
2757 impl RenderBox for OrderParent {
2758 crate::render_box_accessors!();
2759 }
2760
2761 let child = RenderHandle::new_box(
2762 &mut app,
2763 OrderLeaf {
2764 render_object: RenderObjectData::new(),
2765 render_box: RenderBoxData::new(),
2766 name: "child",
2767 order: child_order,
2768 },
2769 );
2770 let parent = RenderHandle::new_box(
2771 &mut app,
2772 OrderParent {
2773 render_object: RenderObjectData::new(),
2774 render_box: RenderBoxData::new(),
2775 name: "parent",
2776 child: Some(child.as_box()),
2777 order: parent_order,
2778 },
2779 );
2780 parent.adopt_child(&mut app, child.as_object());
2781 parent.as_object().attach(&mut app, owner);
2782 parent.layout(&mut app, tight(), false);
2783 child.layout(&mut app, tight(), false);
2784 parent.as_object().mark_needs_layout(&mut app);
2785 child.as_object().mark_needs_layout(&mut app);
2786 order.borrow_mut().clear();
2787 owner.flush_layout(&mut app);
2788 assert_eq!(*order.borrow(), ["parent", "child"]);
2789 }
2790
2791 #[test]
2792 fn mark_needs_layout_requests_visual_update() {
2793 let cell = AppCell::new();
2794 let mut app = cell.borrow_mut();
2795 let updates = Rc::new(Cell::new(0));
2796 let updates_cb = Rc::clone(&updates);
2797 let owner = PipelineOwner::new(
2798 &mut app,
2799 Some(Listener::new(move |_| {
2800 updates_cb.set(updates_cb.get() + 1);
2801 })),
2802 );
2803 let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2804 owner.set_root_node(&mut app, Some(node.as_object()));
2805 node.layout(&mut app, tight(), false);
2806 assert_eq!(updates.get(), 0);
2807 node.as_object().mark_needs_layout(&mut app);
2808 assert_eq!(updates.get(), 1);
2809 }
2810}