diff --git a/src/geom/spec.rs b/src/geom/spec.rs index a257214bf..4d631399f 100644 --- a/src/geom/spec.rs +++ b/src/geom/spec.rs @@ -31,6 +31,23 @@ impl Spec { Spec { x: f(self.x), y: f(self.y) } } + /// Zip two instances into an instance over a tuple. + pub fn zip(self, other: impl Into>) -> Spec<(T, U)> { + let other = other.into(); + Spec { + x: (self.x, other.x), + y: (self.y, other.y), + } + } + + /// Whether a condition is true for both fields. + pub fn all(self, mut f: F) -> bool + where + F: FnMut(&T) -> bool, + { + f(&self.x) && f(&self.y) + } + /// Convert to the generic representation. pub fn to_gen(self, block: SpecAxis) -> Gen { match block { @@ -38,14 +55,11 @@ impl Spec { SpecAxis::Vertical => Gen::new(self.x, self.y), } } +} - /// Compares if this instance's field are equal to that of another with - /// respect to `eq`. - pub fn eq_by(&self, other: &Spec, eq: F) -> bool - where - F: Fn(&T, &U) -> bool, - { - eq(&self.x, &other.x) && eq(&self.y, &other.y) +impl From for Spec { + fn from(size: Size) -> Self { + size.to_spec() } } diff --git a/src/layout/constraints.rs b/src/layout/constraints.rs index 7dc16446e..11f4e5c20 100644 --- a/src/layout/constraints.rs +++ b/src/layout/constraints.rs @@ -40,23 +40,15 @@ impl Constraints { /// Check whether the constraints are fullfilled in a region with the given /// properties. pub fn check(&self, current: Size, base: Size, expand: Spec) -> bool { - let current = current.to_spec(); - let base = base.to_spec(); self.expand == expand - && current.eq_by(&self.min, |x, y| y.map_or(true, |y| x.fits(y))) - && current.eq_by(&self.max, |x, y| y.map_or(true, |y| x < &y)) - && current.eq_by(&self.exact, |x, y| y.map_or(true, |y| x.approx_eq(y))) - && base.eq_by(&self.base, |x, y| y.map_or(true, |y| x.approx_eq(y))) - } - - /// Set the appropriate base constraints for linear width and height sizing. - pub fn set_base_if_linear(&mut self, base: Size, sizing: Spec>) { - // The full sizes need to be equal if there is a relative component in the sizes. - if sizing.x.map_or(false, |l| l.is_relative()) { - self.base.x = Some(base.w); - } - if sizing.y.map_or(false, |l| l.is_relative()) { - self.base.y = Some(base.h); - } + && verify(self.min, current, |m, c| c.fits(m)) + && verify(self.max, current, |m, c| m.fits(c)) + && verify(self.exact, current, Length::approx_eq) + && verify(self.base, base, Length::approx_eq) } } + +/// Verify a single constraint. +fn verify(spec: Spec>, size: Size, f: fn(Length, Length) -> bool) -> bool { + spec.zip(size).all(|&(opt, s)| opt.map_or(true, |m| f(m, s))) +}