Make Shrink have priority over Fill in layout

This commit is contained in:
Héctor Ramón Jiménez 2023-03-16 20:23:25 +01:00 committed by Héctor Ramón Jiménez
parent 68c0484b5c
commit 0655a20ad1
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
46 changed files with 264 additions and 273 deletions

View file

@ -1,12 +1,11 @@
#![allow(clippy::manual_clamp)]
use crate::{Length, Padding, Size};
use crate::{Length, Size};
/// A set of size constraints for layouting.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Limits {
min: Size,
max: Size,
fill: Size,
}
impl Limits {
@ -14,16 +13,11 @@ impl Limits {
pub const NONE: Limits = Limits {
min: Size::ZERO,
max: Size::INFINITY,
fill: Size::INFINITY,
};
/// Creates new [`Limits`] with the given minimum and maximum [`Size`].
pub const fn new(min: Size, max: Size) -> Limits {
Limits {
min,
max,
fill: Size::INFINITY,
}
Limits { min, max }
}
/// Returns the minimum [`Size`] of the [`Limits`].
@ -36,26 +30,15 @@ impl Limits {
self.max
}
/// Returns the fill [`Size`] of the [`Limits`].
pub fn fill(&self) -> Size {
self.fill
}
/// Applies a width constraint to the current [`Limits`].
pub fn width(mut self, width: impl Into<Length>) -> Limits {
match width.into() {
Length::Shrink => {
self.fill.width = self.min.width;
}
Length::Fill | Length::FillPortion(_) => {
self.fill.width = self.fill.width.min(self.max.width);
}
Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
Length::Fixed(amount) => {
let new_width = amount.min(self.max.width).max(self.min.width);
self.min.width = new_width;
self.max.width = new_width;
self.fill.width = new_width;
}
}
@ -65,19 +48,13 @@ impl Limits {
/// Applies a height constraint to the current [`Limits`].
pub fn height(mut self, height: impl Into<Length>) -> Limits {
match height.into() {
Length::Shrink => {
self.fill.height = self.min.height;
}
Length::Fill | Length::FillPortion(_) => {
self.fill.height = self.fill.height.min(self.max.height);
}
Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
Length::Fixed(amount) => {
let new_height =
amount.min(self.max.height).max(self.min.height);
self.min.height = new_height;
self.max.height = new_height;
self.fill.height = new_height;
}
}
@ -112,13 +89,10 @@ impl Limits {
self
}
/// Shrinks the current [`Limits`] to account for the given padding.
pub fn pad(&self, padding: Padding) -> Limits {
self.shrink(Size::new(padding.horizontal(), padding.vertical()))
}
/// Shrinks the current [`Limits`] by the given [`Size`].
pub fn shrink(&self, size: Size) -> Limits {
pub fn shrink(&self, size: impl Into<Size>) -> Limits {
let size = size.into();
let min = Size::new(
(self.min().width - size.width).max(0.0),
(self.min().height - size.height).max(0.0),
@ -129,12 +103,7 @@ impl Limits {
(self.max().height - size.height).max(0.0),
);
let fill = Size::new(
(self.fill.width - size.width).max(0.0),
(self.fill.height - size.height).max(0.0),
);
Limits { min, max, fill }
Limits { min, max }
}
/// Removes the minimum width constraint for the current [`Limits`].
@ -142,22 +111,38 @@ impl Limits {
Limits {
min: Size::ZERO,
max: self.max,
fill: self.fill,
}
}
/// Computes the resulting [`Size`] that fits the [`Limits`] given the
/// intrinsic size of some content.
pub fn resolve(&self, intrinsic_size: Size) -> Size {
Size::new(
intrinsic_size
.width
.min(self.max.width)
.max(self.fill.width),
intrinsic_size
pub fn resolve(
&self,
intrinsic_size: Size,
width: impl Into<Length>,
height: impl Into<Length>,
) -> Size {
let width = match width.into() {
Length::Fill | Length::FillPortion(_) => self.max.width,
Length::Fixed(amount) => {
amount.min(self.max.width).max(self.min.width)
}
Length::Shrink => {
intrinsic_size.width.min(self.max.width).max(self.min.width)
}
};
let height = match height.into() {
Length::Fill | Length::FillPortion(_) => self.max.height,
Length::Fixed(amount) => {
amount.min(self.max.height).max(self.min.height)
}
Length::Shrink => intrinsic_size
.height
.min(self.max.height)
.max(self.fill.height),
)
.max(self.min.height),
};
Size::new(width, height)
}
}