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 pub fn new(
782 app: &mut App,
783 alignment: AlignmentGeometry,
784 text_direction: Option<TextDirection>,
785 child: Option<AnyRenderBox>,
786 ) -> RenderHandle<Self> {
787 let this = RenderHandle::new_box(
788 app,
789 RenderConstrainedOverflowBox {
790 render_object: RenderObjectData::new(),
791 render_box: RenderBoxData::new(),
792 child: RenderObjectWithChildData::new(),
793 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
794 min_width: None,
795 max_width: None,
796 min_height: None,
797 max_height: None,
798 fit: OverflowBoxFit::Max,
799 },
800 );
801 this.set_child(app, child);
802 this
803 }
804
805 pub fn min_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
808 self.get(app).min_width
809 }
810
811 pub fn set_min_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
813 if self.get(app).min_width == value {
814 return;
815 }
816 self.get_mut(app).min_width = value;
817 self.mark_needs_layout(app);
818 }
819
820 pub fn max_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
823 self.get(app).max_width
824 }
825
826 pub fn set_max_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
828 if self.get(app).max_width == value {
829 return;
830 }
831 self.get_mut(app).max_width = value;
832 self.mark_needs_layout(app);
833 }
834
835 pub fn min_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
838 self.get(app).min_height
839 }
840
841 pub fn set_min_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
843 if self.get(app).min_height == value {
844 return;
845 }
846 self.get_mut(app).min_height = value;
847 self.mark_needs_layout(app);
848 }
849
850 pub fn max_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
853 self.get(app).max_height
854 }
855
856 pub fn set_max_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
858 if self.get(app).max_height == value {
859 return;
860 }
861 self.get_mut(app).max_height = value;
862 self.mark_needs_layout(app);
863 }
864
865 pub fn fit(self: RenderHandle<Self>, app: &App) -> OverflowBoxFit {
873 self.get(app).fit
874 }
875
876 pub fn set_fit(self: RenderHandle<Self>, app: &mut App, value: OverflowBoxFit) {
878 if self.get(app).fit == value {
879 return;
880 }
881 self.get_mut(app).fit = value;
882 self.as_object()
883 .mark_needs_layout_for_sized_by_parent_change(app);
884 }
885
886 fn get_inner_constraints(
887 self: RenderHandle<Self>,
888 app: &App,
889 constraints: BoxConstraints,
890 ) -> BoxConstraints {
891 let this = self.get(app);
892 BoxConstraints {
893 min_width: this.min_width.unwrap_or(constraints.min_width),
894 max_width: this.max_width.unwrap_or(constraints.max_width),
895 min_height: this.min_height.unwrap_or(constraints.min_height),
896 max_height: this.max_height.unwrap_or(constraints.max_height),
897 }
898 }
899}
900
901impl RenderObjectWithChildMixin for RenderConstrainedOverflowBox {
902 type ChildType = AnyRenderBox;
903
904 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
905 &self.get(app).child
906 }
907
908 fn child_data_mut(
909 self: RenderHandle<Self>,
910 app: &mut App,
911 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
912 &mut self.get_mut(app).child
913 }
914}
915
916impl RenderShiftedBox for RenderConstrainedOverflowBox {}
917
918impl RenderAligningShiftedBox for RenderConstrainedOverflowBox {
919 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
920 &self.get(app).aligning
921 }
922
923 fn aligning_data_mut(
924 self: RenderHandle<Self>,
925 app: &mut App,
926 ) -> &mut RenderAligningShiftedBoxData {
927 &mut self.get_mut(app).aligning
928 }
929}
930
931impl RenderObject for RenderConstrainedOverflowBox {
932 crate::render_object_accessors!();
933
934 fn sized_by_parent(self: RenderHandle<Self>, app: &App) -> bool {
935 match self.fit(app) {
936 OverflowBoxFit::Max => true,
937 OverflowBoxFit::DeferToChild => false,
940 }
941 }
942
943 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
944 let constraints = self.constraints(app);
945 match self.child(app) {
946 Some(child) => {
947 let inner = self.get_inner_constraints(app, constraints);
948 child.layout(app, inner, true);
949 match self.fit(app) {
950 OverflowBoxFit::Max => debug_assert!(self.sized_by_parent(app)),
951 OverflowBoxFit::DeferToChild => {
952 let size = constraints.constrain(child.size(app));
953 self.set_size(app, size);
954 }
955 }
956 self.align_child(app);
957 }
958 None => match self.fit(app) {
959 OverflowBoxFit::Max => debug_assert!(self.sized_by_parent(app)),
960 OverflowBoxFit::DeferToChild => self.set_size(app, constraints.smallest()),
961 },
962 }
963 }
964
965 fn paint(
966 self: RenderHandle<Self>,
967 app: &mut App,
968 context: &mut PaintingContext,
969 offset: Offset,
970 ) {
971 RenderShiftedBox::paint(self, app, context, offset);
972 }
973
974 fn visit_children(
975 self: RenderHandle<Self>,
976 app: &App,
977 visitor: &mut dyn FnMut(AnyRenderObject),
978 ) {
979 if let Some(child) = self.child(app) {
980 visitor(child.as_object());
981 }
982 }
983}
984
985impl RenderBox for RenderConstrainedOverflowBox {
986 crate::render_box_accessors!();
987
988 fn hit_test_children(
989 self: RenderHandle<Self>,
990 app: &mut App,
991 result: &mut BoxHitTestResult<'_>,
992 position: Offset,
993 ) -> bool {
994 RenderShiftedBox::hit_test_children(self, app, result, position)
995 }
996
997 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
998 RenderShiftedBox::compute_min_intrinsic_width(self, app, height)
999 }
1000
1001 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1002 RenderShiftedBox::compute_max_intrinsic_width(self, app, height)
1003 }
1004
1005 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1006 RenderShiftedBox::compute_min_intrinsic_height(self, app, width)
1007 }
1008
1009 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1010 RenderShiftedBox::compute_max_intrinsic_height(self, app, width)
1011 }
1012
1013 fn compute_distance_to_actual_baseline(
1014 self: RenderHandle<Self>,
1015 app: &mut App,
1016 baseline: TextBaseline,
1017 ) -> Option<f64> {
1018 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1019 }
1020
1021 fn compute_dry_layout(
1022 self: RenderHandle<Self>,
1023 app: &mut App,
1024 constraints: BoxConstraints,
1025 ) -> Size {
1026 match self.fit(app) {
1027 OverflowBoxFit::Max => constraints.biggest(),
1028 OverflowBoxFit::DeferToChild => match self.child(app) {
1029 Some(child) => child.get_dry_layout(app, constraints),
1030 None => constraints.smallest(),
1031 },
1032 }
1033 }
1034
1035 fn compute_dry_baseline(
1036 self: RenderHandle<Self>,
1037 app: &mut App,
1038 constraints: BoxConstraints,
1039 baseline: TextBaseline,
1040 ) -> Option<f64> {
1041 let child = self.child(app)?;
1042 let child_constraints = self.get_inner_constraints(app, constraints);
1043 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1044 let child_size = child.get_dry_layout(app, child_constraints);
1045 let size = self.get_dry_layout(app, constraints);
1046 Some(
1047 result
1048 + self
1049 .resolved_alignment(app)
1050 .along_offset(size - child_size)
1051 .dy(),
1052 )
1053 }
1054}
1055
1056pub struct RenderConstraintsTransformBox {
1071 render_object: RenderObjectData,
1072 render_box: RenderBoxData,
1073 child: RenderObjectWithChildData<AnyRenderBox>,
1074 aligning: RenderAligningShiftedBoxData,
1075 constraints_transform: BoxConstraintsTransform,
1076 clip_behavior: Clip,
1077 clip_rect_layer: LayerHandle<Handle<ClipRectLayer>>,
1078 overflow_container_rect: Rect,
1079 overflow_child_rect: Rect,
1080 is_overflowing: bool,
1081 child_constraints: Option<BoxConstraints>,
1082}
1083
1084impl RenderConstraintsTransformBox {
1085 pub fn new(
1088 app: &mut App,
1089 alignment: AlignmentGeometry,
1090 text_direction: Option<TextDirection>,
1091 constraints_transform: BoxConstraintsTransform,
1092 child: Option<AnyRenderBox>,
1093 ) -> RenderHandle<Self> {
1094 let this = RenderHandle::new_box(
1095 app,
1096 RenderConstraintsTransformBox {
1097 render_object: RenderObjectData::new(),
1098 render_box: RenderBoxData::new(),
1099 child: RenderObjectWithChildData::new(),
1100 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1101 constraints_transform,
1102 clip_behavior: Clip::None,
1103 clip_rect_layer: LayerHandle::new(),
1104 overflow_container_rect: Rect::ZERO,
1105 overflow_child_rect: Rect::ZERO,
1106 is_overflowing: false,
1107 child_constraints: None,
1108 },
1109 );
1110 this.set_child(app, child);
1111 this
1112 }
1113
1114 pub fn constraints_transform(self: RenderHandle<Self>, app: &App) -> BoxConstraintsTransform {
1116 self.get(app).constraints_transform
1117 }
1118
1119 pub fn set_constraints_transform(
1121 self: RenderHandle<Self>,
1122 app: &mut App,
1123 value: BoxConstraintsTransform,
1124 ) {
1125 if std::ptr::fn_addr_eq(self.get(app).constraints_transform, value) {
1126 return;
1127 }
1128 self.get_mut(app).constraints_transform = value;
1129 let needs_layout = match self.get(app).child_constraints {
1132 Some(child_constraints) => child_constraints != value(self.constraints(app)),
1133 None => true,
1134 };
1135 if needs_layout {
1136 self.mark_needs_layout(app);
1137 }
1138 }
1139
1140 pub fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
1142 self.get(app).clip_behavior
1143 }
1144
1145 pub fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
1147 if self.get(app).clip_behavior == value {
1148 return;
1149 }
1150 self.get_mut(app).clip_behavior = value;
1151 self.mark_needs_paint(app);
1152 }
1153}
1154
1155impl RenderObjectWithChildMixin for RenderConstraintsTransformBox {
1156 type ChildType = AnyRenderBox;
1157
1158 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1159 &self.get(app).child
1160 }
1161
1162 fn child_data_mut(
1163 self: RenderHandle<Self>,
1164 app: &mut App,
1165 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1166 &mut self.get_mut(app).child
1167 }
1168}
1169
1170impl RenderShiftedBox for RenderConstraintsTransformBox {}
1171
1172impl RenderAligningShiftedBox for RenderConstraintsTransformBox {
1173 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1174 &self.get(app).aligning
1175 }
1176
1177 fn aligning_data_mut(
1178 self: RenderHandle<Self>,
1179 app: &mut App,
1180 ) -> &mut RenderAligningShiftedBoxData {
1181 &mut self.get_mut(app).aligning
1182 }
1183}
1184
1185impl RenderObject for RenderConstraintsTransformBox {
1186 crate::render_object_accessors!();
1187
1188 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1189 let constraints = self.constraints(app);
1190 match self.child(app) {
1191 Some(child) => {
1192 let child_constraints = (self.constraints_transform(app))(constraints);
1193 debug_assert!(
1194 child_constraints.is_normalized(),
1195 "{child_constraints} is not normalized"
1196 );
1197 self.get_mut(app).child_constraints = Some(child_constraints);
1198 child.layout(app, child_constraints, true);
1199 let size = constraints.constrain(child.size(app));
1200 self.set_size(app, size);
1201 self.align_child(app);
1202 let child_offset = child
1203 .as_object()
1204 .parent_data_of::<BoxParentData>(app)
1205 .offset;
1206 let child_rect = child_offset & child.size(app);
1207 let this = self.get_mut(app);
1208 this.overflow_container_rect = Offset::ZERO & size;
1209 this.overflow_child_rect = child_rect;
1210 }
1211 None => {
1212 self.set_size(app, constraints.smallest());
1213 let this = self.get_mut(app);
1214 this.overflow_container_rect = Rect::ZERO;
1215 this.overflow_child_rect = Rect::ZERO;
1216 }
1217 }
1218 let this = self.get_mut(app);
1219 this.is_overflowing =
1220 RelativeRect::from_rect(this.overflow_container_rect, this.overflow_child_rect)
1221 .has_insets();
1222 }
1223
1224 fn paint(
1225 self: RenderHandle<Self>,
1226 app: &mut App,
1227 context: &mut PaintingContext,
1228 offset: Offset,
1229 ) {
1230 if self.child(app).is_none() {
1231 return;
1232 }
1233 if !self.get(app).is_overflowing {
1234 RenderShiftedBox::paint(self, app, context, offset);
1235 return;
1236 }
1237 let clip_rect = Offset::ZERO & self.size(app);
1239 let clip_behavior = self.clip_behavior(app);
1240 let old = self.get(app).clip_rect_layer.layer();
1241 let layer = context.push_clip_rect(
1242 app,
1243 self.as_object().needs_compositing(app),
1244 offset,
1245 clip_rect,
1246 |app, context, offset| RenderShiftedBox::paint(self, app, context, offset),
1247 clip_behavior,
1248 old,
1249 );
1250 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).clip_rect_layer, layer);
1251 }
1252
1253 fn dispose(self: RenderHandle<Self>, app: &mut App) {
1254 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).clip_rect_layer, None);
1255 crate::object::RenderObjectBase::dispose(self, app);
1256 }
1257
1258 fn visit_children(
1259 self: RenderHandle<Self>,
1260 app: &App,
1261 visitor: &mut dyn FnMut(AnyRenderObject),
1262 ) {
1263 if let Some(child) = self.child(app) {
1264 visitor(child.as_object());
1265 }
1266 }
1267}
1268
1269impl RenderBox for RenderConstraintsTransformBox {
1270 crate::render_box_accessors!();
1271
1272 fn hit_test_children(
1273 self: RenderHandle<Self>,
1274 app: &mut App,
1275 result: &mut BoxHitTestResult<'_>,
1276 position: Offset,
1277 ) -> bool {
1278 RenderShiftedBox::hit_test_children(self, app, result, position)
1279 }
1280
1281 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1282 let transformed =
1283 (self.constraints_transform(app))(BoxConstraints::new().max_height(height));
1284 RenderShiftedBox::compute_min_intrinsic_width(self, app, transformed.max_height)
1285 }
1286
1287 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1288 let transformed =
1289 (self.constraints_transform(app))(BoxConstraints::new().max_height(height));
1290 RenderShiftedBox::compute_max_intrinsic_width(self, app, transformed.max_height)
1291 }
1292
1293 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1294 let transformed = (self.constraints_transform(app))(BoxConstraints::new().max_width(width));
1295 RenderShiftedBox::compute_min_intrinsic_height(self, app, transformed.max_width)
1296 }
1297
1298 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1299 let transformed = (self.constraints_transform(app))(BoxConstraints::new().max_width(width));
1300 RenderShiftedBox::compute_max_intrinsic_height(self, app, transformed.max_width)
1301 }
1302
1303 fn compute_distance_to_actual_baseline(
1304 self: RenderHandle<Self>,
1305 app: &mut App,
1306 baseline: TextBaseline,
1307 ) -> Option<f64> {
1308 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1309 }
1310
1311 fn compute_dry_layout(
1312 self: RenderHandle<Self>,
1313 app: &mut App,
1314 constraints: BoxConstraints,
1315 ) -> Size {
1316 match self.child(app) {
1317 Some(child) => {
1318 let child_constraints = (self.constraints_transform(app))(constraints);
1319 let child_size = child.get_dry_layout(app, child_constraints);
1320 constraints.constrain(child_size)
1321 }
1322 None => constraints.smallest(),
1323 }
1324 }
1325
1326 fn compute_dry_baseline(
1327 self: RenderHandle<Self>,
1328 app: &mut App,
1329 constraints: BoxConstraints,
1330 baseline: TextBaseline,
1331 ) -> Option<f64> {
1332 let child = self.child(app)?;
1333 let child_constraints = (self.constraints_transform(app))(constraints);
1334 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1335 let child_size = child.get_dry_layout(app, child_constraints);
1336 let size = constraints.constrain(child_size);
1337 Some(
1338 result
1339 + self
1340 .resolved_alignment(app)
1341 .along_offset(size - child_size)
1342 .dy(),
1343 )
1344 }
1345}
1346
1347pub struct RenderSizedOverflowBox {
1353 render_object: RenderObjectData,
1354 render_box: RenderBoxData,
1355 child: RenderObjectWithChildData<AnyRenderBox>,
1356 aligning: RenderAligningShiftedBoxData,
1357 requested_size: Size,
1358}
1359
1360impl RenderSizedOverflowBox {
1361 pub fn new(
1363 app: &mut App,
1364 requested_size: Size,
1365 alignment: AlignmentGeometry,
1366 text_direction: Option<TextDirection>,
1367 child: Option<AnyRenderBox>,
1368 ) -> RenderHandle<Self> {
1369 let this = RenderHandle::new_box(
1370 app,
1371 RenderSizedOverflowBox {
1372 render_object: RenderObjectData::new(),
1373 render_box: RenderBoxData::new(),
1374 child: RenderObjectWithChildData::new(),
1375 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1376 requested_size,
1377 },
1378 );
1379 this.set_child(app, child);
1380 this
1381 }
1382
1383 pub fn requested_size(self: RenderHandle<Self>, app: &App) -> Size {
1385 self.get(app).requested_size
1386 }
1387
1388 pub fn set_requested_size(self: RenderHandle<Self>, app: &mut App, value: Size) {
1390 if self.get(app).requested_size == value {
1391 return;
1392 }
1393 self.get_mut(app).requested_size = value;
1394 self.mark_needs_layout(app);
1395 }
1396}
1397
1398impl RenderObjectWithChildMixin for RenderSizedOverflowBox {
1399 type ChildType = AnyRenderBox;
1400
1401 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1402 &self.get(app).child
1403 }
1404
1405 fn child_data_mut(
1406 self: RenderHandle<Self>,
1407 app: &mut App,
1408 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1409 &mut self.get_mut(app).child
1410 }
1411}
1412
1413impl RenderShiftedBox for RenderSizedOverflowBox {}
1414
1415impl RenderAligningShiftedBox for RenderSizedOverflowBox {
1416 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1417 &self.get(app).aligning
1418 }
1419
1420 fn aligning_data_mut(
1421 self: RenderHandle<Self>,
1422 app: &mut App,
1423 ) -> &mut RenderAligningShiftedBoxData {
1424 &mut self.get_mut(app).aligning
1425 }
1426}
1427
1428impl RenderObject for RenderSizedOverflowBox {
1429 crate::render_object_accessors!();
1430
1431 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1432 let constraints = self.constraints(app);
1433 let size = constraints.constrain(self.requested_size(app));
1434 self.set_size(app, size);
1435 if let Some(child) = self.child(app) {
1436 child.layout(app, constraints, true);
1437 self.align_child(app);
1438 }
1439 }
1440
1441 fn paint(
1442 self: RenderHandle<Self>,
1443 app: &mut App,
1444 context: &mut PaintingContext,
1445 offset: Offset,
1446 ) {
1447 RenderShiftedBox::paint(self, app, context, offset);
1448 }
1449
1450 fn visit_children(
1451 self: RenderHandle<Self>,
1452 app: &App,
1453 visitor: &mut dyn FnMut(AnyRenderObject),
1454 ) {
1455 if let Some(child) = self.child(app) {
1456 visitor(child.as_object());
1457 }
1458 }
1459}
1460
1461impl RenderBox for RenderSizedOverflowBox {
1462 crate::render_box_accessors!();
1463
1464 fn hit_test_children(
1465 self: RenderHandle<Self>,
1466 app: &mut App,
1467 result: &mut BoxHitTestResult<'_>,
1468 position: Offset,
1469 ) -> bool {
1470 RenderShiftedBox::hit_test_children(self, app, result, position)
1471 }
1472
1473 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, _height: f64) -> f64 {
1474 self.requested_size(app).width()
1475 }
1476
1477 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, _height: f64) -> f64 {
1478 self.requested_size(app).width()
1479 }
1480
1481 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, _width: f64) -> f64 {
1482 self.requested_size(app).height()
1483 }
1484
1485 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, _width: f64) -> f64 {
1486 self.requested_size(app).height()
1487 }
1488
1489 fn compute_distance_to_actual_baseline(
1490 self: RenderHandle<Self>,
1491 app: &mut App,
1492 baseline: TextBaseline,
1493 ) -> Option<f64> {
1494 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1495 }
1496
1497 fn compute_dry_layout(
1498 self: RenderHandle<Self>,
1499 app: &mut App,
1500 constraints: BoxConstraints,
1501 ) -> Size {
1502 constraints.constrain(self.requested_size(app))
1503 }
1504
1505 fn compute_dry_baseline(
1506 self: RenderHandle<Self>,
1507 app: &mut App,
1508 constraints: BoxConstraints,
1509 baseline: TextBaseline,
1510 ) -> Option<f64> {
1511 let child = self.child(app)?;
1512 let result = child.get_dry_baseline(app, constraints, baseline)?;
1513 let child_size = child.get_dry_layout(app, constraints);
1514 let size = self.get_dry_layout(app, constraints);
1515 Some(
1516 result
1517 + self
1518 .resolved_alignment(app)
1519 .along_offset(size - child_size)
1520 .dy(),
1521 )
1522 }
1523}
1524
1525pub struct RenderFractionallySizedOverflowBox {
1536 render_object: RenderObjectData,
1537 render_box: RenderBoxData,
1538 child: RenderObjectWithChildData<AnyRenderBox>,
1539 aligning: RenderAligningShiftedBoxData,
1540 width_factor: Option<f64>,
1541 height_factor: Option<f64>,
1542}
1543
1544impl RenderFractionallySizedOverflowBox {
1545 pub fn new(
1547 app: &mut App,
1548 alignment: AlignmentGeometry,
1549 text_direction: Option<TextDirection>,
1550 child: Option<AnyRenderBox>,
1551 ) -> RenderHandle<Self> {
1552 let this = RenderHandle::new_box(
1553 app,
1554 RenderFractionallySizedOverflowBox {
1555 render_object: RenderObjectData::new(),
1556 render_box: RenderBoxData::new(),
1557 child: RenderObjectWithChildData::new(),
1558 aligning: RenderAligningShiftedBoxData::new(alignment, text_direction),
1559 width_factor: None,
1560 height_factor: None,
1561 },
1562 );
1563 this.set_child(app, child);
1564 this
1565 }
1566
1567 pub fn width_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
1573 self.get(app).width_factor
1574 }
1575
1576 pub fn set_width_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
1578 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
1579 if self.get(app).width_factor == value {
1580 return;
1581 }
1582 self.get_mut(app).width_factor = value;
1583 self.mark_needs_layout(app);
1584 }
1585
1586 pub fn height_factor(self: RenderHandle<Self>, app: &App) -> Option<f64> {
1592 self.get(app).height_factor
1593 }
1594
1595 pub fn set_height_factor(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
1597 debug_assert!(value.is_none_or(|factor| factor >= 0.0));
1598 if self.get(app).height_factor == value {
1599 return;
1600 }
1601 self.get_mut(app).height_factor = value;
1602 self.mark_needs_layout(app);
1603 }
1604
1605 fn get_inner_constraints(
1606 self: RenderHandle<Self>,
1607 app: &App,
1608 constraints: BoxConstraints,
1609 ) -> BoxConstraints {
1610 let (width_factor, height_factor) = {
1611 let this = self.get(app);
1612 (this.width_factor, this.height_factor)
1613 };
1614 let mut min_width = constraints.min_width;
1615 let mut max_width = constraints.max_width;
1616 if let Some(factor) = width_factor {
1617 let width = max_width * factor;
1618 min_width = width;
1619 max_width = width;
1620 }
1621 let mut min_height = constraints.min_height;
1622 let mut max_height = constraints.max_height;
1623 if let Some(factor) = height_factor {
1624 let height = max_height * factor;
1625 min_height = height;
1626 max_height = height;
1627 }
1628 BoxConstraints {
1629 min_width,
1630 max_width,
1631 min_height,
1632 max_height,
1633 }
1634 }
1635}
1636
1637impl RenderObjectWithChildMixin for RenderFractionallySizedOverflowBox {
1638 type ChildType = AnyRenderBox;
1639
1640 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1641 &self.get(app).child
1642 }
1643
1644 fn child_data_mut(
1645 self: RenderHandle<Self>,
1646 app: &mut App,
1647 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1648 &mut self.get_mut(app).child
1649 }
1650}
1651
1652impl RenderShiftedBox for RenderFractionallySizedOverflowBox {}
1653
1654impl RenderAligningShiftedBox for RenderFractionallySizedOverflowBox {
1655 fn aligning_data(self: RenderHandle<Self>, app: &App) -> &RenderAligningShiftedBoxData {
1656 &self.get(app).aligning
1657 }
1658
1659 fn aligning_data_mut(
1660 self: RenderHandle<Self>,
1661 app: &mut App,
1662 ) -> &mut RenderAligningShiftedBoxData {
1663 &mut self.get_mut(app).aligning
1664 }
1665}
1666
1667impl RenderObject for RenderFractionallySizedOverflowBox {
1668 crate::render_object_accessors!();
1669
1670 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1671 let constraints = self.constraints(app);
1672 let inner = self.get_inner_constraints(app, constraints);
1673 match self.child(app) {
1674 Some(child) => {
1675 child.layout(app, inner, true);
1676 let size = constraints.constrain(child.size(app));
1677 self.set_size(app, size);
1678 self.align_child(app);
1679 }
1680 None => {
1681 let size = constraints.constrain(inner.constrain(Size::ZERO));
1682 self.set_size(app, size);
1683 }
1684 }
1685 }
1686
1687 fn paint(
1688 self: RenderHandle<Self>,
1689 app: &mut App,
1690 context: &mut PaintingContext,
1691 offset: Offset,
1692 ) {
1693 RenderShiftedBox::paint(self, app, context, offset);
1694 }
1695
1696 fn visit_children(
1697 self: RenderHandle<Self>,
1698 app: &App,
1699 visitor: &mut dyn FnMut(AnyRenderObject),
1700 ) {
1701 if let Some(child) = self.child(app) {
1702 visitor(child.as_object());
1703 }
1704 }
1705}
1706
1707impl RenderBox for RenderFractionallySizedOverflowBox {
1708 crate::render_box_accessors!();
1709
1710 fn hit_test_children(
1711 self: RenderHandle<Self>,
1712 app: &mut App,
1713 result: &mut BoxHitTestResult<'_>,
1714 position: Offset,
1715 ) -> bool {
1716 RenderShiftedBox::hit_test_children(self, app, result, position)
1717 }
1718
1719 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1720 let (width_factor, height_factor) = {
1721 let this = self.get(app);
1722 (this.width_factor, this.height_factor)
1723 };
1724 let result = match self.child(app) {
1725 Some(child) => {
1727 child.get_min_intrinsic_width(app, height * height_factor.unwrap_or(1.0))
1728 }
1729 None => RenderShiftedBox::compute_min_intrinsic_width(self, app, height),
1730 };
1731 debug_assert!(result.is_finite());
1732 result / width_factor.unwrap_or(1.0)
1733 }
1734
1735 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1736 let (width_factor, height_factor) = {
1737 let this = self.get(app);
1738 (this.width_factor, this.height_factor)
1739 };
1740 let result = match self.child(app) {
1741 Some(child) => {
1742 child.get_max_intrinsic_width(app, height * height_factor.unwrap_or(1.0))
1743 }
1744 None => RenderShiftedBox::compute_max_intrinsic_width(self, app, height),
1745 };
1746 debug_assert!(result.is_finite());
1747 result / width_factor.unwrap_or(1.0)
1748 }
1749
1750 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1751 let (width_factor, height_factor) = {
1752 let this = self.get(app);
1753 (this.width_factor, this.height_factor)
1754 };
1755 let result = match self.child(app) {
1756 Some(child) => child.get_min_intrinsic_height(app, width * width_factor.unwrap_or(1.0)),
1757 None => RenderShiftedBox::compute_min_intrinsic_height(self, app, width),
1758 };
1759 debug_assert!(result.is_finite());
1760 result / height_factor.unwrap_or(1.0)
1761 }
1762
1763 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1764 let (width_factor, height_factor) = {
1765 let this = self.get(app);
1766 (this.width_factor, this.height_factor)
1767 };
1768 let result = match self.child(app) {
1769 Some(child) => child.get_max_intrinsic_height(app, width * width_factor.unwrap_or(1.0)),
1770 None => RenderShiftedBox::compute_max_intrinsic_height(self, app, width),
1771 };
1772 debug_assert!(result.is_finite());
1773 result / height_factor.unwrap_or(1.0)
1774 }
1775
1776 fn compute_distance_to_actual_baseline(
1777 self: RenderHandle<Self>,
1778 app: &mut App,
1779 baseline: TextBaseline,
1780 ) -> Option<f64> {
1781 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
1782 }
1783
1784 fn compute_dry_layout(
1785 self: RenderHandle<Self>,
1786 app: &mut App,
1787 constraints: BoxConstraints,
1788 ) -> Size {
1789 let inner = self.get_inner_constraints(app, constraints);
1790 match self.child(app) {
1791 Some(child) => {
1792 let child_size = child.get_dry_layout(app, inner);
1793 constraints.constrain(child_size)
1794 }
1795 None => constraints.constrain(inner.constrain(Size::ZERO)),
1796 }
1797 }
1798
1799 fn compute_dry_baseline(
1800 self: RenderHandle<Self>,
1801 app: &mut App,
1802 constraints: BoxConstraints,
1803 baseline: TextBaseline,
1804 ) -> Option<f64> {
1805 let child = self.child(app)?;
1806 let child_constraints = self.get_inner_constraints(app, constraints);
1807 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
1808 let child_size = child.get_dry_layout(app, child_constraints);
1809 let size = self.get_dry_layout(app, constraints);
1810 Some(
1811 result
1812 + self
1813 .resolved_alignment(app)
1814 .along_offset(size - child_size)
1815 .dy(),
1816 )
1817 }
1818}
1819
1820pub struct RenderBaseline {
1834 render_object: RenderObjectData,
1835 render_box: RenderBoxData,
1836 child: RenderObjectWithChildData<AnyRenderBox>,
1837 baseline: f64,
1838 baseline_type: TextBaseline,
1839}
1840
1841struct BaselineSizes {
1843 size: Size,
1844 top: f64,
1845}
1846
1847impl RenderBaseline {
1848 pub fn new(
1850 app: &mut App,
1851 baseline: f64,
1852 baseline_type: TextBaseline,
1853 child: Option<AnyRenderBox>,
1854 ) -> RenderHandle<Self> {
1855 let this = RenderHandle::new_box(
1856 app,
1857 RenderBaseline {
1858 render_object: RenderObjectData::new(),
1859 render_box: RenderBoxData::new(),
1860 child: RenderObjectWithChildData::new(),
1861 baseline,
1862 baseline_type,
1863 },
1864 );
1865 this.set_child(app, child);
1866 this
1867 }
1868
1869 pub fn baseline(self: RenderHandle<Self>, app: &App) -> f64 {
1872 self.get(app).baseline
1873 }
1874
1875 pub fn set_baseline(self: RenderHandle<Self>, app: &mut App, value: f64) {
1877 if self.get(app).baseline == value {
1878 return;
1879 }
1880 self.get_mut(app).baseline = value;
1881 self.mark_needs_layout(app);
1882 }
1883
1884 pub fn baseline_type(self: RenderHandle<Self>, app: &App) -> TextBaseline {
1886 self.get(app).baseline_type
1887 }
1888
1889 pub fn set_baseline_type(self: RenderHandle<Self>, app: &mut App, value: TextBaseline) {
1891 if self.get(app).baseline_type == value {
1892 return;
1893 }
1894 self.get_mut(app).baseline_type = value;
1895 self.mark_needs_layout(app);
1896 }
1897
1898 fn compute_sizes(
1900 self: RenderHandle<Self>,
1901 app: &mut App,
1902 constraints: BoxConstraints,
1903 layout_child: ChildLayouter,
1904 get_baseline: ChildBaselineGetter,
1905 ) -> BaselineSizes {
1906 let Some(child) = self.child(app) else {
1907 return BaselineSizes {
1908 size: constraints.smallest(),
1909 top: 0.0,
1910 };
1911 };
1912 let child_constraints = constraints.loosen();
1913 let child_size = layout_child(app, child, child_constraints);
1914 let baseline_type = self.baseline_type(app);
1915 let child_baseline = get_baseline(app, child, child_constraints, baseline_type)
1916 .unwrap_or(child_size.height());
1917 let top = self.baseline(app) - child_baseline;
1918 BaselineSizes {
1919 size: constraints.constrain(Size::new(child_size.width(), top + child_size.height())),
1920 top,
1921 }
1922 }
1923}
1924
1925impl RenderObjectWithChildMixin for RenderBaseline {
1926 type ChildType = AnyRenderBox;
1927
1928 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1929 &self.get(app).child
1930 }
1931
1932 fn child_data_mut(
1933 self: RenderHandle<Self>,
1934 app: &mut App,
1935 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1936 &mut self.get_mut(app).child
1937 }
1938}
1939
1940impl RenderShiftedBox for RenderBaseline {}
1941
1942impl RenderObject for RenderBaseline {
1943 crate::render_object_accessors!();
1944
1945 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1946 let constraints = self.constraints(app);
1947 let sizes = self.compute_sizes(
1948 app,
1949 constraints,
1950 ChildLayoutHelper::layout_child,
1951 ChildLayoutHelper::get_baseline,
1952 );
1953 self.set_size(app, sizes.size);
1954 if let Some(child) = self.child(app) {
1955 child.parent_data_of_mut::<BoxParentData>(app).offset = Offset::new(0.0, sizes.top);
1956 }
1957 }
1958
1959 fn paint(
1960 self: RenderHandle<Self>,
1961 app: &mut App,
1962 context: &mut PaintingContext,
1963 offset: Offset,
1964 ) {
1965 RenderShiftedBox::paint(self, app, context, offset);
1966 }
1967
1968 fn visit_children(
1969 self: RenderHandle<Self>,
1970 app: &App,
1971 visitor: &mut dyn FnMut(AnyRenderObject),
1972 ) {
1973 if let Some(child) = self.child(app) {
1974 visitor(child.as_object());
1975 }
1976 }
1977}
1978
1979impl RenderBox for RenderBaseline {
1980 crate::render_box_accessors!();
1981
1982 fn hit_test_children(
1983 self: RenderHandle<Self>,
1984 app: &mut App,
1985 result: &mut BoxHitTestResult<'_>,
1986 position: Offset,
1987 ) -> bool {
1988 RenderShiftedBox::hit_test_children(self, app, result, position)
1989 }
1990
1991 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1992 RenderShiftedBox::compute_min_intrinsic_width(self, app, height)
1993 }
1994
1995 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1996 RenderShiftedBox::compute_max_intrinsic_width(self, app, height)
1997 }
1998
1999 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2000 RenderShiftedBox::compute_min_intrinsic_height(self, app, width)
2001 }
2002
2003 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2004 RenderShiftedBox::compute_max_intrinsic_height(self, app, width)
2005 }
2006
2007 fn compute_distance_to_actual_baseline(
2008 self: RenderHandle<Self>,
2009 app: &mut App,
2010 baseline: TextBaseline,
2011 ) -> Option<f64> {
2012 RenderShiftedBox::compute_distance_to_actual_baseline(self, app, baseline)
2013 }
2014
2015 fn compute_dry_layout(
2016 self: RenderHandle<Self>,
2017 app: &mut App,
2018 constraints: BoxConstraints,
2019 ) -> Size {
2020 self.compute_sizes(
2021 app,
2022 constraints,
2023 ChildLayoutHelper::dry_layout_child,
2024 ChildLayoutHelper::get_dry_baseline,
2025 )
2026 .size
2027 }
2028
2029 fn compute_dry_baseline(
2030 self: RenderHandle<Self>,
2031 app: &mut App,
2032 constraints: BoxConstraints,
2033 baseline: TextBaseline,
2034 ) -> Option<f64> {
2035 let child = self.child(app)?;
2036 let child_constraints = constraints.loosen();
2037 let baseline_type = self.baseline_type(app);
2038 let result1 = child.get_dry_baseline(app, child_constraints, baseline)?;
2039 let result2 = child.get_dry_baseline(app, child_constraints, baseline_type)?;
2040 Some(self.baseline(app) + result1 - result2)
2041 }
2042}
2043
2044pub trait SingleChildLayoutDelegate: Debug + 'static {
2059 fn relayout(&self) -> Option<&Rc<dyn Listenable>> {
2063 None
2064 }
2065
2066 fn get_size(&self, constraints: BoxConstraints) -> Size {
2070 constraints.biggest()
2071 }
2072
2073 fn get_constraints_for_child(&self, constraints: BoxConstraints) -> BoxConstraints {
2080 constraints
2081 }
2082
2083 fn get_position_for_child(&self, size: Size, child_size: Size) -> Offset {
2093 let _ = (size, child_size);
2094 Offset::ZERO
2095 }
2096
2097 fn should_relayout(&self, old_delegate: &dyn SingleChildLayoutDelegate) -> bool;
2117
2118 fn as_any(&self) -> &dyn Any;
2121}
2122
2123pub struct RenderCustomSingleChildLayoutBox {
2129 render_object: RenderObjectData,
2130 render_box: RenderBoxData,
2131 child: RenderObjectWithChildData<AnyRenderBox>,
2132 delegate: Rc<dyn SingleChildLayoutDelegate>,
2133}
2134
2135impl RenderCustomSingleChildLayoutBox {
2136 pub fn new(
2138 app: &mut App,
2139 delegate: Rc<dyn SingleChildLayoutDelegate>,
2140 child: Option<AnyRenderBox>,
2141 ) -> RenderHandle<RenderCustomSingleChildLayoutBox> {
2142 let this = RenderHandle::new_box(
2143 app,
2144 RenderCustomSingleChildLayoutBox {
2145 render_object: RenderObjectData::new(),
2146 render_box: RenderBoxData::new(),
2147 child: RenderObjectWithChildData::new(),
2148 delegate,
2149 },
2150 );
2151 this.set_child(app, child);
2152 this
2153 }
2154
2155 pub fn delegate(self: RenderHandle<Self>, app: &App) -> Rc<dyn SingleChildLayoutDelegate> {
2157 Rc::clone(&self.get(app).delegate)
2158 }
2159
2160 pub fn set_delegate(
2162 self: RenderHandle<Self>,
2163 app: &mut App,
2164 new_delegate: Rc<dyn SingleChildLayoutDelegate>,
2165 ) {
2166 let old_delegate = Rc::clone(&self.get(app).delegate);
2167 if Rc::ptr_eq(&old_delegate, &new_delegate) {
2168 return;
2169 }
2170 if new_delegate.as_any().type_id() != old_delegate.as_any().type_id()
2171 || new_delegate.should_relayout(&*old_delegate)
2172 {
2173 self.mark_needs_layout(app);
2174 }
2175 self.get_mut(app).delegate = Rc::clone(&new_delegate);
2176 if self.attached(app) {
2177 if let Some(relayout) = old_delegate.relayout() {
2178 relayout.remove_listener(app, &self.relayout_listener());
2179 }
2180 if let Some(relayout) = new_delegate.relayout() {
2181 relayout.add_listener(app, self.relayout_listener());
2182 }
2183 }
2184 }
2185
2186 fn relayout_listener(self: RenderHandle<Self>) -> Listener {
2188 Listener::handle_method(self.handle(), mark_needs_layout_custom_single_child)
2189 }
2190
2191 fn get_size(self: RenderHandle<Self>, app: &App, constraints: BoxConstraints) -> Size {
2193 constraints.constrain(self.get(app).delegate.get_size(constraints))
2194 }
2195}
2196
2197fn mark_needs_layout_custom_single_child(
2198 this: Handle<RenderCustomSingleChildLayoutBox>,
2199 app: &mut App,
2200) {
2201 RenderHandle::from_handle(this).mark_needs_layout(app);
2202}
2203
2204impl RenderObjectWithChildMixin for RenderCustomSingleChildLayoutBox {
2205 type ChildType = AnyRenderBox;
2206
2207 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2208 &self.get(app).child
2209 }
2210
2211 fn child_data_mut(
2212 self: RenderHandle<Self>,
2213 app: &mut App,
2214 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2215 &mut self.get_mut(app).child
2216 }
2217}
2218
2219impl RenderShiftedBox for RenderCustomSingleChildLayoutBox {}
2220
2221impl RenderObject for RenderCustomSingleChildLayoutBox {
2222 crate::render_object_accessors!();
2223
2224 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2225 let constraints = self.constraints(app);
2226 let size = self.get_size(app, constraints);
2227 self.set_size(app, size);
2228 if let Some(child) = self.child(app) {
2229 let child_constraints = self
2230 .get(app)
2231 .delegate
2232 .get_constraints_for_child(constraints);
2233 debug_assert!(child_constraints.debug_assert_is_valid(true));
2234 child.layout(app, child_constraints, !child_constraints.is_tight());
2235 let child_size = if child_constraints.is_tight() {
2236 child_constraints.smallest()
2237 } else {
2238 child.size(app)
2239 };
2240 child.parent_data_of_mut::<BoxParentData>(app).offset = self
2241 .get(app)
2242 .delegate
2243 .get_position_for_child(size, child_size);
2244 }
2245 }
2246
2247 fn paint(
2248 self: RenderHandle<Self>,
2249 app: &mut App,
2250 context: &mut PaintingContext,
2251 offset: Offset,
2252 ) {
2253 RenderShiftedBox::paint(self, app, context, offset);
2254 }
2255
2256 fn visit_children(
2257 self: RenderHandle<Self>,
2258 app: &App,
2259 visitor: &mut dyn FnMut(AnyRenderObject),
2260 ) {
2261 if let Some(child) = self.child(app) {
2262 visitor(child.as_object());
2263 }
2264 }
2265
2266 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
2267 if let Some(child) = self.child(app) {
2268 child.as_object().attach(app, owner);
2269 }
2270 if let Some(relayout) = self.delegate(app).relayout() {
2271 relayout.add_listener(app, self.relayout_listener());
2272 }
2273 }
2274
2275 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
2276 if let Some(relayout) = self.delegate(app).relayout() {
2277 relayout.remove_listener(app, &self.relayout_listener());
2278 }
2279 if let Some(child) = self.child(app) {
2280 child.as_object().detach(app);
2281 }
2282 }
2283}
2284
2285impl RenderBox for RenderCustomSingleChildLayoutBox {
2286 crate::render_box_accessors!();
2287
2288 fn hit_test_children(
2289 self: RenderHandle<Self>,
2290 app: &mut App,
2291 result: &mut BoxHitTestResult<'_>,
2292 position: Offset,
2293 ) -> bool {
2294 RenderShiftedBox::hit_test_children(self, app, result, position)
2295 }
2296
2297 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2302 let width = self
2303 .get_size(app, BoxConstraints::tight_for_finite(f64::INFINITY, height))
2304 .width();
2305 if width.is_finite() { width } else { 0.0 }
2306 }
2307
2308 fn compute_max_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_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2316 let height = self
2317 .get_size(app, BoxConstraints::tight_for_finite(width, f64::INFINITY))
2318 .height();
2319 if height.is_finite() { height } else { 0.0 }
2320 }
2321
2322 fn compute_max_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_dry_layout(
2330 self: RenderHandle<Self>,
2331 app: &mut App,
2332 constraints: BoxConstraints,
2333 ) -> Size {
2334 self.get_size(app, constraints)
2335 }
2336
2337 fn compute_dry_baseline(
2338 self: RenderHandle<Self>,
2339 app: &mut App,
2340 constraints: BoxConstraints,
2341 baseline: TextBaseline,
2342 ) -> Option<f64> {
2343 let child = self.child(app)?;
2344 let child_constraints = self
2345 .get(app)
2346 .delegate
2347 .get_constraints_for_child(constraints);
2348 let result = child.get_dry_baseline(app, child_constraints, baseline)?;
2349 let child_size = if child_constraints.is_tight() {
2350 child_constraints.smallest()
2351 } else {
2352 child.get_dry_layout(app, child_constraints)
2353 };
2354 Some(
2355 result
2356 + self
2357 .get(app)
2358 .delegate
2359 .get_position_for_child(self.get_size(app, constraints), child_size)
2360 .dy(),
2361 )
2362 }
2363}
2364
2365#[cfg(test)]
2366mod tests {
2367 use super::*;
2368 use inset_embedder::Size;
2369 use inset_foundation::AppCell;
2370
2371 use crate::box_::BoxConstraints;
2372 use crate::layer::{ContainerLayer, ErasedLayer, OffsetLayer, PictureLayer};
2373 use crate::pipeline_owner::PipelineOwner;
2374 use crate::proxy_box::{RenderConstrainedBox, RenderRepaintBoundary};
2375 use inset_embedder::valo::Op;
2376
2377 #[test]
2380 fn padding_intrinsics_add_the_insets() {
2381 let cell = AppCell::new();
2382 let mut app = cell.borrow_mut();
2383 let child =
2384 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2385 let padding = RenderPadding::new(
2386 &mut app,
2387 EdgeInsetsGeometry::all(8.0),
2388 None,
2389 Some(child.as_box()),
2390 );
2391 let padded = padding.as_box();
2392 assert_eq!(padded.get_min_intrinsic_width(&mut app, 100.0), 96.0);
2393 assert_eq!(padded.get_max_intrinsic_width(&mut app, 100.0), 96.0);
2394 assert_eq!(padded.get_min_intrinsic_height(&mut app, 100.0), 56.0);
2395 assert_eq!(padded.get_max_intrinsic_height(&mut app, 100.0), 56.0);
2396 }
2397
2398 #[test]
2400 fn padding_intrinsics_without_a_child_are_the_insets() {
2401 let cell = AppCell::new();
2402 let mut app = cell.borrow_mut();
2403 let padding = RenderPadding::new(&mut app, EdgeInsetsGeometry::all(10.0), None, None);
2404 assert_eq!(
2405 padding.as_box().get_min_intrinsic_width(&mut app, 0.0),
2406 20.0
2407 );
2408 assert_eq!(
2409 padding.as_box().get_max_intrinsic_height(&mut app, 0.0),
2410 20.0
2411 );
2412 }
2413
2414 #[test]
2416 fn padding_dry_layout_matches_its_layout() {
2417 let cell = AppCell::new();
2418 let mut app = cell.borrow_mut();
2419 let child =
2420 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2421 let padding = RenderPadding::new(
2422 &mut app,
2423 EdgeInsetsGeometry::all(8.0),
2424 None,
2425 Some(child.as_box()),
2426 );
2427 let constraints = BoxConstraints::new().max_width(500.0).max_height(500.0);
2428 let dry = padding.as_box().get_dry_layout(&mut app, constraints);
2429 padding.layout(&mut app, constraints, false);
2430 assert_eq!(dry, padding.size(&app));
2431 }
2432
2433 #[test]
2437 fn constraints_transform_box_leaves_the_child_unconstrained_and_aligns_it() {
2438 let cell = AppCell::new();
2439 let mut app = cell.borrow_mut();
2440 let child =
2441 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(50.0, 20.0)), None);
2442 let unconstrained = RenderConstraintsTransformBox::new(
2443 &mut app,
2444 AlignmentGeometry::CENTER,
2445 None,
2446 |_| BoxConstraints::new(),
2447 Some(child.as_box()),
2448 );
2449 unconstrained.layout(
2450 &mut app,
2451 BoxConstraints::tight(Size::new(100.0, 100.0)),
2452 false,
2453 );
2454 assert_eq!(child.size(&app), Size::new(50.0, 20.0));
2455 assert_eq!(unconstrained.size(&app), Size::new(100.0, 100.0));
2456 assert_eq!(
2457 child.as_box().box_parent_data(&app).offset,
2458 Offset::new(25.0, 40.0)
2459 );
2460 }
2461
2462 #[test]
2464 fn constraints_transform_box_clips_an_overflowing_child() {
2465 let cell = AppCell::new();
2466 let mut app = cell.borrow_mut();
2467 let child = RenderConstrainedBox::new(
2468 &mut app,
2469 BoxConstraints::tight(Size::new(200.0, 200.0)),
2470 None,
2471 );
2472 let unconstrained = RenderConstraintsTransformBox::new(
2473 &mut app,
2474 AlignmentGeometry::CENTER,
2475 None,
2476 |_| BoxConstraints::new(),
2477 Some(child.as_box()),
2478 );
2479 unconstrained.set_clip_behavior(&mut app, Clip::HardEdge);
2480 let root = RenderRepaintBoundary::new(&mut app, Some(unconstrained.as_box()));
2481 let owner = PipelineOwner::new(&mut app, None);
2482 owner.set_root_node(&mut app, Some(root.as_object()));
2483 root.layout(
2484 &mut app,
2485 BoxConstraints::tight(Size::new(100.0, 100.0)),
2486 false,
2487 );
2488 let paint_root = OffsetLayer::new(&mut app, Offset::ZERO);
2489 paint_root
2490 .as_layer()
2491 .attach(&mut app, root.as_object().id());
2492 root.as_object()
2493 .schedule_initial_paint(&mut app, paint_root.as_container_layer());
2494 owner.flush_compositing_bits(&mut app);
2495 owner.flush_paint(&mut app);
2496
2497 assert_eq!(unconstrained.size(&app), Size::new(100.0, 100.0));
2498 let layer = root.as_object().debug_layer(&app).expect("painted");
2499 let clipped = layer
2500 .depth_first_iterate_children(&app)
2501 .into_iter()
2502 .filter_map(|child| {
2503 app.handle::<PictureLayer>(child.id())
2504 .and_then(|picture| picture.picture(&app).map(|p| p.ops().to_vec()))
2505 })
2506 .flatten()
2507 .any(|op| matches!(op, Op::ClipPath { .. }));
2508 assert!(clipped, "the overflowing child is clipped");
2509 }
2510
2511 #[test]
2513 fn constrained_overflow_box_sizes_itself_to_the_parent() {
2514 let cell = AppCell::new();
2515 let mut app = cell.borrow_mut();
2516 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::new(), None);
2517 let overflow = RenderConstrainedOverflowBox::new(
2518 &mut app,
2519 AlignmentGeometry::CENTER,
2520 None,
2521 Some(child.as_box()),
2522 );
2523 overflow.set_min_width(&mut app, Some(200.0));
2524 overflow.set_max_width(&mut app, Some(200.0));
2525 overflow.layout(
2526 &mut app,
2527 BoxConstraints::tight(Size::new(100.0, 100.0)),
2528 false,
2529 );
2530 assert_eq!(overflow.size(&app), Size::new(100.0, 100.0));
2531 assert_eq!(child.size(&app).width(), 200.0);
2532 assert_eq!(
2533 child.as_box().box_parent_data(&app).offset.dx(),
2534 -50.0,
2535 "the child is centered, so it overflows both sides"
2536 );
2537 }
2538
2539 #[test]
2542 fn sized_overflow_box_takes_its_requested_size() {
2543 let cell = AppCell::new();
2544 let mut app = cell.borrow_mut();
2545 let child =
2546 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(30.0, 30.0)), None);
2547 let sized = RenderSizedOverflowBox::new(
2548 &mut app,
2549 Size::new(50.0, 50.0),
2550 AlignmentGeometry::CENTER,
2551 None,
2552 Some(child.as_box()),
2553 );
2554 sized.layout(&mut app, BoxConstraints::new().max_width(100.0), false);
2555 assert_eq!(sized.size(&app), Size::new(50.0, 50.0));
2556 assert_eq!(sized.as_box().get_min_intrinsic_width(&mut app, 0.0), 50.0);
2557 assert_eq!(sized.as_box().get_max_intrinsic_height(&mut app, 0.0), 50.0);
2558 }
2559
2560 #[test]
2563 fn fractionally_sized_box_tightens_the_child_to_a_fraction() {
2564 let cell = AppCell::new();
2565 let mut app = cell.borrow_mut();
2566 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::new(), None);
2567 let fraction = RenderFractionallySizedOverflowBox::new(
2568 &mut app,
2569 AlignmentGeometry::CENTER,
2570 None,
2571 Some(child.as_box()),
2572 );
2573 fraction.set_width_factor(&mut app, Some(0.5));
2574 fraction.layout(
2575 &mut app,
2576 BoxConstraints::new().max_width(200.0).max_height(80.0),
2577 false,
2578 );
2579 assert_eq!(child.size(&app).width(), 100.0);
2580 assert_eq!(fraction.size(&app).width(), 100.0);
2581 }
2582
2583 #[test]
2586 fn baseline_shifts_the_child_down_to_its_baseline() {
2587 let cell = AppCell::new();
2588 let mut app = cell.borrow_mut();
2589 let child =
2590 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2591 let baseline = RenderBaseline::new(
2592 &mut app,
2593 30.0,
2594 TextBaseline::Alphabetic,
2595 Some(child.as_box()),
2596 );
2597 baseline.layout(&mut app, BoxConstraints::new(), false);
2598 assert_eq!(
2600 child.as_box().box_parent_data(&app).offset,
2601 Offset::new(0.0, 10.0)
2602 );
2603 assert_eq!(baseline.size(&app), Size::new(20.0, 30.0));
2604 }
2605
2606 #[test]
2607 fn padding_around_tight_child() {
2608 let cell = AppCell::new();
2609 let mut app = cell.borrow_mut();
2610 let child =
2611 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
2612 let padding = RenderPadding::new(
2613 &mut app,
2614 EdgeInsetsGeometry::all(8.0),
2615 None,
2616 Some(child.as_box()),
2617 );
2618 padding.layout(&mut app, BoxConstraints::new(), false);
2619 assert_eq!(child.size(&app), Size::new(80.0, 40.0));
2620 assert_eq!(padding.size(&app), Size::new(96.0, 56.0));
2621 assert_eq!(
2622 child.as_box().box_parent_data(&app).offset,
2623 Offset::new(8.0, 8.0)
2624 );
2625 }
2626
2627 #[test]
2628 fn positioned_box_centers_its_child() {
2629 let cell = AppCell::new();
2630 let mut app = cell.borrow_mut();
2631 let child =
2632 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2633 let positioned = RenderPositionedBox::new(
2634 &mut app,
2635 AlignmentGeometry::CENTER,
2636 None,
2637 None,
2638 None,
2639 Some(child.as_box()),
2640 );
2641 positioned.layout(
2642 &mut app,
2643 BoxConstraints::tight(Size::new(100.0, 100.0)),
2644 false,
2645 );
2646 assert_eq!(positioned.size(&app), Size::new(100.0, 100.0));
2647 assert_eq!(
2648 child.as_box().box_parent_data(&app).offset,
2649 Offset::new(40.0, 40.0)
2650 );
2651 }
2652
2653 #[test]
2654 fn positioned_box_shrink_wraps_with_a_factor() {
2655 let cell = AppCell::new();
2656 let mut app = cell.borrow_mut();
2657 let child =
2658 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)), None);
2659 let positioned = RenderPositionedBox::new(
2660 &mut app,
2661 AlignmentGeometry::CENTER,
2662 None,
2663 Some(2.0),
2664 None,
2665 Some(child.as_box()),
2666 );
2667 positioned.layout(
2668 &mut app,
2669 BoxConstraints::new().max_width(100.0).max_height(100.0),
2670 false,
2671 );
2672 assert_eq!(positioned.size(&app), Size::new(40.0, 100.0));
2673 assert_eq!(
2674 child.as_box().box_parent_data(&app).offset,
2675 Offset::new(10.0, 40.0)
2676 );
2677 }
2678
2679 #[test]
2680 fn padding_without_child() {
2681 let cell = AppCell::new();
2682 let mut app = cell.borrow_mut();
2683 let padding = RenderPadding::new(&mut app, EdgeInsetsGeometry::all(10.0), None, None);
2684 padding.layout(
2685 &mut app,
2686 BoxConstraints::tight(Size::new(100.0, 100.0)),
2687 false,
2688 );
2689 assert_eq!(padding.size(&app), Size::new(100.0, 100.0));
2690 }
2691
2692 #[derive(Debug)]
2693 struct OffsetDelegate {
2694 offset: Offset,
2695 }
2696
2697 impl SingleChildLayoutDelegate for OffsetDelegate {
2698 fn get_size(&self, constraints: BoxConstraints) -> Size {
2699 constraints.biggest()
2700 }
2701
2702 fn get_constraints_for_child(&self, constraints: BoxConstraints) -> BoxConstraints {
2703 constraints.loosen()
2704 }
2705
2706 fn get_position_for_child(&self, _size: Size, _child_size: Size) -> Offset {
2707 self.offset
2708 }
2709
2710 fn should_relayout(&self, old_delegate: &dyn SingleChildLayoutDelegate) -> bool {
2711 old_delegate
2712 .as_any()
2713 .downcast_ref::<OffsetDelegate>()
2714 .is_none_or(|old| old.offset != self.offset)
2715 }
2716
2717 fn as_any(&self) -> &dyn Any {
2718 self
2719 }
2720 }
2721
2722 #[test]
2723 fn custom_single_child_layout_positions_the_child() {
2724 let cell = AppCell::new();
2725 let mut app = cell.borrow_mut();
2726 let child =
2727 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(20.0, 10.0)), None);
2728 let parent = RenderCustomSingleChildLayoutBox::new(
2729 &mut app,
2730 Rc::new(OffsetDelegate {
2731 offset: Offset::new(8.0, 4.0),
2732 }),
2733 Some(child.as_box()),
2734 );
2735 parent.layout(
2736 &mut app,
2737 BoxConstraints::tight(Size::new(100.0, 50.0)),
2738 false,
2739 );
2740 assert_eq!(parent.size(&app), Size::new(100.0, 50.0));
2741 assert_eq!(
2742 child.as_box().box_parent_data(&app).offset,
2743 Offset::new(8.0, 4.0)
2744 );
2745 }
2746}