#![allow(clippy::manual_clamp)]
use crate::{Length, Size};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Limits {
min: Size,
max: Size,
compression: Size<bool>,
}
impl Limits {
pub const NONE: Limits = Limits {
min: Size::ZERO,
max: Size::INFINITE,
compression: Size::new(false, false),
};
pub const fn new(min: Size, max: Size) -> Limits {
Limits::with_compression(min, max, Size::new(false, false))
}
pub const fn with_compression(
min: Size,
max: Size,
compress: Size<bool>,
) -> Self {
Limits {
min,
max,
compression: compress,
}
}
pub fn min(&self) -> Size {
self.min
}
pub fn max(&self) -> Size {
self.max
}
pub fn compression(&self) -> Size<bool> {
self.compression
}
pub fn width(mut self, width: impl Into<Length>) -> Limits {
match width.into() {
Length::Shrink => {
self.compression.width = true;
}
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.compression.width = false;
}
Length::Fill | Length::FillPortion(_) => {}
}
self
}
pub fn height(mut self, height: impl Into<Length>) -> Limits {
match height.into() {
Length::Shrink => {
self.compression.height = true;
}
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.compression.height = false;
}
Length::Fill | Length::FillPortion(_) => {}
}
self
}
pub fn min_width(mut self, min_width: f32) -> Limits {
self.min.width = self.min.width.max(min_width).min(self.max.width);
self
}
pub fn max_width(mut self, max_width: f32) -> Limits {
self.max.width = self.max.width.min(max_width).max(self.min.width);
self
}
pub fn min_height(mut self, min_height: f32) -> Limits {
self.min.height = self.min.height.max(min_height).min(self.max.height);
self
}
pub fn max_height(mut self, max_height: f32) -> Limits {
self.max.height = self.max.height.min(max_height).max(self.min.height);
self
}
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),
);
let max = Size::new(
(self.max().width - size.width).max(0.0),
(self.max().height - size.height).max(0.0),
);
Limits {
min,
max,
compression: self.compression,
}
}
pub fn loose(&self) -> Limits {
Limits {
min: Size::ZERO,
max: self.max,
compression: self.compression,
}
}
pub fn resolve(
&self,
width: impl Into<Length>,
height: impl Into<Length>,
intrinsic_size: Size,
) -> Size {
let width = match width.into() {
Length::Fill | Length::FillPortion(_)
if !self.compression.width =>
{
self.max.width
}
Length::Fixed(amount) => {
amount.min(self.max.width).max(self.min.width)
}
_ => intrinsic_size.width.min(self.max.width).max(self.min.width),
};
let height = match height.into() {
Length::Fill | Length::FillPortion(_)
if !self.compression.height =>
{
self.max.height
}
Length::Fixed(amount) => {
amount.min(self.max.height).max(self.min.height)
}
_ => intrinsic_size
.height
.min(self.max.height)
.max(self.min.height),
};
Size::new(width, height)
}
}