Propagate Limits::compression in flex layout

This commit is contained in:
Héctor Ramón Jiménez 2025-08-21 06:22:22 +02:00
parent 04639a4194
commit 7711b49f6b
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 56 additions and 35 deletions

View file

@ -78,13 +78,13 @@ where
let total_spacing = spacing * items.len().saturating_sub(1) as f32; let total_spacing = spacing * items.len().saturating_sub(1) as f32;
let max_cross = axis.cross(limits.max()); let max_cross = axis.cross(limits.max());
let compression = limits.compression();
let (main_compress, cross_compress) =
axis.pack(compression.width, compression.height);
let mut fill_main_sum = 0; let mut fill_main_sum = 0;
let mut some_fill_cross = false; let mut some_fill_cross = false;
let (mut cross, cross_compress) = match axis { let mut cross = if cross_compress { 0.0 } else { max_cross };
Axis::Vertical if width == Length::Shrink => (0.0, true),
Axis::Horizontal if height == Length::Shrink => (0.0, true),
_ => (max_cross, false),
};
let mut available = axis.main(limits.max()) - total_spacing; let mut available = axis.main(limits.max()) - total_spacing;
@ -103,7 +103,8 @@ where
axis.pack(size.width.fill_factor(), size.height.fill_factor()) axis.pack(size.width.fill_factor(), size.height.fill_factor())
}; };
if fill_main_factor == 0 && (!cross_compress || fill_cross_factor == 0) if (main_compress || fill_main_factor == 0)
&& (!cross_compress || fill_cross_factor == 0)
{ {
let (max_width, max_height) = axis.pack( let (max_width, max_height) = axis.pack(
available, available,
@ -114,8 +115,11 @@ where
}, },
); );
let child_limits = let child_limits = Limits::with_compression(
Limits::new(Size::ZERO, Size::new(max_width, max_height)); Size::ZERO,
Size::new(max_width, max_height),
compression,
);
let layout = let layout =
child.as_widget_mut().layout(tree, renderer, &child_limits); child.as_widget_mut().layout(tree, renderer, &child_limits);
@ -159,8 +163,11 @@ where
let (max_width, max_height) = axis.pack(available, cross); let (max_width, max_height) = axis.pack(available, cross);
let child_limits = let child_limits = Limits::with_compression(
Limits::new(Size::ZERO, Size::new(max_width, max_height)); Size::ZERO,
Size::new(max_width, max_height),
compression,
);
let layout = let layout =
child.as_widget_mut().layout(tree, renderer, &child_limits); child.as_widget_mut().layout(tree, renderer, &child_limits);
@ -174,16 +181,7 @@ where
} }
} }
let remaining = match axis { let remaining = available.max(0.0);
Axis::Horizontal => match width {
Length::Shrink => 0.0,
_ => available.max(0.0),
},
Axis::Vertical => match height {
Length::Shrink => 0.0,
_ => available.max(0.0),
},
};
// THIRD PASS // THIRD PASS
// We lay out the elements that are fluid in the main axis. // We lay out the elements that are fluid in the main axis.
@ -196,7 +194,7 @@ where
axis.pack(size.width.fill_factor(), size.height.fill_factor()) axis.pack(size.width.fill_factor(), size.height.fill_factor())
}; };
if fill_main_factor != 0 { if !main_compress && fill_main_factor != 0 {
let max_main = let max_main =
remaining * fill_main_factor as f32 / fill_main_sum as f32; remaining * fill_main_factor as f32 / fill_main_sum as f32;
@ -222,9 +220,10 @@ where
}, },
); );
let child_limits = Limits::new( let child_limits = Limits::with_compression(
Size::new(min_width, min_height), Size::new(min_width, min_height),
Size::new(max_width, max_height), Size::new(max_width, max_height),
compression,
); );
let layout = let layout =
@ -254,8 +253,11 @@ where
let (max_width, max_height) = axis.pack(main, cross); let (max_width, max_height) = axis.pack(main, cross);
let child_limits = let child_limits = Limits::with_compression(
Limits::new(Size::ZERO, Size::new(max_width, max_height)); Size::ZERO,
Size::new(max_width, max_height),
compression,
);
let layout = let layout =
child.as_widget_mut().layout(tree, renderer, &child_limits); child.as_widget_mut().layout(tree, renderer, &child_limits);

