1use cranpose_ui_layout::{
2 Axis, Constraints, MeasurePolicy, MeasureResult, MeasureScope, ParentData, Placement,
3 bias_offset,
4};
5use smallvec::SmallVec;
6
7use crate::layout::core::{
8 Alignment, Arrangement, HorizontalAlignment, LinearArrangement, Measurable, VerticalAlignment,
9};
10
11#[derive(Clone, Debug, PartialEq)]
13pub struct BoxMeasurePolicy {
14 pub content_alignment: Alignment,
15 pub propagate_min_constraints: bool,
16}
17
18impl BoxMeasurePolicy {
19 pub fn new(content_alignment: Alignment, propagate_min_constraints: bool) -> Self {
20 Self {
21 content_alignment,
22 propagate_min_constraints,
23 }
24 }
25}
26
27impl MeasurePolicy for BoxMeasurePolicy {
28 fn measure(
29 &self,
30 scope: &dyn MeasureScope,
31 measurables: &[Box<dyn Measurable>],
32 constraints: Constraints,
33 ) -> MeasureResult {
34 let mut placements = Vec::new();
35 let size = self.measure_into(scope, measurables, constraints, &mut placements);
36 MeasureResult::new(size, placements)
37 }
38
39 fn measure_into(
40 &self,
41 scope: &dyn MeasureScope,
42 measurables: &[Box<dyn Measurable>],
43 constraints: Constraints,
44 placements: &mut Vec<Placement>,
45 ) -> crate::modifier::Size {
46 placements.clear();
47 let child_constraints = if self.propagate_min_constraints {
48 constraints
49 } else {
50 Constraints {
51 min_width: 0.0,
52 max_width: constraints.max_width,
53 min_height: 0.0,
54 max_height: constraints.max_height,
55 }
56 };
57
58 let mut max_width = 0.0_f32;
59 let mut max_height = 0.0_f32;
60 let mut placeables: SmallVec<[(cranpose_ui_layout::Placeable, Alignment); 8]> =
61 SmallVec::new();
62
63 for measurable in measurables {
64 let placeable = measurable.measure(child_constraints);
65 max_width = max_width.max(placeable.width());
66 max_height = max_height.max(placeable.height());
67 let alignment = measurable
68 .parent_data()
69 .box_alignment
70 .unwrap_or(self.content_alignment);
71 placeables.push((placeable, alignment));
72 }
73
74 let width = max_width.clamp(constraints.min_width, constraints.max_width);
75 let height = max_height.clamp(constraints.min_height, constraints.max_height);
76
77 placements.reserve(placeables.len());
78 for (placeable, alignment) in placeables {
79 let child_width = placeable.width();
80 let child_height = placeable.height();
81
82 let x = alignment
83 .horizontal
84 .align(width, child_width, scope.density());
85 let y = alignment
86 .vertical
87 .align(height, child_height, scope.density());
88
89 placeable.place(x, y);
90 placements.push(Placement::new(placeable.node_id(), x, y, 0));
91 }
92
93 crate::modifier::Size { width, height }
94 }
95
96 fn min_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
97 measurables
98 .iter()
99 .map(|m| m.min_intrinsic_width(height))
100 .fold(0.0, f32::max)
101 }
102
103 fn max_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
104 measurables
105 .iter()
106 .map(|m| m.max_intrinsic_width(height))
107 .fold(0.0, f32::max)
108 }
109
110 fn min_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
111 measurables
112 .iter()
113 .map(|m| m.min_intrinsic_height(width))
114 .fold(0.0, f32::max)
115 }
116
117 fn max_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
118 measurables
119 .iter()
120 .map(|m| m.max_intrinsic_height(width))
121 .fold(0.0, f32::max)
122 }
123}
124
125#[derive(Clone, Debug, PartialEq)]
163pub struct FlexMeasurePolicy {
164 pub axis: Axis,
166 pub main_axis_arrangement: LinearArrangement,
168 pub cross_axis_alignment: CrossAxisAlignment,
170 pub density: f32,
173}
174
175pub(crate) struct WeightShares {
179 density: f32,
180 unit_px: f32,
181 remainder_px: f32,
182}
183
184impl WeightShares {
185 pub(crate) fn new(
186 remaining: f32,
187 weights: impl Iterator<Item = f32> + Clone,
188 density: f32,
189 ) -> Self {
190 let density = if density > 0.0 && density.is_finite() {
191 density
192 } else {
193 1.0
194 };
195 let total_weight: f32 = weights.clone().sum();
196 let remaining_px = (remaining * density).round();
197 let unit_px = if total_weight > 0.0 {
198 remaining_px / total_weight
199 } else {
200 0.0
201 };
202 let rounded_px: f32 = weights.map(|weight| (unit_px * weight + 0.5).floor()).sum();
203 Self {
204 density,
205 unit_px,
206 remainder_px: remaining_px - rounded_px,
207 }
208 }
209
210 pub(crate) fn next_share(&mut self, weight: f32) -> f32 {
212 let step = if self.remainder_px > 0.0 {
213 1.0
214 } else if self.remainder_px < 0.0 {
215 -1.0
216 } else {
217 0.0
218 };
219 self.remainder_px -= step;
220 ((self.unit_px * weight + 0.5).floor() + step).max(0.0) / self.density
221 }
222}
223
224#[derive(Clone, Copy, Debug, PartialEq)]
227pub enum CrossAxisAlignment {
228 Start,
230 Center,
232 End,
234}
235
236impl CrossAxisAlignment {
237 fn align(&self, available: f32, child: f32, density: f32) -> f32 {
239 let bias = match self {
240 CrossAxisAlignment::Start => -1.0,
241 CrossAxisAlignment::Center => 0.0,
242 CrossAxisAlignment::End => 1.0,
243 };
244 bias_offset(bias, available, child, density)
245 }
246}
247
248impl From<HorizontalAlignment> for CrossAxisAlignment {
249 fn from(alignment: HorizontalAlignment) -> Self {
250 match alignment {
251 HorizontalAlignment::Start => CrossAxisAlignment::Start,
252 HorizontalAlignment::CenterHorizontally => CrossAxisAlignment::Center,
253 HorizontalAlignment::End => CrossAxisAlignment::End,
254 }
255 }
256}
257
258impl From<VerticalAlignment> for CrossAxisAlignment {
259 fn from(alignment: VerticalAlignment) -> Self {
260 match alignment {
261 VerticalAlignment::Top => CrossAxisAlignment::Start,
262 VerticalAlignment::CenterVertically => CrossAxisAlignment::Center,
263 VerticalAlignment::Bottom => CrossAxisAlignment::End,
264 }
265 }
266}
267
268impl FlexMeasurePolicy {
269 pub fn new(
271 axis: Axis,
272 main_axis_arrangement: LinearArrangement,
273 cross_axis_alignment: CrossAxisAlignment,
274 density: f32,
275 ) -> Self {
276 Self {
277 axis,
278 main_axis_arrangement,
279 cross_axis_alignment,
280 density,
281 }
282 }
283
284 pub fn row(
286 horizontal_arrangement: LinearArrangement,
287 vertical_alignment: VerticalAlignment,
288 density: f32,
289 ) -> Self {
290 Self::new(
291 Axis::Horizontal,
292 horizontal_arrangement,
293 vertical_alignment.into(),
294 density,
295 )
296 }
297
298 pub fn column(
300 vertical_arrangement: LinearArrangement,
301 horizontal_alignment: HorizontalAlignment,
302 density: f32,
303 ) -> Self {
304 Self::new(
305 Axis::Vertical,
306 vertical_arrangement,
307 horizontal_alignment.into(),
308 density,
309 )
310 }
311
312 fn get_axis_constraints(&self, constraints: Constraints) -> (f32, f32, f32, f32) {
313 match self.axis {
314 Axis::Horizontal => (
315 constraints.min_width,
316 constraints.max_width,
317 constraints.min_height,
318 constraints.max_height,
319 ),
320 Axis::Vertical => (
321 constraints.min_height,
322 constraints.max_height,
323 constraints.min_width,
324 constraints.max_width,
325 ),
326 }
327 }
328
329 fn make_constraints(
330 &self,
331 min_main: f32,
332 max_main: f32,
333 min_cross: f32,
334 max_cross: f32,
335 ) -> Constraints {
336 match self.axis {
337 Axis::Horizontal => Constraints {
338 min_width: min_main,
339 max_width: max_main,
340 min_height: min_cross,
341 max_height: max_cross,
342 },
343 Axis::Vertical => Constraints {
344 min_width: min_cross,
345 max_width: max_cross,
346 min_height: min_main,
347 max_height: max_main,
348 },
349 }
350 }
351
352 fn get_main_axis_size(&self, width: f32, height: f32) -> f32 {
353 match self.axis {
354 Axis::Horizontal => width,
355 Axis::Vertical => height,
356 }
357 }
358
359 fn get_cross_axis_size(&self, width: f32, height: f32) -> f32 {
360 match self.axis {
361 Axis::Horizontal => height,
362 Axis::Vertical => width,
363 }
364 }
365
366 fn measure_fixed_children(
372 &self,
373 measurables: &[Box<dyn Measurable>],
374 fixed_children: &[usize],
375 (max_main, max_cross): (f32, f32),
376 spacing: f32,
377 placeables: &mut [Option<cranpose_ui_layout::Placeable>],
378 ) -> (f32, f32) {
379 let main_axis_bounded = max_main.is_finite();
380 let mut fixed_space = 0.0_f32;
381 let mut max_cross_size = 0.0_f32;
382 for &idx in fixed_children {
383 let available_main = if main_axis_bounded {
384 (max_main - fixed_space).max(0.0)
385 } else {
386 max_main
387 };
388 let placeable = measurables[idx].measure(self.make_constraints(
389 0.0,
390 available_main,
391 0.0,
392 max_cross,
393 ));
394 let main_size = self.get_main_axis_size(placeable.width(), placeable.height());
395 let spacing_after = if main_axis_bounded {
396 spacing.min(available_main - main_size).max(0.0)
397 } else {
398 spacing
399 };
400 fixed_space += main_size + spacing_after;
401 max_cross_size =
402 max_cross_size.max(self.get_cross_axis_size(placeable.width(), placeable.height()));
403 placeables[idx] = Some(placeable);
404 }
405 (fixed_space, max_cross_size)
406 }
407
408 fn get_spacing(&self) -> f32 {
409 self.main_axis_arrangement.spacing(self.density)
410 }
411}
412
413impl MeasurePolicy for FlexMeasurePolicy {
414 fn measure(
415 &self,
416 scope: &dyn MeasureScope,
417 measurables: &[Box<dyn Measurable>],
418 constraints: Constraints,
419 ) -> MeasureResult {
420 let mut placements = Vec::new();
421 let size = self.measure_into(scope, measurables, constraints, &mut placements);
422 MeasureResult::new(size, placements)
423 }
424
425 fn measure_into(
426 &self,
427 _scope: &dyn MeasureScope,
428 measurables: &[Box<dyn Measurable>],
429 constraints: Constraints,
430 placements: &mut Vec<Placement>,
431 ) -> crate::modifier::Size {
432 placements.clear();
433 if measurables.is_empty() {
434 let (width, height) = constraints.constrain(0.0, 0.0);
435 return crate::modifier::Size { width, height };
436 }
437
438 let (min_main, max_main, min_cross, max_cross) = self.get_axis_constraints(constraints);
439 let main_axis_bounded = max_main.is_finite();
440 let spacing = self.get_spacing();
441
442 let mut fixed_children: SmallVec<[usize; 8]> = SmallVec::new();
443 let parent_data: SmallVec<[ParentData; 8]> = measurables
444 .iter()
445 .map(|child| child.parent_data())
446 .collect();
447 let mut weighted_children: SmallVec<[(usize, ParentData); 8]> = SmallVec::new();
448
449 for (idx, data) in parent_data.iter().copied().enumerate() {
450 if data.has_weight() {
451 weighted_children.push((idx, data));
452 } else {
453 fixed_children.push(idx);
454 }
455 }
456
457 let child_constraints = self.make_constraints(0.0, max_main, 0.0, max_cross);
458
459 let mut placeables: SmallVec<[Option<cranpose_ui_layout::Placeable>; 8]> = SmallVec::new();
460 placeables.resize_with(measurables.len(), || None);
461 let (fixed_space, mut max_cross_size) = self.measure_fixed_children(
462 measurables,
463 &fixed_children,
464 (max_main, max_cross),
465 spacing,
466 &mut placeables,
467 );
468
469 let num_children = measurables.len();
470 let total_spacing = if num_children > 1 {
471 spacing * (num_children - 1) as f32
472 } else {
473 0.0
474 };
475
476 if !weighted_children.is_empty() {
477 if main_axis_bounded {
478 let weighted_spacing = spacing * (weighted_children.len() - 1) as f32;
479 let remaining_main = (max_main - fixed_space - weighted_spacing).max(0.0);
480
481 let mut shares = WeightShares::new(
482 remaining_main,
483 weighted_children.iter().map(|(_, data)| data.weight),
484 self.density,
485 );
486
487 for &(idx, parent_data) in &weighted_children {
488 let measurable = &measurables[idx];
489 let allocated = shares.next_share(parent_data.weight);
490
491 let weighted_constraints = if parent_data.fill {
492 self.make_constraints(allocated, allocated, 0.0, max_cross)
493 } else {
494 self.make_constraints(0.0, allocated, 0.0, max_cross)
495 };
496
497 let placeable = measurable.measure(weighted_constraints);
498 let cross_size =
499 self.get_cross_axis_size(placeable.width(), placeable.height());
500 max_cross_size = max_cross_size.max(cross_size);
501 placeables[idx] = Some(placeable);
502 }
503 } else {
504 for &(idx, _) in &weighted_children {
505 let measurable = &measurables[idx];
506 let placeable = measurable.measure(child_constraints);
507 let cross_size =
508 self.get_cross_axis_size(placeable.width(), placeable.height());
509 max_cross_size = max_cross_size.max(cross_size);
510 placeables[idx] = Some(placeable);
511 }
512 }
513 }
514
515 let placeables: SmallVec<[cranpose_ui_layout::Placeable; 8]> = placeables
516 .into_iter()
517 .enumerate()
518 .map(|(idx, placeable)| {
519 placeable.unwrap_or_else(|| measurables[idx].measure(child_constraints))
520 })
521 .collect();
522
523 let total_main: f32 = placeables
524 .iter()
525 .map(|p| self.get_main_axis_size(p.width(), p.height()))
526 .sum::<f32>()
527 + total_spacing;
528
529 let container_main = total_main.clamp(min_main, max_main);
530 let container_cross = max_cross_size.clamp(min_cross, max_cross);
531
532 let child_main_sizes: SmallVec<[f32; 8]> = placeables
533 .iter()
534 .map(|p| self.get_main_axis_size(p.width(), p.height()))
535 .collect();
536
537 let mut main_positions: SmallVec<[f32; 8]> =
538 SmallVec::with_capacity(child_main_sizes.len());
539 main_positions.resize(child_main_sizes.len(), 0.0);
540
541 let arrangement = if total_main > container_main
542 && !matches!(self.main_axis_arrangement, LinearArrangement::SpacedBy(_))
543 {
544 LinearArrangement::Start
545 } else {
546 self.main_axis_arrangement
547 };
548 arrangement.arrange(
549 self.density,
550 container_main,
551 &child_main_sizes,
552 &mut main_positions,
553 );
554
555 placements.reserve(placeables.len());
556 for (idx, (placeable, main_pos)) in placeables.into_iter().zip(main_positions).enumerate() {
557 let child_cross = self.get_cross_axis_size(placeable.width(), placeable.height());
558 let cross_axis_alignment = match self.axis {
559 Axis::Horizontal => parent_data[idx]
560 .row_alignment
561 .map_or(self.cross_axis_alignment, Into::into),
562 Axis::Vertical => parent_data[idx]
563 .column_alignment
564 .map_or(self.cross_axis_alignment, Into::into),
565 };
566 let cross_pos = cross_axis_alignment.align(container_cross, child_cross, self.density);
567
568 let (x, y) = match self.axis {
569 Axis::Horizontal => (main_pos, cross_pos),
570 Axis::Vertical => (cross_pos, main_pos),
571 };
572
573 placeable.place(x, y);
574 placements.push(Placement::new(placeable.node_id(), x, y, 0));
575 }
576
577 let (width, height) = match self.axis {
578 Axis::Horizontal => (container_main, container_cross),
579 Axis::Vertical => (container_cross, container_main),
580 };
581
582 crate::modifier::Size { width, height }
583 }
584
585 fn min_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
586 let spacing = self.get_spacing();
587 let total_spacing = if measurables.len() > 1 {
588 spacing * (measurables.len() - 1) as f32
589 } else {
590 0.0
591 };
592
593 match self.axis {
594 Axis::Horizontal => {
595 measurables
596 .iter()
597 .map(|m| m.min_intrinsic_width(height))
598 .sum::<f32>()
599 + total_spacing
600 }
601 Axis::Vertical => measurables
602 .iter()
603 .map(|m| m.min_intrinsic_width(height))
604 .fold(0.0, f32::max),
605 }
606 }
607
608 fn max_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
609 let spacing = self.get_spacing();
610 let total_spacing = if measurables.len() > 1 {
611 spacing * (measurables.len() - 1) as f32
612 } else {
613 0.0
614 };
615
616 match self.axis {
617 Axis::Horizontal => {
618 measurables
619 .iter()
620 .map(|m| m.max_intrinsic_width(height))
621 .sum::<f32>()
622 + total_spacing
623 }
624 Axis::Vertical => measurables
625 .iter()
626 .map(|m| m.max_intrinsic_width(height))
627 .fold(0.0, f32::max),
628 }
629 }
630
631 fn min_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
632 let spacing = self.get_spacing();
633 let total_spacing = if measurables.len() > 1 {
634 spacing * (measurables.len() - 1) as f32
635 } else {
636 0.0
637 };
638
639 match self.axis {
640 Axis::Horizontal => measurables
641 .iter()
642 .map(|m| m.min_intrinsic_height(width))
643 .fold(0.0, f32::max),
644 Axis::Vertical => {
645 measurables
646 .iter()
647 .map(|m| m.min_intrinsic_height(width))
648 .sum::<f32>()
649 + total_spacing
650 }
651 }
652 }
653
654 fn max_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
655 let spacing = self.get_spacing();
656 let total_spacing = if measurables.len() > 1 {
657 spacing * (measurables.len() - 1) as f32
658 } else {
659 0.0
660 };
661
662 match self.axis {
663 Axis::Horizontal => measurables
664 .iter()
665 .map(|m| m.max_intrinsic_height(width))
666 .fold(0.0, f32::max),
667 Axis::Vertical => {
668 measurables
669 .iter()
670 .map(|m| m.max_intrinsic_height(width))
671 .sum::<f32>()
672 + total_spacing
673 }
674 }
675 }
676}
677
678#[derive(Clone, Debug, PartialEq)]
691pub struct FlowRowMeasurePolicy {
692 pub main_axis_spacing: f32,
694 pub cross_axis_spacing: f32,
696}
697
698impl FlowRowMeasurePolicy {
699 pub fn new(main_axis_spacing: f32, cross_axis_spacing: f32) -> Self {
700 Self {
701 main_axis_spacing: main_axis_spacing.max(0.0),
702 cross_axis_spacing: cross_axis_spacing.max(0.0),
703 }
704 }
705
706 fn wrapped_intrinsic_height(
707 &self,
708 measurables: &[Box<dyn Measurable>],
709 available_width: f32,
710 use_min_height: bool,
711 ) -> f32 {
712 let mut cursor_x = 0.0_f32;
713 let mut line_top = 0.0_f32;
714 let mut line_height = 0.0_f32;
715
716 for measurable in measurables {
717 let child_width = measurable.max_intrinsic_width(f32::INFINITY);
718 let child_height = if use_min_height {
719 measurable.min_intrinsic_height(child_width)
720 } else {
721 measurable.max_intrinsic_height(child_width)
722 };
723
724 if cursor_x > 0.0 && cursor_x + self.main_axis_spacing + child_width > available_width {
725 line_top += line_height + self.cross_axis_spacing;
726 cursor_x = 0.0;
727 line_height = 0.0;
728 }
729 cursor_x += if cursor_x > 0.0 {
730 self.main_axis_spacing + child_width
731 } else {
732 child_width
733 };
734 line_height = line_height.max(child_height);
735 }
736
737 line_top + line_height
738 }
739}
740
741impl MeasurePolicy for FlowRowMeasurePolicy {
742 fn measure(
743 &self,
744 scope: &dyn MeasureScope,
745 measurables: &[Box<dyn Measurable>],
746 constraints: Constraints,
747 ) -> MeasureResult {
748 let mut placements = Vec::new();
749 let size = self.measure_into(scope, measurables, constraints, &mut placements);
750 MeasureResult::new(size, placements)
751 }
752
753 fn measure_into(
754 &self,
755 _scope: &dyn MeasureScope,
756 measurables: &[Box<dyn Measurable>],
757 constraints: Constraints,
758 placements: &mut Vec<Placement>,
759 ) -> crate::modifier::Size {
760 placements.clear();
761 if measurables.is_empty() {
762 let (width, height) = constraints.constrain(0.0, 0.0);
763 return crate::modifier::Size { width, height };
764 }
765
766 let child_constraints = Constraints {
767 min_width: 0.0,
768 max_width: constraints.max_width,
769 min_height: 0.0,
770 max_height: constraints.max_height,
771 };
772
773 let placeables: SmallVec<[cranpose_ui_layout::Placeable; 8]> = measurables
774 .iter()
775 .map(|measurable| measurable.measure(child_constraints))
776 .collect();
777
778 let mut cursor_x = 0.0_f32;
779 let mut line_top = 0.0_f32;
780 let mut line_height = 0.0_f32;
781 let mut max_line_width = 0.0_f32;
782
783 placements.reserve(placeables.len());
784 for placeable in placeables {
785 let child_width = placeable.width();
786 let child_height = placeable.height();
787
788 if cursor_x > 0.0
789 && cursor_x + self.main_axis_spacing + child_width > constraints.max_width
790 {
791 max_line_width = max_line_width.max(cursor_x);
792 line_top += line_height + self.cross_axis_spacing;
793 cursor_x = 0.0;
794 line_height = 0.0;
795 }
796
797 let x = if cursor_x > 0.0 {
798 cursor_x + self.main_axis_spacing
799 } else {
800 0.0
801 };
802 placeable.place(x, line_top);
803 placements.push(Placement::new(placeable.node_id(), x, line_top, 0));
804
805 cursor_x = x + child_width;
806 line_height = line_height.max(child_height);
807 }
808 max_line_width = max_line_width.max(cursor_x);
809
810 let width = max_line_width.clamp(constraints.min_width, constraints.max_width);
811 let height = (line_top + line_height).clamp(constraints.min_height, constraints.max_height);
812 crate::modifier::Size { width, height }
813 }
814
815 fn min_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
816 measurables
817 .iter()
818 .map(|m| m.min_intrinsic_width(height))
819 .fold(0.0, f32::max)
820 }
821
822 fn max_intrinsic_width(&self, measurables: &[Box<dyn Measurable>], height: f32) -> f32 {
823 let total_spacing = if measurables.len() > 1 {
824 self.main_axis_spacing * (measurables.len() - 1) as f32
825 } else {
826 0.0
827 };
828 measurables
829 .iter()
830 .map(|m| m.max_intrinsic_width(height))
831 .sum::<f32>()
832 + total_spacing
833 }
834
835 fn min_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
836 self.wrapped_intrinsic_height(measurables, width, true)
837 }
838
839 fn max_intrinsic_height(&self, measurables: &[Box<dyn Measurable>], width: f32) -> f32 {
840 self.wrapped_intrinsic_height(measurables, width, false)
841 }
842}
843
844#[derive(Clone, Debug, PartialEq)]
847pub struct LeafMeasurePolicy {
848 pub intrinsic_size: crate::modifier::Size,
849}
850
851impl LeafMeasurePolicy {
852 pub fn new(intrinsic_size: crate::modifier::Size) -> Self {
853 Self { intrinsic_size }
854 }
855}
856
857impl MeasurePolicy for LeafMeasurePolicy {
858 fn measure(
859 &self,
860 scope: &dyn MeasureScope,
861 _measurables: &[Box<dyn Measurable>],
862 constraints: Constraints,
863 ) -> MeasureResult {
864 let mut placements = Vec::new();
865 let size = self.measure_into(scope, &[], constraints, &mut placements);
866 MeasureResult::new(size, placements)
867 }
868
869 fn measure_into(
870 &self,
871 _scope: &dyn MeasureScope,
872 _measurables: &[Box<dyn Measurable>],
873 constraints: Constraints,
874 placements: &mut Vec<Placement>,
875 ) -> crate::modifier::Size {
876 placements.clear();
877 let (width, height) =
878 constraints.constrain(self.intrinsic_size.width, self.intrinsic_size.height);
879
880 crate::modifier::Size { width, height }
881 }
882
883 fn min_intrinsic_width(&self, _measurables: &[Box<dyn Measurable>], _height: f32) -> f32 {
884 self.intrinsic_size.width
885 }
886
887 fn max_intrinsic_width(&self, _measurables: &[Box<dyn Measurable>], _height: f32) -> f32 {
888 self.intrinsic_size.width
889 }
890
891 fn min_intrinsic_height(&self, _measurables: &[Box<dyn Measurable>], _width: f32) -> f32 {
892 self.intrinsic_size.height
893 }
894
895 fn max_intrinsic_height(&self, _measurables: &[Box<dyn Measurable>], _width: f32) -> f32 {
896 self.intrinsic_size.height
897 }
898}
899
900#[derive(Clone, Debug, PartialEq)]
906pub struct EmptyMeasurePolicy;
907
908impl EmptyMeasurePolicy {
909 pub fn new() -> Self {
910 Self
911 }
912}
913
914impl Default for EmptyMeasurePolicy {
915 fn default() -> Self {
916 Self::new()
917 }
918}
919
920impl MeasurePolicy for EmptyMeasurePolicy {
921 fn measure(
922 &self,
923 scope: &dyn MeasureScope,
924 _measurables: &[Box<dyn Measurable>],
925 constraints: Constraints,
926 ) -> MeasureResult {
927 let mut placements = Vec::new();
928 let size = self.measure_into(scope, &[], constraints, &mut placements);
929 MeasureResult::new(size, placements)
930 }
931
932 fn measure_into(
933 &self,
934 _scope: &dyn MeasureScope,
935 _measurables: &[Box<dyn Measurable>],
936 constraints: Constraints,
937 placements: &mut Vec<Placement>,
938 ) -> crate::modifier::Size {
939 placements.clear();
940 let (width, height) = constraints.constrain(0.0, 0.0);
941
942 crate::modifier::Size { width, height }
943 }
944
945 fn min_intrinsic_width(&self, _measurables: &[Box<dyn Measurable>], _height: f32) -> f32 {
946 0.0
947 }
948
949 fn max_intrinsic_width(&self, _measurables: &[Box<dyn Measurable>], _height: f32) -> f32 {
950 0.0
951 }
952
953 fn min_intrinsic_height(&self, _measurables: &[Box<dyn Measurable>], _width: f32) -> f32 {
954 0.0
955 }
956
957 fn max_intrinsic_height(&self, _measurables: &[Box<dyn Measurable>], _width: f32) -> f32 {
958 0.0
959 }
960}
961
962#[cfg(test)]
963#[path = "tests/policies_tests.rs"]
964mod tests;