diff options
| author | Martin <mhaug@live.de> | 2021-08-19 15:07:11 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-19 15:07:11 +0200 |
| commit | fdab7158c91c52a4ace211c804fdd8e9110f56de (patch) | |
| tree | 7ec34f942bc89b2ade554618648825654a587ace /src/layout/constraints.rs | |
| parent | c44ecbfbd2706bf8e09728f2c85135aa2299d542 (diff) | |
Pattern properties (#42)
Included in this package are:
* Code review I: The unnamed review.
* Code Review II: How I met your review.
* Code Review III: Code, the final frontier. These are the voyages of the USS Review ...
Diffstat (limited to 'src/layout/constraints.rs')
| -rw-r--r-- | src/layout/constraints.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/layout/constraints.rs b/src/layout/constraints.rs new file mode 100644 index 00000000..d13433ec --- /dev/null +++ b/src/layout/constraints.rs @@ -0,0 +1,96 @@ +use std::ops::Deref; + +use crate::util::OptionExt; + +use super::*; + +/// Carries an item that is only valid in certain regions and the constraints +/// that describe these regions. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct Constrained<T> { + /// The item that is only valid if the constraints are fullfilled. + pub item: T, + /// Constraints on regions in which the item is valid. + pub constraints: Constraints, +} + +impl<T> Deref for Constrained<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.item + } +} + +/// Describe regions that match them. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct Constraints { + /// The minimum available length in the region. + pub min: Spec<Option<Length>>, + /// The maximum available length in the region. + pub max: Spec<Option<Length>>, + /// The available length in the region. + pub exact: Spec<Option<Length>>, + /// The base length of the region used for relative length resolution. + pub base: Spec<Option<Length>>, + /// The expand settings of the region. + pub expand: Spec<bool>, +} + +impl Constraints { + /// Create a new region constraint. + pub fn new(expand: Spec<bool>) -> Self { + Self { + min: Spec::default(), + max: Spec::default(), + exact: Spec::default(), + base: Spec::default(), + expand, + } + } + + /// Check whether the constraints are fullfilled in a region with the given + /// properties. + pub fn check(&self, current: Size, base: Size, expand: Spec<bool>) -> 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 (relative) width and height + /// metrics, respectively. + pub fn set_base_using_linears( + &mut self, + size: Spec<Option<Linear>>, + regions: &Regions, + ) { + // The full sizes need to be equal if there is a relative component in the sizes. + if size.horizontal.map_or(false, |l| l.is_relative()) { + self.base.horizontal = Some(regions.base.width); + } + if size.vertical.map_or(false, |l| l.is_relative()) { + self.base.vertical = Some(regions.base.height); + } + } + + /// Changes all constraints by adding the `size` to them if they are `Some`. + pub fn inflate(&mut self, size: Size, regions: &Regions) { + for spec in [&mut self.min, &mut self.max] { + if let Some(horizontal) = spec.horizontal.as_mut() { + *horizontal += size.width; + } + if let Some(vertical) = spec.vertical.as_mut() { + *vertical += size.height; + } + } + + self.exact.horizontal.and_set(Some(regions.current.width)); + self.exact.vertical.and_set(Some(regions.current.height)); + self.base.horizontal.and_set(Some(regions.base.width)); + self.base.vertical.and_set(Some(regions.base.height)); + } +} |
