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> {
99 let any: &dyn Any = self;
100 any.downcast_ref()
101 .or_else(|| self.provide(TypeId::of::<P>())?.downcast_ref())
102 }
103
104 pub fn part_mut<P: 'static>(&mut self) -> Option<&mut P> {
106 if (self as &dyn Any).is::<P>() {
107 return (self as &mut dyn Any).downcast_mut();
108 }
109 self.provide_mut(TypeId::of::<P>())?.downcast_mut()
110 }
111}
112
113#[derive(Debug, Default)]
115pub struct EmptyParentData;
116
117impl ParentData for EmptyParentData {}
118
119impl Display for EmptyParentData {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str("<none>")
122 }
123}
124
125pub struct RenderObjectData {
127 pub(crate) object_vtable: Option<&'static RenderObjectVTable>,
131 pub(crate) parent: Option<AnyRenderObject>,
132 pub(crate) owner: Option<Handle<PipelineOwner>>,
133 pub(crate) depth: i32,
134 pub(crate) parent_data: Option<Box<dyn ParentData>>,
135 pub(crate) needs_layout: bool,
136 pub(crate) needs_paint: bool,
137 pub(crate) needs_composited_layer_update: bool,
138 pub(crate) needs_compositing_bits_update: bool,
139 pub(crate) needs_compositing: bool,
140 pub(crate) was_repaint_boundary: bool,
141 pub(crate) layer: LayerHandle<AnyContainerLayer>,
143 pub(crate) is_relayout_boundary: Option<bool>,
144 pub(crate) doing_this_layout_with_callback: bool,
145 pub(crate) debug_doing_this_layout: bool,
146 pub(crate) debug_doing_this_resize: bool,
147 pub(crate) debug_doing_this_paint: bool,
148 pub(crate) debug_can_parent_use_size: Option<bool>,
149 pub(crate) debug_mutations_locked: bool,
150}
151
152impl RenderObjectData {
153 pub fn new() -> RenderObjectData {
155 RenderObjectData {
156 object_vtable: None,
157 parent: None,
158 owner: None,
159 depth: 0,
160 parent_data: None,
161 needs_layout: true,
162 needs_paint: true,
163 needs_composited_layer_update: false,
164 needs_compositing_bits_update: false,
165 needs_compositing: false,
166 was_repaint_boundary: false,
167 layer: LayerHandle::new(),
168 is_relayout_boundary: None,
169 doing_this_layout_with_callback: false,
170 debug_doing_this_layout: false,
171 debug_doing_this_resize: false,
172 debug_doing_this_paint: false,
173 debug_can_parent_use_size: None,
174 debug_mutations_locked: false,
175 }
176 }
177}
178
179impl Default for RenderObjectData {
180 fn default() -> RenderObjectData {
181 RenderObjectData::new()
182 }
183}
184
185pub struct RenderObjectWithChildData<C> {
187 pub(crate) child: Option<C>,
188}
189
190impl<C> RenderObjectWithChildData<C> {
191 pub const fn new() -> RenderObjectWithChildData<C> {
193 RenderObjectWithChildData { child: None }
194 }
195}
196
197impl<C> Default for RenderObjectWithChildData<C> {
198 fn default() -> RenderObjectWithChildData<C> {
199 RenderObjectWithChildData::new()
200 }
201}
202
203#[derive(Debug)]
205pub struct ContainerParentData<ChildType> {
206 pub(crate) previous_sibling: Option<ChildType>,
207 pub(crate) next_sibling: Option<ChildType>,
208}
209
210impl<ChildType> ContainerParentData<ChildType> {
211 pub const fn new() -> ContainerParentData<ChildType> {
213 ContainerParentData {
214 previous_sibling: None,
215 next_sibling: None,
216 }
217 }
218}
219
220impl<ChildType> Default for ContainerParentData<ChildType> {
221 fn default() -> ContainerParentData<ChildType> {
222 ContainerParentData::new()
223 }
224}
225
226pub trait ContainerParentDataMixin: ParentData {
235 type ChildType: Copy + PartialEq;
237
238 fn container_parent_data(&self) -> &ContainerParentData<Self::ChildType>;
240
241 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<Self::ChildType>;
243
244 fn previous_sibling(&self) -> Option<Self::ChildType> {
246 self.container_parent_data().previous_sibling
247 }
248
249 fn set_previous_sibling(&mut self, value: Option<Self::ChildType>) {
251 self.container_parent_data_mut().previous_sibling = value;
252 }
253
254 fn next_sibling(&self) -> Option<Self::ChildType> {
256 self.container_parent_data().next_sibling
257 }
258
259 fn set_next_sibling(&mut self, value: Option<Self::ChildType>) {
261 self.container_parent_data_mut().next_sibling = value;
262 }
263
264 fn detach(&mut self) {
268 debug_assert!(
269 self.previous_sibling().is_none(),
270 "Pointers to siblings must be nulled before detaching ParentData."
271 );
272 debug_assert!(
273 self.next_sibling().is_none(),
274 "Pointers to siblings must be nulled before detaching ParentData."
275 );
276 }
277}
278
279pub struct ContainerRenderObjectData<ChildType> {
282 pub(crate) child_count: usize,
283 pub(crate) first_child: Option<ChildType>,
284 pub(crate) last_child: Option<ChildType>,
285}
286
287impl<ChildType> ContainerRenderObjectData<ChildType> {
288 pub const fn new() -> ContainerRenderObjectData<ChildType> {
290 ContainerRenderObjectData {
291 child_count: 0,
292 first_child: None,
293 last_child: None,
294 }
295 }
296}
297
298impl<ChildType> Default for ContainerRenderObjectData<ChildType> {
299 fn default() -> ContainerRenderObjectData<ChildType> {
300 ContainerRenderObjectData::new()
301 }
302}
303
304pub trait ErasedRenderObject: Copy + PartialEq + Debug + 'static {
309 fn as_object(self) -> AnyRenderObject;
311
312 fn from_object(object: AnyRenderObject) -> Self;
318}
319
320pub trait RenderObjectWithChildMixin: RenderObject {
325 type ChildType: ErasedRenderObject;
327
328 fn child_data(
330 self: RenderHandle<Self>,
331 app: &App,
332 ) -> &RenderObjectWithChildData<Self::ChildType>;
333
334 fn child_data_mut(
336 self: RenderHandle<Self>,
337 app: &mut App,
338 ) -> &mut RenderObjectWithChildData<Self::ChildType>;
339
340 fn child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
342 self.child_data(app).child
343 }
344
345 fn set_child(self: RenderHandle<Self>, app: &mut App, value: Option<Self::ChildType>) {
347 if let Some(old) = self.child(app) {
348 self.as_render_object(app).drop_child(app, old.as_object());
349 }
350 self.child_data_mut(app).child = value;
351 if let Some(new) = value {
352 self.as_render_object(app).adopt_child(app, new.as_object());
353 }
354 }
355}
356
357pub trait ContainerRenderObjectMixin: RenderObject {
370 type ChildType: ErasedRenderObject;
372
373 type ParentDataType: ContainerParentDataMixin<ChildType = Self::ChildType> + 'static;
375
376 fn container_data(
378 self: RenderHandle<Self>,
379 app: &App,
380 ) -> &ContainerRenderObjectData<Self::ChildType>;
381
382 fn container_data_mut(
384 self: RenderHandle<Self>,
385 app: &mut App,
386 ) -> &mut ContainerRenderObjectData<Self::ChildType>;
387
388 fn child_count(self: RenderHandle<Self>, app: &App) -> usize {
390 self.container_data(app).child_count
391 }
392
393 fn insert(
398 self: RenderHandle<Self>,
399 app: &mut App,
400 child: Self::ChildType,
401 after: Option<Self::ChildType>,
402 ) {
403 ContainerRenderObjectBase::insert(self, app, child, after)
404 }
405
406 fn add(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
408 let last_child = self.last_child(app);
409 self.insert(app, child, last_child);
410 }
411
412 fn add_all(self: RenderHandle<Self>, app: &mut App, children: Option<Vec<Self::ChildType>>) {
414 for child in children.into_iter().flatten() {
415 self.add(app, child);
416 }
417 }
418
419 fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
423 ContainerRenderObjectBase::remove(self, app, child)
424 }
425
426 fn remove_all(self: RenderHandle<Self>, app: &mut App) {
430 ContainerRenderObjectBase::remove_all(self, app)
431 }
432
433 fn move_child(
439 self: RenderHandle<Self>,
440 app: &mut App,
441 child: Self::ChildType,
442 after: Option<Self::ChildType>,
443 ) {
444 ContainerRenderObjectBase::move_child(self, app, child, after)
445 }
446
447 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
449 let mut child = self.first_child(app);
450 while let Some(current) = child {
451 current.as_object().attach(app, owner);
452 child = current
453 .as_object()
454 .parent_data_of::<Self::ParentDataType>(app)
455 .next_sibling();
456 }
457 }
458
459 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
461 let mut child = self.first_child(app);
462 while let Some(current) = child {
463 current.as_object().detach(app);
464 child = current
465 .as_object()
466 .parent_data_of::<Self::ParentDataType>(app)
467 .next_sibling();
468 }
469 }
470
471 fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
473 let mut child = self.first_child(app);
474 while let Some(current) = child {
475 self.as_render_object(app)
476 .redepth_child(app, current.as_object());
477 child = current
478 .as_object()
479 .parent_data_of::<Self::ParentDataType>(app)
480 .next_sibling();
481 }
482 }
483
484 fn visit_children(
486 self: RenderHandle<Self>,
487 app: &App,
488 visitor: &mut dyn FnMut(AnyRenderObject),
489 ) {
490 let mut child = self.first_child(app);
491 while let Some(current) = child {
492 visitor(current.as_object());
493 child = current
494 .as_object()
495 .parent_data_of::<Self::ParentDataType>(app)
496 .next_sibling();
497 }
498 }
499
500 fn first_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
502 self.container_data(app).first_child
503 }
504
505 fn last_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
507 self.container_data(app).last_child
508 }
509
510 fn child_before(
512 self: RenderHandle<Self>,
513 app: &App,
514 child: Self::ChildType,
515 ) -> Option<Self::ChildType> {
516 debug_assert_eq!(
517 child.as_object().parent(app),
518 Some(self.as_render_object(app))
519 );
520 child
521 .as_object()
522 .parent_data_of::<Self::ParentDataType>(app)
523 .previous_sibling()
524 }
525
526 fn child_after(
528 self: RenderHandle<Self>,
529 app: &App,
530 child: Self::ChildType,
531 ) -> Option<Self::ChildType> {
532 debug_assert_eq!(
533 child.as_object().parent(app),
534 Some(self.as_render_object(app))
535 );
536 child
537 .as_object()
538 .parent_data_of::<Self::ParentDataType>(app)
539 .next_sibling()
540 }
541
542 fn children_as_list(self: RenderHandle<Self>, app: &App) -> Vec<Self::ChildType> {
546 let mut result = Vec::new();
547 let mut child = self.first_child(app);
548 while let Some(current) = child {
549 result.push(current);
550 child = current
551 .as_object()
552 .parent_data_of::<Self::ParentDataType>(app)
553 .next_sibling();
554 }
555 result
556 }
557}
558
559pub trait ContainerRenderObjectBase: ContainerRenderObjectMixin {
564 fn insert(
566 self: RenderHandle<Self>,
567 app: &mut App,
568 child: Self::ChildType,
569 after: Option<Self::ChildType>,
570 ) {
571 debug_assert!(
572 child.as_object() != self.as_render_object(app),
573 "A RenderObject cannot be inserted into itself."
574 );
575 debug_assert!(
576 after.is_none_or(|after| after.as_object() != self.as_render_object(app)),
577 "A RenderObject cannot simultaneously be both the parent and the sibling of another \
578 RenderObject."
579 );
580 debug_assert!(
581 after != Some(child),
582 "A RenderObject cannot be inserted after itself."
583 );
584 debug_assert!(Some(child) != self.first_child(app));
585 debug_assert!(Some(child) != self.last_child(app));
586 self.as_render_object(app)
587 .adopt_child(app, child.as_object());
588 debug_assert!(
589 child
590 .as_object()
591 .parent_data_is::<Self::ParentDataType>(app),
592 "A child has parent data that does not conform to this render object's \
593 ParentDataType. Override setup_parent_data to install it."
594 );
595 insert_into_child_list(self, app, child, after);
596 }
597
598 fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
600 remove_from_child_list(self, app, child);
601 self.as_render_object(app)
602 .drop_child(app, child.as_object());
603 }
604
605 fn remove_all(self: RenderHandle<Self>, app: &mut App) {
607 let mut child = self.first_child(app);
608 while let Some(current) = child {
609 let child_parent_data = current
610 .as_object()
611 .parent_data_of_mut::<Self::ParentDataType>(app);
612 let next = child_parent_data.next_sibling();
613 child_parent_data.set_previous_sibling(None);
614 child_parent_data.set_next_sibling(None);
615 self.as_render_object(app)
616 .drop_child(app, current.as_object());
617 child = next;
618 }
619 let container = self.container_data_mut(app);
620 container.first_child = None;
621 container.last_child = None;
622 container.child_count = 0;
623 }
624
625 fn move_child(
627 self: RenderHandle<Self>,
628 app: &mut App,
629 child: Self::ChildType,
630 after: Option<Self::ChildType>,
631 ) {
632 debug_assert!(child.as_object() != self.as_render_object(app));
633 debug_assert!(after.is_none_or(|after| after.as_object() != self.as_render_object(app)));
634 debug_assert!(after != Some(child));
635 debug_assert_eq!(
636 child.as_object().parent(app),
637 Some(self.as_render_object(app)),
638 "the child must already be a child of this render object"
639 );
640 if child
641 .as_object()
642 .parent_data_of::<Self::ParentDataType>(app)
643 .previous_sibling()
644 == after
645 {
646 return;
647 }
648 remove_from_child_list(self, app, child);
649 insert_into_child_list(self, app, child, after);
650 self.as_render_object(app).mark_needs_layout(app);
651 }
652}
653
654impl<T: ContainerRenderObjectMixin> ContainerRenderObjectBase for T {}
655
656fn debug_ultimate_previous_sibling_of<P>(
658 app: &App,
659 child: P::ChildType,
660 equals: Option<P::ChildType>,
661) -> bool
662where
663 P: ContainerParentDataMixin + 'static,
664 P::ChildType: ErasedRenderObject,
665{
666 let mut child = child;
667 while let Some(previous) = child
668 .as_object()
669 .parent_data_of::<P>(app)
670 .previous_sibling()
671 {
672 debug_assert!(previous != child);
673 child = previous;
674 }
675 Some(child) == equals
676}
677
678fn debug_ultimate_next_sibling_of<P>(
680 app: &App,
681 child: P::ChildType,
682 equals: Option<P::ChildType>,
683) -> bool
684where
685 P: ContainerParentDataMixin + 'static,
686 P::ChildType: ErasedRenderObject,
687{
688 let mut child = child;
689 while let Some(next) = child.as_object().parent_data_of::<P>(app).next_sibling() {
690 debug_assert!(next != child);
691 child = next;
692 }
693 Some(child) == equals
694}
695
696fn insert_into_child_list<T: ContainerRenderObjectMixin>(
698 this: RenderHandle<T>,
699 app: &mut App,
700 child: T::ChildType,
701 after: Option<T::ChildType>,
702) {
703 type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
704
705 debug_assert!(
706 child
707 .as_object()
708 .parent_data_of::<ParentDataOf<T>>(app)
709 .next_sibling()
710 .is_none()
711 );
712 debug_assert!(
713 child
714 .as_object()
715 .parent_data_of::<ParentDataOf<T>>(app)
716 .previous_sibling()
717 .is_none()
718 );
719 this.container_data_mut(app).child_count += 1;
720 let Some(after) = after else {
721 let first_child = this.first_child(app);
723 child
724 .as_object()
725 .parent_data_of_mut::<ParentDataOf<T>>(app)
726 .set_next_sibling(first_child);
727 if let Some(first_child) = first_child {
728 first_child
729 .as_object()
730 .parent_data_of_mut::<ParentDataOf<T>>(app)
731 .set_previous_sibling(Some(child));
732 }
733 let container = this.container_data_mut(app);
734 container.first_child = Some(child);
735 container.last_child.get_or_insert(child);
736 return;
737 };
738 debug_assert!(this.first_child(app).is_some());
739 debug_assert!(this.last_child(app).is_some());
740 debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
741 app,
742 after,
743 this.first_child(app)
744 ));
745 debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
746 app,
747 after,
748 this.last_child(app)
749 ));
750 let after_next_sibling = after
751 .as_object()
752 .parent_data_of::<ParentDataOf<T>>(app)
753 .next_sibling();
754 let Some(after_next_sibling) = after_next_sibling else {
755 debug_assert_eq!(Some(after), this.last_child(app));
757 child
758 .as_object()
759 .parent_data_of_mut::<ParentDataOf<T>>(app)
760 .set_previous_sibling(Some(after));
761 after
762 .as_object()
763 .parent_data_of_mut::<ParentDataOf<T>>(app)
764 .set_next_sibling(Some(child));
765 this.container_data_mut(app).last_child = Some(child);
766 return;
767 };
768 let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
771 child_parent_data.set_next_sibling(Some(after_next_sibling));
772 child_parent_data.set_previous_sibling(Some(after));
773 after
775 .as_object()
776 .parent_data_of_mut::<ParentDataOf<T>>(app)
777 .set_next_sibling(Some(child));
778 after_next_sibling
779 .as_object()
780 .parent_data_of_mut::<ParentDataOf<T>>(app)
781 .set_previous_sibling(Some(child));
782}
783
784fn remove_from_child_list<T: ContainerRenderObjectMixin>(
786 this: RenderHandle<T>,
787 app: &mut App,
788 child: T::ChildType,
789) {
790 type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
791
792 debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
793 app,
794 child,
795 this.first_child(app)
796 ));
797 debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
798 app,
799 child,
800 this.last_child(app)
801 ));
802 let child_parent_data = child.as_object().parent_data_of::<ParentDataOf<T>>(app);
803 let (previous_sibling, next_sibling) = (
804 child_parent_data.previous_sibling(),
805 child_parent_data.next_sibling(),
806 );
807 match previous_sibling {
808 None => {
809 debug_assert_eq!(this.first_child(app), Some(child));
810 this.container_data_mut(app).first_child = next_sibling;
811 }
812 Some(previous_sibling) => previous_sibling
813 .as_object()
814 .parent_data_of_mut::<ParentDataOf<T>>(app)
815 .set_next_sibling(next_sibling),
816 }
817 match next_sibling {
818 None => {
819 debug_assert_eq!(this.last_child(app), Some(child));
820 this.container_data_mut(app).last_child = previous_sibling;
821 }
822 Some(next_sibling) => next_sibling
823 .as_object()
824 .parent_data_of_mut::<ParentDataOf<T>>(app)
825 .set_previous_sibling(previous_sibling),
826 }
827 let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
828 child_parent_data.set_previous_sibling(None);
829 child_parent_data.set_next_sibling(None);
830 this.container_data_mut(app).child_count -= 1;
831}
832
833pub trait RenderObject: 'static + Sized {
840 fn render_object_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectData;
842
843 fn render_object_data_mut(self: RenderHandle<Self>, app: &mut App) -> &mut RenderObjectData;
845
846 fn as_render_object(self: RenderHandle<Self>, app: &App) -> AnyRenderObject {
849 let vtable = self
850 .render_object_data(app)
851 .object_vtable
852 .expect("a render object records its vtable when the protocol creates it");
853 AnyRenderObject::from_vtable(self.id(), vtable)
854 }
855
856 fn perform_layout(self: RenderHandle<Self>, app: &mut App);
861
862 fn perform_resize(self: RenderHandle<Self>, _app: &mut App) {
869 let _ = self;
870 panic!("RenderObject::perform_resize was called; override it when sized_by_parent is true")
871 }
872
873 fn visit_children(
875 self: RenderHandle<Self>,
876 app: &App,
877 visitor: &mut dyn FnMut(AnyRenderObject),
878 ) {
879 let _ = (self, app, visitor);
880 }
881
882 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
887 if child.parent_data(app).is_none() {
888 child.set_parent_data(app, EmptyParentData);
889 }
890 }
891
892 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
896 for child in collect_children(app, self) {
897 child.attach(app, owner);
898 }
899 }
900
901 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
904 for child in collect_children(app, self) {
905 child.detach(app);
906 }
907 }
908
909 fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
911 let depth = self.render_object_data(app).depth;
912 let owner = self.render_object_data(app).owner;
913 for child in collect_children(app, self) {
914 debug_assert_eq!(child.owner(app), owner);
915 child.redepth_below(app, depth);
916 }
917 }
918
919 fn sized_by_parent(self: RenderHandle<Self>, _app: &App) -> bool {
921 let _ = self;
922 false
923 }
924
925 fn apply_paint_transform(
941 self: RenderHandle<Self>,
942 app: &App,
943 child: AnyRenderObject,
944 transform: &mut Matrix4,
945 ) {
946 let _ = transform;
947 debug_assert!(child.parent(app).map(AnyRenderObject::id) == Some(self.id()));
948 }
949
950 fn is_repaint_boundary(self: RenderHandle<Self>, _app: &App) -> bool {
967 let _ = self;
968 false
969 }
970
971 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
981 let _ = self;
982 false
983 }
984
985 fn mouse_tracker_annotation(
989 self: RenderHandle<Self>,
990 _app: &App,
991 ) -> Option<MouseTrackerAnnotation> {
992 let _ = self;
993 None
994 }
995
996 fn update_composited_layer(
1017 self: RenderHandle<Self>,
1018 app: &mut App,
1019 old_layer: Option<AnyOffsetLayer>,
1020 ) -> AnyOffsetLayer {
1021 debug_assert!(self.is_repaint_boundary(app));
1022 old_layer.unwrap_or_else(|| OffsetLayer::new(app, Offset::ZERO).as_offset_layer())
1023 }
1024
1025 fn show_on_screen(
1044 self: RenderHandle<Self>,
1045 app: &mut App,
1046 descendant: Option<AnyRenderObject>,
1047 rect: Option<Rect>,
1048 duration: Duration,
1049 curve: Rc<dyn Curve>,
1050 ) {
1051 RenderObjectBase::show_on_screen(self, app, descendant, rect, duration, curve)
1052 }
1053
1054 fn interface(self: RenderHandle<Self>, id: TypeId) -> Option<Box<dyn Any>> {
1060 let _ = (self, id);
1061 None
1062 }
1063
1064 fn dispose(self: RenderHandle<Self>, app: &mut App) {
1078 RenderObjectBase::dispose(self, app);
1079 }
1080
1081 fn paint(
1087 self: RenderHandle<Self>,
1088 app: &mut App,
1089 context: &mut PaintingContext,
1090 offset: Offset,
1091 ) {
1092 let _ = (self, app, context, offset);
1093 }
1094}
1095
1096fn collect_children<T: RenderObject>(app: &App, this: RenderHandle<T>) -> Vec<AnyRenderObject> {
1097 let mut children = Vec::new();
1098 this.visit_children(app, &mut |child| children.push(child));
1099 children
1100}
1101
1102#[macro_export]
1104macro_rules! render_object_accessors {
1105 () => {
1106 fn render_object_data(
1107 self: $crate::RenderHandle<Self>,
1108 app: &::inset_foundation::App,
1109 ) -> &$crate::RenderObjectData {
1110 &self.get(app).render_object
1111 }
1112 fn render_object_data_mut(
1113 self: $crate::RenderHandle<Self>,
1114 app: &mut ::inset_foundation::App,
1115 ) -> &mut $crate::RenderObjectData {
1116 &mut self.get_mut(app).render_object
1117 }
1118 };
1119}
1120
1121pub struct RenderHandle<T>(Handle<T>);
1126
1127impl<T> Clone for RenderHandle<T> {
1128 fn clone(&self) -> RenderHandle<T> {
1129 *self
1130 }
1131}
1132
1133impl<T> Copy for RenderHandle<T> {}
1134
1135impl<T> Receiver for RenderHandle<T> {
1136 type Target = T;
1137}
1138
1139impl<T> PartialEq for RenderHandle<T> {
1140 fn eq(&self, other: &RenderHandle<T>) -> bool {
1141 self.0 == other.0
1142 }
1143}
1144
1145impl<T> Eq for RenderHandle<T> {}
1146
1147impl<T> Hash for RenderHandle<T> {
1148 fn hash<H: Hasher>(&self, state: &mut H) {
1149 self.0.hash(state);
1150 }
1151}
1152
1153impl<T> Debug for RenderHandle<T> {
1154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155 write!(
1156 f,
1157 "RenderHandle<{}>({:?})",
1158 std::any::type_name::<T>(),
1159 self.0.id()
1160 )
1161 }
1162}
1163
1164impl<T: 'static> RenderHandle<T> {
1165 pub fn get(self, app: &App) -> &T {
1167 app.get(self.0)
1168 }
1169
1170 pub fn get_mut(self, app: &mut App) -> &mut T {
1172 app.get_mut(self.0)
1173 }
1174
1175 pub(crate) fn id(self) -> HandleId {
1176 self.0.id()
1177 }
1178
1179 pub fn handle(self) -> Handle<T> {
1181 self.0
1182 }
1183
1184 pub fn from_handle(handle: Handle<T>) -> RenderHandle<T> {
1186 RenderHandle(handle)
1187 }
1188}
1189
1190pub(crate) fn resolve<T: 'static>(id: HandleId) -> RenderHandle<T> {
1192 RenderHandle(Handle::from_id(id))
1193}
1194
1195pub(crate) fn create<T: 'static>(app: &mut App, object: T) -> RenderHandle<T> {
1196 RenderHandle(app.create(object))
1197}
1198
1199pub(crate) type ShowOnScreenFn =
1201 fn(&mut App, HandleId, Option<AnyRenderObject>, Option<Rect>, Duration, Rc<dyn Curve>);
1202
1203pub(crate) struct RenderObjectVTable {
1207 pub object_data: fn(&App, HandleId) -> &RenderObjectData,
1208 pub object_data_mut: fn(&mut App, HandleId) -> &mut RenderObjectData,
1209 pub visit_children: fn(&App, HandleId, &mut dyn FnMut(AnyRenderObject)),
1210 pub did_attach: fn(&mut App, HandleId, Handle<PipelineOwner>),
1211 pub did_detach: fn(&mut App, HandleId),
1212 pub redepth_children: fn(&mut App, HandleId),
1213 pub setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1214 pub sized_by_parent: fn(&App, HandleId) -> bool,
1215 pub perform_layout: fn(&mut App, HandleId),
1216 pub perform_resize: fn(&mut App, HandleId),
1217 pub mark_needs_layout: fn(&mut App, HandleId),
1218 pub paint_bounds: fn(&App, HandleId) -> Rect,
1219 pub apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1220 pub is_repaint_boundary: fn(&App, HandleId) -> bool,
1221 pub always_needs_compositing: fn(&App, HandleId) -> bool,
1222 pub mouse_tracker_annotation: fn(&App, HandleId) -> Option<MouseTrackerAnnotation>,
1223 pub update_composited_layer: fn(&mut App, HandleId, Option<AnyOffsetLayer>) -> AnyOffsetLayer,
1224 pub show_on_screen: ShowOnScreenFn,
1225 pub interface: fn(HandleId, TypeId) -> Option<Box<dyn Any>>,
1226 pub paint: fn(&mut App, HandleId, &mut PaintingContext, Offset),
1227 pub dispose: fn(&mut App, HandleId),
1228 pub as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1230 pub as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1231}
1232
1233impl RenderObjectVTable {
1234 pub(crate) const fn of<T: RenderObject>(
1238 setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1239 paint_bounds: fn(&App, HandleId) -> Rect,
1240 apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1241 perform_resize: fn(&mut App, HandleId),
1242 mark_needs_layout: fn(&mut App, HandleId),
1243 as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1244 as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1245 ) -> RenderObjectVTable {
1246 RenderObjectVTable {
1247 object_data: |app, id| T::render_object_data(resolve(id), app),
1248 object_data_mut: |app, id| T::render_object_data_mut(resolve(id), app),
1249 visit_children: |app, id, visitor| T::visit_children(resolve(id), app, visitor),
1250 did_attach: |app, id, owner| T::did_attach(resolve(id), app, owner),
1251 did_detach: |app, id| T::did_detach(resolve(id), app),
1252 redepth_children: |app, id| T::redepth_children(resolve(id), app),
1253 setup_parent_data,
1254 sized_by_parent: |app, id| T::sized_by_parent(resolve(id), app),
1255 perform_layout: |app, id| T::perform_layout(resolve(id), app),
1256 perform_resize,
1257 mark_needs_layout,
1258 paint_bounds,
1259 apply_paint_transform,
1260 is_repaint_boundary: |app, id| T::is_repaint_boundary(resolve(id), app),
1261 always_needs_compositing: |app, id| T::always_needs_compositing(resolve(id), app),
1262 mouse_tracker_annotation: |app, id| T::mouse_tracker_annotation(resolve(id), app),
1263 update_composited_layer: |app, id, old_layer| {
1264 T::update_composited_layer(resolve(id), app, old_layer)
1265 },
1266 show_on_screen: |app, id, descendant, rect, duration, curve| {
1267 T::show_on_screen(resolve(id), app, descendant, rect, duration, curve)
1268 },
1269 interface: |id, interface| T::interface(resolve(id), interface),
1270 paint: |app, id, context, offset| T::paint(resolve(id), app, context, offset),
1271 dispose: |app, id| T::dispose(resolve(id), app),
1272 as_box,
1273 as_sliver,
1274 }
1275 }
1276}
1277
1278#[derive(Clone, Copy)]
1283pub struct AnyRenderObject {
1284 id: HandleId,
1285 vtable: &'static RenderObjectVTable,
1286}
1287
1288impl PartialEq for AnyRenderObject {
1289 fn eq(&self, other: &AnyRenderObject) -> bool {
1290 self.id == other.id
1291 }
1292}
1293
1294impl Eq for AnyRenderObject {}
1295
1296impl Hash for AnyRenderObject {
1297 fn hash<H: Hasher>(&self, state: &mut H) {
1298 self.id.hash(state);
1299 }
1300}
1301
1302impl From<AnyRenderObject> for HandleId {
1303 fn from(object: AnyRenderObject) -> HandleId {
1304 object.id
1305 }
1306}
1307
1308impl Debug for AnyRenderObject {
1309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1310 write!(f, "AnyRenderObject({:?})", self.id)
1311 }
1312}
1313
1314impl AnyRenderObject {
1315 pub(crate) fn from_vtable(
1316 id: HandleId,
1317 vtable: &'static RenderObjectVTable,
1318 ) -> AnyRenderObject {
1319 AnyRenderObject { id, vtable }
1320 }
1321
1322 pub fn as_box(self) -> Option<crate::box_::AnyRenderBox> {
1324 self.vtable
1325 .as_box
1326 .map(|vtable| crate::box_::AnyRenderBox::from_vtable(self.id, vtable()))
1327 }
1328
1329 pub fn as_sliver(self) -> Option<crate::sliver::AnyRenderSliver> {
1331 self.vtable
1332 .as_sliver
1333 .map(|vtable| crate::sliver::AnyRenderSliver::from_vtable(self.id, vtable()))
1334 }
1335
1336 pub fn debug_active_layout() -> Option<AnyRenderObject> {
1340 DEBUG_ACTIVE_LAYOUT.get()
1341 }
1342
1343 pub(crate) fn set_debug_active_layout(node: Option<AnyRenderObject>) {
1344 DEBUG_ACTIVE_LAYOUT.set(node);
1345 }
1346
1347 pub fn debug_active_paint() -> Option<AnyRenderObject> {
1351 DEBUG_ACTIVE_PAINT.get()
1352 }
1353
1354 fn data(self, app: &App) -> &RenderObjectData {
1355 (self.vtable.object_data)(app, self.id)
1356 }
1357
1358 pub(crate) fn data_mut(self, app: &mut App) -> &mut RenderObjectData {
1359 (self.vtable.object_data_mut)(app, self.id)
1360 }
1361
1362 pub fn parent_data(self, app: &App) -> Option<&dyn ParentData> {
1364 self.data(app).parent_data.as_deref()
1365 }
1366
1367 pub fn parent_data_mut(self, app: &mut App) -> Option<&mut dyn ParentData> {
1369 self.data_mut(app).parent_data.as_deref_mut()
1370 }
1371
1372 pub fn parent_data_is<P: ParentData + 'static>(self, app: &App) -> bool {
1375 self.parent_data(app)
1376 .is_some_and(|data| data.part::<P>().is_some())
1377 }
1378
1379 pub fn parent_data_of<P: ParentData + 'static>(self, app: &App) -> &P {
1387 self.parent_data(app)
1388 .and_then(|data| data.part::<P>())
1389 .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1390 }
1391
1392 pub fn parent_data_of_mut<P: ParentData + 'static>(self, app: &mut App) -> &mut P {
1394 self.parent_data_mut(app)
1395 .and_then(|data| data.part_mut::<P>())
1396 .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1397 }
1398
1399 pub fn set_parent_data(self, app: &mut App, parent_data: impl ParentData + 'static) {
1401 self.data_mut(app).parent_data = Some(Box::new(parent_data));
1402 }
1403
1404 fn clear_parent_data(self, app: &mut App) {
1405 self.data_mut(app).parent_data = None;
1406 }
1407
1408 pub fn parent(self, app: &App) -> Option<AnyRenderObject> {
1410 self.data(app).parent
1411 }
1412
1413 fn set_parent(self, app: &mut App, parent: Option<AnyRenderObject>) {
1414 self.data_mut(app).parent = parent;
1415 }
1416
1417 pub fn owner(self, app: &App) -> Option<Handle<PipelineOwner>> {
1419 self.data(app).owner
1420 }
1421
1422 pub fn attached(self, app: &App) -> bool {
1424 self.owner(app).is_some()
1425 }
1426
1427 pub fn depth(self, app: &App) -> i32 {
1429 self.data(app).depth
1430 }
1431
1432 fn set_depth(self, app: &mut App, depth: i32) {
1433 self.data_mut(app).depth = depth;
1434 }
1435
1436 pub(crate) fn needs_layout(self, app: &App) -> bool {
1437 self.data(app).needs_layout
1438 }
1439
1440 fn set_needs_layout(self, app: &mut App, value: bool) {
1441 self.data_mut(app).needs_layout = value;
1442 }
1443
1444 pub fn debug_needs_layout(self, app: &App) -> bool {
1448 if !cfg!(debug_assertions) {
1449 return false;
1450 }
1451 self.needs_layout(app)
1452 }
1453
1454 pub(crate) fn is_relayout_boundary(self, app: &App) -> Option<bool> {
1455 self.data(app).is_relayout_boundary
1456 }
1457
1458 fn set_is_relayout_boundary(self, app: &mut App, value: Option<bool>) {
1459 self.data_mut(app).is_relayout_boundary = value;
1460 }
1461
1462 fn doing_this_layout_with_callback(self, app: &App) -> bool {
1463 self.data(app).doing_this_layout_with_callback
1464 }
1465
1466 pub(crate) fn debug_doing_this_layout(self, app: &App) -> bool {
1467 self.data(app).debug_doing_this_layout
1468 }
1469
1470 fn set_debug_doing_this_layout(self, app: &mut App, value: bool) {
1471 self.data_mut(app).debug_doing_this_layout = value;
1472 }
1473
1474 pub(crate) fn debug_doing_this_resize(self, app: &App) -> bool {
1475 self.data(app).debug_doing_this_resize
1476 }
1477
1478 fn set_debug_doing_this_resize(self, app: &mut App, value: bool) {
1479 self.data_mut(app).debug_doing_this_resize = value;
1480 }
1481
1482 fn set_debug_can_parent_use_size(self, app: &mut App, value: Option<bool>) {
1483 self.data_mut(app).debug_can_parent_use_size = value;
1484 }
1485
1486 fn debug_mutations_locked(self, app: &App) -> bool {
1487 self.data(app).debug_mutations_locked
1488 }
1489
1490 fn set_debug_mutations_locked(self, app: &mut App, value: bool) {
1491 self.data_mut(app).debug_mutations_locked = value;
1492 }
1493
1494 fn sized_by_parent(self, app: &App) -> bool {
1495 (self.vtable.sized_by_parent)(app, self.id)
1496 }
1497
1498 pub fn visit_children(self, app: &App, visitor: &mut dyn FnMut(AnyRenderObject)) {
1500 (self.vtable.visit_children)(app, self.id, visitor)
1501 }
1502
1503 pub fn setup_parent_data(self, app: &mut App, child: AnyRenderObject) {
1505 (self.vtable.setup_parent_data)(app, self.id, child)
1506 }
1507
1508 pub fn redepth_child(self, app: &mut App, child: AnyRenderObject) {
1510 debug_assert_eq!(child.owner(app), self.owner(app));
1511 child.redepth_below(app, self.depth(app));
1512 }
1513
1514 pub(crate) fn redepth_below(self, app: &mut App, parent_depth: i32) {
1516 if self.depth(app) <= parent_depth {
1517 self.set_depth(app, parent_depth + 1);
1518 (self.vtable.redepth_children)(app, self.id);
1519 }
1520 }
1521
1522 pub fn adopt_child(self, app: &mut App, child: AnyRenderObject) {
1524 debug_assert!(child.parent(app).is_none());
1525 if cfg!(debug_assertions) {
1526 let mut node = Some(self);
1527 while let Some(current) = node {
1528 debug_assert_ne!(current, child, "adopt_child would create a cycle");
1529 node = current.parent(app);
1530 }
1531 }
1532 self.setup_parent_data(app, child);
1533 self.mark_needs_layout(app);
1534 self.mark_needs_compositing_bits_update(app);
1535 child.set_parent(app, Some(self));
1536 if self.attached(app) {
1537 child.attach(app, self.owner(app).expect("attached parent has an owner"));
1538 }
1539 self.redepth_child(app, child);
1540 }
1541
1542 pub fn drop_child(self, app: &mut App, child: AnyRenderObject) {
1544 debug_assert_eq!(child.parent(app), Some(self));
1545 debug_assert_eq!(child.attached(app), self.attached(app));
1546 debug_assert!(child.parent_data(app).is_some());
1547 if !child.is_relayout_boundary(app).unwrap_or(true) {
1548 child.set_is_relayout_boundary(app, None);
1549 }
1550 if let Some(parent_data) = child.parent_data_mut(app) {
1551 parent_data.detach();
1552 }
1553 child.clear_parent_data(app);
1554 child.set_parent(app, None);
1555 if self.attached(app) {
1556 child.detach(app);
1557 }
1558 self.mark_needs_layout(app);
1559 self.mark_needs_compositing_bits_update(app);
1560 }
1561
1562 pub fn attach(self, app: &mut App, owner: Handle<PipelineOwner>) {
1567 debug_assert!(
1568 !app.is_disposed(self.id),
1569 "attach on a disposed render object"
1570 );
1571 debug_assert!(self.owner(app).is_none());
1572 self.data_mut(app).owner = Some(owner);
1573 if self.needs_layout(app) && self.is_relayout_boundary(app).is_some() {
1574 self.set_needs_layout(app, false);
1575 self.mark_needs_layout(app);
1576 }
1577 if self.needs_compositing_bits_update(app) {
1578 self.set_needs_compositing_bits_update(app, false);
1579 self.mark_needs_compositing_bits_update(app);
1580 }
1581 if self.needs_paint(app) && self.layer(app).is_some() {
1582 self.set_needs_paint(app, false);
1583 self.mark_needs_paint(app);
1584 }
1585 (self.vtable.did_attach)(app, self.id, owner)
1586 }
1587
1588 pub fn detach(self, app: &mut App) {
1593 debug_assert!(self.owner(app).is_some());
1594 self.data_mut(app).owner = None;
1595 debug_assert!(
1596 self.parent(app).is_none()
1597 || self.attached(app)
1598 == self.parent(app).is_some_and(|parent| parent.attached(app))
1599 );
1600 (self.vtable.did_detach)(app, self.id)
1601 }
1602
1603 pub fn mark_needs_layout(self, app: &mut App) {
1608 debug_assert!(
1609 !app.is_disposed(self.id),
1610 "mark_needs_layout on a disposed render object"
1611 );
1612 (self.vtable.mark_needs_layout)(app, self.id)
1613 }
1614
1615 pub fn mark_parent_needs_layout(self, app: &mut App) {
1618 self.set_needs_layout(app, true);
1619 let parent = self
1620 .parent(app)
1621 .expect("mark_parent_needs_layout requires a parent");
1622 if !self.doing_this_layout_with_callback(app) {
1623 parent.mark_needs_layout(app);
1624 } else {
1625 debug_assert!(parent.debug_doing_this_layout(app));
1626 }
1627 debug_assert_eq!(Some(parent), self.parent(app));
1628 }
1629
1630 pub fn invoke_layout_callback(self, app: &mut App, callback: impl FnOnce(&mut App)) {
1646 debug_assert!(self.debug_mutations_locked(app));
1647 debug_assert!(self.debug_doing_this_layout(app));
1648 debug_assert!(!self.doing_this_layout_with_callback(app));
1649 self.data_mut(app).doing_this_layout_with_callback = true;
1650 let owner = self.owner(app).expect("a laying-out object is attached");
1651 owner.enable_mutations_to_dirty_subtrees(app, callback);
1652 self.data_mut(app).doing_this_layout_with_callback = false;
1653 }
1654
1655 pub fn mark_needs_layout_for_sized_by_parent_change(self, app: &mut App) {
1656 self.mark_needs_layout(app);
1657 self.mark_parent_needs_layout(app);
1658 }
1659
1660 pub fn schedule_initial_layout(self, app: &mut App) {
1662 debug_assert!(self.attached(app));
1663 debug_assert!(self.parent(app).is_none());
1664 debug_assert!(!self.owner(app).expect("attached").debug_doing_layout(app));
1665 debug_assert!(self.is_relayout_boundary(app).is_none());
1666 self.set_is_relayout_boundary(app, Some(true));
1667 if cfg!(debug_assertions) {
1668 self.set_debug_can_parent_use_size(app, Some(false));
1669 }
1670 let owner = self.owner(app).expect("attached");
1671 owner.add_node_needing_layout(app, self);
1672 }
1673
1674 pub(crate) fn layout_without_resize(self, app: &mut App) {
1675 debug_assert!(self.needs_layout(app));
1676 debug_assert!(self.is_relayout_boundary(app).unwrap_or(false));
1677 let perform_layout = self.vtable.perform_layout;
1678 let previous = if cfg!(debug_assertions) {
1679 debug_assert!(!self.doing_this_layout_with_callback(app));
1680 self.set_debug_mutations_locked(app, true);
1681 self.set_debug_doing_this_layout(app, true);
1682 let previous = AnyRenderObject::debug_active_layout();
1683 AnyRenderObject::set_debug_active_layout(Some(self));
1684 if crate::debug::debug_print_layouts() {
1685 eprintln!("Laying out (without resize) {self:?}");
1686 }
1687 previous
1688 } else {
1689 None
1690 };
1691 perform_layout(app, self.id);
1692 if cfg!(debug_assertions) {
1693 AnyRenderObject::set_debug_active_layout(previous);
1694 self.set_debug_doing_this_layout(app, false);
1695 self.set_debug_mutations_locked(app, false);
1696 }
1697 self.set_needs_layout(app, false);
1698 self.mark_needs_paint(app);
1699 }
1700
1701 pub(crate) fn run_layout(
1703 self,
1704 app: &mut App,
1705 parent_uses_size: bool,
1706 constraints_tight: bool,
1707 same_constraints: bool,
1708 store_constraints: impl FnOnce(&mut App),
1709 ) {
1710 debug_assert!(!self.debug_doing_this_resize(app));
1711 debug_assert!(!self.debug_doing_this_layout(app));
1712 if cfg!(debug_assertions) {
1713 self.set_debug_can_parent_use_size(app, Some(parent_uses_size));
1714 }
1715
1716 let sized_by_parent = self.sized_by_parent(app);
1717 self.set_is_relayout_boundary(
1718 app,
1719 Some(
1720 !parent_uses_size
1721 || sized_by_parent
1722 || constraints_tight
1723 || self.parent(app).is_none(),
1724 ),
1725 );
1726 if !self.needs_layout(app) && same_constraints {
1727 return;
1728 }
1729 store_constraints(app);
1730
1731 if sized_by_parent {
1732 if cfg!(debug_assertions) {
1733 self.set_debug_doing_this_resize(app, true);
1734 }
1735 (self.vtable.perform_resize)(app, self.id);
1736 if cfg!(debug_assertions) {
1737 self.set_debug_doing_this_resize(app, false);
1738 }
1739 }
1740
1741 let previous = if cfg!(debug_assertions) {
1742 debug_assert!(!self.doing_this_layout_with_callback(app));
1743 self.set_debug_mutations_locked(app, true);
1744 self.set_debug_doing_this_layout(app, true);
1745 let previous = AnyRenderObject::debug_active_layout();
1746 AnyRenderObject::set_debug_active_layout(Some(self));
1747 if crate::debug::debug_print_layouts() {
1748 eprintln!(
1749 "Laying out ({}) {self:?}",
1750 if sized_by_parent {
1751 "with separate resize"
1752 } else {
1753 "with resize allowed"
1754 }
1755 );
1756 }
1757 previous
1758 } else {
1759 None
1760 };
1761 (self.vtable.perform_layout)(app, self.id);
1762 if cfg!(debug_assertions) {
1763 AnyRenderObject::set_debug_active_layout(previous);
1764 self.set_debug_doing_this_layout(app, false);
1765 self.set_debug_mutations_locked(app, false);
1766 }
1767 self.set_needs_layout(app, false);
1768 self.mark_needs_paint(app);
1769 }
1770
1771 pub(crate) fn needs_paint(self, app: &App) -> bool {
1774 self.data(app).needs_paint
1775 }
1776
1777 fn set_needs_paint(self, app: &mut App, value: bool) {
1778 self.data_mut(app).needs_paint = value;
1779 }
1780
1781 pub fn debug_needs_paint(self, app: &App) -> bool {
1785 if !cfg!(debug_assertions) {
1786 return false;
1787 }
1788 self.needs_paint(app)
1789 }
1790
1791 pub(crate) fn needs_composited_layer_update(self, app: &App) -> bool {
1792 self.data(app).needs_composited_layer_update
1793 }
1794
1795 pub(crate) fn set_needs_composited_layer_update(self, app: &mut App, value: bool) {
1796 self.data_mut(app).needs_composited_layer_update = value;
1797 }
1798
1799 pub fn debug_needs_composited_layer_update(self, app: &App) -> bool {
1803 if !cfg!(debug_assertions) {
1804 return false;
1805 }
1806 self.needs_composited_layer_update(app)
1807 }
1808
1809 pub(crate) fn was_repaint_boundary(self, app: &App) -> bool {
1810 self.data(app).was_repaint_boundary
1811 }
1812
1813 pub fn id(self) -> HandleId {
1815 self.id
1816 }
1817
1818 pub fn downcast<T: RenderObject>(self, app: &App) -> Option<RenderHandle<T>> {
1820 app.handle::<T>(self.id).map(RenderHandle::from_handle)
1821 }
1822
1823 pub fn dispose(self, app: &mut App) {
1830 debug_assert!(!self.attached(app));
1831 (self.vtable.dispose)(app, self.id);
1832 app.destroy(self.id);
1833 }
1834
1835 pub fn is_repaint_boundary(self, app: &App) -> bool {
1837 (self.vtable.is_repaint_boundary)(app, self.id)
1838 }
1839
1840 pub fn paint_bounds(self, app: &App) -> Rect {
1842 (self.vtable.paint_bounds)(app, self.id)
1843 }
1844
1845 pub fn apply_paint_transform(self, app: &App, child: AnyRenderObject, transform: &mut Matrix4) {
1847 (self.vtable.apply_paint_transform)(app, self.id, child, transform)
1848 }
1849
1850 pub fn get_transform_to(self, app: &App, target: Option<AnyRenderObject>) -> Matrix4 {
1861 debug_assert!(self.attached(app));
1862 let mut from_path: Option<Vec<AnyRenderObject>> = None;
1868 let mut to_path: Option<Vec<AnyRenderObject>> = None;
1871
1872 let mut from = self;
1873 let mut to = target.unwrap_or_else(|| {
1874 self.owner(app)
1875 .and_then(|owner| owner.root_node(app))
1876 .expect("an attached render object has a root")
1877 });
1878
1879 while from != to {
1880 let from_depth = from.depth(app);
1881 let to_depth = to.depth(app);
1882
1883 if from_depth >= to_depth {
1884 let from_parent = from.parent(app).unwrap_or_else(|| {
1885 panic!("{target:?} and {self:?} are not in the same render tree.")
1886 });
1887 from_path
1888 .get_or_insert_with(|| vec![self])
1889 .push(from_parent);
1890 from = from_parent;
1891 }
1892 if from_depth <= to_depth {
1893 let to_parent = to.parent(app).unwrap_or_else(|| {
1894 panic!("{target:?} and {self:?} are not in the same render tree.")
1895 });
1896 debug_assert!(
1897 target.is_some(),
1898 "{self:?} has a depth that is less than or equal to the root node"
1899 );
1900 to_path
1901 .get_or_insert_with(|| vec![target.expect("checked above")])
1902 .push(to_parent);
1903 to = to_parent;
1904 }
1905 }
1906
1907 let mut from_transform: Option<Matrix4> = None;
1908 if let Some(from_path) = &from_path {
1909 debug_assert!(from_path.len() > 1);
1910 let mut transform = Matrix4::IDENTITY;
1911 let last_index = if target.is_none() {
1912 from_path.len() - 2
1913 } else {
1914 from_path.len() - 1
1915 };
1916 for index in (1..=last_index).rev() {
1917 from_path[index].apply_paint_transform(app, from_path[index - 1], &mut transform);
1918 }
1919 from_transform = Some(transform);
1920 }
1921 let Some(to_path) = to_path else {
1922 return from_transform.unwrap_or(Matrix4::IDENTITY);
1923 };
1924
1925 debug_assert!(to_path.len() > 1);
1926 let mut to_transform = Matrix4::IDENTITY;
1927 for index in (1..to_path.len()).rev() {
1928 to_path[index].apply_paint_transform(app, to_path[index - 1], &mut to_transform);
1929 }
1930 let Some(to_transform) = to_transform.invert() else {
1931 return zero_matrix();
1933 };
1934 match from_transform {
1935 Some(mut from_transform) => {
1936 multiply(&mut from_transform, &to_transform);
1937 from_transform
1938 }
1939 None => to_transform,
1940 }
1941 }
1942
1943 pub fn mouse_tracker_annotation(self, app: &App) -> Option<MouseTrackerAnnotation> {
1946 if !app.contains(self.id) {
1947 return None;
1948 }
1949 (self.vtable.mouse_tracker_annotation)(app, self.id)
1950 }
1951
1952 pub fn interface<I: 'static>(self) -> Option<I> {
1955 (self.vtable.interface)(self.id, TypeId::of::<I>())?
1956 .downcast()
1957 .ok()
1958 .map(|handle| *handle)
1959 }
1960
1961 pub fn show_on_screen(
1963 self,
1964 app: &mut App,
1965 descendant: Option<AnyRenderObject>,
1966 rect: Option<Rect>,
1967 duration: Duration,
1968 curve: Rc<dyn Curve>,
1969 ) {
1970 (self.vtable.show_on_screen)(app, self.id, descendant, rect, duration, curve)
1971 }
1972
1973 pub fn update_composited_layer(
1975 self,
1976 app: &mut App,
1977 old_layer: Option<AnyOffsetLayer>,
1978 ) -> AnyOffsetLayer {
1979 (self.vtable.update_composited_layer)(app, self.id, old_layer)
1980 }
1981
1982 pub fn always_needs_compositing(self, app: &App) -> bool {
1984 (self.vtable.always_needs_compositing)(app, self.id)
1985 }
1986
1987 pub fn layer(self, app: &App) -> Option<AnyContainerLayer> {
2005 debug_assert!(
2006 !self.is_repaint_boundary(app)
2007 || self.data(app).layer.layer().is_none()
2008 || self
2009 .data(app)
2010 .layer
2011 .layer()
2012 .is_some_and(|layer| layer.as_offset_layer().is_some())
2013 );
2014 self.data(app).layer.layer()
2015 }
2016
2017 pub fn set_layer(self, app: &mut App, new_layer: Option<AnyContainerLayer>) {
2020 debug_assert!(
2021 !self.is_repaint_boundary(app),
2022 "Attempted to set a layer to a repaint boundary render object.\n\
2023 The framework creates and assigns an OffsetLayer to a repaint \
2024 boundary automatically."
2025 );
2026 LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, new_layer);
2027 }
2028
2029 pub fn layer_as<T: 'static>(self, app: &App) -> Option<Handle<T>> {
2031 self.layer(app)
2032 .and_then(|layer| app.handle::<T>(layer.id()))
2033 }
2034
2035 pub fn debug_layer(self, app: &App) -> Option<AnyContainerLayer> {
2043 if !cfg!(debug_assertions) {
2044 return None;
2045 }
2046 self.data(app).layer.layer()
2047 }
2048
2049 pub(crate) fn needs_compositing_bits_update(self, app: &App) -> bool {
2050 self.data(app).needs_compositing_bits_update
2051 }
2052
2053 fn set_needs_compositing_bits_update(self, app: &mut App, value: bool) {
2054 self.data_mut(app).needs_compositing_bits_update = value;
2055 }
2056
2057 pub fn mark_needs_compositing_bits_update(self, app: &mut App) {
2074 debug_assert!(
2075 !app.is_disposed(self.id),
2076 "mark_needs_compositing_bits_update on a disposed render object"
2077 );
2078 if self.needs_compositing_bits_update(app) {
2079 return;
2080 }
2081 self.set_needs_compositing_bits_update(app, true);
2082 if let Some(parent) = self.parent(app) {
2083 if parent.needs_compositing_bits_update(app) {
2084 return;
2085 }
2086 if (!self.data(app).needs_compositing || !self.is_repaint_boundary(app))
2090 && !parent.is_repaint_boundary(app)
2091 {
2092 parent.mark_needs_compositing_bits_update(app);
2093 return;
2094 }
2095 }
2096 if let Some(owner) = self.owner(app) {
2098 owner.add_node_needing_compositing_bits_update(app, self);
2099 }
2100 }
2101
2102 pub fn needs_compositing(self, app: &App) -> bool {
2110 debug_assert!(
2111 !self.needs_compositing_bits_update(app),
2112 "make sure we don't use this bit when it is dirty"
2113 );
2114 self.data(app).needs_compositing
2115 }
2116
2117 pub(crate) fn update_compositing_bits(self, app: &mut App) {
2119 if !self.needs_compositing_bits_update(app) {
2120 return;
2121 }
2122 let old_needs_compositing = self.data(app).needs_compositing;
2123 self.data_mut(app).needs_compositing = false;
2124 let mut children = Vec::new();
2125 self.visit_children(app, &mut |child| children.push(child));
2126 for child in children {
2127 child.update_compositing_bits(app);
2128 if child.needs_compositing(app) {
2129 self.data_mut(app).needs_compositing = true;
2130 }
2131 }
2132 if self.is_repaint_boundary(app) || self.always_needs_compositing(app) {
2133 self.data_mut(app).needs_compositing = true;
2134 }
2135 if !self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2141 self.set_needs_paint(app, false);
2142 self.set_needs_composited_layer_update(app, false);
2143 if let Some(owner) = self.owner(app) {
2144 owner.remove_node_needing_paint(app, self);
2145 }
2146 self.set_needs_compositing_bits_update(app, false);
2147 self.mark_needs_paint(app);
2148 } else if old_needs_compositing != self.data(app).needs_compositing {
2149 self.set_needs_compositing_bits_update(app, false);
2150 self.mark_needs_paint(app);
2151 } else {
2152 self.set_needs_compositing_bits_update(app, false);
2153 }
2154 }
2155
2156 pub fn mark_needs_paint(self, app: &mut App) {
2163 debug_assert!(
2164 !app.is_disposed(self.id),
2165 "mark_needs_paint on a disposed render object"
2166 );
2167 debug_assert!(
2168 self.owner(app)
2169 .is_none_or(|owner| !owner.debug_doing_paint(app))
2170 );
2171 if self.needs_paint(app) {
2172 return;
2173 }
2174 self.set_needs_paint(app, true);
2175 if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2176 if crate::debug::debug_print_mark_needs_paint_stacks() {
2177 eprintln!("markNeedsPaint() called for {self:?}");
2178 }
2179 debug_assert!(
2180 self.layer(app)
2181 .is_some_and(|layer| layer.as_offset_layer().is_some())
2182 );
2183 if let Some(owner) = self.owner(app) {
2184 owner.add_node_needing_paint(app, self);
2185 owner.request_visual_update(app);
2186 }
2187 } else if let Some(parent) = self.parent(app) {
2188 parent.mark_needs_paint(app);
2189 } else {
2190 if crate::debug::debug_print_mark_needs_paint_stacks() {
2191 eprintln!("markNeedsPaint() called for {self:?} (root of render tree)");
2192 }
2193 if let Some(owner) = self.owner(app) {
2194 owner.request_visual_update(app);
2195 }
2196 }
2197 }
2198
2199 pub fn mark_needs_composited_layer_update(self, app: &mut App) {
2212 debug_assert!(
2213 !app.is_disposed(self.id),
2214 "mark_needs_composited_layer_update on a disposed render object"
2215 );
2216 debug_assert!(
2217 self.owner(app)
2218 .is_none_or(|owner| !owner.debug_doing_paint(app))
2219 );
2220 if self.needs_composited_layer_update(app) || self.needs_paint(app) {
2221 return;
2222 }
2223 self.set_needs_composited_layer_update(app, true);
2224 if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2225 debug_assert!(self.layer(app).is_some());
2226 if let Some(owner) = self.owner(app) {
2227 owner.add_node_needing_paint(app, self);
2228 owner.request_visual_update(app);
2229 }
2230 } else {
2231 self.mark_needs_paint(app);
2232 }
2233 }
2234
2235 pub(crate) fn skipped_painting_on_layer(self, app: &mut App) {
2238 debug_assert!(self.attached(app));
2239 debug_assert!(self.is_repaint_boundary(app));
2240 debug_assert!(self.needs_paint(app) || self.needs_composited_layer_update(app));
2241 debug_assert!(self.layer(app).is_some());
2242 debug_assert!(
2243 self.layer(app)
2244 .is_some_and(|layer| !layer.as_layer().attached(app))
2245 );
2246 let mut node = self.parent(app);
2247 while let Some(current) = node {
2248 if current.is_repaint_boundary(app) {
2249 match current.layer(app) {
2250 None => break,
2251 Some(layer) if layer.as_layer().attached(app) => break,
2252 Some(_) => current.set_needs_paint(app, true),
2253 }
2254 }
2255 node = current.parent(app);
2256 }
2257 }
2258
2259 pub fn schedule_initial_paint(self, app: &mut App, root_layer: AnyContainerLayer) {
2264 debug_assert!(root_layer.as_layer().attached(app));
2265 debug_assert!(self.attached(app));
2266 debug_assert!(self.parent(app).is_none());
2267 debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2268 debug_assert!(self.is_repaint_boundary(app));
2269 debug_assert!(self.layer(app).is_none());
2270 LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, Some(root_layer));
2271 debug_assert!(self.needs_paint(app));
2272 let owner = self.owner(app).expect("attached");
2273 owner.add_node_needing_paint(app, self);
2274 }
2275
2276 pub fn replace_root_layer(self, app: &mut App, root_layer: AnyOffsetLayer) {
2282 debug_assert!(
2283 !app.is_disposed(self.id),
2284 "replace_root_layer on a disposed render object"
2285 );
2286 debug_assert!(root_layer.as_layer().attached(app));
2287 debug_assert!(self.attached(app));
2288 debug_assert!(self.parent(app).is_none());
2289 debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2290 debug_assert!(self.is_repaint_boundary(app));
2291 debug_assert!(
2292 self.layer(app).is_some(),
2293 "use schedule_initial_paint the first time"
2294 );
2295 self.layer(app).expect("checked").as_layer().detach(app);
2296 LayerHandle::set_layer(
2297 app,
2298 |app| &mut self.data_mut(app).layer,
2299 Some(root_layer.as_container_layer()),
2300 );
2301 self.mark_needs_paint(app);
2302 }
2303
2304 pub(crate) fn paint_with_context(
2306 self,
2307 app: &mut App,
2308 context: &mut PaintingContext,
2309 offset: Offset,
2310 ) {
2311 debug_assert!(
2312 !self.data(app).debug_doing_this_paint,
2313 "Tried to paint a RenderObject reentrantly: {self:?}"
2314 );
2315 if self.needs_layout(app) {
2316 return;
2317 }
2318 debug_assert!(
2319 !self.needs_compositing_bits_update(app),
2320 "Tried to paint a RenderObject before its compositing bits were updated.\n\
2321 The following RenderObject was marked as having dirty compositing bits \
2322 at the time that it was painted: {self:?}\n\
2323 A RenderObject that still has dirty compositing bits cannot be painted \
2324 because this indicates that the tree has not yet been properly configured \
2325 for creating the layer tree.\n\
2326 This usually indicates an error in the Flutter framework itself."
2327 );
2328 let debug_last_active_paint = if cfg!(debug_assertions) {
2329 self.data_mut(app).debug_doing_this_paint = true;
2330 let previous = DEBUG_ACTIVE_PAINT.replace(Some(self));
2331 debug_assert!(!self.is_repaint_boundary(app) || self.layer(app).is_some());
2332 previous
2333 } else {
2334 None
2335 };
2336 self.set_needs_paint(app, false);
2337 self.set_needs_composited_layer_update(app, false);
2338 let is_repaint_boundary = self.is_repaint_boundary(app);
2339 self.data_mut(app).was_repaint_boundary = is_repaint_boundary;
2340 (self.vtable.paint)(app, self.id, context, offset);
2341 debug_assert!(!self.needs_layout(app));
2342 debug_assert!(!self.needs_paint(app));
2343 if cfg!(debug_assertions) {
2344 DEBUG_ACTIVE_PAINT.set(debug_last_active_paint);
2345 self.data_mut(app).debug_doing_this_paint = false;
2346 }
2347 }
2348}
2349
2350pub trait RenderObjectBase: RenderObject {
2355 fn dispose(self: RenderHandle<Self>, app: &mut App) {
2358 LayerHandle::set_layer(app, |app| &mut self.render_object_data_mut(app).layer, None);
2359 }
2360
2361 fn mark_needs_layout(self: RenderHandle<Self>, app: &mut App) {
2364 let this = self.as_render_object(app);
2365 if this.needs_layout(app) {
2366 return;
2367 }
2368 this.set_needs_layout(app, true);
2369 if let Some(owner) = this.owner(app)
2370 && this.is_relayout_boundary(app).unwrap_or(false)
2371 {
2372 if crate::debug::debug_print_mark_needs_layout_stacks() {
2373 eprintln!("markNeedsLayout() called for {this:?}");
2374 }
2375 owner.add_node_needing_layout(app, this);
2376 owner.request_visual_update(app);
2377 } else if this.parent(app).is_some() {
2378 this.mark_parent_needs_layout(app);
2379 }
2380 }
2381
2382 fn show_on_screen(
2384 self: RenderHandle<Self>,
2385 app: &mut App,
2386 descendant: Option<AnyRenderObject>,
2387 rect: Option<Rect>,
2388 duration: Duration,
2389 curve: Rc<dyn Curve>,
2390 ) {
2391 let this = self.as_render_object(app);
2392 if let Some(parent) = this.parent(app) {
2393 parent.show_on_screen(app, Some(descendant.unwrap_or(this)), rect, duration, curve);
2394 }
2395 }
2396}
2397
2398impl<T: RenderObject> RenderObjectBase for T {}
2399
2400pub(crate) fn zero_matrix() -> Matrix4 {
2402 Matrix4::from_flutter_array(&[0.0; 16])
2403}
2404
2405pub(crate) fn multiply(transform: &mut Matrix4, other: &Matrix4) {
2408 *transform = transform.then(other);
2409}
2410
2411pub(crate) fn translate(transform: &mut Matrix4, dx: f64, dy: f64) {
2413 multiply(transform, &Matrix4::translation(dx as f32, dy as f32));
2414}
2415
2416pub(crate) fn perspective_transform(transform: &Matrix4, point: [f64; 3]) -> [f64; 3] {
2419 let m = transform.to_flutter_array().map(f64::from);
2420 let [x, y, z] = point;
2421 let out = |row: usize| m[row] * x + m[4 + row] * y + m[8 + row] * z + m[12 + row];
2422 let w = out(3);
2423 [out(0) / w, out(1) / w, out(2) / w]
2424}
2425
2426#[derive(Debug)]
2428pub struct RenderObjectWithLayoutCallbackData {
2429 needs_rebuild: bool,
2433}
2434
2435impl Default for RenderObjectWithLayoutCallbackData {
2436 fn default() -> RenderObjectWithLayoutCallbackData {
2437 RenderObjectWithLayoutCallbackData {
2438 needs_rebuild: true,
2439 }
2440 }
2441}
2442
2443pub trait RenderObjectWithLayoutCallbackMixin: crate::box_::RenderBox {
2451 fn layout_callback_data(
2453 self: RenderHandle<Self>,
2454 app: &App,
2455 ) -> &RenderObjectWithLayoutCallbackData;
2456
2457 fn layout_callback_data_mut(
2459 self: RenderHandle<Self>,
2460 app: &mut App,
2461 ) -> &mut RenderObjectWithLayoutCallbackData;
2462
2463 fn layout_callback(self: RenderHandle<Self>, app: &mut App);
2467
2468 fn run_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2473 debug_assert!(self.as_object().debug_doing_this_layout(app));
2474 self.as_object()
2475 .invoke_layout_callback(app, |app| Self::layout_callback(self, app));
2476 self.layout_callback_data_mut(app).needs_rebuild = false;
2477 }
2478
2479 fn schedule_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2482 if self.layout_callback_data(app).needs_rebuild {
2483 debug_assert!(self.as_object().needs_layout(app));
2484 return;
2485 }
2486 self.layout_callback_data_mut(app).needs_rebuild = true;
2487 if let Some(owner) = self.as_object().owner(app) {
2492 owner.add_node_needing_layout(app, self.as_object());
2493 }
2494 self.as_object().mark_needs_layout(app);
2497 }
2498}
2499
2500#[cfg(test)]
2501mod tests {
2502 use std::cell::Cell;
2503 use std::rc::Rc;
2504
2505 use inset_foundation::{App, AppCell, Listener};
2506
2507 use super::*;
2508 use crate::box_::{BoxConstraints, RenderBox, RenderBoxData};
2509 use crate::pipeline_owner::PipelineOwner;
2510
2511 struct TestLeaf {
2512 render_object: RenderObjectData,
2513 render_box: RenderBoxData,
2514 layouts: Rc<Cell<u32>>,
2515 }
2516
2517 impl RenderObject for TestLeaf {
2518 render_object_accessors!();
2519
2520 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2521 let layouts = self.get(app).layouts.clone();
2522 layouts.set(layouts.get() + 1);
2523 let size = self.constraints(app).smallest();
2524 self.set_size(app, size);
2525 }
2526 }
2527
2528 impl RenderBox for TestLeaf {
2529 crate::render_box_accessors!();
2530 }
2531
2532 struct TestParent {
2533 render_object: RenderObjectData,
2534 render_box: RenderBoxData,
2535 child: Option<crate::AnyRenderBox>,
2536 layouts: Rc<Cell<u32>>,
2537 parent_uses_size: bool,
2538 lay_out_child: bool,
2539 }
2540
2541 impl RenderObject for TestParent {
2542 render_object_accessors!();
2543
2544 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2545 let layouts = self.get(app).layouts.clone();
2546 layouts.set(layouts.get() + 1);
2547 let child = self.get(app).child;
2548 let parent_uses_size = self.get(app).parent_uses_size;
2549 let lay_out_child = self.get(app).lay_out_child;
2550 let constraints = self.constraints(app);
2551 if let Some(child) = child
2552 && lay_out_child
2553 {
2554 child.layout(app, constraints, parent_uses_size);
2555 let _again = self.get(app).layouts.get();
2556 if parent_uses_size {
2557 self.set_size(app, child.size(app));
2558 return;
2559 }
2560 }
2561 self.set_size(app, constraints.smallest());
2562 }
2563
2564 fn visit_children(
2565 self: RenderHandle<Self>,
2566 app: &App,
2567 visitor: &mut dyn FnMut(AnyRenderObject),
2568 ) {
2569 if let Some(child) = self.get(app).child {
2570 visitor(child.as_object());
2571 }
2572 }
2573 }
2574
2575 impl RenderBox for TestParent {
2576 crate::render_box_accessors!();
2577 }
2578
2579 fn tight() -> BoxConstraints {
2580 BoxConstraints::tight_for_finite(100.0, 100.0)
2581 }
2582
2583 fn loose() -> BoxConstraints {
2584 BoxConstraints::new()
2585 }
2586
2587 fn leaf(layouts: Rc<Cell<u32>>) -> TestLeaf {
2588 TestLeaf {
2589 render_object: RenderObjectData::new(),
2590 render_box: RenderBoxData::new(),
2591 layouts,
2592 }
2593 }
2594
2595 fn parent(
2596 child: Option<crate::AnyRenderBox>,
2597 layouts: Rc<Cell<u32>>,
2598 parent_uses_size: bool,
2599 lay_out_child: bool,
2600 ) -> TestParent {
2601 TestParent {
2602 render_object: RenderObjectData::new(),
2603 render_box: RenderBoxData::new(),
2604 child,
2605 layouts,
2606 parent_uses_size,
2607 lay_out_child,
2608 }
2609 }
2610
2611 #[test]
2613 fn nodes_needing_layout_updated_with_layout_changes() {
2614 let cell = AppCell::new();
2615 let mut app = cell.borrow_mut();
2616 let owner = PipelineOwner::new(&mut app, None, None);
2617 let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2618 node.as_object().attach(&mut app, owner);
2619 assert!(owner.nodes_needing_layout(&app).is_empty());
2620
2621 node.layout(&mut app, tight(), false);
2622 node.as_object().mark_needs_layout(&mut app);
2623 assert!(owner.nodes_needing_layout(&app).contains(&node.as_object()));
2624
2625 owner.flush_layout(&mut app);
2626 assert!(owner.nodes_needing_layout(&app).is_empty());
2627 }
2628
2629 #[test]
2630 fn clean_layout_skips_perform_layout() {
2631 let cell = AppCell::new();
2632 let mut app = cell.borrow_mut();
2633 let layouts = Rc::new(Cell::new(0));
2634 let node = RenderHandle::new_box(&mut app, leaf(Rc::clone(&layouts)));
2635 node.layout(&mut app, tight(), false);
2636 assert_eq!(layouts.get(), 1);
2637 node.layout(&mut app, tight(), false);
2638 assert_eq!(layouts.get(), 1);
2639 node.as_object().mark_needs_layout(&mut app);
2640 node.layout(&mut app, tight(), false);
2641 assert_eq!(layouts.get(), 2);
2642 }
2643
2644 #[test]
2645 fn parent_uses_size_marks_parent() {
2646 let cell = AppCell::new();
2647 let mut app = cell.borrow_mut();
2648 let owner = PipelineOwner::new(&mut app, None, None);
2649 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2650 let parent = RenderHandle::new_box(
2651 &mut app,
2652 parent(Some(child.as_box()), Rc::new(Cell::new(0)), true, true),
2653 );
2654 parent.adopt_child(&mut app, child.as_object());
2655 parent.as_object().attach(&mut app, owner);
2656 parent.layout(&mut app, loose(), false);
2657 assert!(!parent.debug_needs_layout(&app));
2658 assert!(!child.debug_needs_layout(&app));
2659
2660 child.as_object().mark_needs_layout(&mut app);
2661 assert!(parent.debug_needs_layout(&app));
2662 assert!(
2663 owner
2664 .nodes_needing_layout(&app)
2665 .contains(&parent.as_object())
2666 );
2667 }
2668
2669 #[test]
2670 fn adopt_drop_attach_detach() {
2671 let cell = AppCell::new();
2672 let mut app = cell.borrow_mut();
2673 let owner = PipelineOwner::new(&mut app, None, None);
2674 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2675 let parent = RenderHandle::new_box(
2676 &mut app,
2677 parent(Some(child.as_box()), Rc::new(Cell::new(0)), false, true),
2678 );
2679 parent.adopt_child(&mut app, child.as_object());
2680 assert_eq!(child.parent(&app), Some(parent.as_object()));
2681 assert_eq!(
2682 child.as_object().depth(&app),
2683 parent.as_object().depth(&app) + 1
2684 );
2685 assert!(!child.attached(&app));
2686
2687 parent.as_object().attach(&mut app, owner);
2688 assert!(parent.attached(&app));
2689 assert!(child.attached(&app));
2690 assert_eq!(child.owner(&app), Some(owner));
2691
2692 parent.drop_child(&mut app, child.as_object());
2693 assert!(child.parent(&app).is_none());
2694 assert!(!child.attached(&app));
2695 assert!(parent.attached(&app));
2696 }
2697
2698 #[test]
2699 fn parent_reenters_itself_after_child_layout() {
2700 let cell = AppCell::new();
2701 let mut app = cell.borrow_mut();
2702 let layouts = Rc::new(Cell::new(0));
2703 let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2704 let parent = RenderHandle::new_box(
2705 &mut app,
2706 parent(Some(child.as_box()), Rc::clone(&layouts), true, true),
2707 );
2708 parent.adopt_child(&mut app, child.as_object());
2709 parent.layout(&mut app, loose(), false);
2710 assert_eq!(layouts.get(), 1);
2711 assert_eq!(parent.size(&app), child.size(&app));
2712 }
2713
2714 #[test]
2715 fn flush_layout_orders_by_depth() {
2716 let cell = AppCell::new();
2717 let mut app = cell.borrow_mut();
2718 let owner = PipelineOwner::new(&mut app, None, None);
2719 let order = Rc::new(std::cell::RefCell::new(Vec::new()));
2720 let child_order = Rc::clone(&order);
2721 let parent_order = Rc::clone(&order);
2722
2723 struct OrderLeaf {
2724 render_object: RenderObjectData,
2725 render_box: RenderBoxData,
2726 name: &'static str,
2727 order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2728 }
2729 impl RenderObject for OrderLeaf {
2730 render_object_accessors!();
2731
2732 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2733 let name = self.get(app).name;
2734 self.get(app).order.borrow_mut().push(name);
2735 let size = self.constraints(app).smallest();
2736 self.set_size(app, size);
2737 }
2738 }
2739 impl RenderBox for OrderLeaf {
2740 crate::render_box_accessors!();
2741 }
2742
2743 struct OrderParent {
2744 render_object: RenderObjectData,
2745 render_box: RenderBoxData,
2746 name: &'static str,
2747 child: Option<crate::AnyRenderBox>,
2748 order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2749 }
2750 impl RenderObject for OrderParent {
2751 render_object_accessors!();
2752
2753 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2754 let name = self.get(app).name;
2755 self.get(app).order.borrow_mut().push(name);
2756 let size = self.constraints(app).smallest();
2757 self.set_size(app, size);
2758 }
2759 fn visit_children(
2760 self: RenderHandle<Self>,
2761 app: &App,
2762 visitor: &mut dyn FnMut(AnyRenderObject),
2763 ) {
2764 if let Some(child) = self.get(app).child {
2765 visitor(child.as_object());
2766 }
2767 }
2768 }
2769 impl RenderBox for OrderParent {
2770 crate::render_box_accessors!();
2771 }
2772
2773 let child = RenderHandle::new_box(
2774 &mut app,
2775 OrderLeaf {
2776 render_object: RenderObjectData::new(),
2777 render_box: RenderBoxData::new(),
2778 name: "child",
2779 order: child_order,
2780 },
2781 );
2782 let parent = RenderHandle::new_box(
2783 &mut app,
2784 OrderParent {
2785 render_object: RenderObjectData::new(),
2786 render_box: RenderBoxData::new(),
2787 name: "parent",
2788 child: Some(child.as_box()),
2789 order: parent_order,
2790 },
2791 );
2792 parent.adopt_child(&mut app, child.as_object());
2793 parent.as_object().attach(&mut app, owner);
2794 parent.layout(&mut app, tight(), false);
2795 child.layout(&mut app, tight(), false);
2796 parent.as_object().mark_needs_layout(&mut app);
2797 child.as_object().mark_needs_layout(&mut app);
2798 order.borrow_mut().clear();
2799 owner.flush_layout(&mut app);
2800 assert_eq!(*order.borrow(), ["parent", "child"]);
2801 }
2802
2803 #[test]
2804 fn mark_needs_layout_requests_visual_update() {
2805 let cell = AppCell::new();
2806 let mut app = cell.borrow_mut();
2807 let updates = Rc::new(Cell::new(0));
2808 let updates_cb = Rc::clone(&updates);
2809 let owner = PipelineOwner::new(
2810 &mut app,
2811 Some(Listener::new(move |_| {
2812 updates_cb.set(updates_cb.get() + 1);
2813 })),
2814 None,
2815 );
2816 let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2817 owner.set_root_node(&mut app, Some(node.as_object()));
2818 node.layout(&mut app, tight(), false);
2819 assert_eq!(updates.get(), 0);
2820 node.as_object().mark_needs_layout(&mut app);
2821 assert_eq!(updates.get(), 1);
2822 }
2823}