#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Constraints {
pub min_width: f32,
pub max_width: f32,
pub min_height: f32,
pub max_height: f32,
}
impl Constraints {
pub fn tight(width: f32, height: f32) -> Self {
Self {
min_width: width,
max_width: width,
min_height: height,
max_height: height,
}
}
pub fn loose(max_width: f32, max_height: f32) -> Self {
Self {
min_width: 0.0,
max_width,
min_height: 0.0,
max_height,
}
}
pub fn is_tight(&self) -> bool {
self.min_width == self.max_width && self.min_height == self.max_height
}
pub fn is_bounded(&self) -> bool {
self.max_width.is_finite() && self.max_height.is_finite()
}
pub fn constrain(&self, width: f32, height: f32) -> (f32, f32) {
(
width.clamp(self.min_width, self.max_width),
height.clamp(self.min_height, self.max_height),
)
}
#[inline]
pub fn has_bounded_width(&self) -> bool {
self.max_width.is_finite()
}
#[inline]
pub fn has_bounded_height(&self) -> bool {
self.max_height.is_finite()
}
#[inline]
pub fn has_tight_width(&self) -> bool {
self.min_width == self.max_width
}
#[inline]
pub fn has_tight_height(&self) -> bool {
self.min_height == self.max_height
}
pub fn tighten_width(self, width: f32) -> Self {
Self {
min_width: width,
max_width: width,
..self
}
}
pub fn tighten_height(self, height: f32) -> Self {
Self {
min_height: height,
max_height: height,
..self
}
}
pub fn copy_with_width(self, min_width: f32, max_width: f32) -> Self {
Self {
min_width,
max_width,
..self
}
}
pub fn copy_with_height(self, min_height: f32, max_height: f32) -> Self {
Self {
min_height,
max_height,
..self
}
}
pub fn deflate(self, horizontal: f32, vertical: f32) -> Self {
Self {
min_width: (self.min_width - horizontal).max(0.0),
max_width: (self.max_width - horizontal).max(0.0),
min_height: (self.min_height - vertical).max(0.0),
max_height: (self.max_height - vertical).max(0.0),
}
}
pub fn loosen(self) -> Self {
Self {
min_width: 0.0,
min_height: 0.0,
..self
}
}
pub fn enforce(self, width: f32, height: f32) -> Self {
Self {
min_width: width.clamp(self.min_width, self.max_width),
max_width: width.clamp(self.min_width, self.max_width),
min_height: height.clamp(self.min_height, self.max_height),
max_height: height.clamp(self.min_height, self.max_height),
}
}
}
#[cfg(test)]
#[path = "tests/constraints_tests.rs"]
mod tests;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BoundRange {
pub low: f32,
pub high: f32,
}
impl BoundRange {
pub const ANY: Self = Self {
low: f32::NEG_INFINITY,
high: f32::INFINITY,
};
pub const fn exactly(value: f32) -> Self {
Self {
low: value,
high: value,
}
}
pub const fn up_to(value: f32) -> Self {
Self {
low: f32::NEG_INFINITY,
high: value,
}
}
pub const fn from(value: f32) -> Self {
Self {
low: value,
high: f32::INFINITY,
}
}
pub fn contains(self, value: f32) -> bool {
self.low <= value && value <= self.high
}
pub fn intersect(self, other: Self) -> Option<Self> {
let range = Self {
low: self.low.max(other.low),
high: self.high.min(other.high),
};
(range.low <= range.high).then_some(range)
}
pub fn outset(self, inset: f32) -> Self {
Self {
low: if self.low <= 0.0 {
f32::NEG_INFINITY
} else {
self.low + inset
},
high: self.high + inset,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AxisHold {
pub min: BoundRange,
pub max: BoundRange,
}
impl AxisHold {
pub const fn sized(size: f32) -> Self {
Self {
min: BoundRange::up_to(size),
max: BoundRange::from(size),
}
}
pub const fn at_min(size: f32) -> Self {
Self {
min: BoundRange::exactly(size),
max: BoundRange::from(size),
}
}
pub fn contains(self, min: f32, max: f32) -> bool {
self.min.contains(min) && self.max.contains(max)
}
pub fn intersect(self, other: Self) -> Option<Self> {
Some(Self {
min: self.min.intersect(other.min)?,
max: self.max.intersect(other.max)?,
})
}
pub fn outset(self, inset: f32) -> Self {
Self {
min: self.min.outset(inset),
max: self.max.outset(inset),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ConstraintsHold {
pub width: AxisHold,
pub height: AxisHold,
}
impl ConstraintsHold {
pub const fn sized(width: f32, height: f32) -> Self {
Self {
width: AxisHold::sized(width),
height: AxisHold::sized(height),
}
}
pub const fn at_min(width: f32, height: f32) -> Self {
Self {
width: AxisHold::at_min(width),
height: AxisHold::at_min(height),
}
}
pub fn contains(&self, constraints: Constraints) -> bool {
self.width
.contains(constraints.min_width, constraints.max_width)
&& self
.height
.contains(constraints.min_height, constraints.max_height)
}
pub fn intersect(self, other: Self) -> Option<Self> {
Some(Self {
width: self.width.intersect(other.width)?,
height: self.height.intersect(other.height)?,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct WrappedHold {
pub size: cranpose_ui_graphics::Size,
pub hold: Option<ConstraintsHold>,
}