use crate::constraint::{CalcExpr, Constraint};
#[inline]
pub fn px(value: f32) -> Constraint {
Constraint::Px(value)
}
#[inline]
pub fn percent(value: f32) -> Constraint {
Constraint::Percent(value)
}
#[inline]
pub fn vw(value: f32) -> Constraint {
Constraint::Vw(value)
}
#[inline]
pub fn vh(value: f32) -> Constraint {
Constraint::Vh(value)
}
#[inline]
pub fn vmin(value: f32) -> Constraint {
Constraint::Vmin(value)
}
#[inline]
pub fn vmax(value: f32) -> Constraint {
Constraint::Vmax(value)
}
#[inline]
pub fn auto() -> Constraint {
Constraint::Auto
}
pub fn calc(expr: CalcExpr) -> Constraint {
Constraint::Calc(Box::new(expr.simplify()))
}
pub fn min2(a: Constraint, b: Constraint) -> Constraint {
Constraint::Min(vec![a, b])
}
pub fn min_of(values: Vec<Constraint>) -> Constraint {
Constraint::Min(values)
}
pub fn max2(a: Constraint, b: Constraint) -> Constraint {
Constraint::Max(vec![a, b])
}
pub fn max_of(values: Vec<Constraint>) -> Constraint {
Constraint::Max(values)
}
pub fn clamp(min: Constraint, val: Constraint, max: Constraint) -> Constraint {
Constraint::Clamp {
min: Box::new(min),
val: Box::new(val),
max: Box::new(max),
}
}
pub trait IntoCalcExpr {
fn into_expr(self) -> CalcExpr;
}
impl IntoCalcExpr for Constraint {
fn into_expr(self) -> CalcExpr {
CalcExpr::Value(self)
}
}
impl IntoCalcExpr for f32 {
fn into_expr(self) -> CalcExpr {
CalcExpr::Value(Constraint::Px(self))
}
}
impl std::ops::Add<Constraint> for Constraint {
type Output = CalcExpr;
fn add(self, rhs: Constraint) -> CalcExpr {
CalcExpr::Add(
Box::new(CalcExpr::Value(self)),
Box::new(CalcExpr::Value(rhs)),
)
}
}
impl std::ops::Sub<Constraint> for Constraint {
type Output = CalcExpr;
fn sub(self, rhs: Constraint) -> CalcExpr {
CalcExpr::Sub(
Box::new(CalcExpr::Value(self)),
Box::new(CalcExpr::Value(rhs)),
)
}
}
impl std::ops::Mul<f32> for Constraint {
type Output = CalcExpr;
fn mul(self, rhs: f32) -> CalcExpr {
CalcExpr::Mul(Box::new(CalcExpr::Value(self)), rhs)
}
}
impl std::ops::Div<f32> for Constraint {
type Output = CalcExpr;
fn div(self, rhs: f32) -> CalcExpr {
CalcExpr::Div(Box::new(CalcExpr::Value(self)), rhs)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_constructors() {
assert_eq!(px(100.0), Constraint::Px(100.0));
assert_eq!(percent(50.0), Constraint::Percent(50.0));
assert_eq!(vw(80.0), Constraint::Vw(80.0));
assert_eq!(vh(60.0), Constraint::Vh(60.0));
assert_eq!(vmin(10.0), Constraint::Vmin(10.0));
assert_eq!(vmax(10.0), Constraint::Vmax(10.0));
assert_eq!(auto(), Constraint::Auto);
}
#[test]
fn test_calc_expr() {
let width = calc(percent(100.0) - px(40.0));
match width {
Constraint::Calc(expr) => match *expr {
CalcExpr::Sub(lhs, rhs) => {
assert_eq!(*lhs, CalcExpr::Value(Constraint::Percent(100.0)));
assert_eq!(*rhs, CalcExpr::Value(Constraint::Px(40.0)));
}
_ => panic!("Expected Sub expression"),
},
_ => panic!("Expected Calc constraint"),
}
}
#[test]
fn test_min_max() {
let min_width = min2(percent(50.0), px(400.0));
match min_width {
Constraint::Min(values) => {
assert_eq!(values.len(), 2);
assert_eq!(values[0], Constraint::Percent(50.0));
assert_eq!(values[1], Constraint::Px(400.0));
}
_ => panic!("Expected Min constraint"),
}
let max_width = max2(px(200.0), percent(30.0));
match max_width {
Constraint::Max(values) => {
assert_eq!(values.len(), 2);
assert_eq!(values[0], Constraint::Px(200.0));
assert_eq!(values[1], Constraint::Percent(30.0));
}
_ => panic!("Expected Max constraint"),
}
}
#[test]
fn test_clamp() {
let width = clamp(px(100.0), percent(50.0), px(800.0));
match width {
Constraint::Clamp { min, val, max } => {
assert_eq!(*min, Constraint::Px(100.0));
assert_eq!(*val, Constraint::Percent(50.0));
assert_eq!(*max, Constraint::Px(800.0));
}
_ => panic!("Expected Clamp constraint"),
}
}
#[test]
fn test_constraint_operators() {
let add_expr = px(10.0) + px(20.0);
let simplified = add_expr.simplify();
assert_eq!(simplified, CalcExpr::Value(Constraint::Px(30.0)));
let sub_expr = px(50.0) - px(20.0);
let simplified = sub_expr.simplify();
assert_eq!(simplified, CalcExpr::Value(Constraint::Px(30.0)));
let mul_expr = px(10.0) * 3.0;
let simplified = mul_expr.simplify();
assert_eq!(simplified, CalcExpr::Value(Constraint::Px(30.0)));
let div_expr = px(60.0) / 2.0;
let simplified = div_expr.simplify();
assert_eq!(simplified, CalcExpr::Value(Constraint::Px(30.0)));
}
}