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 builder() -> SliverGeometryBuilder {
395 SliverGeometryBuilder {
396 scroll_extent: 0.0,
397 paint_origin: 0.0,
398 paint_extent: 0.0,
399 layout_extent: None,
400 max_paint_extent: 0.0,
401 max_scroll_obstruction_extent: 0.0,
402 hit_test_extent: None,
403 visible: None,
404 has_visual_overflow: false,
405 scroll_offset_correction: None,
406 cache_extent: None,
407 cross_axis_extent: None,
408 }
409 }
410
411 pub const fn copy_with(self) -> SliverGeometryBuilder {
413 SliverGeometryBuilder {
414 scroll_extent: self.scroll_extent,
415 paint_origin: self.paint_origin,
416 paint_extent: self.paint_extent,
417 layout_extent: Some(self.layout_extent),
418 max_paint_extent: self.max_paint_extent,
419 max_scroll_obstruction_extent: self.max_scroll_obstruction_extent,
420 hit_test_extent: Some(self.hit_test_extent),
421 visible: Some(self.visible),
422 has_visual_overflow: self.has_visual_overflow,
423 scroll_offset_correction: self.scroll_offset_correction,
424 cache_extent: Some(self.cache_extent),
425 cross_axis_extent: self.cross_axis_extent,
426 }
427 }
428
429 pub fn is_zero(&self) -> bool {
432 self.scroll_extent == SliverGeometry::ZERO.scroll_extent
433 && self.paint_origin == SliverGeometry::ZERO.paint_origin
434 && self.paint_extent == SliverGeometry::ZERO.paint_extent
435 && self.layout_extent == SliverGeometry::ZERO.layout_extent
436 && self.max_paint_extent == SliverGeometry::ZERO.max_paint_extent
437 && self.max_scroll_obstruction_extent
438 == SliverGeometry::ZERO.max_scroll_obstruction_extent
439 && self.hit_test_extent == SliverGeometry::ZERO.hit_test_extent
440 && self.visible == SliverGeometry::ZERO.visible
441 && self.has_visual_overflow == SliverGeometry::ZERO.has_visual_overflow
442 && self.scroll_offset_correction == SliverGeometry::ZERO.scroll_offset_correction
443 && self.cache_extent == SliverGeometry::ZERO.cache_extent
444 && self.cross_axis_extent == SliverGeometry::ZERO.cross_axis_extent
445 }
446
447 pub fn debug_assert_is_valid(&self) -> bool {
451 debug_assert!(self.scroll_extent >= 0.0, "The scroll_extent is negative.");
452 debug_assert!(self.paint_extent >= 0.0, "The paint_extent is negative.");
453 debug_assert!(self.layout_extent >= 0.0, "The layout_extent is negative.");
454 debug_assert!(self.cache_extent >= 0.0, "The cache_extent is negative.");
455 debug_assert!(
456 self.layout_extent <= self.paint_extent,
457 "The layout_extent ({}) exceeds the paint_extent ({}).",
458 self.layout_extent,
459 self.paint_extent
460 );
461 debug_assert!(
464 self.paint_extent - self.max_paint_extent <= PRECISION_ERROR_TOLERANCE,
465 "The max_paint_extent ({}) is less than the paint_extent ({}). By definition, a \
466 sliver can't paint more than the maximum that it can paint!",
467 self.max_paint_extent,
468 self.paint_extent
469 );
470 debug_assert!(
471 self.hit_test_extent >= 0.0,
472 "The hit_test_extent is negative."
473 );
474 debug_assert!(
475 self.scroll_offset_correction != Some(0.0),
476 "The scroll_offset_correction is zero."
477 );
478 true
479 }
480}
481
482#[derive(Clone, Copy, Debug)]
485pub struct SliverGeometryBuilder {
486 scroll_extent: f64,
487 paint_origin: f64,
488 paint_extent: f64,
489 layout_extent: Option<f64>,
490 max_paint_extent: f64,
491 max_scroll_obstruction_extent: f64,
492 hit_test_extent: Option<f64>,
493 visible: Option<bool>,
494 has_visual_overflow: bool,
495 scroll_offset_correction: Option<f64>,
496 cache_extent: Option<f64>,
497 cross_axis_extent: Option<f64>,
498}
499
500impl SliverGeometryBuilder {
501 pub const fn scroll_extent(mut self, value: f64) -> SliverGeometryBuilder {
503 self.scroll_extent = value;
504 self
505 }
506
507 pub const fn paint_origin(mut self, value: f64) -> SliverGeometryBuilder {
509 self.paint_origin = value;
510 self
511 }
512
513 pub const fn paint_extent(mut self, value: f64) -> SliverGeometryBuilder {
515 self.paint_extent = value;
516 self
517 }
518
519 pub const fn layout_extent(mut self, value: f64) -> SliverGeometryBuilder {
521 self.layout_extent = Some(value);
522 self
523 }
524
525 pub const fn max_paint_extent(mut self, value: f64) -> SliverGeometryBuilder {
527 self.max_paint_extent = value;
528 self
529 }
530
531 pub const fn max_scroll_obstruction_extent(mut self, value: f64) -> SliverGeometryBuilder {
533 self.max_scroll_obstruction_extent = value;
534 self
535 }
536
537 pub const fn hit_test_extent(mut self, value: f64) -> SliverGeometryBuilder {
539 self.hit_test_extent = Some(value);
540 self
541 }
542
543 pub const fn visible(mut self, value: bool) -> SliverGeometryBuilder {
545 self.visible = Some(value);
546 self
547 }
548
549 pub const fn has_visual_overflow(mut self, value: bool) -> SliverGeometryBuilder {
551 self.has_visual_overflow = value;
552 self
553 }
554
555 pub fn scroll_offset_correction(mut self, value: f64) -> SliverGeometryBuilder {
557 debug_assert!(value != 0.0);
558 self.scroll_offset_correction = Some(value);
559 self
560 }
561
562 pub const fn cache_extent(mut self, value: f64) -> SliverGeometryBuilder {
564 self.cache_extent = Some(value);
565 self
566 }
567
568 pub const fn cross_axis_extent(mut self, value: f64) -> SliverGeometryBuilder {
570 self.cross_axis_extent = Some(value);
571 self
572 }
573
574 pub fn build(self) -> SliverGeometry {
578 SliverGeometry {
579 scroll_extent: self.scroll_extent,
580 paint_origin: self.paint_origin,
581 paint_extent: self.paint_extent,
582 layout_extent: self.layout_extent.unwrap_or(self.paint_extent),
583 max_paint_extent: self.max_paint_extent,
584 max_scroll_obstruction_extent: self.max_scroll_obstruction_extent,
585 hit_test_extent: self.hit_test_extent.unwrap_or(self.paint_extent),
586 visible: self.visible.unwrap_or(self.paint_extent > 0.0),
587 has_visual_overflow: self.has_visual_overflow,
588 scroll_offset_correction: self.scroll_offset_correction,
589 cache_extent: self
590 .cache_extent
591 .or(self.layout_extent)
592 .unwrap_or(self.paint_extent),
593 cross_axis_extent: self.cross_axis_extent,
594 }
595 }
596}
597
598impl Default for SliverGeometry {
599 fn default() -> SliverGeometry {
600 SliverGeometry::builder().build()
601 }
602}
603
604impl Display for SliverGeometry {
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 write!(
607 f,
608 "SliverGeometry({}x{})",
609 self.scroll_extent, self.paint_extent
610 )
611 }
612}
613
614pub type SliverHitTest<'r> = dyn FnOnce(&mut SliverHitTestResult<'r>, f64, f64) -> bool;
622
623pub struct SliverHitTestResult<'a>(&'a mut HitTestResult);
628
629impl<'a> SliverHitTestResult<'a> {
630 pub fn wrap(result: &'a mut HitTestResult) -> SliverHitTestResult<'a> {
635 SliverHitTestResult(result)
636 }
637
638 pub fn add_with_axis_offset(
657 &mut self,
658 paint_offset: Option<Offset>,
659 main_axis_offset: f64,
660 cross_axis_offset: f64,
661 main_axis_position: f64,
662 cross_axis_position: f64,
663 hit_test: impl FnOnce(&mut SliverHitTestResult<'_>, f64, f64) -> bool,
664 ) -> bool {
665 if let Some(paint_offset) = paint_offset {
666 self.0.push_offset(Offset::ZERO - paint_offset);
667 }
668 let is_hit = hit_test(
669 self,
670 main_axis_position - main_axis_offset,
671 cross_axis_position - cross_axis_offset,
672 );
673 if paint_offset.is_some() {
674 self.0.pop_transform();
675 }
676 is_hit
677 }
678}
679
680impl Deref for SliverHitTestResult<'_> {
681 type Target = HitTestResult;
682
683 fn deref(&self) -> &HitTestResult {
684 self.0
685 }
686}
687
688impl DerefMut for SliverHitTestResult<'_> {
689 fn deref_mut(&mut self) -> &mut HitTestResult {
690 self.0
691 }
692}
693
694#[derive(Clone, Copy, Debug)]
702pub struct SliverHitTestEntry {
703 target: AnyRenderSliver,
704 main_axis_position: f64,
705 cross_axis_position: f64,
706}
707
708impl SliverHitTestEntry {
709 pub fn new(
711 target: AnyRenderSliver,
712 main_axis_position: f64,
713 cross_axis_position: f64,
714 ) -> SliverHitTestEntry {
715 SliverHitTestEntry {
716 target,
717 main_axis_position,
718 cross_axis_position,
719 }
720 }
721
722 pub fn target(&self) -> AnyRenderSliver {
724 self.target
725 }
726
727 pub fn main_axis_position(&self) -> f64 {
733 self.main_axis_position
734 }
735
736 pub fn cross_axis_position(&self) -> f64 {
746 self.cross_axis_position
747 }
748}
749
750impl HitTestTarget for SliverHitTestEntry {
751 fn retained_handle(&self) -> Option<HandleId> {
752 Some(self.target.id)
753 }
754
755 fn handle_event(&self, app: &mut App, event: &PointerEvent, _entry: &HitTestEntry) {
756 self.target.handle_event(app, event, self);
757 }
758}
759
760impl From<SliverHitTestEntry> for HitTestEntry {
761 fn from(entry: SliverHitTestEntry) -> HitTestEntry {
762 HitTestEntry::new(entry)
763 }
764}
765
766#[derive(Clone, Copy, Debug, Default)]
772pub struct SliverLogicalParentData {
773 pub layout_offset: Option<f64>,
782}
783
784impl SliverLogicalParentData {
785 pub const fn new() -> SliverLogicalParentData {
787 SliverLogicalParentData {
788 layout_offset: None,
789 }
790 }
791}
792
793impl ParentData for SliverLogicalParentData {
794 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
795 (id == TypeId::of::<SliverLogicalParentData>()).then_some(self)
796 }
797
798 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
799 (id == TypeId::of::<SliverLogicalParentData>()).then_some(self)
800 }
801}
802
803impl Display for SliverLogicalParentData {
804 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
805 match self.layout_offset {
806 None => f.write_str("layoutOffset=None"),
807 Some(offset) => write!(f, "layoutOffset={offset:.1}"),
808 }
809 }
810}
811
812#[derive(Debug)]
815pub struct SliverLogicalContainerParentData {
816 sliver_logical: SliverLogicalParentData,
817 container: ContainerParentData<AnyRenderSliver>,
818}
819
820impl SliverLogicalContainerParentData {
821 pub const fn new() -> SliverLogicalContainerParentData {
823 SliverLogicalContainerParentData {
824 sliver_logical: SliverLogicalParentData::new(),
825 container: ContainerParentData::new(),
826 }
827 }
828
829 pub fn sliver_logical_parent_data(&self) -> &SliverLogicalParentData {
831 &self.sliver_logical
832 }
833
834 pub fn sliver_logical_parent_data_mut(&mut self) -> &mut SliverLogicalParentData {
836 &mut self.sliver_logical
837 }
838
839 pub fn layout_offset(&self) -> Option<f64> {
841 self.sliver_logical.layout_offset
842 }
843
844 pub fn set_layout_offset(&mut self, value: Option<f64>) {
846 self.sliver_logical.layout_offset = value;
847 }
848}
849
850impl Default for SliverLogicalContainerParentData {
851 fn default() -> SliverLogicalContainerParentData {
852 SliverLogicalContainerParentData::new()
853 }
854}
855
856impl ParentData for SliverLogicalContainerParentData {
857 fn detach(&mut self) {
858 ContainerParentDataMixin::detach(self);
859 }
860
861 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
862 if id == TypeId::of::<SliverLogicalContainerParentData>() {
863 return Some(self);
864 }
865 self.sliver_logical.provide(id)
866 }
867
868 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
869 if id == TypeId::of::<SliverLogicalContainerParentData>() {
870 return Some(self);
871 }
872 self.sliver_logical.provide_mut(id)
873 }
874}
875
876impl ContainerParentDataMixin for SliverLogicalContainerParentData {
877 type ChildType = AnyRenderSliver;
878
879 fn container_parent_data(&self) -> &ContainerParentData<AnyRenderSliver> {
880 &self.container
881 }
882
883 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<AnyRenderSliver> {
884 &mut self.container
885 }
886}
887
888impl Display for SliverLogicalContainerParentData {
889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
890 Display::fmt(&self.sliver_logical, f)
891 }
892}
893
894#[derive(Clone, Copy, Debug)]
904pub struct SliverPhysicalParentData {
905 pub paint_offset: Offset,
910
911 pub cross_axis_flex: Option<i32>,
920}
921
922impl SliverPhysicalParentData {
923 pub const fn new() -> SliverPhysicalParentData {
925 SliverPhysicalParentData {
926 paint_offset: Offset::ZERO,
927 cross_axis_flex: None,
928 }
929 }
930
931 pub fn apply_paint_transform(&self, transform: &mut Matrix4) {
936 translate(transform, self.paint_offset.dx(), self.paint_offset.dy());
938 }
939}
940
941impl Default for SliverPhysicalParentData {
942 fn default() -> SliverPhysicalParentData {
943 SliverPhysicalParentData::new()
944 }
945}
946
947impl ParentData for SliverPhysicalParentData {
948 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
949 (id == TypeId::of::<SliverPhysicalParentData>()).then_some(self)
950 }
951
952 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
953 (id == TypeId::of::<SliverPhysicalParentData>()).then_some(self)
954 }
955}
956
957impl Display for SliverPhysicalParentData {
958 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959 write!(f, "paintOffset={:?}", self.paint_offset)
960 }
961}
962
963#[derive(Debug)]
966pub struct SliverPhysicalContainerParentData {
967 sliver_physical: SliverPhysicalParentData,
968 container: ContainerParentData<AnyRenderSliver>,
969}
970
971impl SliverPhysicalContainerParentData {
972 pub const fn new() -> SliverPhysicalContainerParentData {
974 SliverPhysicalContainerParentData {
975 sliver_physical: SliverPhysicalParentData::new(),
976 container: ContainerParentData::new(),
977 }
978 }
979
980 pub fn sliver_physical_parent_data(&self) -> &SliverPhysicalParentData {
982 &self.sliver_physical
983 }
984
985 pub fn sliver_physical_parent_data_mut(&mut self) -> &mut SliverPhysicalParentData {
987 &mut self.sliver_physical
988 }
989
990 pub fn paint_offset(&self) -> Offset {
992 self.sliver_physical.paint_offset
993 }
994
995 pub fn set_paint_offset(&mut self, value: Offset) {
997 self.sliver_physical.paint_offset = value;
998 }
999
1000 pub fn apply_paint_transform(&self, transform: &mut Matrix4) {
1002 self.sliver_physical.apply_paint_transform(transform);
1003 }
1004}
1005
1006impl Default for SliverPhysicalContainerParentData {
1007 fn default() -> SliverPhysicalContainerParentData {
1008 SliverPhysicalContainerParentData::new()
1009 }
1010}
1011
1012impl ParentData for SliverPhysicalContainerParentData {
1013 fn detach(&mut self) {
1014 ContainerParentDataMixin::detach(self);
1015 }
1016
1017 fn provide(&self, id: TypeId) -> Option<&dyn Any> {
1018 if id == TypeId::of::<SliverPhysicalContainerParentData>() {
1019 return Some(self);
1020 }
1021 self.sliver_physical.provide(id)
1022 }
1023
1024 fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
1025 if id == TypeId::of::<SliverPhysicalContainerParentData>() {
1026 return Some(self);
1027 }
1028 self.sliver_physical.provide_mut(id)
1029 }
1030}
1031
1032impl ContainerParentDataMixin for SliverPhysicalContainerParentData {
1033 type ChildType = AnyRenderSliver;
1034
1035 fn container_parent_data(&self) -> &ContainerParentData<AnyRenderSliver> {
1036 &self.container
1037 }
1038
1039 fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<AnyRenderSliver> {
1040 &mut self.container
1041 }
1042}
1043
1044impl Display for SliverPhysicalContainerParentData {
1045 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1046 Display::fmt(&self.sliver_physical, f)
1047 }
1048}
1049
1050pub(crate) fn calculate_paint_offset(constraints: SliverConstraints, from: f64, to: f64) -> f64 {
1052 debug_assert!(from <= to);
1053 let a = constraints.scroll_offset;
1054 let b = constraints.scroll_offset + constraints.remaining_paint_extent;
1055 clamp_double(
1057 clamp_double(to, a, b) - clamp_double(from, a, b),
1058 0.0,
1059 constraints.remaining_paint_extent,
1060 )
1061}
1062
1063pub(crate) fn calculate_cache_offset(constraints: SliverConstraints, from: f64, to: f64) -> f64 {
1065 debug_assert!(from <= to);
1066 let a = constraints.scroll_offset + constraints.cache_origin;
1067 let b = constraints.scroll_offset + constraints.remaining_cache_extent;
1068 clamp_double(
1070 clamp_double(to, a, b) - clamp_double(from, a, b),
1071 0.0,
1072 constraints.remaining_cache_extent,
1073 )
1074}
1075
1076pub struct RenderSliverData {
1078 pub(crate) geometry: Option<SliverGeometry>,
1079 pub(crate) constraints: Option<SliverConstraints>,
1080}
1081
1082impl RenderSliverData {
1083 pub fn new() -> RenderSliverData {
1085 RenderSliverData {
1086 geometry: None,
1087 constraints: None,
1088 }
1089 }
1090}
1091
1092impl Default for RenderSliverData {
1093 fn default() -> RenderSliverData {
1094 RenderSliverData::new()
1095 }
1096}
1097
1098#[macro_export]
1100macro_rules! render_sliver_accessors {
1101 () => {
1102 fn render_sliver_data(
1103 self: $crate::RenderHandle<Self>,
1104 app: &::inset_foundation::App,
1105 ) -> &$crate::RenderSliverData {
1106 &self.get(app).render_sliver
1107 }
1108 fn render_sliver_data_mut(
1109 self: $crate::RenderHandle<Self>,
1110 app: &mut ::inset_foundation::App,
1111 ) -> &mut $crate::RenderSliverData {
1112 &mut self.get_mut(app).render_sliver
1113 }
1114 };
1115}
1116
1117pub trait RenderSliver: RenderObject {
1123 fn render_sliver_data(self: RenderHandle<Self>, app: &App) -> &RenderSliverData;
1125
1126 fn render_sliver_data_mut(self: RenderHandle<Self>, app: &mut App) -> &mut RenderSliverData;
1128
1129 fn constraints(self: RenderHandle<Self>, app: &App) -> SliverConstraints {
1131 self.render_sliver_data(app).constraints.unwrap_or_else(|| {
1132 panic!("A RenderObject does not have any constraints before it has been laid out.")
1133 })
1134 }
1135
1136 fn geometry(self: RenderHandle<Self>, app: &App) -> SliverGeometry {
1138 self.as_sliver().geometry(app)
1139 }
1140
1141 fn set_geometry(self: RenderHandle<Self>, app: &mut App, geometry: SliverGeometry) {
1143 self.as_sliver().set_geometry(app, geometry)
1144 }
1145
1146 fn paint_bounds(self: RenderHandle<Self>, app: &App) -> Rect {
1149 let constraints = self.constraints(app);
1150 let geometry = self.geometry(app);
1151 match constraints.axis() {
1152 Axis::Horizontal => Rect::from_ltwh(
1153 0.0,
1154 0.0,
1155 geometry.paint_extent,
1156 constraints.cross_axis_extent,
1157 ),
1158 Axis::Vertical => Rect::from_ltwh(
1159 0.0,
1160 0.0,
1161 constraints.cross_axis_extent,
1162 geometry.paint_extent,
1163 ),
1164 }
1165 }
1166
1167 fn center_offset_adjustment(self: RenderHandle<Self>, _app: &App) -> f64 {
1178 let _ = self;
1179 0.0
1180 }
1181
1182 fn hit_test(
1210 self: RenderHandle<Self>,
1211 app: &mut App,
1212 result: &mut SliverHitTestResult<'_>,
1213 main_axis_position: f64,
1214 cross_axis_position: f64,
1215 ) -> bool {
1216 if main_axis_position >= 0.0
1217 && main_axis_position < self.geometry(app).hit_test_extent
1218 && cross_axis_position >= 0.0
1219 && cross_axis_position < self.constraints(app).cross_axis_extent
1220 && (self.hit_test_children(app, result, main_axis_position, cross_axis_position)
1221 || self.hit_test_self(app, main_axis_position, cross_axis_position))
1222 {
1223 result.add(
1224 SliverHitTestEntry::new(self.as_sliver(), main_axis_position, cross_axis_position)
1225 .into(),
1226 );
1227 return true;
1228 }
1229 false
1230 }
1231
1232 fn hit_test_self(
1237 self: RenderHandle<Self>,
1238 _app: &App,
1239 _main_axis_position: f64,
1240 _cross_axis_position: f64,
1241 ) -> bool {
1242 let _ = self;
1243 false
1244 }
1245
1246 fn hit_test_children(
1255 self: RenderHandle<Self>,
1256 _app: &mut App,
1257 _result: &mut SliverHitTestResult<'_>,
1258 _main_axis_position: f64,
1259 _cross_axis_position: f64,
1260 ) -> bool {
1261 let _ = self;
1262 false
1263 }
1264
1265 fn handle_event(
1267 self: RenderHandle<Self>,
1268 _app: &mut App,
1269 _event: &PointerEvent,
1270 _entry: &SliverHitTestEntry,
1271 ) {
1272 let _ = self;
1273 }
1274
1275 fn calculate_paint_offset(
1287 self: RenderHandle<Self>,
1288 _app: &App,
1289 constraints: SliverConstraints,
1290 from: f64,
1291 to: f64,
1292 ) -> f64 {
1293 let _ = self;
1294 calculate_paint_offset(constraints, from, to)
1295 }
1296
1297 fn calculate_cache_offset(
1306 self: RenderHandle<Self>,
1307 _app: &App,
1308 constraints: SliverConstraints,
1309 from: f64,
1310 to: f64,
1311 ) -> f64 {
1312 let _ = self;
1313 calculate_cache_offset(constraints, from, to)
1314 }
1315
1316 fn child_main_axis_position(
1338 self: RenderHandle<Self>,
1339 _app: &App,
1340 _child: AnyRenderObject,
1341 ) -> f64 {
1342 let _ = self;
1343 panic!("this RenderSliver does not implement child_main_axis_position")
1344 }
1345
1346 fn child_cross_axis_position(
1357 self: RenderHandle<Self>,
1358 _app: &App,
1359 _child: AnyRenderObject,
1360 ) -> f64 {
1361 let _ = self;
1362 0.0
1363 }
1364
1365 fn child_scroll_offset(
1376 self: RenderHandle<Self>,
1377 app: &App,
1378 child: AnyRenderObject,
1379 ) -> Option<f64> {
1380 debug_assert_eq!(child.parent(app), Some(self.as_object()));
1381 Some(0.0)
1382 }
1383
1384 fn get_absolute_size_relative_to_origin(self: RenderHandle<Self>, app: &App) -> Size {
1394 debug_assert!(!self.as_object().debug_needs_layout(app));
1395 let constraints = self.constraints(app);
1396 let paint_extent = self.geometry(app).paint_extent;
1397 match apply_growth_direction_to_axis_direction(
1398 constraints.axis_direction,
1399 constraints.growth_direction,
1400 ) {
1401 AxisDirection::Up => Size::new(constraints.cross_axis_extent, -paint_extent),
1402 AxisDirection::Down => Size::new(constraints.cross_axis_extent, paint_extent),
1403 AxisDirection::Left => Size::new(-paint_extent, constraints.cross_axis_extent),
1404 AxisDirection::Right => Size::new(paint_extent, constraints.cross_axis_extent),
1405 }
1406 }
1407
1408 fn get_absolute_size(self: RenderHandle<Self>, app: &App) -> Size {
1418 debug_assert!(!self.as_object().debug_needs_layout(app));
1419 let constraints = self.constraints(app);
1420 let paint_extent = self.geometry(app).paint_extent;
1421 match constraints.axis_direction {
1422 AxisDirection::Up | AxisDirection::Down => {
1423 Size::new(constraints.cross_axis_extent, paint_extent)
1424 }
1425 AxisDirection::Right | AxisDirection::Left => {
1426 Size::new(paint_extent, constraints.cross_axis_extent)
1427 }
1428 }
1429 }
1430
1431 fn get_max_paint_rect(self: RenderHandle<Self>, app: &App) -> Rect {
1437 let Some(geometry) = self.render_sliver_data(app).geometry else {
1438 return Rect::ZERO;
1439 };
1440 if geometry.is_zero() {
1441 return Rect::ZERO;
1442 }
1443 let constraints = self.constraints(app);
1444 let mut max_paint_extent = geometry.max_paint_extent;
1445 if max_paint_extent.is_infinite() {
1446 max_paint_extent =
1447 constraints.scroll_offset + geometry.cache_extent + constraints.cache_origin;
1448 }
1449 let paint_extent = geometry.paint_extent;
1450 let leading_offset = clamp_double(
1453 constraints.scroll_offset,
1454 0.0,
1455 geometry.scroll_extent - geometry.max_scroll_obstruction_extent,
1456 );
1457 let cross_axis_extent = geometry
1458 .cross_axis_extent
1459 .unwrap_or(constraints.cross_axis_extent);
1460
1461 let rect = match constraints.axis() {
1462 Axis::Horizontal => {
1463 Rect::from_ltwh(-leading_offset, 0.0, max_paint_extent, cross_axis_extent)
1464 }
1465 Axis::Vertical => {
1466 Rect::from_ltwh(0.0, -leading_offset, cross_axis_extent, max_paint_extent)
1467 }
1468 };
1469
1470 match apply_growth_direction_to_axis_direction(
1471 constraints.axis_direction,
1472 constraints.growth_direction,
1473 ) {
1474 AxisDirection::Right | AxisDirection::Down => rect,
1475 AxisDirection::Left => Rect::from_ltrb(
1476 paint_extent - rect.right,
1477 rect.top,
1478 paint_extent - rect.left,
1479 rect.bottom,
1480 ),
1481 AxisDirection::Up => Rect::from_ltrb(
1482 rect.left,
1483 paint_extent - rect.bottom,
1484 rect.right,
1485 paint_extent - rect.top,
1486 ),
1487 }
1488 }
1489
1490 fn layout(
1492 self: RenderHandle<Self>,
1493 app: &mut App,
1494 constraints: SliverConstraints,
1495 parent_uses_size: bool,
1496 ) {
1497 self.as_sliver().layout(app, constraints, parent_uses_size)
1498 }
1499
1500 fn as_sliver(self: RenderHandle<Self>) -> AnyRenderSliver {
1502 AnyRenderSliver {
1503 id: self.id(),
1504 vtable: const { &RenderSliverVTable::of::<Self>() },
1505 }
1506 }
1507
1508 fn as_object(self: RenderHandle<Self>) -> AnyRenderObject {
1510 self.as_sliver().as_object()
1511 }
1512
1513 fn adopt_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1515 self.as_object().adopt_child(app, child)
1516 }
1517
1518 fn drop_child(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1520 self.as_object().drop_child(app, child)
1521 }
1522
1523 fn mark_needs_layout(self: RenderHandle<Self>, app: &mut App) {
1525 self.as_object().mark_needs_layout(app)
1526 }
1527
1528 fn mark_needs_paint(self: RenderHandle<Self>, app: &mut App) {
1530 self.as_object().mark_needs_paint(app)
1531 }
1532
1533 fn mark_needs_composited_layer_update(self: RenderHandle<Self>, app: &mut App) {
1535 self.as_object().mark_needs_composited_layer_update(app)
1536 }
1537
1538 fn schedule_initial_layout(self: RenderHandle<Self>, app: &mut App) {
1540 self.as_object().schedule_initial_layout(app)
1541 }
1542
1543 fn parent(self: RenderHandle<Self>, app: &App) -> Option<AnyRenderObject> {
1545 self.as_object().parent(app)
1546 }
1547
1548 fn owner(self: RenderHandle<Self>, app: &App) -> Option<Handle<PipelineOwner>> {
1550 self.as_object().owner(app)
1551 }
1552
1553 fn attached(self: RenderHandle<Self>, app: &App) -> bool {
1555 self.as_object().attached(app)
1556 }
1557
1558 fn debug_needs_layout(self: RenderHandle<Self>, app: &App) -> bool {
1560 self.as_object().debug_needs_layout(app)
1561 }
1562}
1563
1564pub(crate) struct RenderSliverVTable {
1566 pub object: RenderObjectVTable,
1567 pub sliver_data: fn(&App, HandleId) -> &RenderSliverData,
1568 pub sliver_data_mut: fn(&mut App, HandleId) -> &mut RenderSliverData,
1569 pub hit_test: fn(&mut App, HandleId, &mut SliverHitTestResult<'_>, f64, f64) -> bool,
1570 pub handle_event: fn(&mut App, HandleId, &PointerEvent, &SliverHitTestEntry),
1571 pub center_offset_adjustment: fn(&App, HandleId) -> f64,
1572 pub child_scroll_offset: fn(&App, HandleId, AnyRenderObject) -> Option<f64>,
1573 pub child_main_axis_position: fn(&App, HandleId, AnyRenderObject) -> f64,
1574}
1575
1576impl RenderSliverVTable {
1577 const fn of<T: RenderSliver>() -> RenderSliverVTable {
1578 RenderSliverVTable {
1579 object: RenderObjectVTable::of::<T>(
1580 |app, id, child| <T as RenderObject>::setup_parent_data(resolve(id), app, child),
1581 |app, id| T::paint_bounds(resolve(id), app),
1582 |app, id, child, transform| {
1583 <T as RenderObject>::apply_paint_transform(resolve(id), app, child, transform)
1584 },
1585 |app, id| <T as RenderObject>::perform_resize(resolve(id), app),
1586 |app, id| crate::object::RenderObjectBase::mark_needs_layout(resolve::<T>(id), app),
1587 None,
1588 Some(|| const { &RenderSliverVTable::of::<T>() }),
1589 ),
1590 sliver_data: |app, id| T::render_sliver_data(resolve(id), app),
1591 sliver_data_mut: |app, id| T::render_sliver_data_mut(resolve(id), app),
1592 hit_test: |app, id, result, main, cross| {
1593 T::hit_test(resolve(id), app, result, main, cross)
1594 },
1595 handle_event: |app, id, event, entry| T::handle_event(resolve(id), app, event, entry),
1596 center_offset_adjustment: |app, id| T::center_offset_adjustment(resolve(id), app),
1597 child_scroll_offset: |app, id, child| T::child_scroll_offset(resolve(id), app, child),
1598 child_main_axis_position: |app, id, child| {
1599 T::child_main_axis_position(resolve(id), app, child)
1600 },
1601 }
1602 }
1603}
1604
1605impl<T: RenderSliver> RenderHandle<T> {
1606 pub fn new_sliver(app: &mut App, object: T) -> RenderHandle<T> {
1608 let this = create(app, object);
1609 let data = this.render_object_data_mut(app);
1610 data.object_vtable = Some(&const { RenderSliverVTable::of::<T>() }.object);
1611 let is_repaint_boundary = this.is_repaint_boundary(app);
1615 let always_needs_compositing = this.always_needs_compositing(app);
1616 let data = this.render_object_data_mut(app);
1617 data.was_repaint_boundary = is_repaint_boundary;
1618 data.needs_compositing = is_repaint_boundary || always_needs_compositing;
1619 this
1620 }
1621}
1622
1623#[derive(Clone, Copy)]
1625pub struct AnyRenderSliver {
1626 id: HandleId,
1627 vtable: &'static RenderSliverVTable,
1628}
1629
1630impl PartialEq for AnyRenderSliver {
1631 fn eq(&self, other: &AnyRenderSliver) -> bool {
1632 self.id == other.id
1633 }
1634}
1635
1636impl Eq for AnyRenderSliver {}
1637
1638impl std::hash::Hash for AnyRenderSliver {
1639 fn hash<H: Hasher>(&self, state: &mut H) {
1640 self.id.hash(state);
1641 }
1642}
1643
1644impl Debug for AnyRenderSliver {
1645 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1646 write!(f, "AnyRenderSliver({:?})", self.id)
1647 }
1648}
1649
1650impl AnyRenderSliver {
1651 pub(crate) fn from_vtable(
1652 id: HandleId,
1653 vtable: &'static RenderSliverVTable,
1654 ) -> AnyRenderSliver {
1655 AnyRenderSliver { id, vtable }
1656 }
1657
1658 pub fn as_object(self) -> AnyRenderObject {
1660 AnyRenderObject::from_vtable(self.id, &self.vtable.object)
1661 }
1662
1663 fn sliver_data(self, app: &App) -> &RenderSliverData {
1664 (self.vtable.sliver_data)(app, self.id)
1665 }
1666
1667 fn sliver_data_mut(self, app: &mut App) -> &mut RenderSliverData {
1668 (self.vtable.sliver_data_mut)(app, self.id)
1669 }
1670
1671 pub fn layout(self, app: &mut App, constraints: SliverConstraints, parent_uses_size: bool) {
1673 debug_assert!(constraints.debug_assert_is_valid(true));
1674 let same = self.sliver_data(app).constraints == Some(constraints);
1675 self.as_object()
1676 .run_layout(app, parent_uses_size, constraints.is_tight(), same, |app| {
1677 self.sliver_data_mut(app).constraints = Some(constraints)
1678 });
1679 }
1680
1681 pub fn constraints(self, app: &App) -> SliverConstraints {
1687 self.sliver_data(app).constraints.unwrap_or_else(|| {
1688 panic!("A RenderObject does not have any constraints before it has been laid out.")
1689 })
1690 }
1691
1692 pub fn hit_test(
1694 self,
1695 app: &mut App,
1696 result: &mut SliverHitTestResult<'_>,
1697 main_axis_position: f64,
1698 cross_axis_position: f64,
1699 ) -> bool {
1700 (self.vtable.hit_test)(
1701 app,
1702 self.id,
1703 result,
1704 main_axis_position,
1705 cross_axis_position,
1706 )
1707 }
1708
1709 pub fn handle_event(self, app: &mut App, event: &PointerEvent, entry: &SliverHitTestEntry) {
1711 (self.vtable.handle_event)(app, self.id, event, entry)
1712 }
1713
1714 pub fn center_offset_adjustment(self, app: &App) -> f64 {
1716 (self.vtable.center_offset_adjustment)(app, self.id)
1717 }
1718
1719 pub fn child_scroll_offset(self, app: &App, child: AnyRenderObject) -> Option<f64> {
1721 (self.vtable.child_scroll_offset)(app, self.id, child)
1722 }
1723
1724 pub fn child_main_axis_position(self, app: &App, child: AnyRenderObject) -> f64 {
1726 (self.vtable.child_main_axis_position)(app, self.id, child)
1727 }
1728
1729 pub fn geometry(self, app: &App) -> SliverGeometry {
1735 self.sliver_data(app)
1736 .geometry
1737 .unwrap_or_else(|| panic!("RenderSliver was not laid out: {self:?}"))
1738 }
1739
1740 pub fn set_geometry(self, app: &mut App, geometry: SliverGeometry) {
1742 self.sliver_data_mut(app).geometry = Some(geometry);
1743 }
1744}
1745
1746impl crate::object::ErasedRenderObject for AnyRenderSliver {
1747 fn as_object(self) -> AnyRenderObject {
1748 AnyRenderSliver::as_object(self)
1749 }
1750
1751 fn from_object(object: AnyRenderObject) -> AnyRenderSliver {
1752 object
1753 .as_sliver()
1754 .expect("the render object is not a RenderSliver")
1755 }
1756}
1757
1758impl From<AnyRenderSliver> for AnyRenderObject {
1759 fn from(sliver: AnyRenderSliver) -> AnyRenderObject {
1760 sliver.as_object()
1761 }
1762}
1763
1764fn get_right_way_up(constraints: SliverConstraints) -> bool {
1769 let reversed = axis_direction_is_reversed(constraints.axis_direction);
1770 match constraints.growth_direction {
1771 GrowthDirection::Forward => !reversed,
1772 GrowthDirection::Reverse => reversed,
1773 }
1774}
1775
1776pub trait RenderSliverHelpers: RenderSliver {
1778 fn hit_test_box_child(
1789 self: RenderHandle<Self>,
1790 app: &mut App,
1791 result: &mut BoxHitTestResult<'_>,
1792 child: AnyRenderBox,
1793 main_axis_position: f64,
1794 cross_axis_position: f64,
1795 ) -> bool {
1796 let constraints = self.constraints(app);
1797 let right_way_up = get_right_way_up(constraints);
1798 let mut delta = self.child_main_axis_position(app, child.as_object());
1799 let cross_axis_delta = self.child_cross_axis_position(app, child.as_object());
1800 let mut absolute_position = main_axis_position - delta;
1801 let absolute_cross_axis_position = cross_axis_position - cross_axis_delta;
1802 let size = child.size(app);
1803 let paint_extent = self.geometry(app).paint_extent;
1804 let (paint_offset, transformed_position) = match constraints.axis() {
1805 Axis::Horizontal => {
1806 if !right_way_up {
1807 absolute_position = size.width() - absolute_position;
1808 delta = paint_extent - size.width() - delta;
1809 }
1810 (
1811 Offset::new(delta, cross_axis_delta),
1812 Offset::new(absolute_position, absolute_cross_axis_position),
1813 )
1814 }
1815 Axis::Vertical => {
1816 if !right_way_up {
1817 absolute_position = size.height() - absolute_position;
1818 delta = paint_extent - size.height() - delta;
1819 }
1820 (
1821 Offset::new(cross_axis_delta, delta),
1822 Offset::new(absolute_cross_axis_position, absolute_position),
1823 )
1824 }
1825 };
1826 result.add_with_out_of_band_position(Some(paint_offset), None, None, |result| {
1827 child.hit_test(app, result, transformed_position)
1828 })
1829 }
1830
1831 fn apply_paint_transform_for_box_child(
1840 self: RenderHandle<Self>,
1841 app: &App,
1842 child: AnyRenderBox,
1843 transform: &mut Matrix4,
1844 ) {
1845 let constraints = self.constraints(app);
1846 let right_way_up = get_right_way_up(constraints);
1847 let mut delta = self.child_main_axis_position(app, child.as_object());
1848 let cross_axis_delta = self.child_cross_axis_position(app, child.as_object());
1849 let size = child.size(app);
1850 let paint_extent = self.geometry(app).paint_extent;
1851 match constraints.axis() {
1852 Axis::Horizontal => {
1853 if !right_way_up {
1854 delta = paint_extent - size.width() - delta;
1855 }
1856 translate(transform, delta, cross_axis_delta);
1857 }
1858 Axis::Vertical => {
1859 if !right_way_up {
1860 delta = paint_extent - size.height() - delta;
1861 }
1862 translate(transform, cross_axis_delta, delta);
1863 }
1864 }
1865 }
1866}
1867
1868pub trait RenderSliverSingleBoxAdapter:
1878 RenderSliver + RenderObjectWithChildMixin<ChildType = AnyRenderBox> + RenderSliverHelpers
1879{
1880 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1883 if !child.parent_data_is::<SliverPhysicalParentData>(app) {
1884 child.set_parent_data(app, SliverPhysicalParentData::new());
1885 }
1886 }
1887
1888 fn set_child_parent_data(
1892 self: RenderHandle<Self>,
1893 app: &mut App,
1894 child: AnyRenderObject,
1895 constraints: SliverConstraints,
1896 geometry: SliverGeometry,
1897 ) {
1898 let paint_offset = match apply_growth_direction_to_axis_direction(
1899 constraints.axis_direction,
1900 constraints.growth_direction,
1901 ) {
1902 AxisDirection::Up => Offset::new(
1903 0.0,
1904 geometry.paint_extent + constraints.scroll_offset - geometry.scroll_extent,
1905 ),
1906 AxisDirection::Left => Offset::new(
1907 geometry.paint_extent + constraints.scroll_offset - geometry.scroll_extent,
1908 0.0,
1909 ),
1910 AxisDirection::Right => Offset::new(-constraints.scroll_offset, 0.0),
1911 AxisDirection::Down => Offset::new(0.0, -constraints.scroll_offset),
1912 };
1913 child
1914 .parent_data_of_mut::<SliverPhysicalParentData>(app)
1915 .paint_offset = paint_offset;
1916 }
1917
1918 fn hit_test_children(
1920 self: RenderHandle<Self>,
1921 app: &mut App,
1922 result: &mut SliverHitTestResult<'_>,
1923 main_axis_position: f64,
1924 cross_axis_position: f64,
1925 ) -> bool {
1926 debug_assert!(self.geometry(app).hit_test_extent > 0.0);
1927 let Some(child) = self.child(app) else {
1928 return false;
1929 };
1930 self.hit_test_box_child(
1931 app,
1932 &mut BoxHitTestResult::wrap(result),
1933 child,
1934 main_axis_position,
1935 cross_axis_position,
1936 )
1937 }
1938
1939 fn child_main_axis_position(
1941 self: RenderHandle<Self>,
1942 app: &App,
1943 child: AnyRenderObject,
1944 ) -> f64 {
1945 debug_assert_eq!(Some(child), self.child(app).map(AnyRenderBox::as_object));
1946 -self.constraints(app).scroll_offset
1947 }
1948
1949 fn apply_paint_transform(
1951 self: RenderHandle<Self>,
1952 app: &App,
1953 child: AnyRenderObject,
1954 transform: &mut Matrix4,
1955 ) {
1956 debug_assert_eq!(Some(child), self.child(app).map(AnyRenderBox::as_object));
1957 child
1958 .parent_data_of::<SliverPhysicalParentData>(app)
1959 .apply_paint_transform(transform);
1960 }
1961
1962 fn paint(
1964 self: RenderHandle<Self>,
1965 app: &mut App,
1966 context: &mut PaintingContext,
1967 offset: Offset,
1968 ) {
1969 let Some(child) = self.child(app) else {
1970 return;
1971 };
1972 if !self.geometry(app).visible {
1973 return;
1974 }
1975 let paint_offset = child
1976 .as_object()
1977 .parent_data_of::<SliverPhysicalParentData>(app)
1978 .paint_offset;
1979 context.paint_child(app, child.as_object(), offset + paint_offset);
1980 }
1981}
1982
1983pub struct RenderSliverToBoxAdapter {
1994 render_object: crate::object::RenderObjectData,
1995 render_sliver: RenderSliverData,
1996 child: RenderObjectWithChildData<AnyRenderBox>,
1997}
1998
1999impl RenderSliverToBoxAdapter {
2000 pub fn new(
2002 app: &mut App,
2003 child: Option<AnyRenderBox>,
2004 ) -> RenderHandle<RenderSliverToBoxAdapter> {
2005 let this = RenderHandle::new_sliver(
2006 app,
2007 RenderSliverToBoxAdapter {
2008 render_object: crate::object::RenderObjectData::new(),
2009 render_sliver: RenderSliverData::new(),
2010 child: RenderObjectWithChildData::new(),
2011 },
2012 );
2013 this.set_child(app, child);
2014 this
2015 }
2016}
2017
2018impl RenderObjectWithChildMixin for RenderSliverToBoxAdapter {
2019 type ChildType = AnyRenderBox;
2020
2021 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2022 &self.get(app).child
2023 }
2024
2025 fn child_data_mut(
2026 self: RenderHandle<Self>,
2027 app: &mut App,
2028 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2029 &mut self.get_mut(app).child
2030 }
2031}
2032
2033impl RenderSliverHelpers for RenderSliverToBoxAdapter {}
2034
2035impl RenderSliverSingleBoxAdapter for RenderSliverToBoxAdapter {}
2036
2037impl RenderObject for RenderSliverToBoxAdapter {
2038 crate::render_object_accessors!();
2039
2040 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2041 RenderSliverSingleBoxAdapter::setup_parent_data(self, app, child)
2042 }
2043
2044 fn visit_children(
2045 self: RenderHandle<Self>,
2046 app: &App,
2047 visitor: &mut dyn FnMut(AnyRenderObject),
2048 ) {
2049 if let Some(child) = self.child(app) {
2050 visitor(child.as_object());
2051 }
2052 }
2053
2054 fn apply_paint_transform(
2055 self: RenderHandle<Self>,
2056 app: &App,
2057 child: AnyRenderObject,
2058 transform: &mut Matrix4,
2059 ) {
2060 RenderSliverSingleBoxAdapter::apply_paint_transform(self, app, child, transform)
2061 }
2062
2063 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2064 let Some(child) = self.child(app) else {
2065 self.set_geometry(app, SliverGeometry::ZERO);
2066 return;
2067 };
2068 let constraints = self.constraints(app);
2069 child.layout(
2070 app,
2071 constraints.as_box_constraints(0.0, f64::INFINITY, None),
2072 true,
2073 );
2074 let child_extent = match constraints.axis() {
2075 Axis::Horizontal => child.size(app).width(),
2076 Axis::Vertical => child.size(app).height(),
2077 };
2078 let painted_child_size = calculate_paint_offset(constraints, 0.0, child_extent);
2079 let cache_extent = calculate_cache_offset(constraints, 0.0, child_extent);
2080
2081 debug_assert!(painted_child_size.is_finite());
2082 debug_assert!(painted_child_size >= 0.0);
2083 let geometry = SliverGeometry::builder()
2084 .scroll_extent(child_extent)
2085 .paint_extent(painted_child_size)
2086 .cache_extent(cache_extent)
2087 .max_paint_extent(child_extent)
2088 .hit_test_extent(painted_child_size)
2089 .has_visual_overflow(
2090 child_extent > constraints.remaining_paint_extent
2091 || constraints.scroll_offset > 0.0,
2092 )
2093 .build();
2094 self.set_geometry(app, geometry);
2095 self.set_child_parent_data(app, child.as_object(), constraints, geometry);
2096 }
2097
2098 fn paint(
2099 self: RenderHandle<Self>,
2100 app: &mut App,
2101 context: &mut PaintingContext,
2102 offset: Offset,
2103 ) {
2104 RenderSliverSingleBoxAdapter::paint(self, app, context, offset)
2105 }
2106}
2107
2108impl RenderSliver for RenderSliverToBoxAdapter {
2109 render_sliver_accessors!();
2110
2111 fn hit_test_children(
2112 self: RenderHandle<Self>,
2113 app: &mut App,
2114 result: &mut SliverHitTestResult<'_>,
2115 main_axis_position: f64,
2116 cross_axis_position: f64,
2117 ) -> bool {
2118 RenderSliverSingleBoxAdapter::hit_test_children(
2119 self,
2120 app,
2121 result,
2122 main_axis_position,
2123 cross_axis_position,
2124 )
2125 }
2126
2127 fn child_main_axis_position(
2128 self: RenderHandle<Self>,
2129 app: &App,
2130 child: AnyRenderObject,
2131 ) -> f64 {
2132 RenderSliverSingleBoxAdapter::child_main_axis_position(self, app, child)
2133 }
2134}
2135
2136#[cfg(test)]
2137mod tests {
2138 use inset_foundation::AppCell;
2139 use inset_gestures::HitTestResult;
2140
2141 use super::*;
2142 use crate::box_::{RenderBox, RenderBoxData};
2143 use crate::proxy_box::RenderConstrainedBox;
2144
2145 struct TestSliver {
2146 render_object: crate::object::RenderObjectData,
2147 render_sliver: RenderSliverData,
2148 }
2149
2150 impl RenderObject for TestSliver {
2151 crate::render_object_accessors!();
2152
2153 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2154 let constraints = self.constraints(app);
2155 let extent = constraints.remaining_paint_extent.min(20.0);
2156 self.set_geometry(
2157 app,
2158 SliverGeometry::builder()
2159 .scroll_extent(20.0)
2160 .paint_extent(extent)
2161 .max_paint_extent(20.0)
2162 .build(),
2163 );
2164 }
2165 }
2166
2167 impl RenderSliver for TestSliver {
2168 render_sliver_accessors!();
2169 }
2170
2171 fn vertical_constraints(remaining_paint: f64) -> SliverConstraints {
2172 SliverConstraints::new(
2173 AxisDirection::Down,
2174 GrowthDirection::Forward,
2175 ScrollDirection::Idle,
2176 0.0,
2177 0.0,
2178 0.0,
2179 remaining_paint,
2180 100.0,
2181 AxisDirection::Right,
2182 400.0,
2183 remaining_paint,
2184 0.0,
2185 )
2186 }
2187
2188 #[test]
2189 fn sliver_layout_sets_geometry() {
2190 let cell = AppCell::new();
2191 let mut app = cell.borrow_mut();
2192 let sliver = RenderHandle::new_sliver(
2193 &mut app,
2194 TestSliver {
2195 render_object: crate::object::RenderObjectData::new(),
2196 render_sliver: RenderSliverData::new(),
2197 },
2198 );
2199 sliver.layout(&mut app, vertical_constraints(50.0), false);
2200 let geometry = sliver.geometry(&app);
2201 assert_eq!(geometry.scroll_extent, 20.0);
2202 assert_eq!(geometry.paint_extent, 20.0);
2203 assert!(geometry.visible);
2204 }
2205
2206 struct HitTestableBox {
2209 render_object: crate::object::RenderObjectData,
2210 render_box: RenderBoxData,
2211 }
2212
2213 impl RenderObject for HitTestableBox {
2214 crate::render_object_accessors!();
2215
2216 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2217 let size = self.constraints(app).constrain(Size::new(60.0, 60.0));
2218 self.set_size(app, size);
2219 }
2220 }
2221
2222 impl RenderBox for HitTestableBox {
2223 crate::render_box_accessors!();
2224
2225 fn hit_test_self(self: RenderHandle<Self>, _app: &App, _position: Offset) -> bool {
2226 let _ = self;
2227 true
2228 }
2229 }
2230
2231 fn hit_testable_box(app: &mut App) -> AnyRenderBox {
2232 RenderHandle::new_box(
2233 app,
2234 HitTestableBox {
2235 render_object: crate::object::RenderObjectData::new(),
2236 render_box: RenderBoxData::new(),
2237 },
2238 )
2239 .as_box()
2240 }
2241
2242 fn adapter_constraints(scroll_offset: f64, remaining_paint: f64) -> SliverConstraints {
2243 SliverConstraints::new(
2244 AxisDirection::Down,
2245 GrowthDirection::Forward,
2246 ScrollDirection::Idle,
2247 scroll_offset,
2248 0.0,
2249 0.0,
2250 remaining_paint,
2251 100.0,
2252 AxisDirection::Right,
2253 remaining_paint,
2254 remaining_paint,
2255 0.0,
2256 )
2257 }
2258
2259 #[test]
2262 fn a_box_adapter_reports_its_child_extent() {
2263 let cell = AppCell::new();
2264 let mut app = cell.borrow_mut();
2265 let child =
2266 RenderConstrainedBox::new(&mut app, BoxConstraints::tight_for(None, Some(60.0)), None);
2267 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child.as_box()));
2268
2269 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2270
2271 let geometry = adapter.geometry(&app);
2272 assert_eq!(geometry.scroll_extent, 60.0);
2273 assert_eq!(geometry.paint_extent, 60.0);
2274 assert_eq!(geometry.max_paint_extent, 60.0);
2275 assert!(!geometry.has_visual_overflow);
2276 assert_eq!(child.size(&app), Size::new(100.0, 60.0));
2278 assert_eq!(
2279 child
2280 .as_box()
2281 .as_object()
2282 .parent_data_of::<SliverPhysicalParentData>(&app)
2283 .paint_offset,
2284 Offset::ZERO
2285 );
2286 }
2287
2288 #[test]
2290 fn a_scrolled_box_adapter_offsets_its_child() {
2291 let cell = AppCell::new();
2292 let mut app = cell.borrow_mut();
2293 let child =
2294 RenderConstrainedBox::new(&mut app, BoxConstraints::tight_for(None, Some(60.0)), None);
2295 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child.as_box()));
2296
2297 adapter.layout(&mut app, adapter_constraints(20.0, 400.0), true);
2298
2299 let geometry = adapter.geometry(&app);
2300 assert_eq!(geometry.scroll_extent, 60.0);
2301 assert_eq!(geometry.paint_extent, 40.0);
2302 assert!(geometry.has_visual_overflow);
2303 assert_eq!(
2304 child
2305 .as_box()
2306 .as_object()
2307 .parent_data_of::<SliverPhysicalParentData>(&app)
2308 .paint_offset,
2309 Offset::new(0.0, -20.0)
2310 );
2311 assert_eq!(
2312 RenderSliver::child_main_axis_position(adapter, &app, child.as_object()),
2313 -20.0
2314 );
2315 }
2316
2317 #[test]
2319 fn a_childless_box_adapter_is_zero() {
2320 let cell = AppCell::new();
2321 let mut app = cell.borrow_mut();
2322 let adapter = RenderSliverToBoxAdapter::new(&mut app, None);
2323 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2324 assert!(adapter.geometry(&app).is_zero());
2325 }
2326
2327 #[test]
2329 fn a_box_adapter_hit_tests_its_child() {
2330 let cell = AppCell::new();
2331 let mut app = cell.borrow_mut();
2332 let child = hit_testable_box(&mut app);
2333 let adapter = RenderSliverToBoxAdapter::new(&mut app, Some(child));
2334 adapter.layout(&mut app, adapter_constraints(0.0, 400.0), true);
2335
2336 let mut result = HitTestResult::new();
2337 let hit = adapter.hit_test(
2338 &mut app,
2339 &mut SliverHitTestResult::wrap(&mut result),
2340 30.0,
2341 50.0,
2342 );
2343
2344 assert!(hit);
2345 assert_eq!(result.path().len(), 2);
2346 }
2347
2348 #[test]
2350 fn paint_and_cache_offsets_clamp_to_the_window() {
2351 let constraints = adapter_constraints(20.0, 50.0);
2352 assert_eq!(calculate_paint_offset(constraints, 0.0, 100.0), 50.0);
2353 assert_eq!(calculate_paint_offset(constraints, 0.0, 30.0), 10.0);
2354 assert_eq!(calculate_paint_offset(constraints, 0.0, 10.0), 0.0);
2355 assert_eq!(calculate_cache_offset(constraints, 0.0, 100.0), 50.0);
2356 }
2357
2358 #[test]
2360 fn a_consistent_geometry_is_valid() {
2361 let geometry = SliverGeometry::builder()
2362 .scroll_extent(100.0)
2363 .paint_extent(40.0)
2364 .max_paint_extent(100.0)
2365 .build();
2366 assert!(geometry.debug_assert_is_valid());
2367 assert!(!geometry.is_zero());
2368 assert!(SliverGeometry::ZERO.is_zero());
2369 }
2370
2371 #[test]
2372 fn extents_left_out_follow_the_ones_given_in_any_order() {
2373 let geometry = SliverGeometry::builder()
2374 .layout_extent(10.0)
2375 .hit_test_extent(20.0)
2376 .paint_extent(40.0)
2377 .build();
2378 assert_eq!(geometry.layout_extent, 10.0);
2379 assert_eq!(geometry.hit_test_extent, 20.0);
2380 assert_eq!(geometry.cache_extent, 10.0);
2381 assert!(geometry.visible);
2382 let geometry = SliverGeometry::builder()
2383 .cache_extent(5.0)
2384 .layout_extent(10.0)
2385 .paint_extent(40.0)
2386 .build();
2387 assert_eq!(geometry.cache_extent, 5.0);
2388 }
2389
2390 #[test]
2391 fn a_copy_keeps_the_extents_it_was_made_with() {
2392 let copy = SliverGeometry::builder()
2393 .paint_extent(40.0)
2394 .layout_extent(10.0)
2395 .build()
2396 .copy_with()
2397 .paint_extent(0.0)
2398 .build();
2399 assert_eq!(copy.layout_extent, 10.0);
2400 assert_eq!(copy.cache_extent, 10.0);
2401 assert!(copy.visible);
2402 }
2403}