View file

@ -6,7 +6,7 @@ use crate::{Length, Size};
pub struct Limits { pub struct Limits {
min: Size, min: Size,
max: Size, max: Size,
compress: Size<bool>, compression: Size<bool>,
} }
impl Limits { impl Limits {
@ -14,15 +14,25 @@ impl Limits {
pub const NONE: Limits = Limits { pub const NONE: Limits = Limits {
min: Size::ZERO, min: Size::ZERO,
max: Size::INFINITE, max: Size::INFINITE,
compress: Size::new(false, false), compression: Size::new(false, false),
}; };
/// Creates new [`Limits`] with the given minimum and maximum [`Size`]. /// Creates new [`Limits`] with the given minimum and maximum [`Size`].
pub const fn new(min: Size, max: Size) -> Limits { pub const fn new(min: Size, max: Size) -> Limits {
Limits::with_compression(min, max, Size::new(false, false))
}
/// Creates new [`Limits`] with the given minimun and maximum [`Size`], and
/// whether fluid lengths should be compressed to intrinsic dimensions.
pub const fn with_compression(
min: Size,
max: Size,
compress: Size<bool>,
) -> Self {
Limits { Limits {
min, min,
max, max,
compress: Size::new(false, false), compression: compress,
} }
} }
@ -36,18 +46,23 @@ impl Limits {
self.max self.max
} }
/// Returns the compression of the [`Limits`].
pub fn compression(&self) -> Size<bool> {
self.compression
}
/// Applies a width constraint to the current [`Limits`]. /// Applies a width constraint to the current [`Limits`].
pub fn width(mut self, width: impl Into<Length>) -> Limits { pub fn width(mut self, width: impl Into<Length>) -> Limits {
match width.into() { match width.into() {
Length::Shrink => { Length::Shrink => {
self.compress.width = true; self.compression.width = true;
} }
Length::Fixed(amount) => { Length::Fixed(amount) => {
let new_width = amount.min(self.max.width).max(self.min.width); let new_width = amount.min(self.max.width).max(self.min.width);
self.min.width = new_width; self.min.width = new_width;
self.max.width = new_width; self.max.width = new_width;
self.compress.width = false; self.compression.width = false;
} }
Length::Fill | Length::FillPortion(_) => {} Length::Fill | Length::FillPortion(_) => {}
} }
@ -59,7 +74,7 @@ impl Limits {
pub fn height(mut self, height: impl Into<Length>) -> Limits { pub fn height(mut self, height: impl Into<Length>) -> Limits {
match height.into() { match height.into() {
Length::Shrink => { Length::Shrink => {
self.compress.height = true; self.compression.height = true;
} }
Length::Fixed(amount) => { Length::Fixed(amount) => {
let new_height = let new_height =
@ -67,7 +82,7 @@ impl Limits {
self.min.height = new_height; self.min.height = new_height;
self.max.height = new_height; self.max.height = new_height;
self.compress.height = false; self.compression.height = false;
} }
Length::Fill | Length::FillPortion(_) => {} Length::Fill | Length::FillPortion(_) => {}
} }
@ -120,7 +135,7 @@ impl Limits {
Limits { Limits {
min, min,
max, max,
compress: self.compress, compression: self.compression,
} }
} }
@ -129,7 +144,7 @@ impl Limits {
Limits { Limits {
min: Size::ZERO, min: Size::ZERO,
max: self.max, max: self.max,
compress: self.compress, compression: self.compression,
} }
} }
@ -143,7 +158,9 @@ impl Limits {
intrinsic_size: Size, intrinsic_size: Size,
) -> Size { ) -> Size {
let width = match width.into() { let width = match width.into() {
Length::Fill | Length::FillPortion(_) if !self.compress.width => { Length::Fill | Length::FillPortion(_)
if !self.compression.width =>
{
self.max.width self.max.width
} }
Length::Fixed(amount) => { Length::Fixed(amount) => {
@ -153,7 +170,9 @@ impl Limits {
}; };
let height = match height.into() { let height = match height.into() {
Length::Fill | Length::FillPortion(_) if !self.compress.height => { Length::Fill | Length::FillPortion(_)
if !self.compression.height =>
{
self.max.height self.max.height
} }
Length::Fixed(amount) => { Length::Fixed(amount) => {