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