1use std::any::Any;
8use std::fmt::Debug;
9use std::rc::Rc;
10
11use inset_embedder::{Clip, Offset, Rect, Size, TextBaseline};
12use inset_foundation::{App, Handle, Listenable, Listener};
13use inset_painting::{Alignment, AlignmentGeometry, EdgeInsets, EdgeInsetsGeometry, TextDirection};
14
15use crate::box_::{
16 AnyRenderBox, BoxConstraints, BoxHitTestResult, BoxParentData, RenderBox, RenderBoxData,
17};
18use crate::layer::{ClipRectLayer, LayerHandle};
19use crate::layout_helper::{ChildBaselineGetter, ChildLayoutHelper, ChildLayouter};
20use crate::object::{
21 AnyRenderObject, Constraints, RenderHandle, RenderObject, RenderObjectData,
22 RenderObjectWithChildData, RenderObjectWithChildMixin,
23};
24use crate::painting_context::PaintingContext;
25use crate::pipeline_owner::PipelineOwner;
26use crate::stack::RelativeRect;
27
28pub type BoxConstraintsTransform = fn(BoxConstraints) -> BoxConstraints;
33
34pub trait RenderShiftedBox:
40 RenderObjectWithChildMixin<ChildType = AnyRenderBox> + RenderBox
41{
42 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
44 match self.child(app) {
45 Some(child) => child.get_min_intrinsic_width(app, height),
46 None => 0.0,
47 }
48 }
49
50 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
52 match self.child(app) {
53 Some(child) => child.get_max_intrinsic_width(app, height),
54 None => 0.0,
55 }
56 }
57
58 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
60 match self.child(app) {
61 Some(child) => child.get_min_intrinsic_height(app, width),
62 None => 0.0,
63 }
64 }
65
66 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
68 match self.child(app) {
69 Some(child) => child.get_max_intrinsic_height(app, width),
70 None => 0.0,
71 }
72 }
73
74 fn compute_distance_to_actual_baseline(
76 self: RenderHandle<Self>,
77 app: &mut App,
78 baseline: TextBaseline,
79 ) -> Option<f64> {
80 debug_assert!(!self.as_object().debug_needs_layout(app));
81 let child = self.child(app)?;
82 debug_assert!(!child.as_object().debug_needs_layout(app));
83 let result = child.get_distance_to_actual_baseline(app, baseline)?;
84 let offset = child
85 .as_object()
86 .parent_data_of::<BoxParentData>(app)
87 .offset;
88 Some(result + offset.dy())
89 }
90
91 fn compute_dry_baseline(
94 self: RenderHandle<Self>,
95 app: &mut App,
96 constraints: BoxConstraints,
97 baseline: TextBaseline,
98 ) -> Option<f64> {
99 self.child(app)
100 .and_then(|child| child.get_dry_baseline(app, constraints, baseline))
101 }
102
103 fn hit_test_children(
105 self: RenderHandle<Self>,
106 app: &mut App,
107 result: &mut BoxHitTestResult<'_>,
108 position: Offset,
109 ) -> bool {
110 let Some(child) = self.child(app) else {
111 return false;
112 };
113 let child_offset = child
114 .as_object()
115 .parent_data_of::<BoxParentData>(app)
116 .offset;
117 result.add_with_paint_offset(Some(child_offset), position, |result, transformed| {
118 debug_assert_eq!(transformed, position - child_offset);
119 child.hit_test(app, result, transformed)
120 })
121 }
122
123 fn paint(
125 self: RenderHandle<Self>,
126 app: &mut App,
127 context: &mut PaintingContext,
128 offset: Offset,
129 ) {
130 if let Some(child) = self.child(app) {
131 let child_offset = child
132 .as_object()
133 .parent_data_of::<BoxParentData>(app)
134 .offset;
135 context.paint_child(app, child.as_object(), child_offset + offset);
136 }
137 }
138}
139
140pub struct RenderPadding {
142 render_object: RenderObjectData,
143 render_box: RenderBoxData,
144 child: RenderObjectWithChildData<AnyRenderBox>,
145 resolved_padding_cache: Option<EdgeInsets>,
146 padding: EdgeInsetsGeometry,
147 text_direction: Option<TextDirection>,
148}
149
150impl RenderPadding {
151 pub fn new(
155 app: &mut App,
156 padding: EdgeInsetsGeometry,
157 text_direction: Option<TextDirection>,
158 child: Option<AnyRenderBox>,
159 ) -> RenderHandle<RenderPadding> {
160 debug_assert!(padding.is_non_negative());
161 let this = RenderHandle::new_box(
162 app,
163 RenderPadding {
164 render_object: RenderObjectData::new(),
165 render_box: RenderBoxData::new(),
166 child: RenderObjectWithChildData::new(),
167 resolved_padding_cache: None,
168 padding,
169 text_direction,
170 },
171 );
172 this.set_child(app, child);
173 this
174 }
175
176 pub fn padding(self: RenderHandle<Self>, app: &App) -> EdgeInsetsGeometry {
178 self.get(app).padding
179 }
180
181 pub fn set_padding(self: RenderHandle<Self>, app: &mut App, value: EdgeInsetsGeometry) {
183 debug_assert!(value.is_non_negative());
184 if self.get(app).padding == value {
185 return;
186 }
187 self.get_mut(app).padding = value;
188 self.mark_need_resolution(app);
189 }
190
191 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
193 self.get(app).text_direction
194 }
195
196 pub fn set_text_direction(
198 self: RenderHandle<Self>,
199 app: &mut App,
200 value: Option<TextDirection>,
201 ) {
202 if self.get(app).text_direction == value {
203 return;
204 }
205 self.get_mut(app).text_direction = value;
206 self.mark_need_resolution(app);
207 }
208
209 fn resolved_padding(&mut self) -> EdgeInsets {
210 if let Some(cached) = self.resolved_padding_cache {
211 return cached;
212 }
213 let resolved = self.padding.resolve(self.text_direction);
214 debug_assert!(resolved.is_non_negative());
215 self.resolved_padding_cache = Some(resolved);
216 resolved
217 }
218
219 fn mark_need_resolution(self: RenderHandle<Self>, app: &mut App) {
220 self.get_mut(app).resolved_padding_cache = None;
221 self.mark_needs_layout(app);
222 }
223}
224
225impl RenderObjectWithChildMixin for RenderPadding {
226 type ChildType = AnyRenderBox;
227
228 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
229 &self.get(app).child
230 }
231
232 fn child_data_mut(
233 self: RenderHandle<Self>,
234 app: &mut App,
235 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
236 &mut self.get_mut(app).child
237 }
238}
239
240impl RenderShiftedBox for RenderPadding {}
241
242impl RenderObject for RenderPadding {
243 crate::render_object_accessors!();
244
245 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
246 let constraints = self.constraints(app);
247 let padding = self.get_mut(app).resolved_padding();
248 let child = self.child(app);
249 if child.is_none() {
250 self.set_size(
251 app,
252 constraints.constrain(Size::new(padding.horizontal(), padding.vertical())),
253 );
254 return;
255 }
256 let child = child.expect("checked");
257 let inner_constraints = constraints.deflate(EdgeInsetsGeometry::Insets(padding));
258 child.layout(app, inner_constraints, true);
259 child.parent_data_of_mut::<BoxParentData>(app).offset =
260 Offset::new(padding.left, padding.top);
261 self.set_size(
262 app,
263 constraints.constrain(Size::new(
264 padding.horizontal() + child.size(app).width(),
265 padding.vertical() + child.size(app).height(),
266 )),
267 );
268 }
269
270 fn paint(
271 self: RenderHandle<Self>,
272 app: &mut App,
273 context: &mut PaintingContext,
274 offset: Offset,
275 ) {
276 RenderShiftedBox::paint(self, app, context, offset);
277 }
278
279 fn visit_children(
280 self: RenderHandle<Self>,
281 app: &App,
282 visitor: &mut dyn FnMut(AnyRenderObject),
283 ) {
284 if let Some(child) = self.child(app) {
285 visitor(child.as_object());
286 }
287 }
288}
289
290impl RenderBox for RenderPadding {
291 crate::render_box_accessors!();
292
293 fn hit_test_children(
294 self: RenderHandle<Self>,
295 app: &mut App,
296 result: &mut BoxHitTestResult<'_>,
297 position: Offset,
298 ) -> bool {
299 RenderShiftedBox::hit_test_children(self, app, result, position)
300 }
301
302 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
303 let padding = self.get_mut(app).resolved_padding();
304 match self.child(app) {
305 Some(child) => {
307 child.get_min_intrinsic_width(app, (height - padding.vertical()).max(0.0))
308 + padding.horizontal()
309 }
310 None => padding.horizontal(),
311 }
312 }
313
314 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
315 let padding = self.get_mut(app).resolved_padding();
316 match self.child(app) {
317 Some(child) => {
318 child.get_max_intrinsic_width(app, (height - padding.vertical()).max(0.0))
319 + padding.horizontal()
320 }
321 None => padding.horizontal(),
322 }
323 }
324
325 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
326 let padding = self.get_mut(app).resolved_padding();
327 match self.child(app) {
328 Some(child) => {
329 child.get_min_intrinsic_height(app, (width - padding.horizontal()).max(0.0))
330 + padding.vertical()
331 }
332 None => padding.vertical(),
333 }
334 }
335
336 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
337 let padding = self.get_mut(app).resolved_padding();
338 match self.child(app) {
339 Some(child) => {
340 child.get_max_intrinsic_height(app, (width - padding.horizontal()).max(0.0))
341 + padding.vertical()
342 }
343 None => padding.vertical(),
344 }
345 }
346
347 fn compute_distance_to_actual_baseline(
348 self: RenderHandle<Self>,
349 app: &mut App,
350 baseline: TextBaseline,
351 ) -> Option<f64> {
352 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
353 }
354
355 fn compute_dry_baseline(
356 self: RenderHandle<Self>,
357 app: &mut App,
358 constraints: BoxConstraints,
359 baseline: TextBaseline,
360 ) -> Option<f64> {
361 let child = self.child(app)?;
362 let padding = self.get_mut(app).resolved_padding();
363 let inner_constraints = constraints.deflate(EdgeInsetsGeometry::Insets(padding));
364 let child_baseline = child.get_dry_baseline(app, inner_constraints, baseline)?;
365 Some(child_baseline + padding.top)
366 }
367
368 fn compute_dry_layout(
369 self: RenderHandle<Self>,
370 app: &mut App,
371 constraints: BoxConstraints,
372 ) -> Size {
373 let padding = self.get_mut(app).resolved_padding();
374 let Some(child) = self.child(app) else {
375 return constraints.constrain(Size::new(padding.horizontal(), padding.vertical()));
376 };
377 let inner_constraints = constraints.deflate(EdgeInsetsGeometry::Insets(padding));
378 let child_size = child.get_dry_layout(app, inner_constraints);
379 constraints.constrain(Size::new(
380 padding.horizontal() + child_size.width(),
381 padding.vertical() + child_size.height(),
382 ))
383 }
384}
385
386pub struct RenderAligningShiftedBoxData {
388 resolved_alignment: Option<Alignment>,
389 alignment: AlignmentGeometry,
390 text_direction: Option<TextDirection>,
391}
392
393impl RenderAligningShiftedBoxData {
394 pub const fn new(
396 alignment: AlignmentGeometry,
397 text_direction: Option<TextDirection>,
398 ) -> RenderAligningShiftedBoxData {
399 RenderAligningShiftedBoxData {
400 resolved_alignment: None,
401 alignment,
402 text_direction,
403 }
404 }
405}
406
407pub trait RenderAligningShiftedBox: RenderShiftedBox {
410 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData;
412
413 fn aligning_data_mut(
415 self: RenderHandle<Self>,
416 app: &mut App,
417 ) -> &mut RenderAligningShiftedBoxData;
418
419 fn resolved_alignment(self: RenderHandle<Self>, app: &mut App) -> Alignment {
421 let data = self.aligning_data(app);
422 if let Some(resolved) = data.resolved_alignment {
423 return resolved;
424 }
425 let resolved = data.alignment.resolve(data.text_direction);
426 self.aligning_data_mut(app).resolved_alignment = Some(resolved);
427 resolved
428 }
429
430 fn mark_need_resolution(self: RenderHandle<Self>, app: &mut App) {
431 self.aligning_data_mut(app).resolved_alignment = None;
432 self.mark_needs_layout(app);
433 }
434
435 fn alignment(self: RenderHandle<Self>, app: &App) -> AlignmentGeometry {
443 self.aligning_data(app).alignment
444 }
445
446 fn set_alignment(self: RenderHandle<Self>, app: &mut App, value: AlignmentGeometry) {
448 if self.aligning_data(app).alignment == value {
449 return;
450 }
451 self.aligning_data_mut(app).alignment = value;
452 self.mark_need_resolution(app);
453 }
454
455 fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
457 self.aligning_data(app).text_direction
458 }
459
460 fn set_text_direction(self: RenderHandle<Self>, app: &mut App, value: Option<TextDirection>) {
462 if self.aligning_data(app).text_direction == value {
463 return;
464 }
465 self.aligning_data_mut(app).text_direction = value;
466 self.mark_need_resolution(app);
467 }
468
469 fn align_child(self: RenderHandle<Self>, app: &mut App) {
475 let child = self.child(app).expect("align_child requires a child");
476 debug_assert!(!child.as_object().debug_needs_layout(app));
477 let offset = self
478 .resolved_alignment(app)
479 .along_offset(self.size(app) - child.size(app));
480 child
481 .as_object()
482 .parent_data_of_mut::<BoxParentData>(app)
483 .offset = offset;
484 }
485}
486
487pub struct RenderPositionedBox {
498 render_object: RenderObjectData,
499 render_box: RenderBoxData,
500 child: RenderObjectWithChildData<AnyRenderBox>,
501 aligning: RenderAligningShiftedBoxData,
502 width_factor: Option<f64>,
503 height_factor: Option<f64>,
504}
505
506impl RenderPositionedBox {
507 pub fn new(
511 app: &mut App,
512 alignment: AlignmentGeometry,
513 text_direction: Option<TextDirection>,
514 width_factor: Option<f64>,
515 height_factor: Option<f64>,
516 child: Option<AnyRenderBox>,
517 ) -> RenderHandle<Self> {
518 debug_assert!(width_factor.is_none_or(|factor| factor >= 0.0));
519 debug_assert!(height_factor.is_none_or(|factor| factor >= 0.0));
520 let this = RenderHandle::new_box(
521 app,
522 RenderPositionedBox {
523 render_object: RenderObjectData::new(),
524 render_box: RenderBoxData::new(),
525 child: RenderObjectWithChildData::new(),
526 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
527 width_factor,
528 height_factor,
529 },
530 );
531 this.set_child(app, child);
532 this
533 }
534
535 pub fn width_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
539 self.get(app).width_factor
540 }
541
542 pub fn set_width_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
544 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
545 if self.get(app).width_factor == value {
546 return;
547 }
548 self.get_mut(app).width_factor = value;
549 self.mark_needs_layout(app);
550 }
551
552 pub fn height_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
556 self.get(app).height_factor
557 }
558
559 pub fn set_height_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
561 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
562 if self.get(app).height_factor == value {
563 return;
564 }
565 self.get_mut(app).height_factor = value;
566 self.mark_needs_layout(app);
567 }
568}
569
570impl RenderObjectWithChildMixin for RenderPositionedBox {
571 type ChildType = AnyRenderBox;
572
573 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
574 &self.get(app).child
575 }
576
577 fn child_data_mut(
578 self: RenderHandle<Self>,
579 app: &mut App,
580 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
581 &mut self.get_mut(app).child
582 }
583}
584
585impl RenderShiftedBox for RenderPositionedBox {}
586
587impl RenderAligningShiftedBox for RenderPositionedBox {
588 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
589 &self.get(app).aligning
590 }
591
592 fn aligning_data_mut(
593 self: RenderHandle<Self>,
594 app: &mut App,
595 ) -> &mut RenderAligningShiftedBoxData {
596 &mut self.get_mut(app).aligning
597 }
598}
599
600impl RenderPositionedBox {
601 fn size_for_child(
604 self: RenderHandle<Self>,
605 app: &App,
606 constraints: BoxConstraints,
607 child_size: Size,
608 ) -> Size {
609 let (width_factor, height_factor) = {
610 let this = self.get(app);
611 (this.width_factor, this.height_factor)
612 };
613 let shrink_wrap_width = width_factor.is_some() || constraints.max_width == f64::INFINITY;
614 let shrink_wrap_height = height_factor.is_some() || constraints.max_height == f64::INFINITY;
615 constraints.constrain(Size::new(
616 if shrink_wrap_width {
617 child_size.width() * width_factor.unwrap_or(1.0)
618 } else {
619 f64::INFINITY
620 },
621 if shrink_wrap_height {
622 child_size.height() * height_factor.unwrap_or(1.0)
623 } else {
624 f64::INFINITY
625 },
626 ))
627 }
628}
629
630impl RenderObject for RenderPositionedBox {
631 crate::render_object_accessors!();
632
633 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
634 let constraints = self.constraints(app);
635 match self.child(app) {
636 Some(child) => {
637 child.layout(app, constraints.loosen(), true);
638 let child_size = child.size(app);
639 let size = self.size_for_child(app, constraints, child_size);
640 self.set_size(app, size);
641 self.align_child(app);
642 }
643 None => {
644 let size = self.size_for_child(app, constraints, Size::ZERO);
645 self.set_size(app, size);
646 }
647 }
648 }
649
650 fn paint(
651 self: RenderHandle<Self>,
652 app: &mut App,
653 context: &mut PaintingContext,
654 offset: Offset,
655 ) {
656 RenderShiftedBox::paint(self, app, context, offset);
657 }
658
659 fn visit_children(
660 self: RenderHandle<Self>,
661 app: &App,
662 visitor: &mut dyn FnMut(AnyRenderObject),
663 ) {
664 if let Some(child) = self.child(app) {
665 visitor(child.as_object());
666 }
667 }
668}
669
670impl RenderBox for RenderPositionedBox {
671 crate::render_box_accessors!();
672
673 fn hit_test_children(
674 self: RenderHandle<Self>,
675 app: &mut App,
676 result: &mut BoxHitTestResult<'_>,
677 position: Offset,
678 ) -> bool {
679 RenderShiftedBox::hit_test_children(self, app, result, position)
680 }
681
682 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
683 let factor = self.get(app).width_factor.unwrap_or(1.0);
684 RenderShiftedBox::compute_min_intrinsic_width(self, app, height) * factor
685 }
686
687 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
688 let factor = self.get(app).width_factor.unwrap_or(1.0);
689 RenderShiftedBox::compute_max_intrinsic_width(self, app, height) * factor
690 }
691
692 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
693 let factor = self.get(app).height_factor.unwrap_or(1.0);
694 RenderShiftedBox::compute_min_intrinsic_height(self, app, width) * factor
695 }
696
697 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
698 let factor = self.get(app).height_factor.unwrap_or(1.0);
699 RenderShiftedBox::compute_max_intrinsic_height(self, app, width) * factor
700 }
701
702 fn compute_distance_to_actual_baseline(
703 self: RenderHandle<Self>,
704 app: &mut App,
705 baseline: TextBaseline,
706 ) -> Option<f64> {
707 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
708 }
709
710 fn compute_dry_baseline(
711 self: RenderHandle<Self>,
712 app: &mut App,
713 constraints: BoxConstraints,
714 baseline: TextBaseline,
715 ) -> Option<f64> {
716 let child = self.child(app)?;
717 let child_constraints = constraints.loosen();
718 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
719 let child_size = child.get_dry_layout(app, child_constraints);
720 let size = self.size_for_child(app, constraints, child_size);
721 let child_offset = self.resolved_alignment(app).along_offset(size - child_size);
722 Some(result + child_offset.dy())
723 }
724
725 fn compute_dry_layout(
726 self: RenderHandle<Self>,
727 app: &mut App,
728 constraints: BoxConstraints,
729 ) -> Size {
730 match self.child(app) {
731 Some(child) => {
732 let child_size = child.get_dry_layout(app, constraints.loosen());
733 self.size_for_child(app, constraints, child_size)
734 }
735 None => self.size_for_child(app, constraints, Size::ZERO),
736 }
737 }
738}
739
740#[derive(Clone, Copy, Debug, PartialEq, Eq)]
743pub enum OverflowBoxFit {
744 Max,
746
747 DeferToChild,
753}
754
755pub struct RenderConstrainedOverflowBox {
768 render_object: RenderObjectData,
769 render_box: RenderBoxData,
770 child: RenderObjectWithChildData<AnyRenderBox>,
771 aligning: RenderAligningShiftedBoxData,
772 min_width: Option<f64>,
773 max_width: Option<f64>,
774 min_height: Option<f64>,
775 max_height: Option<f64>,
776 fit: OverflowBoxFit,
777}
778
779impl RenderConstrainedOverflowBox {
780 #[allow(clippy::too_many_arguments)]
783 pub fn new(
784 app: &mut App,
785 min_width: Option<f64>,
786 max_width: Option<f64>,
787 min_height: Option<f64>,
788 max_height: Option<f64>,
789 fit: OverflowBoxFit,
790 alignment: AlignmentGeometry,
791 text_direction: Option<TextDirection>,
792 child: Option<AnyRenderBox>,
793 ) -> RenderHandle<Self> {
794 let this = RenderHandle::new_box(
795 app,
796 RenderConstrainedOverflowBox {
797 render_object: RenderObjectData::new(),
798 render_box: RenderBoxData::new(),
799 child: RenderObjectWithChildData::new(),
800 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
801 min_width,
802 max_width,
803 min_height,
804 max_height,
805 fit,
806 },
807 );
808 this.set_child(app, child);
809 this
810 }
811
812 pub fn min_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
815 self.get(app).min_width
816 }
817
818 pub fn set_min_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
820 if self.get(app).min_width == value {
821 return;
822 }
823 self.get_mut(app).min_width = value;
824 self.mark_needs_layout(app);
825 }
826
827 pub fn max_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
830 self.get(app).max_width
831 }
832
833 pub fn set_max_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
835 if self.get(app).max_width == value {
836 return;
837 }
838 self.get_mut(app).max_width = value;
839 self.mark_needs_layout(app);
840 }
841
842 pub fn min_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
845 self.get(app).min_height
846 }
847
848 pub fn set_min_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
850 if self.get(app).min_height == value {
851 return;
852 }
853 self.get_mut(app).min_height = value;
854 self.mark_needs_layout(app);
855 }
856
857 pub fn max_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
860 self.get(app).max_height
861 }
862
863 pub fn set_max_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
865 if self.get(app).max_height == value {
866 return;
867 }
868 self.get_mut(app).max_height = value;
869 self.mark_needs_layout(app);
870 }
871
872 pub fn fit(self: RenderHandle<Self>, app: &App) -> OverflowBoxFit {
880 self.get(app).fit
881 }
882
883 pub fn set_fit(self: RenderHandle<Self>, app: &mut App, value: OverflowBoxFit) {
885 if self.get(app).fit == value {
886 return;
887 }
888 self.get_mut(app).fit = value;
889 self.as_object()
890 .mark_needs_layout_for_sized_by_parent_change(app);
891 }
892
893 fn get_inner_constraints(
894 self: RenderHandle<Self>,
895 app: &App,
896 constraints: BoxConstraints,
897 ) -> BoxConstraints {
898 let this = self.get(app);
899 BoxConstraints {
900 min_width: this.min_width.unwrap_or(constraints.min_width),
901 max_width: this.max_width.unwrap_or(constraints.max_width),
902 min_height: this.min_height.unwrap_or(constraints.min_height),
903 max_height: this.max_height.unwrap_or(constraints.max_height),
904 }
905 }
906}
907
908impl RenderObjectWithChildMixin for RenderConstrainedOverflowBox {
909 type ChildType = AnyRenderBox;
910
911 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
912 &self.get(app).child
913 }
914
915 fn child_data_mut(
916 self: RenderHandle<Self>,
917 app: &mut App,
918 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
919 &mut self.get_mut(app).child
920 }
921}
922
923impl RenderShiftedBox for RenderConstrainedOverflowBox {}
924
925impl RenderAligningShiftedBox for RenderConstrainedOverflowBox {
926 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
927 &self.get(app).aligning
928 }
929
930 fn aligning_data_mut(
931 self: RenderHandle<Self>,
932 app: &mut App,
933 ) -> &mut RenderAligningShiftedBoxData {
934 &mut self.get_mut(app).aligning
935 }
936}
937
938impl RenderObject for RenderConstrainedOverflowBox {
939 crate::render_object_accessors!();
940
941 fn sized_by_parent(self: RenderHandle<Self>, app: &App) -> bool {
942 match self.fit(app) {
943 OverflowBoxFit::Max => true,
944 OverflowBoxFit::DeferToChild => false,
947 }
948 }
949
950 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
951 let constraints = self.constraints(app);
952 match self.child(app) {
953 Some(child) => {
954 let inner = self.get_inner_constraints(app, constraints);
955 child.layout(app, inner, true);
956 match self.fit(app) {
957 OverflowBoxFit::Max => debug_assert!(self.sized_by_parent(app)),
958 OverflowBoxFit::DeferToChild => {
959 let size = constraints.constrain(child.size(app));
960 self.set_size(app, size);
961 }
962 }
963 self.align_child(app);
964 }
965 None => match self.fit(app) {
966 OverflowBoxFit::Max => debug_assert!(self.sized_by_parent(app)),
967 OverflowBoxFit::DeferToChild => self.set_size(app, constraints.smallest()),
968 },
969 }
970 }
971
972 fn paint(
973 self: RenderHandle<Self>,
974 app: &mut App,
975 context: &mut PaintingContext,
976 offset: Offset,
977 ) {
978 RenderShiftedBox::paint(self, app, context, offset);
979 }
980
981 fn visit_children(
982 self: RenderHandle<Self>,
983 app: &App,
984 visitor: &mut dyn FnMut(AnyRenderObject),
985 ) {
986 if let Some(child) = self.child(app) {
987 visitor(child.as_object());
988 }
989 }
990}
991
992impl RenderBox for RenderConstrainedOverflowBox {
993 crate::render_box_accessors!();
994
995 fn hit_test_children(
996 self: RenderHandle<Self>,
997 app: &mut App,
998 result: &mut BoxHitTestResult<'_>,
999 position: Offset,
1000 ) -> bool {
1001 RenderShiftedBox::hit_test_children(self, app, result, position)
1002 }
1003
1004 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1005 RenderShiftedBox::compute_min_intrinsic_width(self, app, height)
1006 }
1007
1008 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1009 RenderShiftedBox::compute_max_intrinsic_width(self, app, height)
1010 }
1011
1012 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1013 RenderShiftedBox::compute_min_intrinsic_height(self, app, width)
1014 }
1015
1016 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1017 RenderShiftedBox::compute_max_intrinsic_height(self, app, width)
1018 }
1019
1020 fn compute_distance_to_actual_baseline(
1021 self: RenderHandle<Self>,
1022 app: &mut App,
1023 baseline: TextBaseline,
1024 ) -> Option<f64> {
1025 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1026 }
1027
1028 fn compute_dry_layout(
1029 self: RenderHandle<Self>,
1030 app: &mut App,
1031 constraints: BoxConstraints,
1032 ) -> Size {
1033 match self.fit(app) {
1034 OverflowBoxFit::Max => constraints.biggest(),
1035 OverflowBoxFit::DeferToChild => match self.child(app) {
1036 Some(child) => child.get_dry_layout(app, constraints),
1037 None => constraints.smallest(),
1038 },
1039 }
1040 }
1041
1042 fn compute_dry_baseline(
1043 self: RenderHandle<Self>,
1044 app: &mut App,
1045 constraints: BoxConstraints,
1046 baseline: TextBaseline,
1047 ) -> Option<f64> {
1048 let child = self.child(app)?;
1049 let child_constraints = self.get_inner_constraints(app, constraints);
1050 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1051 let child_size = child.get_dry_layout(app, child_constraints);
1052 let size = self.get_dry_layout(app, constraints);
1053 Some(
1054 result
1055 + self
1056 .resolved_alignment(app)
1057 .along_offset(size - child_size)
1058 .dy(),
1059 )
1060 }
1061}
1062
1063pub struct RenderConstraintsTransformBox {
1078 render_object: RenderObjectData,
1079 render_box: RenderBoxData,
1080 child: RenderObjectWithChildData<AnyRenderBox>,
1081 aligning: RenderAligningShiftedBoxData,
1082 constraints_transform: BoxConstraintsTransform,
1083 clip_behavior: Clip,
1084 clip_rect_layer: LayerHandle<Handle<ClipRectLayer>>,
1085 overflow_container_rect: Rect,
1086 overflow_child_rect: Rect,
1087 is_overflowing: bool,
1088 child_constraints: Option<BoxConstraints>,
1089}
1090
1091impl RenderConstraintsTransformBox {
1092 pub fn new(
1095 app: &mut App,
1096 alignment: AlignmentGeometry,
1097 text_direction: Option<TextDirection>,
1098 constraints_transform: BoxConstraintsTransform,
1099 child: Option<AnyRenderBox>,
1100 ) -> RenderHandle<Self> {
1101 let this = RenderHandle::new_box(
1102 app,
1103 RenderConstraintsTransformBox {
1104 render_object: RenderObjectData::new(),
1105 render_box: RenderBoxData::new(),
1106 child: RenderObjectWithChildData::new(),
1107 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1108 constraints_transform,
1109 clip_behavior: Clip::None,
1110 clip_rect_layer: LayerHandle::new(),
1111 overflow_container_rect: Rect::ZERO,
1112 overflow_child_rect: Rect::ZERO,
1113 is_overflowing: false,
1114 child_constraints: None,
1115 },
1116 );
1117 this.set_child(app, child);
1118 this
1119 }
1120
1121 pub fn constraints_transform(self: RenderHandle<Self>, app: &App) -> BoxConstraintsTransform {
1123 self.get(app).constraints_transform
1124 }
1125
1126 pub fn set_constraints_transform(
1128 self: RenderHandle<Self>,
1129 app: &mut App,
1130 value: BoxConstraintsTransform,
1131 ) {
1132 if std::ptr::fn_addr_eq(self.get(app).constraints_transform, value) {
1133 return;
1134 }
1135 self.get_mut(app).constraints_transform = value;
1136 let needs_layout = match self.get(app).child_constraints {
1139 Some(child_constraints) => child_constraints != value(self.constraints(app)),
1140 None => true,
1141 };
1142 if needs_layout {
1143 self.mark_needs_layout(app);
1144 }
1145 }
1146
1147 pub fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
1149 self.get(app).clip_behavior
1150 }
1151
1152 pub fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
1154 if self.get(app).clip_behavior == value {
1155 return;
1156 }
1157 self.get_mut(app).clip_behavior = value;
1158 self.mark_needs_paint(app);
1159 }
1160}
1161
1162impl RenderObjectWithChildMixin for RenderConstraintsTransformBox {
1163 type ChildType = AnyRenderBox;
1164
1165 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1166 &self.get(app).child
1167 }
1168
1169 fn child_data_mut(
1170 self: RenderHandle<Self>,
1171 app: &mut App,
1172 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1173 &mut self.get_mut(app).child
1174 }
1175}
1176
1177impl RenderShiftedBox for RenderConstraintsTransformBox {}
1178
1179impl RenderAligningShiftedBox for RenderConstraintsTransformBox {
1180 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1181 &self.get(app).aligning
1182 }
1183
1184 fn aligning_data_mut(
1185 self: RenderHandle<Self>,
1186 app: &mut App,
1187 ) -> &mut RenderAligningShiftedBoxData {
1188 &mut self.get_mut(app).aligning
1189 }
1190}
1191
1192impl RenderObject for RenderConstraintsTransformBox {
1193 crate::render_object_accessors!();
1194
1195 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1196 let constraints = self.constraints(app);
1197 match self.child(app) {
1198 Some(child) => {
1199 let child_constraints = (self.constraints_transform(app))(constraints);
1200 debug_assert!(
1201 child_constraints.is_normalized(),
1202 "{child_constraints} is not normalized"
1203 );
1204 self.get_mut(app).child_constraints = Some(child_constraints);
1205 child.layout(app, child_constraints, true);
1206 let size = constraints.constrain(child.size(app));
1207 self.set_size(app, size);
1208 self.align_child(app);
1209 let child_offset = child
1210 .as_object()
1211 .parent_data_of::<BoxParentData>(app)
1212 .offset;
1213 let child_rect = child_offset & child.size(app);
1214 let this = self.get_mut(app);
1215 this.overflow_container_rect = Offset::ZERO & size;
1216 this.overflow_child_rect = child_rect;
1217 }
1218 None => {
1219 self.set_size(app, constraints.smallest());
1220 let this = self.get_mut(app);
1221 this.overflow_container_rect = Rect::ZERO;
1222 this.overflow_child_rect = Rect::ZERO;
1223 }
1224 }
1225 let this = self.get_mut(app);
1226 this.is_overflowing =
1227 RelativeRect::from_rect(this.overflow_container_rect, this.overflow_child_rect)
1228 .has_insets();
1229 }
1230
1231 fn paint(
1232 self: RenderHandle<Self>,
1233 app: &mut App,
1234 context: &mut PaintingContext,
1235 offset: Offset,
1236 ) {
1237 if self.child(app).is_none() {
1238 return;
1239 }
1240 if !self.get(app).is_overflowing {
1241 RenderShiftedBox::paint(self, app, context, offset);
1242 return;
1243 }
1244 let clip_rect = Offset::ZERO & self.size(app);
1246 let clip_behavior = self.clip_behavior(app);
1247 let old = self.get(app).clip_rect_layer.layer();
1248 let layer = context.push_clip_rect(
1249 app,
1250 self.as_object().needs_compositing(app),
1251 offset,
1252 clip_rect,
1253 |app, context, offset| RenderShiftedBox::paint(self, app, context, offset),
1254 clip_behavior,
1255 old,
1256 );
1257 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).clip_rect_layer, layer);
1258 }
1259
1260 fn dispose(self: RenderHandle<Self>, app: &mut App) {
1261 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).clip_rect_layer, None);
1262 crate::object::RenderObjectBase::dispose(self, app);
1263 }
1264
1265 fn visit_children(
1266 self: RenderHandle<Self>,
1267 app: &App,
1268 visitor: &mut dyn FnMut(AnyRenderObject),
1269 ) {
1270 if let Some(child) = self.child(app) {
1271 visitor(child.as_object());
1272 }
1273 }
1274}
1275
1276impl RenderBox for RenderConstraintsTransformBox {
1277 crate::render_box_accessors!();
1278
1279 fn hit_test_children(
1280 self: RenderHandle<Self>,
1281 app: &mut App,
1282 result: &mut BoxHitTestResult<'_>,
1283 position: Offset,
1284 ) -> bool {
1285 RenderShiftedBox::hit_test_children(self, app, result, position)
1286 }
1287
1288 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1289 let transformed =
1290 (self.constraints_transform(app))(BoxConstraints::new().max_height(height));
1291 RenderShiftedBox::compute_min_intrinsic_width(self, app, transformed.max_height)
1292 }
1293
1294 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1295 let transformed =
1296 (self.constraints_transform(app))(BoxConstraints::new().max_height(height));
1297 RenderShiftedBox::compute_max_intrinsic_width(self, app, transformed.max_height)
1298 }
1299
1300 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1301 let transformed = (self.constraints_transform(app))(BoxConstraints::new().max_width(width));
1302 RenderShiftedBox::compute_min_intrinsic_height(self, app, transformed.max_width)
1303 }
1304
1305 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1306 let transformed = (self.constraints_transform(app))(BoxConstraints::new().max_width(width));
1307 RenderShiftedBox::compute_max_intrinsic_height(self, app, transformed.max_width)
1308 }
1309
1310 fn compute_distance_to_actual_baseline(
1311 self: RenderHandle<Self>,
1312 app: &mut App,
1313 baseline: TextBaseline,
1314 ) -> Option<f64> {
1315 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1316 }
1317
1318 fn compute_dry_layout(
1319 self: RenderHandle<Self>,
1320 app: &mut App,
1321 constraints: BoxConstraints,
1322 ) -> Size {
1323 match self.child(app) {
1324 Some(child) => {
1325 let child_constraints = (self.constraints_transform(app))(constraints);
1326 let child_size = child.get_dry_layout(app, child_constraints);
1327 constraints.constrain(child_size)
1328 }
1329 None => constraints.smallest(),
1330 }
1331 }
1332
1333 fn compute_dry_baseline(
1334 self: RenderHandle<Self>,
1335 app: &mut App,
1336 constraints: BoxConstraints,
1337 baseline: TextBaseline,
1338 ) -> Option<f64> {
1339 let child = self.child(app)?;
1340 let child_constraints = (self.constraints_transform(app))(constraints);
1341 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1342 let child_size = child.get_dry_layout(app, child_constraints);
1343 let size = constraints.constrain(child_size);
1344 Some(
1345 result
1346 + self
1347 .resolved_alignment(app)
1348 .along_offset(size - child_size)
1349 .dy(),
1350 )
1351 }
1352}
1353
1354pub struct RenderSizedOverflowBox {
1360 render_object: RenderObjectData,
1361 render_box: RenderBoxData,
1362 child: RenderObjectWithChildData<AnyRenderBox>,
1363 aligning: RenderAligningShiftedBoxData,
1364 requested_size: Size,
1365}
1366
1367impl RenderSizedOverflowBox {
1368 pub fn new(
1370 app: &mut App,
1371 requested_size: Size,
1372 alignment: AlignmentGeometry,
1373 text_direction: Option<TextDirection>,
1374 child: Option<AnyRenderBox>,
1375 ) -> RenderHandle<Self> {
1376 let this = RenderHandle::new_box(
1377 app,
1378 RenderSizedOverflowBox {
1379 render_object: RenderObjectData::new(),
1380 render_box: RenderBoxData::new(),
1381 child: RenderObjectWithChildData::new(),
1382 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1383 requested_size,
1384 },
1385 );
1386 this.set_child(app, child);
1387 this
1388 }
1389
1390 pub fn requested_size(self: RenderHandle<Self>, app: &App) -> Size {
1392 self.get(app).requested_size
1393 }
1394
1395 pub fn set_requested_size(self: RenderHandle<Self>, app: &mut App, value: Size) {
1397 if self.get(app).requested_size == value {
1398 return;
1399 }
1400 self.get_mut(app).requested_size = value;
1401 self.mark_needs_layout(app);
1402 }
1403}
1404
1405impl RenderObjectWithChildMixin for RenderSizedOverflowBox {
1406 type ChildType = AnyRenderBox;
1407
1408 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1409 &self.get(app).child
1410 }
1411
1412 fn child_data_mut(
1413 self: RenderHandle<Self>,
1414 app: &mut App,
1415 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1416 &mut self.get_mut(app).child
1417 }
1418}
1419
1420impl RenderShiftedBox for RenderSizedOverflowBox {}
1421
1422impl RenderAligningShiftedBox for RenderSizedOverflowBox {
1423 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1424 &self.get(app).aligning
1425 }
1426
1427 fn aligning_data_mut(
1428 self: RenderHandle<Self>,
1429 app: &mut App,
1430 ) -> &mut RenderAligningShiftedBoxData {
1431 &mut self.get_mut(app).aligning
1432 }
1433}
1434
1435impl RenderObject for RenderSizedOverflowBox {
1436 crate::render_object_accessors!();
1437
1438 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1439 let constraints = self.constraints(app);
1440 let size = constraints.constrain(self.requested_size(app));
1441 self.set_size(app, size);
1442 if let Some(child) = self.child(app) {
1443 child.layout(app, constraints, true);
1444 self.align_child(app);
1445 }
1446 }
1447
1448 fn paint(
1449 self: RenderHandle<Self>,
1450 app: &mut App,
1451 context: &mut PaintingContext,
1452 offset: Offset,
1453 ) {
1454 RenderShiftedBox::paint(self, app, context, offset);
1455 }
1456
1457 fn visit_children(
1458 self: RenderHandle<Self>,
1459 app: &App,
1460 visitor: &mut dyn FnMut(AnyRenderObject),
1461 ) {
1462 if let Some(child) = self.child(app) {
1463 visitor(child.as_object());
1464 }
1465 }
1466}
1467
1468impl RenderBox for RenderSizedOverflowBox {
1469 crate::render_box_accessors!();
1470
1471 fn hit_test_children(
1472 self: RenderHandle<Self>,
1473 app: &mut App,
1474 result: &mut BoxHitTestResult<'_>,
1475 position: Offset,
1476 ) -> bool {
1477 RenderShiftedBox::hit_test_children(self, app, result, position)
1478 }
1479
1480 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, _height: f64) -> f64 {
1481 self.requested_size(app).width()
1482 }
1483
1484 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, _height: f64) -> f64 {
1485 self.requested_size(app).width()
1486 }
1487
1488 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, _width: f64) -> f64 {
1489 self.requested_size(app).height()
1490 }
1491
1492 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, _width: f64) -> f64 {
1493 self.requested_size(app).height()
1494 }
1495
1496 fn compute_distance_to_actual_baseline(
1497 self: RenderHandle<Self>,
1498 app: &mut App,
1499 baseline: TextBaseline,
1500 ) -> Option<f64> {
1501 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1502 }
1503
1504 fn compute_dry_layout(
1505 self: RenderHandle<Self>,
1506 app: &mut App,
1507 constraints: BoxConstraints,
1508 ) -> Size {
1509 constraints.constrain(self.requested_size(app))
1510 }
1511
1512 fn compute_dry_baseline(
1513 self: RenderHandle<Self>,
1514 app: &mut App,
1515 constraints: BoxConstraints,
1516 baseline: TextBaseline,
1517 ) -> Option<f64> {
1518 let child = self.child(app)?;
1519 let result = child.get_dry_baseline(app, constraints, baseline)?;
1520 let child_size = child.get_dry_layout(app, constraints);
1521 let size = self.get_dry_layout(app, constraints);
1522 Some(
1523 result
1524 + self
1525 .resolved_alignment(app)
1526 .along_offset(size - child_size)
1527 .dy(),
1528 )
1529 }
1530}
1531
1532pub struct RenderFractionallySizedOverflowBox {
1543 render_object: RenderObjectData,
1544 render_box: RenderBoxData,
1545 child: RenderObjectWithChildData<AnyRenderBox>,
1546 aligning: RenderAligningShiftedBoxData,
1547 width_factor: Option<f64>,
1548 height_factor: Option<f64>,
1549}
1550
1551impl RenderFractionallySizedOverflowBox {
1552 pub fn new(
1554 app: &mut App,
1555 alignment: AlignmentGeometry,
1556 text_direction: Option<TextDirection>,
1557 child: Option<AnyRenderBox>,
1558 ) -> RenderHandle<Self> {
1559 let this = RenderHandle::new_box(
1560 app,
1561 RenderFractionallySizedOverflowBox {
1562 render_object: RenderObjectData::new(),
1563 render_box: RenderBoxData::new(),
1564 child: RenderObjectWithChildData::new(),
1565 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1566 width_factor: None,
1567 height_factor: None,
1568 },
1569 );
1570 this.set_child(app, child);
1571 this
1572 }
1573
1574 pub fn width_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
1580 self.get(app).width_factor
1581 }
1582
1583 pub fn set_width_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
1585 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
1586 if self.get(app).width_factor == value {
1587 return;
1588 }
1589 self.get_mut(app).width_factor = value;
1590 self.mark_needs_layout(app);
1591 }
1592
1593 pub fn height_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
1599 self.get(app).height_factor
1600 }
1601
1602 pub fn set_height_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
1604 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
1605 if self.get(app).height_factor == value {
1606 return;
1607 }
1608 self.get_mut(app).height_factor = value;
1609 self.mark_needs_layout(app);
1610 }
1611
1612 fn get_inner_constraints(
1613 self: RenderHandle<Self>,
1614 app: &App,
1615 constraints: BoxConstraints,
1616 ) -> BoxConstraints {
1617 let (width_factor, height_factor) = {
1618 let this = self.get(app);
1619 (this.width_factor, this.height_factor)
1620 };
1621 let mut min_width = constraints.min_width;
1622 let mut max_width = constraints.max_width;
1623 if let Some(factor) = width_factor {
1624 let width = max_width * factor;
1625 min_width = width;
1626 max_width = width;
1627 }
1628 let mut min_height = constraints.min_height;
1629 let mut max_height = constraints.max_height;
1630 if let Some(factor) = height_factor {
1631 let height = max_height * factor;
1632 min_height = height;
1633 max_height = height;
1634 }
1635 BoxConstraints {
1636 min_width,
1637 max_width,
1638 min_height,
1639 max_height,
1640 }
1641 }
1642}
1643
1644impl RenderObjectWithChildMixin for RenderFractionallySizedOverflowBox {
1645 type ChildType = AnyRenderBox;
1646
1647 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1648 &self.get(app).child
1649 }
1650
1651 fn child_data_mut(
1652 self: RenderHandle<Self>,
1653 app: &mut App,
1654 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1655 &mut self.get_mut(app).child
1656 }
1657}
1658
1659impl RenderShiftedBox for RenderFractionallySizedOverflowBox {}
1660
1661impl RenderAligningShiftedBox for RenderFractionallySizedOverflowBox {
1662 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1663 &self.get(app).aligning
1664 }
1665
1666 fn aligning_data_mut(
1667 self: RenderHandle<Self>,
1668 app: &mut App,
1669 ) -> &mut RenderAligningShiftedBoxData {
1670 &mut self.get_mut(app).aligning
1671 }
1672}
1673
1674impl RenderObject for RenderFractionallySizedOverflowBox {
1675 crate::render_object_accessors!();
1676
1677 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1678 let constraints = self.constraints(app);
1679 let inner = self.get_inner_constraints(app, constraints);
1680 match self.child(app) {
1681 Some(child) => {
1682 child.layout(app, inner, true);
1683 let size = constraints.constrain(child.size(app));
1684 self.set_size(app, size);
1685 self.align_child(app);
1686 }
1687 None => {
1688 let size = constraints.constrain(inner.constrain(Size::ZERO));
1689 self.set_size(app, size);
1690 }
1691 }
1692 }
1693
1694 fn paint(
1695 self: RenderHandle<Self>,
1696 app: &mut App,
1697 context: &mut PaintingContext,
1698 offset: Offset,
1699 ) {
1700 RenderShiftedBox::paint(self, app, context, offset);
1701 }
1702
1703 fn visit_children(
1704 self: RenderHandle<Self>,
1705 app: &App,
1706 visitor: &mut dyn FnMut(AnyRenderObject),
1707 ) {
1708 if let Some(child) = self.child(app) {
1709 visitor(child.as_object());
1710 }
1711 }
1712}
1713
1714impl RenderBox for RenderFractionallySizedOverflowBox {
1715 crate::render_box_accessors!();
1716
1717 fn hit_test_children(
1718 self: RenderHandle<Self>,
1719 app: &mut App,
1720 result: &mut BoxHitTestResult<'_>,
1721 position: Offset,
1722 ) -> bool {
1723 RenderShiftedBox::hit_test_children(self, app, result, position)
1724 }
1725
1726 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1727 let (width_factor, height_factor) = {
1728 let this = self.get(app);
1729 (this.width_factor, this.height_factor)
1730 };
1731 let result = match self.child(app) {
1732 Some(child) => {
1734 child.get_min_intrinsic_width(app, height * height_factor.unwrap_or(1.0))
1735 }
1736 None => RenderShiftedBox::compute_min_intrinsic_width(self, app, height),
1737 };
1738 debug_assert!(result.is_finite());
1739 result / width_factor.unwrap_or(1.0)
1740 }
1741
1742 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1743 let (width_factor, height_factor) = {
1744 let this = self.get(app);
1745 (this.width_factor, this.height_factor)
1746 };
1747 let result = match self.child(app) {
1748 Some(child) => {
1749 child.get_max_intrinsic_width(app, height * height_factor.unwrap_or(1.0))
1750 }
1751 None => RenderShiftedBox::compute_max_intrinsic_width(self, app, height),
1752 };
1753 debug_assert!(result.is_finite());
1754 result / width_factor.unwrap_or(1.0)
1755 }
1756
1757 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1758 let (width_factor, height_factor) = {
1759 let this = self.get(app);
1760 (this.width_factor, this.height_factor)
1761 };
1762 let result = match self.child(app) {
1763 Some(child) => child.get_min_intrinsic_height(app, width * width_factor.unwrap_or(1.0)),
1764 None => RenderShiftedBox::compute_min_intrinsic_height(self, app, width),
1765 };
1766 debug_assert!(result.is_finite());
1767 result / height_factor.unwrap_or(1.0)
1768 }
1769
1770 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1771 let (width_factor, height_factor) = {
1772 let this = self.get(app);
1773 (this.width_factor, this.height_factor)
1774 };
1775 let result = match self.child(app) {
1776 Some(child) => child.get_max_intrinsic_height(app, width * width_factor.unwrap_or(1.0)),
1777 None => RenderShiftedBox::compute_max_intrinsic_height(self, app, width),
1778 };
1779 debug_assert!(result.is_finite());
1780 result / height_factor.unwrap_or(1.0)
1781 }
1782
1783 fn compute_distance_to_actual_baseline(
1784 self: RenderHandle<Self>,
1785 app: &mut App,
1786 baseline: TextBaseline,
1787 ) -> Option<f64> {
1788 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1789 }
1790
1791 fn compute_dry_layout(
1792 self: RenderHandle<Self>,
1793 app: &mut App,
1794 constraints: BoxConstraints,
1795 ) -> Size {
1796 let inner = self.get_inner_constraints(app, constraints);
1797 match self.child(app) {
1798 Some(child) => {
1799 let child_size = child.get_dry_layout(app, inner);
1800 constraints.constrain(child_size)
1801 }
1802 None => constraints.constrain(inner.constrain(Size::ZERO)),
1803 }
1804 }
1805
1806 fn compute_dry_baseline(
1807 self: RenderHandle<Self>,
1808 app: &mut App,
1809 constraints: BoxConstraints,
1810 baseline: TextBaseline,
1811 ) -> Option<f64> {
1812 let child = self.child(app)?;
1813 let child_constraints = self.get_inner_constraints(app, constraints);
1814 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1815 let child_size = child.get_dry_layout(app, child_constraints);
1816 let size = self.get_dry_layout(app, constraints);
1817 Some(
1818 result
1819 + self
1820 .resolved_alignment(app)
1821 .along_offset(size - child_size)
1822 .dy(),
1823 )
1824 }
1825}
1826
1827pub struct RenderBaseline {
1841 render_object: RenderObjectData,
1842 render_box: RenderBoxData,
1843 child: RenderObjectWithChildData<AnyRenderBox>,
1844 baseline: f64,
1845 baseline_type: TextBaseline,
1846}
1847
1848struct BaselineSizes {
1850 size: Size,
1851 top: f64,
1852}
1853
1854impl RenderBaseline {
1855 pub fn new(
1857 app: &mut App,
1858 baseline: f64,
1859 baseline_type: TextBaseline,
1860 child: Option<AnyRenderBox>,
1861 ) -> RenderHandle<Self> {
1862 let this = RenderHandle::new_box(
1863 app,
1864 RenderBaseline {
1865 render_object: RenderObjectData::new(),
1866 render_box: RenderBoxData::new(),
1867 child: RenderObjectWithChildData::new(),
1868 baseline,
1869 baseline_type,
1870 },
1871 );
1872 this.set_child(app, child);
1873 this
1874 }
1875
1876 pub fn baseline(self: RenderHandle<Self>, app: &App) -> f64 {
1879 self.get(app).baseline
1880 }
1881
1882 pub fn set_baseline(self: RenderHandle<Self>, app: &mut App, value: f64) {
1884 if self.get(app).baseline == value {
1885 return;
1886 }
1887 self.get_mut(app).baseline = value;
1888 self.mark_needs_layout(app);
1889 }
1890
1891 pub fn baseline_type(self: RenderHandle<Self>, app: &App) -> TextBaseline {
1893 self.get(app).baseline_type
1894 }
1895
1896 pub fn set_baseline_type(self: RenderHandle<Self>, app: &mut App, value: TextBaseline) {
1898 if self.get(app).baseline_type == value {
1899 return;
1900 }
1901 self.get_mut(app).baseline_type = value;
1902 self.mark_needs_layout(app);
1903 }
1904
1905 fn compute_sizes(
1907 self: RenderHandle<Self>,
1908 app: &mut App,
1909 constraints: BoxConstraints,
1910 layout_child: ChildLayouter,
1911 get_baseline: ChildBaselineGetter,
1912 ) -> BaselineSizes {
1913 let Some(child) = self.child(app) else {
1914 return BaselineSizes {
1915 size: constraints.smallest(),
1916 top: 0.0,
1917 };
1918 };
1919 let child_constraints = constraints.loosen();
1920 let child_size = layout_child(app, child, child_constraints);
1921 let baseline_type = self.baseline_type(app);
1922 let child_baseline = get_baseline(app, child, child_constraints, baseline_type)
1923 .unwrap_or(child_size.height());
1924 let top = self.baseline(app) - child_baseline;
1925 BaselineSizes {
1926 size: constraints.constrain(Size::new(child_size.width(), top + child_size.height())),
1927 top,
1928 }
1929 }
1930}
1931
1932impl RenderObjectWithChildMixin for RenderBaseline {
1933 type ChildType = AnyRenderBox;
1934
1935 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1936 &self.get(app).child
1937 }
1938
1939 fn child_data_mut(
1940 self: RenderHandle<Self>,
1941 app: &mut App,
1942 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1943 &mut self.get_mut(app).child
1944 }
1945}
1946
1947impl RenderShiftedBox for RenderBaseline {}
1948
1949impl RenderObject for RenderBaseline {
1950 crate::render_object_accessors!();
1951
1952 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1953 let constraints = self.constraints(app);
1954 let sizes = self.compute_sizes(
1955 app,
1956 constraints,
1957 ChildLayoutHelper::layout_child,
1958 ChildLayoutHelper::get_baseline,
1959 );
1960 self.set_size(app, sizes.size);
1961 if let Some(child) = self.child(app) {
1962 child.parent_data_of_mut::<BoxParentData>(app).offset = Offset::new(0.0, sizes.top);
1963 }
1964 }
1965
1966 fn paint(
1967 self: RenderHandle<Self>,
1968 app: &mut App,
1969 context: &mut PaintingContext,
1970 offset: Offset,
1971 ) {
1972 RenderShiftedBox::paint(self, app, context, offset);
1973 }
1974
1975 fn visit_children(
1976 self: RenderHandle<Self>,
1977 app: &App,
1978 visitor: &mut dyn FnMut(AnyRenderObject),
1979 ) {
1980 if let Some(child) = self.child(app) {
1981 visitor(child.as_object());
1982 }
1983 }
1984}
1985
1986impl RenderBox for RenderBaseline {
1987 crate::render_box_accessors!();
1988
1989 fn hit_test_children(
1990 self: RenderHandle<Self>,
1991 app: &mut App,
1992 result: &mut BoxHitTestResult<'_>,
1993 position: Offset,
1994 ) -> bool {
1995 RenderShiftedBox::hit_test_children(self, app, result, position)
1996 }
1997
1998 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1999 RenderShiftedBox::compute_min_intrinsic_width(self, app, height)
2000 }
2001
2002 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2003 RenderShiftedBox::compute_max_intrinsic_width(self, app, height)
2004 }
2005
2006 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2007 RenderShiftedBox::compute_min_intrinsic_height(self, app, width)
2008 }
2009
2010 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2011 RenderShiftedBox::compute_max_intrinsic_height(self, app, width)
2012 }
2013
2014 fn compute_distance_to_actual_baseline(
2015 self: RenderHandle<Self>,
2016 app: &mut App,
2017 baseline: TextBaseline,
2018 ) -> Option<f64> {
2019 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
2020 }
2021
2022 fn compute_dry_layout(
2023 self: RenderHandle<Self>,
2024 app: &mut App,
2025 constraints: BoxConstraints,
2026 ) -> Size {
2027 self.compute_sizes(
2028 app,
2029 constraints,
2030 ChildLayoutHelper::dry_layout_child,
2031 ChildLayoutHelper::get_dry_baseline,
2032 )
2033 .size
2034 }
2035
2036 fn compute_dry_baseline(
2037 self: RenderHandle<Self>,
2038 app: &mut App,
2039 constraints: BoxConstraints,
2040 baseline: TextBaseline,
2041 ) -> Option<f64> {
2042 let child = self.child(app)?;
2043 let child_constraints = constraints.loosen();
2044 let baseline_type = self.baseline_type(app);
2045 let result1 = child.get_dry_baseline(app, child_constraints, baseline)?;
2046 let result2 = child.get_dry_baseline(app, child_constraints, baseline_type)?;
2047 Some(self.baseline(app) + result1 - result2)
2048 }
2049}
2050
2051pub trait SingleChildLayoutDelegate: Debug + 'static {
2066 fn relayout(&self) -> Option<&Rc<dyn Listenable>> {
2070 None
2071 }
2072
2073 fn get_size(&self, constraints: BoxConstraints) -> Size {
2077 constraints.biggest()
2078 }
2079
2080 fn get_constraints_for_child(&self, constraints: BoxConstraints) -> BoxConstraints {
2087 constraints
2088 }
2089
2090 fn get_position_for_child(&self, size: Size, child_size: Size) -> Offset {
2100 let _ = (size, child_size);
2101 Offset::ZERO
2102 }
2103
2104 fn should_relayout(&self, old_delegate: &dyn SingleChildLayoutDelegate) -> bool;
2124
2125 fn as_any(&self) -> &dyn Any;
2128}
2129
2130pub struct RenderCustomSingleChildLayoutBox {
2136 render_object: RenderObjectData,
2137 render_box: RenderBoxData,
2138 child: RenderObjectWithChildData<AnyRenderBox>,
2139 delegate: Rc<dyn SingleChildLayoutDelegate>,
2140}
2141
2142impl RenderCustomSingleChildLayoutBox {
2143 pub fn new(
2145 app: &mut App,
2146 delegate: Rc<dyn SingleChildLayoutDelegate>,
2147 child: Option<AnyRenderBox>,
2148 ) -> RenderHandle<RenderCustomSingleChildLayoutBox> {
2149 let this = RenderHandle::new_box(
2150 app,
2151 RenderCustomSingleChildLayoutBox {
2152 render_object: RenderObjectData::new(),
2153 render_box: RenderBoxData::new(),
2154 child: RenderObjectWithChildData::new(),
2155 delegate,
2156 },
2157 );
2158 this.set_child(app, child);
2159 this
2160 }
2161
2162 pub fn delegate(self: RenderHandle<Self>, app: &App) -> Rc<dyn SingleChildLayoutDelegate> {
2164 Rc::clone(&self.get(app).delegate)
2165 }
2166
2167 pub fn set_delegate(
2169 self: RenderHandle<Self>,
2170 app: &mut App,
2171 new_delegate: Rc<dyn SingleChildLayoutDelegate>,
2172 ) {
2173 let old_delegate = Rc::clone(&self.get(app).delegate);
2174 if Rc::ptr_eq(&old_delegate, &new_delegate) {
2175 return;
2176 }
2177 if new_delegate.as_any().type_id() != old_delegate.as_any().type_id()
2178 || new_delegate.should_relayout(&*old_delegate)
2179 {
2180 self.mark_needs_layout(app);
2181 }
2182 self.get_mut(app).delegate = Rc::clone(&new_delegate);
2183 if self.attached(app) {
2184 if let Some(relayout) = old_delegate.relayout() {
2185 relayout.remove_listener(app, &self.relayout_listener());
2186 }
2187 if let Some(relayout) = new_delegate.relayout() {
2188 relayout.add_listener(app, self.relayout_listener());
2189 }
2190 }
2191 }
2192
2193 fn relayout_listener(self: RenderHandle<Self>) -> Listener {
2195 Listener::handle_method(self.handle(), mark_needs_layout_custom_single_child)
2196 }
2197
2198 fn get_size(self: RenderHandle<Self>, app: &App, constraints: BoxConstraints) -> Size {
2200 constraints.constrain(self.get(app).delegate.get_size(constraints))
2201 }
2202}
2203
2204fn mark_needs_layout_custom_single_child(
2205 this: Handle<RenderCustomSingleChildLayoutBox>,
2206 app: &mut App,
2207) {
2208 RenderHandle::from_handle(this).mark_needs_layout(app);
2209}
2210
2211impl RenderObjectWithChildMixin for RenderCustomSingleChildLayoutBox {
2212 type ChildType = AnyRenderBox;
2213
2214 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2215 &self.get(app).child
2216 }
2217
2218 fn child_data_mut(
2219 self: RenderHandle<Self>,
2220 app: &mut App,
2221 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2222 &mut self.get_mut(app).child
2223 }
2224}
2225
2226impl RenderShiftedBox for RenderCustomSingleChildLayoutBox {}
2227
2228impl RenderObject for RenderCustomSingleChildLayoutBox {
2229 crate::render_object_accessors!();
2230
2231 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2232 let constraints = self.constraints(app);
2233 let size = self.get_size(app, constraints);
2234 self.set_size(app, size);
2235 if let Some(child) = self.child(app) {
2236 let child_constraints = self
2237 .get(app)
2238 .delegate
2239 .get_constraints_for_child(constraints);
2240 debug_assert!(child_constraints.debug_assert_is_valid(true));
2241 child.layout(app, child_constraints, !child_constraints.is_tight());
2242 let child_size = if child_constraints.is_tight() {
2243 child_constraints.smallest()
2244 } else {
2245 child.size(app)
2246 };
2247 child.parent_data_of_mut::<BoxParentData>(app).offset = self
2248 .get(app)
2249 .delegate
2250 .get_position_for_child(size, child_size);
2251 }
2252 }
2253
2254 fn paint(
2255 self: RenderHandle<Self>,
2256 app: &mut App,
2257 context: &mut PaintingContext,
2258 offset: Offset,
2259 ) {
2260 RenderShiftedBox::paint(self, app, context, offset);
2261 }
2262
2263 fn visit_children(
2264 self: RenderHandle<Self>,
2265 app: &App,
2266 visitor: &mut dyn FnMut(AnyRenderObject),
2267 ) {
2268 if let Some(child) = self.child(app) {
2269 visitor(child.as_object());
2270 }
2271 }
2272
2273 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
2274 if let Some(child) = self.child(app) {
2275 child.as_object().attach(app, owner);
2276 }
2277 if let Some(relayout) = self.delegate(app).relayout() {
2278 relayout.add_listener(app, self.relayout_listener());
2279 }
2280 }
2281
2282 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
2283 if let Some(relayout) = self.delegate(app).relayout() {
2284 relayout.remove_listener(app, &self.relayout_listener());
2285 }
2286 if let Some(child) = self.child(app) {
2287 child.as_object().detach(app);
2288 }
2289 }
2290}
2291
2292impl RenderBox for RenderCustomSingleChildLayoutBox {
2293 crate::render_box_accessors!();
2294
2295 fn hit_test_children(
2296 self: RenderHandle<Self>,
2297 app: &mut App,
2298 result: &mut BoxHitTestResult<'_>,
2299 position: Offset,
2300 ) -> bool {
2301 RenderShiftedBox::hit_test_children(self, app, result, position)
2302 }
2303
2304 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2309 let width = self
2310 .get_size(app, BoxConstraints::tight_for_finite(f64::INFINITY, height))
2311 .width();
2312 if width.is_finite() { width } else { 0.0 }
2313 }
2314
2315 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2316 let width = self
2317 .get_size(app, BoxConstraints::tight_for_finite(f64::INFINITY, height))
2318 .width();
2319 if width.is_finite() { width } else { 0.0 }
2320 }
2321
2322 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2323 let height = self
2324 .get_size(app, BoxConstraints::tight_for_finite(width, f64::INFINITY))
2325 .height();
2326 if height.is_finite() { height } else { 0.0 }
2327 }
2328
2329 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2330 let height = self
2331 .get_size(app, BoxConstraints::tight_for_finite(width, f64::INFINITY))
2332 .height();
2333 if height.is_finite() { height } else { 0.0 }
2334 }
2335
2336 fn compute_dry_layout(
2337 self: RenderHandle<Self>,
2338 app: &mut App,
2339 constraints: BoxConstraints,
2340 ) -> Size {
2341 self.get_size(app, constraints)
2342 }
2343
2344 fn compute_dry_baseline(
2345 self: RenderHandle<Self>,
2346 app: &mut App,
2347 constraints: BoxConstraints,
2348 baseline: TextBaseline,
2349 ) -> Option<f64> {
2350 let child = self.child(app)?;
2351 let child_constraints = self
2352 .get(app)
2353 .delegate
2354 .get_constraints_for_child(constraints);
2355 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
2356 let child_size = if child_constraints.is_tight() {
2357 child_constraints.smallest()
2358 } else {
2359 child.get_dry_layout(app, child_constraints)
2360 };
2361 Some(
2362 result
2363 + self
2364 .get(app)
2365 .delegate
2366 .get_position_for_child(self.get_size(app, constraints), child_size)
2367 .dy(),
2368 )
2369 }
2370}
2371
2372#[cfg(test)]
2373mod tests {
2374 use super::*;
2375 use inset_embedder::Size;
2376 use inset_foundation::AppCell;
2377
2378 use crate::box_::BoxConstraints;
2379 use crate::layer::{ContainerLayer, ErasedLayer, OffsetLayer, PictureLayer};
2380 use crate::pipeline_owner::PipelineOwner;
2381 use crate::proxy_box::{RenderConstrainedBox, RenderRepaintBoundary};
2382 use inset_embedder::valo::Op;
2383
2384 #[test]
2387 fn padding_intrinsics_add_the_insets() {
2388 let cell = AppCell::new();
2389 let mut app = cell.borrow_mut();
2390 let child =
2391 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2392 let padding = RenderPadding::new(
2393 &mut app,
2394 EdgeInsetsGeometry::all(8.0),
2395 None,
2396 Some(child.as_box()),
2397 );
2398 let padded = padding.as_box();
2399 assert_eq!(padded.get_min_intrinsic_width(&mut app, 100.0), 96.0);
2400 assert_eq!(padded.get_max_intrinsic_width(&mut app, 100.0), 96.0);
2401 assert_eq!(padded.get_min_intrinsic_height(&mut app, 100.0), 56.0);
2402 assert_eq!(padded.get_max_intrinsic_height(&mut app, 100.0), 56.0);
2403 }
2404
2405 #[test]
2407 fn padding_intrinsics_without_a_child_are_the_insets() {
2408 let cell = AppCell::new();
2409 let mut app = cell.borrow_mut();
2410 let padding = RenderPadding::new(&mut app, EdgeInsetsGeometry::all(10.0), None, None);
2411 assert_eq!(
2412 padding.as_box().get_min_intrinsic_width(&mut app, 0.0),
2413 20.0
2414 );
2415 assert_eq!(
2416 padding.as_box().get_max_intrinsic_height(&mut app, 0.0),
2417 20.0
2418 );
2419 }
2420
2421 #[test]
2423 fn padding_dry_layout_matches_its_layout() {
2424 let cell = AppCell::new();
2425 let mut app = cell.borrow_mut();
2426 let child =
2427 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2428 let padding = RenderPadding::new(
2429 &mut app,
2430 EdgeInsetsGeometry::all(8.0),
2431 None,
2432 Some(child.as_box()),
2433 );
2434 let constraints = BoxConstraints::new().max_width(500.0).max_height(500.0);
2435 let dry = padding.as_box().get_dry_layout(&mut app, constraints);
2436 padding.layout(&mut app, constraints, false);
2437 assert_eq!(dry, padding.size(&app));
2438 }
2439
2440 #[test]
2444 fn constraints_transform_box_leaves_the_child_unconstrained_and_aligns_it() {
2445 let cell = AppCell::new();
2446 let mut app = cell.borrow_mut();
2447 let child =
2448 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(50.0, 20.0)), None);
2449 let unconstrained = RenderConstraintsTransformBox::new(
2450 &mut app,
2451 AlignmentGeometry::CENTER,
2452 None,
2453 |_| BoxConstraints::new(),
2454 Some(child.as_box()),
2455 );
2456 unconstrained.layout(
2457 &mut app,
2458 BoxConstraints::tight(Size::new(100.0, 100.0)),
2459 false,
2460 );
2461 assert_eq!(child.size(&app), Size::new(50.0, 20.0));
2462 assert_eq!(unconstrained.size(&app), Size::new(100.0, 100.0));
2463 assert_eq!(
2464 child.as_box().box_parent_data(&app).offset,
2465 Offset::new(25.0, 40.0)
2466 );
2467 }
2468
2469 #[test]
2471 fn constraints_transform_box_clips_an_overflowing_child() {
2472 let cell = AppCell::new();
2473 let mut app = cell.borrow_mut();
2474 let child = RenderConstrainedBox::new(
2475 &mut app,
2476 BoxConstraints::tight(Size::new(200.0, 200.0)),
2477 None,
2478 );
2479 let unconstrained = RenderConstraintsTransformBox::new(
2480 &mut app,
2481 AlignmentGeometry::CENTER,
2482 None,
2483 |_| BoxConstraints::new(),
2484 Some(child.as_box()),
2485 );
2486 unconstrained.set_clip_behavior(&mut app, Clip::HardEdge);
2487 let root = RenderRepaintBoundary::new(&mut app, Some(unconstrained.as_box()));
2488 let owner = PipelineOwner::new(&mut app, None, None);
2489 owner.set_root_node(&mut app, Some(root.as_object()));
2490 root.layout(
2491 &mut app,
2492 BoxConstraints::tight(Size::new(100.0, 100.0)),
2493 false,
2494 );
2495 let paint_root = OffsetLayer::new(&mut app, Offset::ZERO);
2496 paint_root
2497 .as_layer()
2498 .attach(&mut app, root.as_object().id());
2499 root.as_object()
2500 .schedule_initial_paint(&mut app, paint_root.as_container_layer());
2501 owner.flush_compositing_bits(&mut app);
2502 owner.flush_paint(&mut app);
2503
2504 assert_eq!(unconstrained.size(&app), Size::new(100.0, 100.0));
2505 let layer = root.as_object().debug_layer(&app).expect("painted");
2506 let clipped = layer
2507 .depth_first_iterate_children(&app)
2508 .into_iter()
2509 .filter_map(|child| {
2510 app.handle::<PictureLayer>(child.id())
2511 .and_then(|picture| picture.picture(&app).map(|p| p.ops().to_vec()))
2512 })
2513 .flatten()
2514 .any(|op| matches!(op, Op::ClipPath { .. }));
2515 assert!(clipped, "the overflowing child is clipped");
2516 }
2517
2518 #[test]
2520 fn constrained_overflow_box_sizes_itself_to_the_parent() {
2521 let cell = AppCell::new();
2522 let mut app = cell.borrow_mut();
2523 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::new(), None);
2524 let overflow = RenderConstrainedOverflowBox::new(
2525 &mut app,
2526 Some(200.0),
2527 Some(200.0),
2528 None,
2529 None,
2530 OverflowBoxFit::Max,
2531 AlignmentGeometry::CENTER,
2532 None,
2533 Some(child.as_box()),
2534 );
2535 overflow.layout(
2536 &mut app,
2537 BoxConstraints::tight(Size::new(100.0, 100.0)),
2538 false,
2539 );
2540 assert_eq!(overflow.size(&app), Size::new(100.0, 100.0));
2541 assert_eq!(child.size(&app).width(), 200.0);
2542 assert_eq!(
2543 child.as_box().box_parent_data(&app).offset.dx(),
2544 -50.0,
2545 "the child is centered, so it overflows both sides"
2546 );
2547 }
2548
2549 #[test]
2552 fn sized_overflow_box_takes_its_requested_size() {
2553 let cell = AppCell::new();
2554 let mut app = cell.borrow_mut();
2555 let child =
2556 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(30.0, 30.0)), None);
2557 let sized = RenderSizedOverflowBox::new(
2558 &mut app,
2559 Size::new(50.0, 50.0),
2560 AlignmentGeometry::CENTER,
2561 None,
2562 Some(child.as_box()),
2563 );
2564 sized.layout(&mut app, BoxConstraints::new().max_width(100.0), false);
2565 assert_eq!(sized.size(&app), Size::new(50.0, 50.0));
2566 assert_eq!(sized.as_box().get_min_intrinsic_width(&mut app, 0.0), 50.0);
2567 assert_eq!(sized.as_box().get_max_intrinsic_height(&mut app, 0.0), 50.0);
2568 }
2569
2570 #[test]
2573 fn fractionally_sized_box_tightens_the_child_to_a_fraction() {
2574 let cell = AppCell::new();
2575 let mut app = cell.borrow_mut();
2576 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::new(), None);
2577 let fraction = RenderFractionallySizedOverflowBox::new(
2578 &mut app,
2579 AlignmentGeometry::CENTER,
2580 None,
2581 Some(child.as_box()),
2582 );
2583 fraction.set_width_factor(&mut app, Some(0.5));
2584 fraction.layout(
2585 &mut app,
2586 BoxConstraints::new().max_width(200.0).max_height(80.0),
2587 false,
2588 );
2589 assert_eq!(child.size(&app).width(), 100.0);
2590 assert_eq!(fraction.size(&app).width(), 100.0);
2591 }
2592
2593 #[test]
2596 fn baseline_shifts_the_child_down_to_its_baseline() {
2597 let cell = AppCell::new();
2598 let mut app = cell.borrow_mut();
2599 let child =
2600 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2601 let baseline = RenderBaseline::new(
2602 &mut app,
2603 30.0,
2604 TextBaseline::Alphabetic,
2605 Some(child.as_box()),
2606 );
2607 baseline.layout(&mut app, BoxConstraints::new(), false);
2608 assert_eq!(
2610 child.as_box().box_parent_data(&app).offset,
2611 Offset::new(0.0, 10.0)
2612 );
2613 assert_eq!(baseline.size(&app), Size::new(20.0, 30.0));
2614 }
2615
2616 #[test]
2617 fn padding_around_tight_child() {
2618 let cell = AppCell::new();
2619 let mut app = cell.borrow_mut();
2620 let child =
2621 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2622 let padding = RenderPadding::new(
2623 &mut app,
2624 EdgeInsetsGeometry::all(8.0),
2625 None,
2626 Some(child.as_box()),
2627 );
2628 padding.layout(&mut app, BoxConstraints::new(), false);
2629 assert_eq!(child.size(&app), Size::new(80.0, 40.0));
2630 assert_eq!(padding.size(&app), Size::new(96.0, 56.0));
2631 assert_eq!(
2632 child.as_box().box_parent_data(&app).offset,
2633 Offset::new(8.0, 8.0)
2634 );
2635 }
2636
2637 #[test]
2638 fn positioned_box_centers_its_child() {
2639 let cell = AppCell::new();
2640 let mut app = cell.borrow_mut();
2641 let child =
2642 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2643 let positioned = RenderPositionedBox::new(
2644 &mut app,
2645 AlignmentGeometry::CENTER,
2646 None,
2647 None,
2648 None,
2649 Some(child.as_box()),
2650 );
2651 positioned.layout(
2652 &mut app,
2653 BoxConstraints::tight(Size::new(100.0, 100.0)),
2654 false,
2655 );
2656 assert_eq!(positioned.size(&app), Size::new(100.0, 100.0));
2657 assert_eq!(
2658 child.as_box().box_parent_data(&app).offset,
2659 Offset::new(40.0, 40.0)
2660 );
2661 }
2662
2663 #[test]
2664 fn positioned_box_shrink_wraps_with_a_factor() {
2665 let cell = AppCell::new();
2666 let mut app = cell.borrow_mut();
2667 let child =
2668 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2669 let positioned = RenderPositionedBox::new(
2670 &mut app,
2671 AlignmentGeometry::CENTER,
2672 None,
2673 Some(2.0),
2674 None,
2675 Some(child.as_box()),
2676 );
2677 positioned.layout(
2678 &mut app,
2679 BoxConstraints::new().max_width(100.0).max_height(100.0),
2680 false,
2681 );
2682 assert_eq!(positioned.size(&app), Size::new(40.0, 100.0));
2683 assert_eq!(
2684 child.as_box().box_parent_data(&app).offset,
2685 Offset::new(10.0, 40.0)
2686 );
2687 }
2688
2689 #[test]
2690 fn padding_without_child() {
2691 let cell = AppCell::new();
2692 let mut app = cell.borrow_mut();
2693 let padding = RenderPadding::new(&mut app, EdgeInsetsGeometry::all(10.0), None, None);
2694 padding.layout(
2695 &mut app,
2696 BoxConstraints::tight(Size::new(100.0, 100.0)),
2697 false,
2698 );
2699 assert_eq!(padding.size(&app), Size::new(100.0, 100.0));
2700 }
2701
2702 #[derive(Debug)]
2703 struct OffsetDelegate {
2704 offset: Offset,
2705 }
2706
2707 impl SingleChildLayoutDelegate for OffsetDelegate {
2708 fn get_size(&self, constraints: BoxConstraints) -> Size {
2709 constraints.biggest()
2710 }
2711
2712 fn get_constraints_for_child(&self, constraints: BoxConstraints) -> BoxConstraints {
2713 constraints.loosen()
2714 }
2715
2716 fn get_position_for_child(&self, _size: Size, _child_size: Size) -> Offset {
2717 self.offset
2718 }
2719
2720 fn should_relayout(&self, old_delegate: &dyn SingleChildLayoutDelegate) -> bool {
2721 old_delegate
2722 .as_any()
2723 .downcast_ref::<OffsetDelegate>()
2724 .is_none_or(|old| old.offset != self.offset)
2725 }
2726
2727 fn as_any(&self) -> &dyn Any {
2728 self
2729 }
2730 }
2731
2732 #[test]
2733 fn custom_single_child_layout_positions_the_child() {
2734 let cell = AppCell::new();
2735 let mut app = cell.borrow_mut();
2736 let child =
2737 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 10.0)), None);
2738 let parent = RenderCustomSingleChildLayoutBox::new(
2739 &mut app,
2740 Rc::new(OffsetDelegate {
2741 offset: Offset::new(8.0, 4.0),
2742 }),
2743 Some(child.as_box()),
2744 );
2745 parent.layout(
2746 &mut app,
2747 BoxConstraints::tight(Size::new(100.0, 50.0)),
2748 false,
2749 );
2750 assert_eq!(parent.size(&app), Size::new(100.0, 50.0));
2751 assert_eq!(
2752 child.as_box().box_parent_data(&app).offset,
2753 Offset::new(8.0, 4.0)
2754 );
2755 }
2756}