1use std::any::{Any, TypeId};
4use std::fmt::{self, Debug, Display};
5use std::hash::Hasher;
6use std::ops::{Deref, DerefMut};
7
8use inset_embedder::{Matrix4, Offset, Rect, Size, clamp_double};
9use inset_foundation::{App, Handle, HandleId, PRECISION_ERROR_TOLERANCE};
10use inset_gestures::{HitTestEntry, HitTestResult, HitTestTarget, PointerEvent};
11use inset_painting::{
12 Axis, AxisDirection, axis_direction_is_reversed, axis_direction_to_axis, flip_axis_direction,
13};
14
15use crate::box_::{AnyRenderBox, BoxConstraints, BoxHitTestResult};
16use crate::object::{
17 AnyRenderObject, Constraints, ContainerParentData, ContainerParentDataMixin, ParentData,
18 RenderHandle, RenderObject, RenderObjectVTable, RenderObjectWithChildData,
19 RenderObjectWithChildMixin, create, resolve, translate,
20};
21use crate::painting_context::PaintingContext;
22use crate::pipeline_owner::PipelineOwner;
23use crate::viewport_offset::{ScrollDirection, flip_scroll_direction};
24
25pub type ItemExtentBuilder = std::rc::Rc<dyn Fn(i32, SliverLayoutDimensions) -> Option<f64>>;
31
32#[derive(Clone, Copy, Debug, PartialEq)]
34pub struct SliverLayoutDimensions {
35 pub scroll_offset: f64,
38
39 pub preceding_scroll_extent: f64,
41
42 pub viewport_main_axis_extent: f64,
46
47 pub cross_axis_extent: f64,
51}
52
53impl SliverLayoutDimensions {
54 pub const fn new(
56 scroll_offset: f64,
57 preceding_scroll_extent: f64,
58 viewport_main_axis_extent: f64,
59 cross_axis_extent: f64,
60 ) -> SliverLayoutDimensions {
61 SliverLayoutDimensions {
62 scroll_offset,
63 preceding_scroll_extent,
64 viewport_main_axis_extent,
65 cross_axis_extent,
66 }
67 }
68}
69
70impl Display for SliverLayoutDimensions {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(
73 f,
74 "scrollOffset: {} precedingScrollExtent: {} viewportMainAxisExtent: {} \
75 crossAxisExtent: {}",
76 self.scroll_offset,
77 self.preceding_scroll_extent,
78 self.viewport_main_axis_extent,
79 self.cross_axis_extent
80 )
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub enum GrowthDirection {
88 Forward,
90
91 Reverse,
93}
94
95pub fn apply_growth_direction_to_axis_direction(
98 axis_direction: AxisDirection,
99 growth_direction: GrowthDirection,
100) -> AxisDirection {
101 match growth_direction {
102 GrowthDirection::Forward => axis_direction,
103 GrowthDirection::Reverse => flip_axis_direction(axis_direction),
104 }
105}
106
107pub fn apply_growth_direction_to_scroll_direction(
110 scroll_direction: ScrollDirection,
111 growth_direction: GrowthDirection,
112) -> ScrollDirection {
113 match growth_direction {
114 GrowthDirection::Forward => scroll_direction,
115 GrowthDirection::Reverse => flip_scroll_direction(scroll_direction),
116 }
117}
118
119#[derive(Clone, Copy, Debug)]
121pub struct SliverConstraints {
122 pub axis_direction: AxisDirection,
125 pub growth_direction: GrowthDirection,
127 pub user_scroll_direction: ScrollDirection,
129 pub scroll_offset: f64,
132 pub preceding_scroll_extent: f64,
134 pub overlap: f64,
137 pub remaining_paint_extent: f64,
139 pub cross_axis_extent: f64,
141 pub cross_axis_direction: AxisDirection,
143 pub viewport_main_axis_extent: f64,
145 pub remaining_cache_extent: f64,
148 pub cache_origin: f64,
151}
152
153impl SliverConstraints {
154 #[allow(clippy::too_many_arguments)]
156 pub const fn new(
157 axis_direction: AxisDirection,
158 growth_direction: GrowthDirection,
159 user_scroll_direction: ScrollDirection,
160 scroll_offset: f64,
161 preceding_scroll_extent: f64,
162 overlap: f64,
163 remaining_paint_extent: f64,
164 cross_axis_extent: f64,
165 cross_axis_direction: AxisDirection,
166 viewport_main_axis_extent: f64,
167 remaining_cache_extent: f64,
168 cache_origin: f64,
169 ) -> SliverConstraints {
170 SliverConstraints {
171 axis_direction,
172 growth_direction,
173 user_scroll_direction,
174 scroll_offset,
175 preceding_scroll_extent,
176 overlap,
177 remaining_paint_extent,
178 cross_axis_extent,
179 cross_axis_direction,
180 viewport_main_axis_extent,
181 remaining_cache_extent,
182 cache_origin,
183 }
184 }
185
186 pub const fn copy_with(self) -> SliverConstraints {
188 self
189 }
190
191 pub const fn axis_direction(mut self, value: AxisDirection) -> SliverConstraints {
193 self.axis_direction = value;
194 self
195 }
196
197 pub const fn growth_direction(mut self, value: GrowthDirection) -> SliverConstraints {
199 self.growth_direction = value;
200 self
201 }
202
203 pub const fn user_scroll_direction(mut self, value: ScrollDirection) -> SliverConstraints {
205 self.user_scroll_direction = value;
206 self
207 }
208
209 pub const fn scroll_offset(mut self, value: f64) -> SliverConstraints {
211 self.scroll_offset = value;
212 self
213 }
214
215 pub const fn preceding_scroll_extent(mut self, value: f64) -> SliverConstraints {
217 self.preceding_scroll_extent = value;
218 self
219 }
220
221 pub const fn overlap(mut self, value: f64) -> SliverConstraints {
223 self.overlap = value;
224 self
225 }
226
227 pub const fn remaining_paint_extent(mut self, value: f64) -> SliverConstraints {
229 self.remaining_paint_extent = value;
230 self
231 }
232
233 pub const fn cross_axis_extent(mut self, value: f64) -> SliverConstraints {
235 self.cross_axis_extent = value;
236 self
237 }
238
239 pub const fn cross_axis_direction(mut self, value: AxisDirection) -> SliverConstraints {
241 self.cross_axis_direction = value;
242 self
243 }
244
245 pub const fn viewport_main_axis_extent(mut self, value: f64) -> SliverConstraints {
247 self.viewport_main_axis_extent = value;
248 self
249 }
250
251 pub const fn remaining_cache_extent(mut self, value: f64) -> SliverConstraints {
253 self.remaining_cache_extent = value;
254 self
255 }
256
257 pub const fn cache_origin(mut self, value: f64) -> SliverConstraints {
259 self.cache_origin = value;
260 self
261 }
262
263 pub fn axis(self) -> Axis {
265 axis_direction_to_axis(self.axis_direction)
266 }
267
268 pub fn normalized_growth_direction(self) -> GrowthDirection {
271 if axis_direction_is_reversed(self.axis_direction) {
272 match self.growth_direction {
273 GrowthDirection::Forward => GrowthDirection::Reverse,
274 GrowthDirection::Reverse => GrowthDirection::Forward,
275 }
276 } else {
277 self.growth_direction
278 }
279 }
280
281 pub fn as_box_constraints(
286 self,
287 min_extent: f64,
288 max_extent: f64,
289 cross_axis_extent: Option<f64>,
290 ) -> BoxConstraints {
291 let cross = cross_axis_extent.unwrap_or(self.cross_axis_extent);
292 match self.axis() {
293 Axis::Horizontal => BoxConstraints {
294 min_width: min_extent,
295 max_width: max_extent,
296 min_height: cross,
297 max_height: cross,
298 },
299 Axis::Vertical => BoxConstraints {
300 min_width: cross,
301 max_width: cross,
302 min_height: min_extent,
303 max_height: max_extent,
304 },
305 }
306 }
307}
308
309impl Constraints for SliverConstraints {
310 fn is_tight(&self) -> bool {
311 false
312 }
313
314 fn is_normalized(&self) -> bool {
315 self.scroll_offset >= 0.0
316 && self.cross_axis_extent >= 0.0
317 && axis_direction_to_axis(self.axis_direction)
318 != axis_direction_to_axis(self.cross_axis_direction)
319 && self.viewport_main_axis_extent >= 0.0
320 && self.remaining_paint_extent >= 0.0
321 }
322}
323
324impl PartialEq for SliverConstraints {
325 fn eq(&self, other: &SliverConstraints) -> bool {
326 debug_assert!(self.debug_assert_is_valid(false));
327 debug_assert!(other.debug_assert_is_valid(false));
328 self.axis_direction == other.axis_direction
329 && self.growth_direction == other.growth_direction
330 && self.user_scroll_direction == other.user_scroll_direction
331 && self.scroll_offset == other.scroll_offset
332 && self.preceding_scroll_extent == other.preceding_scroll_extent
333 && self.overlap == other.overlap
334 && self.remaining_paint_extent == other.remaining_paint_extent
335 && self.cross_axis_extent == other.cross_axis_extent
336 && self.cross_axis_direction == other.cross_axis_direction
337 && self.viewport_main_axis_extent == other.viewport_main_axis_extent
338 && self.remaining_cache_extent == other.remaining_cache_extent
339 && self.cache_origin == other.cache_origin
340 }
341}
342
343#[derive(Clone, Copy, Debug)]
345pub struct SliverGeometry {
346 pub scroll_extent: f64,
348 pub paint_origin: f64,
351 pub paint_extent: f64,
353 pub layout_extent: f64,
356 pub max_paint_extent: f64,
358 pub max_scroll_obstruction_extent: f64,
360 pub hit_test_extent: f64,
363 pub visible: bool,
365 pub has_visual_overflow: bool,
367 pub scroll_offset_correction: Option<f64>,
369 pub cache_extent: f64,
371 pub cross_axis_extent: Option<f64>,
373}
374
375impl SliverGeometry {
376 pub const ZERO: SliverGeometry = SliverGeometry {
378 scroll_extent: 0.0,
379 paint_origin: 0.0,
380 paint_extent: 0.0,
381 layout_extent: 0.0,
382 max_paint_extent: 0.0,
383 max_scroll_obstruction_extent: 0.0,
384 hit_test_extent: 0.0,
385 visible: false,
386 has_visual_overflow: false,
387 scroll_offset_correction: None,
388 cache_extent: 0.0,
389 cross_axis_extent: None,
390 };
391
392 pub const fn new() -> SliverGeometry {
394 SliverGeometry::ZERO
395 }
396
397 pub const fn scroll_extent(mut self, value: f64) -> SliverGeometry {
399 self.scroll_extent = value;
400 self
401 }
402
403 pub const fn paint_origin(mut self, value: f64) -> SliverGeometry {
405 self.paint_origin = value;
406 self
407 }
408
409 pub const fn paint_extent(mut self, value: f64) -> SliverGeometry {
413 self.paint_extent = value;
414 self.layout_extent = value;
415 self.hit_test_extent = value;
416 self.cache_extent = value;
417 self.visible = value > 0.0;
418 self
419 }
420
421 pub const fn layout_extent(mut self, value: f64) -> SliverGeometry {
423 self.layout_extent = value;
424 self
425 }
426
427 pub const fn max_paint_extent(mut self, value: f64) -> SliverGeometry {
429 self.max_paint_extent = value;
430 self
431 }
432
433 pub const fn max_scroll_obstruction_extent(mut self, value: f64) -> SliverGeometry {
435 self.max_scroll_obstruction_extent = value;
436 self
437 }
438
439 pub const fn hit_test_extent(mut self, value: f64) -> SliverGeometry {
441 self.hit_test_extent = value;
442 self
443 }
444
445 pub const fn visible(mut self, value: bool) -> SliverGeometry {
447 self.visible = value;
448 self
449 }
450
451 pub const fn has_visual_overflow(mut self, value: bool) -> SliverGeometry {
453 self.has_visual_overflow = value;
454 self
455 }
456
457 pub fn scroll_offset_correction(mut self, value: f64) -> SliverGeometry {
459 debug_assert!(value != 0.0);
460 self.scroll_offset_correction = Some(value);
461 self
462 }
463
464 pub const fn cache_extent(mut self, value: f64) -> SliverGeometry {
466 self.cache_extent = value;
467 self
468 }
469
470 pub const fn cross_axis_extent(mut self, value: f64) -> SliverGeometry {
472 self.cross_axis_extent = Some(value);
473 self
474 }
475
476 pub const fn copy_with(self) -> SliverGeometry {
478 self
479 }
480
481 pub fn is_zero(&self) -> bool {
484 self.scroll_extent == SliverGeometry::ZERO.scroll_extent
485 && self.paint_origin == SliverGeometry::ZERO.paint_origin
486 && self.paint_extent == SliverGeometry::ZERO.paint_extent
487 && self.layout_extent == SliverGeometry::ZERO.layout_extent
488 && self.max_paint_extent == SliverGeometry::ZERO.max_paint_extent
489 && self.max_scroll_obstruction_extent
490 == SliverGeometry::ZERO.max_scroll_obstruction_extent
491 && self.hit_test_extent == SliverGeometry::ZERO.hit_test_extent
492 && self.visible == SliverGeometry::ZERO.visible
493 && self.has_visual_overflow == SliverGeometry::ZERO.has_visual_overflow
494 && self.scroll_offset_correction == SliverGeometry::ZERO.scroll_offset_correction
495 && self.cache_extent == SliverGeometry::ZERO.cache_extent
496 && self.cross_axis_extent == SliverGeometry::ZERO.cross_axis_extent
497 }
498
499 pub fn debug_assert_is_valid(&self) -> bool {
503 debug_assert!(self.scroll_extent >= 0.0, "The scroll_extent is negative.");
504 debug_assert!(self.paint_extent >= 0.0, "The paint_extent is negative.");
505 debug_assert!(self.layout_extent >= 0.0, "The layout_extent is negative.");
506 debug_assert!(self.cache_extent >= 0.0, "The cache_extent is negative.");
507 debug_assert!(
508 self.layout_extent <= self.paint_extent,
509 "The layout_extent ({}) exceeds the paint_extent ({}).",
510 self.layout_extent,
511 self.paint_extent
512 );
513 debug_assert!(
516 self.paint_extent - self.max_paint_extent <= PRECISION_ERROR_TOLERANCE,
517 "The max_paint_extent ({}) is less than the paint_extent ({}). By definition, a \
518 sliver can't paint more than the maximum that it can paint!",
519 self.max_paint_extent,
520 self.paint_extent
521 );
522 debug_assert!(
523 self.hit_test_extent >= 0.0,
524 "The hit_test_extent is negative."
525 );
526 debug_assert!(
527 self.scroll_offset_correction != Some(0.0),
528 "The scroll_offset_correction is zero."
529 );
530 true
531 }
532}
533
534impl Default for SliverGeometry {
535 fn default() -> SliverGeometry {
536 SliverGeometry::new()
537 }
538}
539
540impl Display for SliverGeometry {
541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542 write!(
543 f,
544 "SliverGeometry({}x{})",
545 self.scroll_extent, self.paint_extent
546 )
547 }
548}
549
550pub type SliverHitTest<'r> = dyn FnOnce(&mut SliverHitTestResult<'r>, f64, f64) -> bool;
558
559pub struct SliverHitTestResult<'a>(&'a mut HitTestResult);
564
565impl<'a> SliverHitTestResult<'a> {
566 pub fn wrap(result: &'a mut HitTestResult) -> SliverHitTestResult<'a> {
571 SliverHitTestResult(result)
572 }
573
574 pub fn add_with_axis_offset(
593 &mut self,
594 paint_offset: Option<Offset>,
595 main_axis_offset: f64,
596 cross_axis_offset: f64,
597 main_axis_position: f64,
598 cross_axis_position: f64,
599 hit_test: impl FnOnce(&mut SliverHitTestResult<'_>, f64, f64) -> bool,
600 ) -> bool {
601 if let Some(paint_offset) = paint_offset {
602 self.0.push_offset(Offset::ZERO - paint_offset);
603 }
604 let is_hit = hit_test(
605 self,
606 main_axis_position - main_axis_offset,
607 cross_axis_position - cross_axis_offset,
608 );
609 if paint_offset.is_some() {
610 self.0.pop_transform();
611 }
612 is_hit
613 }
614}
615
616impl Deref for SliverHitTestResult<'_> {
617 type Target = HitTestResult;
618
619 fn deref(&self) -> &HitTestResult {
620 self.0
621 }
622}
623
624impl DerefMut for SliverHitTestResult<'_> {
625 fn deref_mut(&mut self) -> &mut HitTestResult {
626 self.0
627 }
628}
629
630#[derive(Clone, Copy, Debug)]
638pub struct SliverHitTestEntry {
639 target: AnyRenderSliver,
640 main_axis_position: f64,
641 cross_axis_position: f64,
642}
643
644impl SliverHitTestEntry {
645 pub fn new(
647 target: AnyRenderSliver,
648 main_axis_position: f64,
649 cross_axis_position: f64,
650 ) -> SliverHitTestEntry {
651 SliverHitTestEntry {
652 target,
653 main_axis_position,
654 cross_axis_position,
655 }
656 }
657
658 pub fn target(&self) -> AnyRenderSliver {
660 self.target
661 }
662
663 pub fn main_axis_position(&self) -> f64 {
669 self.main_axis_position
670 }
671
672 pub fn cross_axis_position(&self) -> f64 {
682 self.cross_axis_position
683 }
684}
685
686impl HitTestTarget for SliverHitTestEntry {
687 fn retained_handle(&self) -> Option<HandleId> {
688 Some(self.target.id)
689 }
690
691 fn handle_event(&self, app: &mut App, event: &PointerEvent, _entry: &HitTestEntry) {
692 self.target.handle_event(app, event, self);
693 }
694}
695
696impl From<SliverHitTestEntry> for HitTestEntry {
697 fn from(entry: SliverHitTestEntry) -> HitTestEntry {
698 HitTestEntry::new(entry)
699 }
700}
701
702#[derive(Clone, Copy, Debug, Default)]
708pub struct SliverLogicalParentData {
709 pub layout_offset: Option<f64>,
718}
719
720impl SliverLogicalParentData {
721 pub const fn new() -> SliverLogicalParentData {
723 SliverLogicalParentData {
724 layout_offset: None,
725 }
726 }
727}
728
729impl ParentData for SliverLogicalParentData {
730 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
731 (id == TypeId::of::<SliverLogicalParentData>()).then_some(self)
732 }
733
734 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
735 (id == TypeId::of::<SliverLogicalParentData>()).then_some(self)
736 }
737}
738
739impl Display for SliverLogicalParentData {
740 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
741 match self.layout_offset {
742 None => f.write_str("layoutOffset=None"),
743 Some(offset) => write!(f, "layoutOffset={offset:.1}"),
744 }
745 }
746}
747
748#[derive(Debug)]
751pub struct SliverLogicalContainerParentData {
752 sliver_logical: SliverLogicalParentData,
753 container: ContainerParentData<AnyRenderSliver>,
754}
755
756impl SliverLogicalContainerParentData {
757 pub const fn new() -> SliverLogicalContainerParentData {
759 SliverLogicalContainerParentData {
760 sliver_logical: SliverLogicalParentData::new(),
761 container: ContainerParentData::new(),
762 }
763 }
764
765 pub fn sliver_logical_parent_data(&self) -> &SliverLogicalParentData {
767 &self.sliver_logical
768 }
769
770 pub fn sliver_logical_parent_data_mut(&mut self) -> &mut SliverLogicalParentData {
772 &mut self.sliver_logical
773 }
774
775 pub fn layout_offset(&self) -> Option<f64> {
777 self.sliver_logical.layout_offset
778 }
779
780 pub fn set_layout_offset(&mut self, value: Option<f64>) {
782 self.sliver_logical.layout_offset = value;
783 }
784}
785
786impl Default for SliverLogicalContainerParentData {
787 fn default() -> SliverLogicalContainerParentData {
788 SliverLogicalContainerParentData::new()
789 }
790}
791
792impl ParentData for SliverLogicalContainerParentData {
793 fn detach(&mut self) {
794 ContainerParentDataMixin::detach(self);
795 }
796
797 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
798 if id == TypeId::of::<SliverLogicalContainerParentData>() {
799 return Some(self);
800 }
801 self.sliver_logical.provide(id)
802 }
803
804 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
805 if id == TypeId::of::<SliverLogicalContainerParentData>() {
806 return Some(self);
807 }
808 self.sliver_logical.provide_mut(id)
809 }
810}
811
812impl ContainerParentDataMixin for SliverLogicalContainerParentData {
813 type ChildType = AnyRenderSliver;
814
815 fn container_parent_data(&self) -> &ContainerParentData<AnyRenderSliver> {
816 &self.container
817 }
818
819 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<AnyRenderSliver> {
820 &mut self.container
821 }
822}
823
824impl Display for SliverLogicalContainerParentData {
825 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826 Display::fmt(&self.sliver_logical, f)
827 }
828}
829
830#[derive(Clone, Copy, Debug)]
840pub struct SliverPhysicalParentData {
841 pub paint_offset: Offset,
846
847 pub cross_axis_flex: Option<i32>,
856}
857
858impl SliverPhysicalParentData {
859 pub const fn new() -> SliverPhysicalParentData {
861 SliverPhysicalParentData {
862 paint_offset: Offset::ZERO,
863 cross_axis_flex: None,
864 }
865 }
866
867 pub fn apply_paint_transform(&self, transform: &mut Matrix4) {
872 translate(transform, self.paint_offset.dx(), self.paint_offset.dy());
874 }
875}
876
877impl Default for SliverPhysicalParentData {
878 fn default() -> SliverPhysicalParentData {
879 SliverPhysicalParentData::new()
880 }
881}
882
883impl ParentData for SliverPhysicalParentData {
884 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
885 (id == TypeId::of::<SliverPhysicalParentData>()).then_some(self)
886 }
887
888 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
889 (id == TypeId::of::<SliverPhysicalParentData>()).then_some(self)
890 }
891}
892
893impl Display for SliverPhysicalParentData {
894 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
895 write!(f, "paintOffset={:?}", self.paint_offset)
896 }
897}
898
899#[derive(Debug)]
902pub struct SliverPhysicalContainerParentData {
903 sliver_physical: SliverPhysicalParentData,
904 container: ContainerParentData<AnyRenderSliver>,
905}
906
907impl SliverPhysicalContainerParentData {
908 pub const fn new() -> SliverPhysicalContainerParentData {
910 SliverPhysicalContainerParentData {
911 sliver_physical: SliverPhysicalParentData::new(),
912 container: ContainerParentData::new(),
913 }
914 }
915
916 pub fn sliver_physical_parent_data(&self) -> &SliverPhysicalParentData {
918 &self.sliver_physical
919 }
920
921 pub fn sliver_physical_parent_data_mut(&mut self) -> &mut SliverPhysicalParentData {
923 &mut self.sliver_physical
924 }
925
926 pub fn paint_offset(&self) -> Offset {
928 self.sliver_physical.paint_offset
929 }
930
931 pub fn set_paint_offset(&mut self, value: Offset) {
933 self.sliver_physical.paint_offset = value;
934 }
935
936 pub fn apply_paint_transform(&self, transform: &mut Matrix4) {
938 self.sliver_physical.apply_paint_transform(transform);
939 }
940}
941
942impl Default for SliverPhysicalContainerParentData {
943 fn default() -> SliverPhysicalContainerParentData {
944 SliverPhysicalContainerParentData::new()
945 }
946}
947
948impl ParentData for SliverPhysicalContainerParentData {
949 fn detach(&mut self) {
950 ContainerParentDataMixin::detach(self);
951 }
952
953 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
954 if id == TypeId::of::<SliverPhysicalContainerParentData>() {
955 return Some(self);
956 }
957 self.sliver_physical.provide(id)
958 }
959
960 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
961 if id == TypeId::of::<SliverPhysicalContainerParentData>() {
962 return Some(self);
963 }
964 self.sliver_physical.provide_mut(id)
965 }
966}
967
968impl ContainerParentDataMixin for SliverPhysicalContainerParentData {
969 type ChildType = AnyRenderSliver;
970
971 fn container_parent_data(&self) -> &ContainerParentData<AnyRenderSliver> {
972 &self.container
973 }
974
975 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<AnyRenderSliver> {
976 &mut self.container
977 }
978}
979
980impl Display for SliverPhysicalContainerParentData {
981 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982 Display::fmt(&self.sliver_physical, f)
983 }
984}
985
986pub(crate) fn calculate_paint_offset(constraints: SliverConstraints, from: f64, to: f64) -> f64 {
988 debug_assert!(from <= to);
989 let a = constraints.scroll_offset;
990 let b = constraints.scroll_offset + constraints.remaining_paint_extent;
991 clamp_double(
993 clamp_double(to, a, b) - clamp_double(from, a, b),
994 0.0,
995 constraints.remaining_paint_extent,
996 )
997}
998
999pub(crate) fn calculate_cache_offset(constraints: SliverConstraints, from: f64, to: f64) -> f64 {
1001 debug_assert!(from <= to);
1002 let a = constraints.scroll_offset + constraints.cache_origin;
1003 let b = constraints.scroll_offset + constraints.remaining_cache_extent;
1004 clamp_double(
1006 clamp_double(to, a, b) - clamp_double(from, a, b),
1007 0.0,
1008 constraints.remaining_cache_extent,
1009 )
1010}
1011
1012pub struct RenderSliverData {
1014 pub(crate) geometry: Option<SliverGeometry>,
1015 pub(crate) constraints: Option<SliverConstraints>,
1016}
1017
1018impl RenderSliverData {
1019 pub fn new() -> RenderSliverData {
1021 RenderSliverData {
1022 geometry: None,
1023 constraints: None,
1024 }
1025 }
1026}
1027
1028impl Default for RenderSliverData {
1029 fn default() -> RenderSliverData {
1030 RenderSliverData::new()
1031 }
1032}
1033
1034#[macro_export]
1036macro_rules! render_sliver_accessors {
1037 () => {
1038 fn render_sliver_data(
1039 self: $crate::RenderHandle<Self>,
1040 app: &::inset_foundation::App,
1041 ) -> &$crate::RenderSliverData {
1042 &self.get(app).render_sliver
1043 }
1044 fn render_sliver_data_mut(
1045 self: $crate::RenderHandle<Self>,
1046 app: &mut ::inset_foundation::App,
1047 ) -> &mut $crate::RenderSliverData {
1048 &mut self.get_mut(app).render_sliver
1049 }
1050 };
1051}
1052
1053pub trait RenderSliver: RenderObject {
1059 fn render_sliver_data(self: RenderHandle<Self>, app: &App) -> &RenderSliverData;
1061
1062 fn render_sliver_data_mut(self: RenderHandle<Self>, app: &mut App) -> &mut RenderSliverData;
1064
1065 fn constraints(self: RenderHandle<Self>, app: &App) -> SliverConstraints {
1067 self.render_sliver_data(app).constraints.unwrap_or_else(|| {
1068 panic!("A RenderObject does not have any constraints before it has been laid out.")
1069 })
1070 }
1071
1072 fn geometry(self: RenderHandle<Self>, app: &App) -> SliverGeometry {
1074 self.as_sliver().geometry(app)
1075 }
1076
1077 fn set_geometry(self: RenderHandle<Self>, app: &mut App, geometry: SliverGeometry) {
1079 self.as_sliver().set_geometry(app, geometry)
1080 }
1081
1082 fn paint_bounds(self: RenderHandle<Self>, app: &App) -> Rect {
1085 let constraints = self.constraints(app);
1086 let geometry = self.geometry(app);
1087 match constraints.axis() {
1088 Axis::Horizontal => Rect::from_ltwh(
1089 0.0,
1090 0.0,
1091 geometry.paint_extent,
1092 constraints.cross_axis_extent,
1093 ),
1094 Axis::Vertical => Rect::from_ltwh(
1095 0.0,
1096 0.0,
1097 constraints.cross_axis_extent,
1098 geometry.paint_extent,
1099 ),
1100 }
1101 }
1102
1103 fn center_offset_adjustment(self: RenderHandle<Self>, _app: &App) -> f64 {
1114 let _ = self;
1115 0.0
1116 }
1117
1118 fn hit_test(
1146 self: RenderHandle<Self>,
1147 app: &mut App,
1148 result: &mut SliverHitTestResult<'_>,
1149 main_axis_position: f64,
1150 cross_axis_position: f64,
1151 ) -> bool {
1152 if main_axis_position >= 0.0
1153 && main_axis_position < self.geometry(app).hit_test_extent
1154 && cross_axis_position >= 0.0
1155 && cross_axis_position < self.constraints(app).cross_axis_extent
1156 && (self.hit_test_children(app, result, main_axis_position, cross_axis_position)
1157 || self.hit_test_self(app, main_axis_position, cross_axis_position))
1158 {
1159 result.add(
1160 SliverHitTestEntry::new(self.as_sliver(), main_axis_position, cross_axis_position)
1161 .into(),
1162 );
1163 return true;
1164 }
1165 false
1166 }
1167
1168 fn hit_test_self(
1173 self: RenderHandle<Self>,
1174 _app: &App,
1175 _main_axis_position: f64,
1176 _cross_axis_position: f64,
1177 ) -> bool {
1178 let _ = self;
1179 false
1180 }
1181
1182 fn hit_test_children(
1191 self: RenderHandle<Self>,
1192 _app: &mut App,
1193 _result: &mut SliverHitTestResult<'_>,
1194 _main_axis_position: f64,
1195 _cross_axis_position: f64,
1196 ) -> bool {
1197 let _ = self;
1198 false
1199 }
1200
1201 fn handle_event(
1203 self: RenderHandle<Self>,
1204 _app: &mut App,
1205 _event: &PointerEvent,
1206 _entry: &SliverHitTestEntry,
1207 ) {
1208 let _ = self;
1209 }
1210
1211 fn calculate_paint_offset(
1223 self: RenderHandle<Self>,
1224 _app: &App,
1225 constraints: SliverConstraints,
1226 from: f64,
1227 to: f64,
1228 ) -> f64 {
1229 let _ = self;
1230 calculate_paint_offset(constraints, from, to)
1231 }
1232
1233 fn calculate_cache_offset(
1242 self: RenderHandle<Self>,
1243 _app: &App,
1244 constraints: SliverConstraints,
1245 from: f64,
1246 to: f64,
1247 ) -> f64 {
1248 let _ = self;
1249 calculate_cache_offset(constraints, from, to)
1250 }
1251
1252 fn child_main_axis_position(
1274 self: RenderHandle<Self>,
1275 _app: &App,
1276 _child: AnyRenderObject,
1277 ) -> f64 {
1278 let _ = self;
1279 panic!("this RenderSliver does not implement child_main_axis_position")
1280 }
1281
1282 fn child_cross_axis_position(
1293 self: RenderHandle<Self>,
1294 _app: &App,
1295 _child: AnyRenderObject,
1296 ) -> f64 {
1297 let _ = self;
1298 0.0
1299 }
1300
1301 fn child_scroll_offset(
1312 self: RenderHandle<Self>,
1313 app: &App,
1314 child: AnyRenderObject,
1315 ) -> Option<f64> {
1316 debug_assert_eq!(child.parent(app), Some(self.as_object()));
1317 Some(0.0)
1318 }
1319
1320 fn get_absolute_size_relative_to_origin(self: RenderHandle<Self>, app: &App) -> Size {
1330 debug_assert!(!self.as_object().debug_needs_layout(app));
1331 let constraints = self.constraints(app);
1332 let paint_extent = self.geometry(app).paint_extent;
1333 match apply_growth_direction_to_axis_direction(
1334 constraints.axis_direction,
1335 constraints.growth_direction,
1336 ) {
1337 AxisDirection::Up => Size::new(constraints.cross_axis_extent, -paint_extent),
1338 AxisDirection::Down => Size::new(constraints.cross_axis_extent, paint_extent),
1339 AxisDirection::Left => Size::new(-paint_extent, constraints.cross_axis_extent),
1340 AxisDirection::Right => Size::new(paint_extent, constraints.cross_axis_extent),
1341 }
1342 }
1343
1344 fn get_absolute_size(self: RenderHandle<Self>, app: &App) -> Size {
1354 debug_assert!(!self.as_object().debug_needs_layout(app));
1355 let constraints = self.constraints(app);
1356 let paint_extent = self.geometry(app).paint_extent;
1357 match constraints.axis_direction {
1358 AxisDirection::Up | AxisDirection::Down => {
1359 Size::new(constraints.cross_axis_extent, paint_extent)
1360 }
1361 AxisDirection::Right | AxisDirection::Left => {
1362 Size::new(paint_extent, constraints.cross_axis_extent)
1363 }
1364 }
1365 }
1366
1367 fn get_max_paint_rect(self: RenderHandle<Self>, app: &App) -> Rect {
1373 let Some(geometry) = self.render_sliver_data(app).geometry else {
1374 return Rect::ZERO;
1375 };
1376 if geometry.is_zero() {
1377 return Rect::ZERO;
1378 }
1379 let constraints = self.constraints(app);
1380 let mut max_paint_extent = geometry.max_paint_extent;
1381 if max_paint_extent.is_infinite() {
1382 max_paint_extent =
1383 constraints.scroll_offset + geometry.cache_extent + constraints.cache_origin;
1384 }
1385 let paint_extent = geometry.paint_extent;
1386 let leading_offset = clamp_double(
1389 constraints.scroll_offset,
1390 0.0,
1391 geometry.scroll_extent - geometry.max_scroll_obstruction_extent,
1392 );
1393 let cross_axis_extent = geometry
1394 .cross_axis_extent
1395 .unwrap_or(constraints.cross_axis_extent);
1396
1397 let rect = match constraints.axis() {
1398 Axis::Horizontal => {
1399 Rect::from_ltwh(-leading_offset, 0.0, max_paint_extent, cross_axis_extent)
1400 }
1401 Axis::Vertical => {
1402 Rect::from_ltwh(0.0, -leading_offset, cross_axis_extent, max_paint_extent)
1403 }
1404 };
1405
1406 match apply_growth_direction_to_axis_direction(
1407 constraints.axis_direction,
1408 constraints.growth_direction,
1409 ) {
1410 AxisDirection::Right | AxisDirection::Down => rect,
1411 AxisDirection::Left => Rect::from_ltrb(
1412 paint_extent - rect.right,
1413 rect.top,
1414 paint_extent - rect.left,
1415 rect.bottom,
1416 ),
1417 AxisDirection::Up => Rect::from_ltrb(
1418 rect.left,
1419 paint_extent - rect.bottom,
1420 rect.right,
1421 paint_extent - rect.top,
1422 ),
1423 }
1424 }
1425
1426 fn layout(
1428 self: RenderHandle<Self>,
1429 app: &mut App,
1430 constraints: SliverConstraints,
1431 parent_uses_size: bool,
1432 ) {
1433 self.as_sliver().layout(app, constraints, parent_uses_size)
1434 }
1435
1436 fn as_sliver(self: RenderHandle<Self>) -> AnyRenderSliver {
1438 AnyRenderSliver {
1439 id: self.id(),
1440 vtable: const { &RenderSliverVTable::of::<Self>() },
1441 }
1442 }
1443
1444 fn as_object(self: RenderHandle<Self>) -> AnyRenderObject {
1446 self.as_sliver().as_object()
1447 }
1448
1449 fn adopt_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1451 self.as_object().adopt_child(app, child)
1452 }
1453
1454 fn drop_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1456 self.as_object().drop_child(app, child)
1457 }
1458
1459 fn mark_needs_layout(self: RenderHandle<Self>, app: &mut App) {
1461 self.as_object().mark_needs_layout(app)
1462 }
1463
1464 fn mark_needs_paint(self: RenderHandle<Self>, app: &mut App) {
1466 self.as_object().mark_needs_paint(app)
1467 }
1468
1469 fn mark_needs_composited_layer_update(self: RenderHandle<Self>, app: &mut App) {
1471 self.as_object().mark_needs_composited_layer_update(app)
1472 }
1473
1474 fn schedule_initial_layout(self: RenderHandle<Self>, app: &mut App) {
1476 self.as_object().schedule_initial_layout(app)
1477 }
1478
1479 fn parent(self: RenderHandle<Self>, app: &App) -> Option<AnyRenderObject> {
1481 self.as_object().parent(app)
1482 }
1483
1484 fn owner(self: RenderHandle<Self>, app: &App) -> Option<Handle<PipelineOwner>> {
1486 self.as_object().owner(app)
1487 }
1488
1489 fn attached(self: RenderHandle<Self>, app: &App) -> bool {
1491 self.as_object().attached(app)
1492 }
1493
1494 fn debug_needs_layout(self: RenderHandle<Self>, app: &App) -> bool {
1496 self.as_object().debug_needs_layout(app)
1497 }
1498}
1499
1500pub(crate) struct RenderSliverVTable {
1502 pub object: RenderObjectVTable,
1503 pub sliver_data: fn(&App, HandleId) -> &RenderSliverData,
1504 pub sliver_data_mut: fn(&mut App, HandleId) -> &mut RenderSliverData,
1505 pub hit_test: fn(&mut App, HandleId, &mut SliverHitTestResult<'_>, f64, f64) -> bool,
1506 pub handle_event: fn(&mut App, HandleId, &PointerEvent, &SliverHitTestEntry),
1507 pub center_offset_adjustment: fn(&App, HandleId) -> f64,
1508 pub child_scroll_offset: fn(&App, HandleId, AnyRenderObject) -> Option<f64>,
1509 pub child_main_axis_position: fn(&App, HandleId, AnyRenderObject) -> f64,
1510}
1511
1512impl RenderSliverVTable {
1513 const fn of<T: RenderSliver>() -> RenderSliverVTable {
1514 RenderSliverVTable {
1515 object: RenderObjectVTable::of::<T>(
1516 |app, id, child| <T as RenderObject>::setup_parent_data(resolve(id), app, child),
1517 |app, id| T::paint_bounds(resolve(id), app),
1518 |app, id, child, transform| {
1519 <T as RenderObject>::apply_paint_transform(resolve(id), app, child, transform)
1520 },
1521 |app, id| <T as RenderObject>::perform_resize(resolve(id), app),
1522 |app, id| crate::object::RenderObjectBase::mark_needs_layout(resolve::<T>(id), app),
1523 None,
1524 Some(|| const { &RenderSliverVTable::of::<T>() }),
1525 ),
1526 sliver_data: |app, id| T::render_sliver_data(resolve(id), app),
1527 sliver_data_mut: |app, id| T::render_sliver_data_mut(resolve(id), app),
1528 hit_test: |app, id, result, main, cross| {
1529 T::hit_test(resolve(id), app, result, main, cross)
1530 },
1531 handle_event: |app, id, event, entry| T::handle_event(resolve(id), app, event, entry),
1532 center_offset_adjustment: |app, id| T::center_offset_adjustment(resolve(id), app),
1533 child_scroll_offset: |app, id, child| T::child_scroll_offset(resolve(id), app, child),
1534 child_main_axis_position: |app, id, child| {
1535 T::child_main_axis_position(resolve(id), app, child)
1536 },
1537 }
1538 }
1539}
1540
1541impl<T: RenderSliver> RenderHandle<T> {
1542 pub fn new_sliver(app: &mut App, object: T) -> RenderHandle<T> {
1544 let this = create(app, object);
1545 let data = this.render_object_data_mut(app);
1546 data.object_vtable = Some(&const { RenderSliverVTable::of::<T>() }.object);
1547 let is_repaint_boundary = this.is_repaint_boundary(app);
1551 let always_needs_compositing = this.always_needs_compositing(app);
1552 let data = this.render_object_data_mut(app);
1553 data.was_repaint_boundary = is_repaint_boundary;
1554 data.needs_compositing = is_repaint_boundary || always_needs_compositing;
1555 this
1556 }
1557}
1558
1559#[derive(Clone, Copy)]
1561pub struct AnyRenderSliver {
1562 id: HandleId,
1563 vtable: &'static RenderSliverVTable,
1564}
1565
1566impl PartialEq for AnyRenderSliver {
1567 fn eq(&self, other: &AnyRenderSliver) -> bool {
1568 self.id == other.id
1569 }
1570}
1571
1572impl Eq for AnyRenderSliver {}
1573
1574impl std::hash::Hash for AnyRenderSliver {
1575 fn hash<H: Hasher>(&self, state: &mut H) {
1576 self.id.hash(state);
1577 }
1578}
1579
1580impl Debug for AnyRenderSliver {
1581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1582 write!(f, "AnyRenderSliver({:?})", self.id)
1583 }
1584}
1585
1586impl AnyRenderSliver {
1587 pub(crate) fn from_vtable(
1588 id: HandleId,
1589 vtable: &'static RenderSliverVTable,
1590 ) -> AnyRenderSliver {
1591 AnyRenderSliver { id, vtable }
1592 }
1593
1594 pub fn as_object(self) -> AnyRenderObject {
1596 AnyRenderObject::from_vtable(self.id, &self.vtable.object)
1597 }
1598
1599 fn sliver_data(self, app: &App) -> &RenderSliverData {
1600 (self.vtable.sliver_data)(app, self.id)
1601 }
1602
1603 fn sliver_data_mut(self, app: &mut App) -> &mut RenderSliverData {
1604 (self.vtable.sliver_data_mut)(app, self.id)
1605 }
1606
1607 pub fn layout(self, app: &mut App, constraints: SliverConstraints, parent_uses_size: bool) {
1609 debug_assert!(constraints.debug_assert_is_valid(true));
1610 let same = self.sliver_data(app).constraints == Some(constraints);
1611 self.as_object()
1612 .run_layout(app, parent_uses_size, constraints.is_tight(), same, |app| {
1613 self.sliver_data_mut(app).constraints = Some(constraints)
1614 });
1615 }
1616
1617 pub fn constraints(self, app: &App) -> SliverConstraints {
1623 self.sliver_data(app).constraints.unwrap_or_else(|| {
1624 panic!("A RenderObject does not have any constraints before it has been laid out.")
1625 })
1626 }
1627
1628 pub fn hit_test(
1630 self,
1631 app: &mut App,
1632 result: &mut SliverHitTestResult<'_>,
1633 main_axis_position: f64,
1634 cross_axis_position: f64,
1635 ) -> bool {
1636 (self.vtable.hit_test)(
1637 app,
1638 self.id,
1639 result,
1640 main_axis_position,
1641 cross_axis_position,
1642 )
1643 }
1644
1645 pub fn handle_event(self, app: &mut App, event: &PointerEvent, entry: &SliverHitTestEntry) {
1647 (self.vtable.handle_event)(app, self.id, event, entry)
1648 }
1649
1650 pub fn center_offset_adjustment(self, app: &App) -> f64 {
1652 (self.vtable.center_offset_adjustment)(app, self.id)
1653 }
1654
1655 pub fn child_scroll_offset(self, app: &App, child: AnyRenderObject) -> Option<f64> {
1657 (self.vtable.child_scroll_offset)(app, self.id, child)
1658 }
1659
1660 pub fn child_main_axis_position(self, app: &App, child: AnyRenderObject) -> f64 {
1662 (self.vtable.child_main_axis_position)(app, self.id, child)
1663 }
1664
1665 pub fn geometry(self, app: &App) -> SliverGeometry {
1671 self.sliver_data(app)
1672 .geometry
1673 .unwrap_or_else(|| panic!("RenderSliver was not laid out: {self:?}"))
1674 }
1675
1676 pub fn set_geometry(self, app: &mut App, geometry: SliverGeometry) {
1678 self.sliver_data_mut(app).geometry = Some(geometry);
1679 }
1680}
1681
1682impl crate::object::ErasedRenderObject for AnyRenderSliver {
1683 fn as_object(self) -> AnyRenderObject {
1684 AnyRenderSliver::as_object(self)
1685 }
1686
1687 fn from_object(object: AnyRenderObject) -> AnyRenderSliver {
1688 object
1689 .as_sliver()
1690 .expect("the render object is not a RenderSliver")
1691 }
1692}
1693
1694impl From<AnyRenderSliver> for AnyRenderObject {
1695 fn from(sliver: AnyRenderSliver) -> AnyRenderObject {
1696 sliver.as_object()
1697 }
1698}
1699
1700fn get_right_way_up(constraints: SliverConstraints) -> bool {
1705 let reversed = axis_direction_is_reversed(constraints.axis_direction);
1706 match constraints.growth_direction {
1707 GrowthDirection::Forward => !reversed,
1708 GrowthDirection::Reverse => reversed,
1709 }
1710}
1711
1712pub trait RenderSliverHelpers: RenderSliver {
1714 fn hit_test_box_child(
1725 self: RenderHandle<Self>,
1726 app: &mut App,
1727 result: &mut BoxHitTestResult<'_>,
1728 child: AnyRenderBox,
1729 main_axis_position: f64,
1730 cross_axis_position: f64,
1731 ) -> bool {
1732 let constraints = self.constraints(app);
1733 let right_way_up = get_right_way_up(constraints);
1734 let mut delta = self.child_main_axis_position(app, child.as_object());
1735 let cross_axis_delta = self.child_cross_axis_position(app, child.as_object());
1736 let mut absolute_position = main_axis_position - delta;
1737 let absolute_cross_axis_position = cross_axis_position - cross_axis_delta;
1738 let size = child.size(app);
1739 let paint_extent = self.geometry(app).paint_extent;
1740 let (paint_offset, transformed_position) = match constraints.axis() {
1741 Axis::Horizontal => {
1742 if !right_way_up {
1743 absolute_position = size.width() - absolute_position;
1744 delta = paint_extent - size.width() - delta;
1745 }
1746 (
1747 Offset::new(delta, cross_axis_delta),
1748 Offset::new(absolute_position, absolute_cross_axis_position),
1749 )
1750 }
1751 Axis::Vertical => {
1752 if !right_way_up {
1753 absolute_position = size.height() - absolute_position;
1754 delta = paint_extent - size.height() - delta;
1755 }
1756 (
1757 Offset::new(cross_axis_delta, delta),
1758 Offset::new(absolute_cross_axis_position, absolute_position),
1759 )
1760 }
1761 };
1762 result.add_with_out_of_band_position(Some(paint_offset), None, None, |result| {
1763 child.hit_test(app, result, transformed_position)
1764 })
1765 }
1766
1767 fn apply_paint_transform_for_box_child(
1776 self: RenderHandle<Self>,
1777 app: &App,
1778 child: AnyRenderBox,
1779 transform: &mut Matrix4,
1780 ) {
1781 let constraints = self.constraints(app);
1782 let right_way_up = get_right_way_up(constraints);
1783 let mut delta = self.child_main_axis_position(app, child.as_object());
1784 let cross_axis_delta = self.child_cross_axis_position(app, child.as_object());
1785 let size = child.size(app);
1786 let paint_extent = self.geometry(app).paint_extent;
1787 match constraints.axis() {
1788 Axis::Horizontal => {
1789 if !right_way_up {
1790 delta = paint_extent - size.width() - delta;
1791 }
1792 translate(transform, delta, cross_axis_delta);
1793 }
1794 Axis::Vertical => {
1795 if !right_way_up {
1796 delta = paint_extent - size.height() - delta;
1797 }
1798 translate(transform, cross_axis_delta, delta);
1799 }
1800 }
1801 }
1802}
1803
1804pub trait RenderSliverSingleBoxAdapter:
1814 RenderSliver + RenderObjectWithChildMixin<ChildType = AnyRenderBox> + RenderSliverHelpers
1815{
1816 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1819 if !child.parent_data_is::<SliverPhysicalParentData>(app) {
1820 child.set_parent_data(app, SliverPhysicalParentData::new());
1821 }
1822 }
1823
1824 fn set_child_parent_data(
1828 self: RenderHandle<Self>,
1829 app: &mut App,
1830 child: AnyRenderObject,
1831 constraints: SliverConstraints,
1832 geometry: SliverGeometry,
1833 ) {
1834 let paint_offset = match apply_growth_direction_to_axis_direction(
1835 constraints.axis_direction,
1836 constraints.growth_direction,
1837 ) {
1838 AxisDirection::Up => Offset::new(
1839 0.0,
1840 geometry.paint_extent + constraints.scroll_offset - geometry.scroll_extent,
1841 ),
1842 AxisDirection::Left => Offset::new(
1843 geometry.paint_extent + constraints.scroll_offset - geometry.scroll_extent,
1844 0.0,
1845 ),
1846 AxisDirection::Right => Offset::new(-constraints.scroll_offset, 0.0),
1847 AxisDirection::Down => Offset::new(0.0, -constraints.scroll_offset),
1848 };
1849 child
1850 .parent_data_of_mut::<SliverPhysicalParentData>(app)
1851 .paint_offset = paint_offset;
1852 }
1853
1854 fn hit_test_children(
1856 self: RenderHandle<Self>,
1857 app: &mut App,
1858 result: &mut SliverHitTestResult<'_>,
1859 main_axis_position: f64,
1860 cross_axis_position: f64,
1861 ) -> bool {
1862 debug_assert!(self.geometry(app).hit_test_extent > 0.0);
1863 let Some(child) = self.child(app) else {
1864 return false;
1865 };
1866 self.hit_test_box_child(
1867 app,
1868 &mut BoxHitTestResult::wrap(result),
1869 child,
1870 main_axis_position,
1871 cross_axis_position,
1872 )
1873 }
1874
1875 fn child_main_axis_position(
1877 self: RenderHandle<Self>,
1878 app: &App,
1879 child: AnyRenderObject,
1880 ) -> f64 {
1881 debug_assert_eq!(Some(child), self.child(app).map(AnyRenderBox::as_object));
1882 -self.constraints(app).scroll_offset
1883 }
1884
1885 fn apply_paint_transform(
1887 self: RenderHandle<Self>,
1888 app: &App,
1889 child: AnyRenderObject,
1890 transform: &mut Matrix4,
1891 ) {
1892 debug_assert_eq!(Some(child), self.child(app).map(AnyRenderBox::as_object));
1893 child
1894 .parent_data_of::<SliverPhysicalParentData>(app)
1895 .apply_paint_transform(transform);
1896 }
1897
1898 fn paint(
1900 self: RenderHandle<Self>,
1901 app: &mut App,
1902 context: &mut PaintingContext,
1903 offset: Offset,
1904 ) {
1905 let Some(child) = self.child(app) else {
1906 return;
1907 };
1908 if !self.geometry(app).visible {
1909 return;
1910 }
1911 let paint_offset = child
1912 .as_object()
1913 .parent_data_of::<SliverPhysicalParentData>(app)
1914 .paint_offset;
1915 context.paint_child(app, child.as_object(), offset + paint_offset);
1916 }
1917}
1918
1919pub struct RenderSliverToBoxAdapter {
1930 render_object: crate::object::RenderObjectData,
1931 render_sliver: RenderSliverData,
1932 child: RenderObjectWithChildData<AnyRenderBox>,
1933}
1934
1935impl RenderSliverToBoxAdapter {
1936 pub fn new(
1938 app: &mut App,
1939 child: Option<AnyRenderBox>,
1940 ) -> RenderHandle<RenderSliverToBoxAdapter> {
1941 let this = RenderHandle::new_sliver(
1942 app,
1943 RenderSliverToBoxAdapter {
1944 render_object: crate::object::RenderObjectData::new(),
1945 render_sliver: RenderSliverData::new(),
1946 child: RenderObjectWithChildData::new(),
1947 },
1948 );
1949 this.set_child(app, child);
1950 this
1951 }
1952}
1953
1954impl RenderObjectWithChildMixin for RenderSliverToBoxAdapter {
1955 type ChildType = AnyRenderBox;
1956
1957 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1958 &self.get(app).child
1959 }
1960
1961 fn child_data_mut(
1962 self: RenderHandle<Self>,
1963 app: &mut App,
1964 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1965 &mut self.get_mut(app).child
1966 }
1967}
1968
1969impl RenderSliverHelpers for RenderSliverToBoxAdapter {}
1970
1971impl RenderSliverSingleBoxAdapter for RenderSliverToBoxAdapter {}
1972
1973impl RenderObject for RenderSliverToBoxAdapter {
1974 crate::render_object_accessors!();
1975
1976 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1977 RenderSliverSingleBoxAdapter::setup_parent_data(self, app, child)
1978 }
1979
1980 fn visit_children(
1981 self: RenderHandle<Self>,
1982 app: &App,
1983 visitor: &mut dyn FnMut(AnyRenderObject),
1984 ) {
1985 if let Some(child) = self.child(app) {
1986 visitor(child.as_object());
1987 }
1988 }
1989
1990 fn apply_paint_transform(
1991 self: RenderHandle<Self>,
1992 app: &App,
1993 child: AnyRenderObject,
1994 transform: &mut Matrix4,
1995 ) {
1996 RenderSliverSingleBoxAdapter::apply_paint_transform(self, app, child, transform)
1997 }
1998
1999 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2000 let Some(child) = self.child(app) else {
2001 self.set_geometry(app, SliverGeometry::ZERO);
2002 return;
2003 };
2004 let constraints = self.constraints(app);
2005 child.layout(
2006 app,
2007 constraints.as_box_constraints(0.0, f64::INFINITY, None),
2008 true,
2009 );
2010 let child_extent = match constraints.axis() {
2011 Axis::Horizontal => child.size(app).width(),
2012 Axis::Vertical => child.size(app).height(),
2013 };
2014 let painted_child_size = calculate_paint_offset(constraints, 0.0, child_extent);
2015 let cache_extent = calculate_cache_offset(constraints, 0.0, child_extent);
2016
2017 debug_assert!(painted_child_size.is_finite());
2018 debug_assert!(painted_child_size >= 0.0);
2019 let geometry = SliverGeometry::new()
2020 .scroll_extent(child_extent)
2021 .paint_extent(painted_child_size)
2022 .cache_extent(cache_extent)
2023 .max_paint_extent(child_extent)
2024 .hit_test_extent(painted_child_size)
2025 .has_visual_overflow(
2026 child_extent > constraints.remaining_paint_extent
2027 || constraints.scroll_offset > 0.0,
2028 );
2029 self.set_geometry(app, geometry);
2030 self.set_child_parent_data(app, child.as_object(), constraints, geometry);
2031 }
2032
2033 fn paint(
2034 self: RenderHandle<Self>,
2035 app: &mut App,
2036 context: &mut PaintingContext,
2037 offset: Offset,
2038 ) {
2039 RenderSliverSingleBoxAdapter::paint(self, app, context, offset)
2040 }
2041}
2042
2043impl RenderSliver for RenderSliverToBoxAdapter {
2044 render_sliver_accessors!();
2045
2046 fn hit_test_children(
2047 self: RenderHandle<Self>,
2048 app: &mut App,
2049 result: &mut SliverHitTestResult<'_>,
2050 main_axis_position: f64,
2051 cross_axis_position: f64,
2052 ) -> bool {
2053 RenderSliverSingleBoxAdapter::hit_test_children(
2054 self,
2055 app,
2056 result,
2057 main_axis_position,
2058 cross_axis_position,
2059 )
2060 }
2061
2062 fn child_main_axis_position(
2063 self: RenderHandle<Self>,
2064 app: &App,
2065 child: AnyRenderObject,
2066 ) -> f64 {
2067 RenderSliverSingleBoxAdapter::child_main_axis_position(self, app, child)
2068 }
2069}
2070
2071#[cfg(test)]
2072mod tests {
2073 use inset_foundation::AppCell;
2074 use inset_gestures::HitTestResult;
2075
2076 use super::*;
2077 use crate::box_::{RenderBox, RenderBoxData};
2078 use crate::proxy_box::RenderConstrainedBox;
2079
2080 struct TestSliver {
2081 render_object: crate::object::RenderObjectData,
2082 render_sliver: RenderSliverData,
2083 }
2084
2085 impl RenderObject for TestSliver {
2086 crate::render_object_accessors!();
2087
2088 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2089 let constraints = self.constraints(app);
2090 let extent = constraints.remaining_paint_extent.min(20.0);
2091 self.set_geometry(
2092 app,
2093 SliverGeometry::new()
2094 .scroll_extent(20.0)
2095 .paint_extent(extent)
2096 .max_paint_extent(20.0),
2097 );
2098 }
2099 }
2100
2101 impl RenderSliver for TestSliver {
2102 render_sliver_accessors!();
2103 }
2104
2105 fn vertical_constraints(remaining_paint: f64) -> SliverConstraints {
2106 SliverConstraints::new(
2107 AxisDirection::Down,
2108 GrowthDirection::Forward,
2109 ScrollDirection::Idle,
2110 0.0,
2111 0.0,
2112 0.0,
2113 remaining_paint,
2114 100.0,
2115 AxisDirection::Right,
2116 400.0,
2117 remaining_paint,
2118 0.0,
2119 )
2120 }
2121
2122 #[test]
2123 fn sliver_layout_sets_geometry() {
2124 let cell = AppCell::new();
2125 let mut app = cell.borrow_mut();
2126 let sliver = RenderHandle::new_sliver(
2127 &mut app,
2128 TestSliver {
2129 render_object: crate::object::RenderObjectData::new(),
2130 render_sliver: RenderSliverData::new(),
2131 },
2132 );
2133 sliver.layout(&mut app, vertical_constraints(50.0), false);
2134 let geometry = sliver.geometry(&app);
2135 assert_eq!(geometry.scroll_extent, 20.0);
2136 assert_eq!(geometry.paint_extent, 20.0);
2137 assert!(geometry.visible);
2138 }
2139
2140 struct HitTestableBox {
2143 render_object: crate::object::RenderObjectData,
2144 render_box: RenderBoxData,
2145 }
2146
2147 impl RenderObject for HitTestableBox {
2148 crate::render_object_accessors!();
2149
2150 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2151 let size = self.constraints(app).constrain(Size::new(60.0, 60.0));
2152 self.set_size(app, size);
2153 }
2154 }
2155
2156 impl RenderBox for HitTestableBox {
2157 crate::render_box_accessors!();
2158
2159 fn hit_test_self(self: RenderHandle<Self>, _app: &App, _position: Offset) -> bool {
2160 let _ = self;
2161 true
2162 }
2163 }
2164
2165 fn hit_testable_box(app: &mut App) -> AnyRenderBox {
2166 RenderHandle::new_box(
2167 app,
2168 HitTestableBox {
2169 render_object: crate::object::RenderObjectData::new(),
2170 render_box: RenderBoxData::new(),
2171 },
2172 )
2173 .as_box()
2174 }
2175
2176 fn adapter_constraints(scroll_offset: f64, remaining_paint: f64) -> SliverConstraints {
2177 SliverConstraints::new(
2178 AxisDirection::Down,
2179 GrowthDirection::Forward,
2180 ScrollDirection::Idle,
2181 scroll_offset,
2182 0.0,
2183 0.0,
2184 remaining_paint,
2185 100.0,
2186 AxisDirection::Right,
2187 remaining_paint,
2188 remaining_paint,
2189 0.0,
2190 )
2191 }
2192
2193 #[test]
2196 fn a_box_adapter_reports_its_child_extent() {
2197 let cell = AppCell::new();
2198 let mut app = cell.borrow_mut();
2199 let child =
2200 RenderConstrainedBox::new(&mut app, BoxConstraints::tight_for(None, Some(60.0)), None);
2201 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child.as_box()));
2202
2203 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2204
2205 let geometry = adapter.geometry(&app);
2206 assert_eq!(geometry.scroll_extent, 60.0);
2207 assert_eq!(geometry.paint_extent, 60.0);
2208 assert_eq!(geometry.max_paint_extent, 60.0);
2209 assert!(!geometry.has_visual_overflow);
2210 assert_eq!(child.size(&app), Size::new(100.0, 60.0));
2212 assert_eq!(
2213 child
2214 .as_box()
2215 .as_object()
2216 .parent_data_of::<SliverPhysicalParentData>(&app)
2217 .paint_offset,
2218 Offset::ZERO
2219 );
2220 }
2221
2222 #[test]
2224 fn a_scrolled_box_adapter_offsets_its_child() {
2225 let cell = AppCell::new();
2226 let mut app = cell.borrow_mut();
2227 let child =
2228 RenderConstrainedBox::new(&mut app, BoxConstraints::tight_for(None, Some(60.0)), None);
2229 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child.as_box()));
2230
2231 adapter.layout(&mut app, adapter_constraints(20.0, 400.0), true);
2232
2233 let geometry = adapter.geometry(&app);
2234 assert_eq!(geometry.scroll_extent, 60.0);
2235 assert_eq!(geometry.paint_extent, 40.0);
2236 assert!(geometry.has_visual_overflow);
2237 assert_eq!(
2238 child
2239 .as_box()
2240 .as_object()
2241 .parent_data_of::<SliverPhysicalParentData>(&app)
2242 .paint_offset,
2243 Offset::new(0.0, -20.0)
2244 );
2245 assert_eq!(
2246 RenderSliver::child_main_axis_position(adapter, &app, child.as_object()),
2247 -20.0
2248 );
2249 }
2250
2251 #[test]
2253 fn a_childless_box_adapter_is_zero() {
2254 let cell = AppCell::new();
2255 let mut app = cell.borrow_mut();
2256 let adapter = RenderSliverToBoxAdapter::new(&mut app, None);
2257 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2258 assert!(adapter.geometry(&app).is_zero());
2259 }
2260
2261 #[test]
2263 fn a_box_adapter_hit_tests_its_child() {
2264 let cell = AppCell::new();
2265 let mut app = cell.borrow_mut();
2266 let child = hit_testable_box(&mut app);
2267 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child));
2268 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2269
2270 let mut result = HitTestResult::new();
2271 let hit = adapter.hit_test(
2272 &mut app,
2273 &mut SliverHitTestResult::wrap(&mut result),
2274 30.0,
2275 50.0,
2276 );
2277
2278 assert!(hit);
2279 assert_eq!(result.path().len(), 2);
2280 }
2281
2282 #[test]
2284 fn paint_and_cache_offsets_clamp_to_the_window() {
2285 let constraints = adapter_constraints(20.0, 50.0);
2286 assert_eq!(calculate_paint_offset(constraints, 0.0, 100.0), 50.0);
2287 assert_eq!(calculate_paint_offset(constraints, 0.0, 30.0), 10.0);
2288 assert_eq!(calculate_paint_offset(constraints, 0.0, 10.0), 0.0);
2289 assert_eq!(calculate_cache_offset(constraints, 0.0, 100.0), 50.0);
2290 }
2291
2292 #[test]
2294 fn a_consistent_geometry_is_valid() {
2295 let geometry = SliverGeometry::new()
2296 .scroll_extent(100.0)
2297 .paint_extent(40.0)
2298 .max_paint_extent(100.0);
2299 assert!(geometry.debug_assert_is_valid());
2300 assert!(!geometry.is_zero());
2301 assert!(SliverGeometry::ZERO.is_zero());
2302 }
2303}