use anathema_geometry::Region;
use crate::layout::Size;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Constraints {
pub min_width: u16,
pub min_height: u16,
max_width: u16,
max_height: u16,
}
impl Constraints {
pub const MAX: Self = Self {
min_width: u16::MAX,
min_height: u16::MAX,
max_width: u16::MAX,
max_height: u16::MAX,
};
pub const ZERO: Self = Self {
min_width: 0,
min_height: 0,
max_width: 0,
max_height: 0,
};
pub fn max_height(&self) -> u16 {
self.max_height
}
pub fn max_width(&self) -> u16 {
self.max_width
}
pub fn sub_max_width(&mut self, width: u16) {
if self.max_width < u16::MAX {
self.max_width = self.max_width.saturating_sub(width);
self.min_width = self.min_width.min(self.max_width);
}
}
pub fn sub_max_height(&mut self, height: u16) {
if self.max_height < u16::MAX {
self.max_height = self.max_height.saturating_sub(height);
self.min_height = self.min_height.min(self.max_height);
}
}
pub fn new(max_width: impl Into<Option<u16>>, max_height: impl Into<Option<u16>>) -> Self {
let max_width = max_width.into().unwrap_or(u16::MAX);
let max_height = max_height.into().unwrap_or(u16::MAX);
Self {
min_width: 0,
min_height: 0,
max_width,
max_height,
}
}
pub fn unbounded() -> Self {
Self {
min_width: 0,
min_height: 0,
max_width: u16::MAX,
max_height: u16::MAX,
}
}
pub fn unbound_height(&mut self) {
self.max_height = u16::MAX;
}
pub fn unbound_width(&mut self) {
self.max_width = u16::MAX;
}
pub fn is_unbounded(&self) -> bool {
self.is_width_unbounded() && self.is_height_unbounded()
}
pub fn is_width_unbounded(&self) -> bool {
self.max_width == u16::MAX
}
pub fn is_height_unbounded(&self) -> bool {
self.max_height == u16::MAX
}
pub fn is_width_tight(&self) -> bool {
self.max_width == self.min_width
}
pub fn is_height_tight(&self) -> bool {
self.max_height == self.min_height
}
pub fn make_width_tight(&mut self, width: u16) {
self.max_width = self.max_width.min(width);
self.min_width = self.max_width;
}
pub fn make_height_tight(&mut self, height: u16) {
self.max_height = self.max_height.min(height);
self.min_height = self.max_height;
}
pub fn expand_horz(&mut self, mut size: Size) -> Size {
size.width = self.max_width;
size
}
pub fn expand_vert(&mut self, mut size: Size) -> Size {
size.height = self.max_height;
size
}
pub fn expand_all(&mut self, mut size: Size) -> Size {
size = self.expand_horz(size);
self.expand_vert(size)
}
pub fn set_max_width(&mut self, width: u16) {
self.max_width = width;
}
pub fn set_max_height(&mut self, height: u16) {
self.max_height = height;
}
pub fn div_assign_max_width(mut self, count: u16, overflow: u16) -> Self {
let width = self.max_width / count + overflow;
self.make_width_tight(width);
self
}
pub fn div_assign_max_height(mut self, count: u16, overflow: u16) -> Self {
let height = self.max_height / count + overflow;
self.make_height_tight(height);
self
}
pub fn has_zero_dimension(&self) -> bool {
self.max_width == 0 || self.max_height == 0
}
pub fn max_size(&self) -> Size {
(self.max_width, self.max_height).into()
}
}
impl From<Size> for Constraints {
fn from(value: Size) -> Self {
Self::new(value.width, value.height)
}
}
impl From<Region> for Constraints {
fn from(value: Region) -> Self {
let width = value.to.x - value.from.x;
let height = value.to.y - value.from.y;
Self::new(width as u16, height as u16)
}
}
impl Default for Constraints {
fn default() -> Self {
Self::ZERO
}
}