1use std::any::{Any, TypeId};
6use std::fmt::{self, Debug, Display};
7use std::rc::Rc;
8
9use indexmap::IndexMap;
10use inset_embedder::{Matrix4, Offset};
11use inset_foundation::{App, Handle};
12use inset_painting::{Axis, AxisDirection};
13
14use crate::box_::{AnyRenderBox, BoxConstraints, BoxHitTestResult};
15use crate::object::{
16 AnyRenderObject, ContainerParentData, ContainerParentDataMixin, ContainerRenderObjectBase,
17 ContainerRenderObjectMixin, ParentData, RenderHandle, zero_matrix,
18};
19use crate::painting_context::PaintingContext;
20use crate::pipeline_owner::PipelineOwner;
21use crate::sliver::{
22 RenderSliver, RenderSliverHelpers, SliverConstraints, SliverHitTestResult,
23 SliverLogicalParentData, apply_growth_direction_to_axis_direction,
24};
25
26pub trait RenderSliverBoxChildManager {
36 fn create_child(&self, app: &mut App, index: i32, after: Option<AnyRenderBox>);
58
59 fn remove_child(&self, app: &mut App, child: AnyRenderBox);
67
68 fn estimate_max_scroll_offset(
73 &self,
74 app: &App,
75 constraints: SliverConstraints,
76 first_index: Option<i32>,
77 last_index: Option<i32>,
78 leading_scroll_offset: Option<f64>,
79 trailing_scroll_offset: Option<f64>,
80 ) -> f64;
81
82 fn child_count(&self, app: &mut App) -> i32;
91
92 fn estimated_child_count(&self, app: &App) -> Option<i32> {
95 let _ = app;
96 None
97 }
98
99 fn did_adopt_child(&self, app: &mut App, child: AnyRenderBox);
106
107 fn set_did_underflow(&self, app: &mut App, value: bool);
115
116 fn did_start_layout(&self, app: &mut App) {
118 let _ = app;
119 }
120
121 fn did_finish_layout(&self, app: &mut App) {
123 let _ = app;
124 }
125
126 fn debug_assert_child_list_locked(&self, app: &App) -> bool {
131 let _ = app;
132 true
133 }
134}
135
136#[derive(Clone, Copy, Debug, Default)]
141pub struct KeepAliveParentData {
142 pub keep_alive: bool,
144 kept_alive: bool,
145}
146
147impl KeepAliveParentData {
148 pub const fn new() -> KeepAliveParentData {
150 KeepAliveParentData {
151 keep_alive: false,
152 kept_alive: false,
153 }
154 }
155
156 pub fn kept_alive(&self) -> bool {
159 self.kept_alive
160 }
161}
162
163pub trait RenderSliverWithKeepAliveMixin: RenderSliver {
168 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
171 let _ = self;
172 debug_assert!(
173 child
174 .parent_data(app)
175 .is_some_and(|parent_data| parent_data.part::<KeepAliveParentData>().is_some())
176 );
177 }
178}
179
180#[derive(Debug)]
182pub struct SliverMultiBoxAdaptorParentData {
183 sliver_logical: SliverLogicalParentData,
184 container: ContainerParentData<AnyRenderBox>,
185 keep_alive: KeepAliveParentData,
186 pub index: Option<i32>,
188}
189
190impl SliverMultiBoxAdaptorParentData {
191 pub const fn new() -> SliverMultiBoxAdaptorParentData {
193 SliverMultiBoxAdaptorParentData {
194 sliver_logical: SliverLogicalParentData::new(),
195 container: ContainerParentData::new(),
196 keep_alive: KeepAliveParentData::new(),
197 index: None,
198 }
199 }
200
201 pub fn layout_offset(&self) -> Option<f64> {
203 self.sliver_logical.layout_offset
204 }
205
206 pub fn set_layout_offset(&mut self, value: Option<f64>) {
208 self.sliver_logical.layout_offset = value;
209 }
210
211 pub fn keep_alive(&self) -> bool {
213 self.keep_alive.keep_alive
214 }
215
216 pub fn set_keep_alive(&mut self, value: bool) {
218 self.keep_alive.keep_alive = value;
219 }
220
221 pub fn kept_alive(&self) -> bool {
223 self.keep_alive.kept_alive
224 }
225}
226
227impl Default for SliverMultiBoxAdaptorParentData {
228 fn default() -> SliverMultiBoxAdaptorParentData {
229 SliverMultiBoxAdaptorParentData::new()
230 }
231}
232
233impl ParentData for SliverMultiBoxAdaptorParentData {
234 fn detach(&mut self) {
235 ContainerParentDataMixin::detach(self);
236 }
237
238 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
239 if id == TypeId::of::<SliverMultiBoxAdaptorParentData>() {
240 return Some(self);
241 }
242 if id == TypeId::of::<KeepAliveParentData>() {
243 return Some(&self.keep_alive);
244 }
245 self.sliver_logical.provide(id)
246 }
247
248 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
249 if id == TypeId::of::<SliverMultiBoxAdaptorParentData>() {
250 return Some(self);
251 }
252 if id == TypeId::of::<KeepAliveParentData>() {
253 return Some(&mut self.keep_alive);
254 }
255 self.sliver_logical.provide_mut(id)
256 }
257}
258
259impl ContainerParentDataMixin for SliverMultiBoxAdaptorParentData {
260 type ChildType = AnyRenderBox;
261
262 fn container_parent_data(&self) -> &ContainerParentData<AnyRenderBox> {
263 &self.container
264 }
265
266 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<AnyRenderBox> {
267 &mut self.container
268 }
269}
270
271impl Display for SliverMultiBoxAdaptorParentData {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 write!(f, "index={:?}; ", self.index)?;
274 if self.keep_alive() {
275 f.write_str("keepAlive; ")?;
276 }
277 Display::fmt(&self.sliver_logical, f)
278 }
279}
280
281pub struct RenderSliverMultiBoxAdaptorData {
283 child_manager: Rc<dyn RenderSliverBoxChildManager>,
284 keep_alive_bucket: IndexMap<i32, AnyRenderBox>,
286 debug_dangling_keep_alives: Vec<AnyRenderBox>,
287 debug_child_integrity_enabled: bool,
288}
289
290impl RenderSliverMultiBoxAdaptorData {
291 pub fn new(
293 child_manager: Rc<dyn RenderSliverBoxChildManager>,
294 ) -> RenderSliverMultiBoxAdaptorData {
295 RenderSliverMultiBoxAdaptorData {
296 child_manager,
297 keep_alive_bucket: IndexMap::new(),
298 debug_dangling_keep_alives: Vec::new(),
299 debug_child_integrity_enabled: true,
300 }
301 }
302}
303
304#[macro_export]
306macro_rules! render_sliver_multi_box_adaptor_accessors {
307 () => {
308 fn adaptor_data(
309 self: $crate::RenderHandle<Self>,
310 app: &::inset_foundation::App,
311 ) -> &$crate::RenderSliverMultiBoxAdaptorData {
312 &self.get(app).adaptor
313 }
314 fn adaptor_data_mut(
315 self: $crate::RenderHandle<Self>,
316 app: &mut ::inset_foundation::App,
317 ) -> &mut $crate::RenderSliverMultiBoxAdaptorData {
318 &mut self.get_mut(app).adaptor
319 }
320 };
321}
322
323pub trait RenderSliverMultiBoxAdaptor:
346 RenderSliver
347 + RenderSliverHelpers
348 + RenderSliverWithKeepAliveMixin
349 + ContainerRenderObjectMixin<
350 ChildType = AnyRenderBox,
351 ParentDataType = SliverMultiBoxAdaptorParentData,
352 >
353{
354 fn adaptor_data(self: RenderHandle<Self>, app: &App) -> &RenderSliverMultiBoxAdaptorData;
356
357 fn adaptor_data_mut(
359 self: RenderHandle<Self>,
360 app: &mut App,
361 ) -> &mut RenderSliverMultiBoxAdaptorData;
362
363 fn child_manager(self: RenderHandle<Self>, app: &App) -> Rc<dyn RenderSliverBoxChildManager> {
369 Rc::clone(&self.adaptor_data(app).child_manager)
370 }
371
372 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
374 if !child.parent_data_is::<SliverMultiBoxAdaptorParentData>(app) {
375 child.set_parent_data(app, SliverMultiBoxAdaptorParentData::new());
376 }
377 }
378
379 fn debug_child_integrity_enabled(self: RenderHandle<Self>, app: &App) -> bool {
387 self.adaptor_data(app).debug_child_integrity_enabled
388 }
389
390 fn set_debug_child_integrity_enabled(self: RenderHandle<Self>, app: &mut App, enabled: bool) {
393 if !cfg!(debug_assertions) {
394 return;
395 }
396 self.adaptor_data_mut(app).debug_child_integrity_enabled = enabled;
397 debug_assert!(self.debug_verify_child_order(app));
398 debug_assert!(
399 !enabled || self.adaptor_data(app).debug_dangling_keep_alives.is_empty(),
400 "a keep-alive child was left dangling by move_child"
401 );
402 }
403
404 fn debug_assert_child_list_locked(self: RenderHandle<Self>, app: &App) -> bool {
406 self.child_manager(app).debug_assert_child_list_locked(app)
407 }
408
409 fn debug_verify_child_order(self: RenderHandle<Self>, app: &App) -> bool {
413 if self.debug_child_integrity_enabled(app) {
414 let mut child = self.first_child(app);
415 while let Some(current) = child {
416 let index = self.index_of(app, current);
417 child = self.child_after(app, current);
418 debug_assert!(child.is_none_or(|next| self.index_of(app, next) > index));
419 }
420 }
421 true
422 }
423
424 fn insert(
426 self: RenderHandle<Self>,
427 app: &mut App,
428 child: AnyRenderBox,
429 after: Option<AnyRenderBox>,
430 ) {
431 debug_assert!(
432 !self
433 .adaptor_data(app)
434 .keep_alive_bucket
435 .values()
436 .any(|kept| *kept == child)
437 );
438 ContainerRenderObjectBase::insert(self, app, child, after);
439 self.did_adopt_child(app, child);
440 debug_assert!(self.first_child(app).is_some());
441 debug_assert!(self.debug_verify_child_order(app));
442 }
443
444 fn did_adopt_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderBox) {
450 let kept_alive = child
451 .as_object()
452 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
453 .kept_alive();
454 if !kept_alive {
455 self.child_manager(app).did_adopt_child(app, child);
456 }
457 }
458
459 fn move_child(
471 self: RenderHandle<Self>,
472 app: &mut App,
473 child: AnyRenderBox,
474 after: Option<AnyRenderBox>,
475 ) {
476 let child_parent_data = child
477 .as_object()
478 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app);
479 let (kept_alive, index) = (child_parent_data.kept_alive(), child_parent_data.index);
480 if !kept_alive {
481 ContainerRenderObjectBase::move_child(self, app, child, after);
482 self.child_manager(app).did_adopt_child(app, child);
484 self.mark_needs_layout(app);
487 return;
488 }
489 if let Some(index) = index
492 && self.adaptor_data(app).keep_alive_bucket.get(&index) == Some(&child)
493 {
494 self.adaptor_data_mut(app)
495 .keep_alive_bucket
496 .shift_remove(&index);
497 }
498 if cfg!(debug_assertions) {
499 self.adaptor_data_mut(app)
500 .debug_dangling_keep_alives
501 .retain(|dangling| *dangling != child);
502 }
503 self.child_manager(app).did_adopt_child(app, child);
505 let new_index = child
509 .as_object()
510 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
511 .index
512 .expect("did_adopt_child sets the index");
513 if cfg!(debug_assertions)
514 && let Some(existing) = self
515 .adaptor_data(app)
516 .keep_alive_bucket
517 .get(&new_index)
518 .copied()
519 {
520 self.adaptor_data_mut(app)
521 .debug_dangling_keep_alives
522 .push(existing);
523 }
524 self.adaptor_data_mut(app)
525 .keep_alive_bucket
526 .insert(new_index, child);
527 }
528
529 fn remove(self: RenderHandle<Self>, app: &mut App, child: AnyRenderBox) {
531 let child_parent_data = child
532 .as_object()
533 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app);
534 let (kept_alive, index) = (child_parent_data.kept_alive(), child_parent_data.index);
535 if !kept_alive {
536 ContainerRenderObjectBase::remove(self, app, child);
537 return;
538 }
539 let index = index.expect("a kept-alive child has an index");
540 debug_assert_eq!(
541 self.adaptor_data(app).keep_alive_bucket.get(&index),
542 Some(&child)
543 );
544 if cfg!(debug_assertions) {
545 self.adaptor_data_mut(app)
546 .debug_dangling_keep_alives
547 .retain(|dangling| *dangling != child);
548 }
549 self.adaptor_data_mut(app)
550 .keep_alive_bucket
551 .shift_remove(&index);
552 self.drop_child(app, child.as_object());
553 }
554
555 fn remove_all(self: RenderHandle<Self>, app: &mut App) {
557 ContainerRenderObjectBase::remove_all(self, app);
558 for child in self.keep_alive_children(app) {
559 self.drop_child(app, child.as_object());
560 }
561 self.adaptor_data_mut(app).keep_alive_bucket.clear();
562 }
563
564 fn keep_alive_children(self: RenderHandle<Self>, app: &App) -> Vec<AnyRenderBox> {
566 self.adaptor_data(app)
567 .keep_alive_bucket
568 .values()
569 .copied()
570 .collect()
571 }
572
573 fn create_or_obtain_child(
575 self: RenderHandle<Self>,
576 app: &mut App,
577 index: i32,
578 after: Option<AnyRenderBox>,
579 ) {
580 self.as_object().invoke_layout_callback(app, |app| {
581 let cached = self
582 .adaptor_data(app)
583 .keep_alive_bucket
584 .get(&index)
585 .copied();
586 let Some(child) = cached else {
587 self.child_manager(app).create_child(app, index, after);
588 return;
589 };
590 self.adaptor_data_mut(app)
591 .keep_alive_bucket
592 .shift_remove(&index);
593 let child_parent_data = child
594 .as_object()
595 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app);
596 debug_assert!(child_parent_data.kept_alive());
597 let (layout_offset, keep_alive, index_of_child) = (
600 child_parent_data.layout_offset(),
601 child_parent_data.keep_alive(),
602 child_parent_data.index,
603 );
604 self.drop_child(app, child.as_object());
605 let mut restored = SliverMultiBoxAdaptorParentData::new();
606 restored.set_layout_offset(layout_offset);
607 restored.set_keep_alive(keep_alive);
608 restored.index = index_of_child;
609 restored.keep_alive.kept_alive = true;
610 child.as_object().set_parent_data(app, restored);
611 RenderSliverMultiBoxAdaptor::insert(self, app, child, after);
612 child
613 .as_object()
614 .parent_data_of_mut::<SliverMultiBoxAdaptorParentData>(app)
615 .keep_alive
616 .kept_alive = false;
617 });
618 }
619
620 fn destroy_or_cache_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderBox) {
622 let child_parent_data = child
623 .as_object()
624 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app);
625 if !child_parent_data.keep_alive() {
626 debug_assert_eq!(child.as_object().parent(app), Some(self.as_object()));
627 self.child_manager(app).remove_child(app, child);
628 debug_assert!(child.as_object().parent(app).is_none());
629 return;
630 }
631 debug_assert!(!child_parent_data.kept_alive());
632 let (layout_offset, index) = (child_parent_data.layout_offset(), child_parent_data.index);
633 let index = index.expect("a cached child has an index");
634 RenderSliverMultiBoxAdaptor::remove(self, app, child);
635 self.adaptor_data_mut(app)
636 .keep_alive_bucket
637 .insert(index, child);
638 let mut restored = SliverMultiBoxAdaptorParentData::new();
639 restored.set_layout_offset(layout_offset);
640 restored.set_keep_alive(true);
641 restored.index = Some(index);
642 restored.keep_alive.kept_alive = true;
643 child.as_object().set_parent_data(app, restored);
644 self.as_object().adopt_child(app, child.as_object());
647 }
648
649 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
651 ContainerRenderObjectMixin::did_attach(self, app, owner);
652 for child in self.keep_alive_children(app) {
653 child.as_object().attach(app, owner);
654 }
655 }
656
657 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
659 ContainerRenderObjectMixin::did_detach(self, app);
660 for child in self.keep_alive_children(app) {
661 child.as_object().detach(app);
662 }
663 }
664
665 fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
667 ContainerRenderObjectMixin::redepth_children(self, app);
668 for child in self.keep_alive_children(app) {
669 self.as_object().redepth_child(app, child.as_object());
670 }
671 }
672
673 fn visit_children(
675 self: RenderHandle<Self>,
676 app: &App,
677 visitor: &mut dyn FnMut(AnyRenderObject),
678 ) {
679 ContainerRenderObjectMixin::visit_children(self, app, visitor);
680 for child in self.keep_alive_children(app) {
681 visitor(child.as_object());
682 }
683 }
684
685 fn add_initial_child(
696 self: RenderHandle<Self>,
697 app: &mut App,
698 index: i32,
699 layout_offset: f64,
700 ) -> bool {
701 debug_assert!(self.debug_assert_child_list_locked(app));
702 debug_assert!(self.first_child(app).is_none());
703 self.create_or_obtain_child(app, index, None);
704 if let Some(first_child) = self.first_child(app) {
705 debug_assert_eq!(Some(first_child), self.last_child(app));
706 debug_assert_eq!(self.index_of(app, first_child), index);
707 first_child
708 .as_object()
709 .parent_data_of_mut::<SliverMultiBoxAdaptorParentData>(app)
710 .set_layout_offset(Some(layout_offset));
711 return true;
712 }
713 self.child_manager(app).set_did_underflow(app, true);
714 false
715 }
716
717 fn insert_and_layout_leading_child(
725 self: RenderHandle<Self>,
726 app: &mut App,
727 child_constraints: BoxConstraints,
728 parent_uses_size: bool,
729 ) -> Option<AnyRenderBox> {
730 debug_assert!(self.debug_assert_child_list_locked(app));
731 let first_child = self.first_child(app).expect("there is a leading child");
732 let index = self.index_of(app, first_child) - 1;
733 self.create_or_obtain_child(app, index, None);
734 let first_child = self.first_child(app).expect("the child list is not empty");
735 if self.index_of(app, first_child) == index {
736 first_child.layout(app, child_constraints, parent_uses_size);
737 return Some(first_child);
738 }
739 self.child_manager(app).set_did_underflow(app, true);
740 None
741 }
742
743 fn insert_and_layout_child(
751 self: RenderHandle<Self>,
752 app: &mut App,
753 child_constraints: BoxConstraints,
754 after: Option<AnyRenderBox>,
755 parent_uses_size: bool,
756 ) -> Option<AnyRenderBox> {
757 debug_assert!(self.debug_assert_child_list_locked(app));
758 let after = after.expect("insert_and_layout_child needs a preceding child");
759 let index = self.index_of(app, after) + 1;
760 self.create_or_obtain_child(app, index, Some(after));
761 let child = self.child_after(app, after);
762 if let Some(child) = child
763 && self.index_of(app, child) == index
764 {
765 child.layout(app, child_constraints, parent_uses_size);
766 return Some(child);
767 }
768 self.child_manager(app).set_did_underflow(app, true);
769 None
770 }
771
772 fn calculate_leading_garbage(self: RenderHandle<Self>, app: &App, first_index: i32) -> usize {
775 let mut walker = self.first_child(app);
776 let mut leading_garbage = 0;
777 while let Some(current) = walker {
778 if self.index_of(app, current) >= first_index {
779 break;
780 }
781 leading_garbage += 1;
782 walker = self.child_after(app, current);
783 }
784 leading_garbage
785 }
786
787 fn calculate_trailing_garbage(self: RenderHandle<Self>, app: &App, last_index: i32) -> usize {
790 let mut walker = self.last_child(app);
791 let mut trailing_garbage = 0;
792 while let Some(current) = walker {
793 if self.index_of(app, current) <= last_index {
794 break;
795 }
796 trailing_garbage += 1;
797 walker = self.child_before(app, current);
798 }
799 trailing_garbage
800 }
801
802 fn collect_garbage(
812 self: RenderHandle<Self>,
813 app: &mut App,
814 leading_garbage: usize,
815 trailing_garbage: usize,
816 ) {
817 debug_assert!(self.debug_assert_child_list_locked(app));
818 debug_assert!(self.child_count(app) >= leading_garbage + trailing_garbage);
819 self.as_object().invoke_layout_callback(app, |app| {
820 for _ in 0..leading_garbage {
821 let first_child = self.first_child(app).expect("counted above");
822 self.destroy_or_cache_child(app, first_child);
823 }
824 for _ in 0..trailing_garbage {
825 let last_child = self.last_child(app).expect("counted above");
826 self.destroy_or_cache_child(app, last_child);
827 }
828 let expired: Vec<AnyRenderBox> = self
832 .keep_alive_children(app)
833 .into_iter()
834 .filter(|child| {
835 !child
836 .as_object()
837 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
838 .keep_alive()
839 })
840 .collect();
841 let child_manager = self.child_manager(app);
842 for child in expired {
843 child_manager.remove_child(app, child);
844 }
845 debug_assert!(self.keep_alive_children(app).iter().all(|child| {
846 child
847 .as_object()
848 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
849 .keep_alive()
850 }));
851 });
852 }
853
854 fn index_of(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> i32 {
857 child
858 .as_object()
859 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
860 .index
861 .expect("a reified child has an index")
862 }
863
864 fn paint_extent_of(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> f64 {
868 debug_assert!(child.has_size(app));
869 match self.constraints(app).axis() {
870 Axis::Horizontal => child.size(app).width(),
871 Axis::Vertical => child.size(app).height(),
872 }
873 }
874
875 fn hit_test_children(
877 self: RenderHandle<Self>,
878 app: &mut App,
879 result: &mut SliverHitTestResult<'_>,
880 main_axis_position: f64,
881 cross_axis_position: f64,
882 ) -> bool {
883 let mut child = self.last_child(app);
884 while let Some(current) = child {
885 let previous = self.child_before(app, current);
886 if self.hit_test_box_child(
887 app,
888 &mut BoxHitTestResult::wrap(result),
889 current,
890 main_axis_position,
891 cross_axis_position,
892 ) {
893 return true;
894 }
895 child = previous;
896 }
897 false
898 }
899
900 fn child_main_axis_position(
902 self: RenderHandle<Self>,
903 app: &App,
904 child: AnyRenderObject,
905 ) -> f64 {
906 RenderSliverMultiBoxAdaptor::child_scroll_offset(self, app, child)
907 .expect("a laid-out child has a scroll offset")
908 - self.constraints(app).scroll_offset
909 }
910
911 fn child_scroll_offset(
913 self: RenderHandle<Self>,
914 app: &App,
915 child: AnyRenderObject,
916 ) -> Option<f64> {
917 debug_assert_eq!(child.parent(app), Some(self.as_object()));
918 child
919 .parent_data_of::<SliverMultiBoxAdaptorParentData>(app)
920 .layout_offset()
921 }
922
923 fn paints_child(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> bool {
928 let index = child
929 .as_object()
930 .parent_data(app)
931 .and_then(|parent_data| {
932 (parent_data as &dyn std::any::Any)
933 .downcast_ref::<SliverMultiBoxAdaptorParentData>()
934 })
935 .and_then(|parent_data| parent_data.index);
936 match index {
937 None => false,
938 Some(index) => !self
939 .adaptor_data(app)
940 .keep_alive_bucket
941 .contains_key(&index),
942 }
943 }
944
945 fn apply_paint_transform(
947 self: RenderHandle<Self>,
948 app: &App,
949 child: AnyRenderObject,
950 transform: &mut Matrix4,
951 ) {
952 let child = child.as_box().expect("the children are boxes");
953 if self.paints_child(app, child) {
954 self.apply_paint_transform_for_box_child(app, child, transform);
955 } else {
956 *transform = zero_matrix();
963 }
964 }
965
966 fn paint(
968 self: RenderHandle<Self>,
969 app: &mut App,
970 context: &mut PaintingContext,
971 offset: Offset,
972 ) {
973 if self.first_child(app).is_none() {
974 return;
975 }
976 let constraints = self.constraints(app);
980 let paint_extent = self.geometry(app).paint_extent;
981 let (main_axis_unit, cross_axis_unit, origin_offset, add_extent) =
982 match apply_growth_direction_to_axis_direction(
983 constraints.axis_direction,
984 constraints.growth_direction,
985 ) {
986 AxisDirection::Up => (
987 Offset::new(0.0, -1.0),
988 Offset::new(1.0, 0.0),
989 offset + Offset::new(0.0, paint_extent),
990 true,
991 ),
992 AxisDirection::Right => {
993 (Offset::new(1.0, 0.0), Offset::new(0.0, 1.0), offset, false)
994 }
995 AxisDirection::Down => {
996 (Offset::new(0.0, 1.0), Offset::new(1.0, 0.0), offset, false)
997 }
998 AxisDirection::Left => (
999 Offset::new(-1.0, 0.0),
1000 Offset::new(0.0, 1.0),
1001 offset + Offset::new(paint_extent, 0.0),
1002 true,
1003 ),
1004 };
1005 let mut child = self.first_child(app);
1006 while let Some(current) = child {
1007 let main_axis_delta = RenderSliverMultiBoxAdaptor::child_main_axis_position(
1008 self,
1009 app,
1010 current.as_object(),
1011 );
1012 let cross_axis_delta = self.child_cross_axis_position(app, current.as_object());
1013 let mut child_offset = Offset::new(
1014 origin_offset.dx()
1015 + main_axis_unit.dx() * main_axis_delta
1016 + cross_axis_unit.dx() * cross_axis_delta,
1017 origin_offset.dy()
1018 + main_axis_unit.dy() * main_axis_delta
1019 + cross_axis_unit.dy() * cross_axis_delta,
1020 );
1021 let child_paint_extent = self.paint_extent_of(app, current);
1022 if add_extent {
1023 child_offset = child_offset + main_axis_unit * child_paint_extent;
1024 }
1025
1026 if main_axis_delta < constraints.remaining_paint_extent
1030 && main_axis_delta + child_paint_extent > 0.0
1031 {
1032 context.paint_child(app, current.as_object(), child_offset);
1033 }
1034
1035 child = self.child_after(app, current);
1036 }
1037 }
1038
1039 fn debug_assert_child_list_is_non_empty_and_contiguous(
1043 self: RenderHandle<Self>,
1044 app: &App,
1045 ) -> bool {
1046 if cfg!(debug_assertions) {
1047 let first_child = self.first_child(app).expect("the child list is not empty");
1048 let mut index = self.index_of(app, first_child);
1049 let mut child = self.child_after(app, first_child);
1050 while let Some(current) = child {
1051 index += 1;
1052 debug_assert_eq!(self.index_of(app, current), index);
1053 child = self.child_after(app, current);
1054 }
1055 }
1056 true
1057 }
1058}
1059
1060#[cfg(test)]
1061pub(crate) mod test_support {
1062 use std::cell::{Cell, RefCell};
1063
1064 use inset_embedder::Size;
1065
1066 use super::*;
1067 use crate::box_::{RenderBox, RenderBoxData};
1068 use crate::object::{RenderObject, RenderObjectData};
1069
1070 pub(crate) struct TestChild {
1072 render_object: RenderObjectData,
1073 render_box: RenderBoxData,
1074 preferred_extent: f64,
1075 }
1076
1077 impl RenderObject for TestChild {
1078 crate::render_object_accessors!();
1079
1080 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1081 let extent = self.get(app).preferred_extent;
1082 let size = self.constraints(app).constrain(Size::new(extent, extent));
1083 self.set_size(app, size);
1084 }
1085 }
1086
1087 impl RenderBox for TestChild {
1088 crate::render_box_accessors!();
1089
1090 fn hit_test_self(self: RenderHandle<Self>, _app: &App, _position: Offset) -> bool {
1091 let _ = self;
1092 true
1093 }
1094 }
1095
1096 pub(crate) fn hit_testable_box(app: &mut App, extent: f64) -> AnyRenderBox {
1099 RenderHandle::new_box(
1100 app,
1101 TestChild {
1102 render_object: RenderObjectData::new(),
1103 render_box: RenderBoxData::new(),
1104 preferred_extent: extent,
1105 },
1106 )
1107 .as_box()
1108 }
1109
1110 pub(crate) struct TestChildManager<T: RenderSliverMultiBoxAdaptor> {
1113 render_object: Cell<Option<RenderHandle<T>>>,
1114 extents: Vec<f64>,
1115 currently_updating_child_index: Cell<Option<i32>>,
1116 pub(crate) created: RefCell<Vec<i32>>,
1118 pub(crate) did_underflow: Cell<bool>,
1120 }
1121
1122 impl<T: RenderSliverMultiBoxAdaptor> TestChildManager<T> {
1123 pub(crate) fn new(extents: Vec<f64>) -> Rc<TestChildManager<T>> {
1124 Rc::new(TestChildManager {
1125 render_object: Cell::new(None),
1126 extents,
1127 currently_updating_child_index: Cell::new(None),
1128 created: RefCell::new(Vec::new()),
1129 did_underflow: Cell::new(false),
1130 })
1131 }
1132
1133 pub(crate) fn attach(&self, render_object: RenderHandle<T>) {
1134 self.render_object.set(Some(render_object));
1135 }
1136
1137 fn adaptor(&self) -> RenderHandle<T> {
1138 self.render_object.get().expect("attached before layout")
1139 }
1140
1141 fn total_extent(&self) -> f64 {
1142 self.extents.iter().sum()
1143 }
1144 }
1145
1146 impl<T: RenderSliverMultiBoxAdaptor> RenderSliverBoxChildManager for TestChildManager<T> {
1147 fn create_child(&self, app: &mut App, index: i32, after: Option<AnyRenderBox>) {
1148 self.created.borrow_mut().push(index);
1149 let Ok(slot) = usize::try_from(index) else {
1150 return;
1151 };
1152 let Some(extent) = self.extents.get(slot).copied() else {
1153 return;
1154 };
1155 let child = RenderHandle::new_box(
1156 app,
1157 TestChild {
1158 render_object: RenderObjectData::new(),
1159 render_box: RenderBoxData::new(),
1160 preferred_extent: extent,
1161 },
1162 )
1163 .as_box();
1164 self.currently_updating_child_index.set(Some(index));
1165 RenderSliverMultiBoxAdaptor::insert(self.adaptor(), app, child, after);
1166 self.currently_updating_child_index.set(None);
1167 }
1168
1169 fn remove_child(&self, app: &mut App, child: AnyRenderBox) {
1170 RenderSliverMultiBoxAdaptor::remove(self.adaptor(), app, child);
1173 }
1174
1175 fn estimate_max_scroll_offset(
1176 &self,
1177 _app: &App,
1178 _constraints: SliverConstraints,
1179 _first_index: Option<i32>,
1180 _last_index: Option<i32>,
1181 _leading_scroll_offset: Option<f64>,
1182 _trailing_scroll_offset: Option<f64>,
1183 ) -> f64 {
1184 self.total_extent()
1185 }
1186
1187 fn child_count(&self, _app: &mut App) -> i32 {
1188 self.extents.len() as i32
1189 }
1190
1191 fn estimated_child_count(&self, _app: &App) -> Option<i32> {
1192 Some(self.extents.len() as i32)
1193 }
1194
1195 fn did_adopt_child(&self, app: &mut App, child: AnyRenderBox) {
1196 child
1197 .as_object()
1198 .parent_data_of_mut::<SliverMultiBoxAdaptorParentData>(app)
1199 .index = self.currently_updating_child_index.get();
1200 }
1201
1202 fn set_did_underflow(&self, _app: &mut App, value: bool) {
1203 self.did_underflow.set(value);
1204 }
1205 }
1206}
1207
1208#[cfg(test)]
1209pub(crate) mod viewport_test_support {
1210 use std::rc::Rc;
1211
1212 use inset_embedder::{Size, View, ViewId, ViewMetrics, ViewRef};
1213 use inset_foundation::Handle;
1214
1215 use super::*;
1216 use crate::box_::RenderBox;
1217 use crate::pipeline_owner::PipelineOwner;
1218 use crate::sliver::AnyRenderSliver;
1219 use crate::view::{RenderView, ViewConfiguration};
1220 use crate::viewport::RenderViewport;
1221 use crate::viewport_offset::{FixedViewportOffset, ViewportOffset};
1222
1223 struct TestView;
1224
1225 impl View for TestView {
1226 fn id(&self) -> ViewId {
1227 ViewId(0)
1228 }
1229
1230 fn metrics(&self) -> ViewMetrics {
1231 ViewMetrics::default()
1232 }
1233
1234 fn present(&self, _scene: std::sync::Arc<inset_embedder::Scene>) {}
1235 }
1236
1237 pub(crate) struct ScrollHarness {
1240 pub(crate) owner: Handle<PipelineOwner>,
1241 pub(crate) viewport: RenderHandle<RenderViewport>,
1242 pub(crate) offset: Handle<FixedViewportOffset>,
1243 }
1244
1245 impl ScrollHarness {
1246 pub(crate) fn new(app: &mut App, sliver: AnyRenderSliver, size: Size) -> ScrollHarness {
1248 let offset = FixedViewportOffset::zero(app);
1249 let viewport = RenderViewport::new(
1250 app,
1251 AxisDirection::Right,
1252 offset.as_viewport_offset(),
1253 Some(vec![sliver]),
1254 None,
1255 );
1256 let constraints = BoxConstraints::tight(size);
1257 let configuration = ViewConfiguration::new(constraints, constraints, 1.0);
1258 let view = RenderView::new(
1259 app,
1260 Some(viewport.as_box()),
1261 Some(configuration),
1262 Rc::new(TestView) as ViewRef,
1263 );
1264 let owner = PipelineOwner::new(app, None, None);
1265 owner.set_root_node(app, Some(view.as_object()));
1266 view.prepare_initial_frame(app);
1267 owner.flush_layout(app);
1268 ScrollHarness {
1269 owner,
1270 viewport,
1271 offset,
1272 }
1273 }
1274
1275 pub(crate) fn scroll_to(&self, app: &mut App, pixels: f64) {
1277 let current = self.offset.pixels(app);
1278 self.offset.correct_by(app, pixels - current);
1279 self.viewport.mark_needs_layout(app);
1280 self.owner.flush_layout(app);
1281 }
1282 }
1283}