use crate::types::{Rect, Size};
pub trait Widget {
fn widget_type(&self) -> &'static str;
fn layout(&self, constraints: Size) -> Size;
fn bounds(&self) -> Option<Rect> {
None
}
}
#[derive(Debug, Clone, Copy)]
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 unbounded() -> Self {
Self {
min_width: 0.0,
max_width: f32::INFINITY,
min_height: 0.0,
max_height: f32::INFINITY,
}
}
pub fn constrain(&self, size: Size) -> Size {
Size::new(
size.width.max(self.min_width).min(self.max_width),
size.height.max(self.min_height).min(self.max_height),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_constraints_tight() {
let c = Constraints::tight(100.0, 200.0);
assert_eq!(c.min_width, 100.0);
assert_eq!(c.max_width, 100.0);
assert_eq!(c.min_height, 200.0);
assert_eq!(c.max_height, 200.0);
}
#[test]
fn test_constraints_constrain() {
let c = Constraints::loose(100.0, 200.0);
let size1 = Size::new(50.0, 50.0);
let constrained1 = c.constrain(size1);
assert_eq!(constrained1, Size::new(50.0, 50.0));
let size2 = Size::new(150.0, 250.0);
let constrained2 = c.constrain(size2);
assert_eq!(constrained2, Size::new(100.0, 200.0));
}
}