diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-12-13 23:59:01 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-12-13 23:59:01 +0100 |
| commit | 665b4d2aca81af48b8e0eaca4e709ef2e7825844 (patch) | |
| tree | 4ada33f607455f14b6a170fe4b7fbe173056567b /src/library/maps/padding.rs | |
| parent | 971ff3a2dcff1e68bf7e19017113469aad5a30c2 (diff) | |
More consistent library code and functions 🎄
Diffstat (limited to 'src/library/maps/padding.rs')
| -rw-r--r-- | src/library/maps/padding.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/library/maps/padding.rs b/src/library/maps/padding.rs new file mode 100644 index 00000000..37f2ba4a --- /dev/null +++ b/src/library/maps/padding.rs @@ -0,0 +1,92 @@ +use super::*; +use AxisKey::*; +use AlignmentKey::*; +use PaddingKey::*; + +/// An argument key which identifies a margin or padding target. +/// +/// A is the used axis type. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum PaddingKey<A> { + /// All four sides should have the specified padding. + All, + /// Both sides of the given axis should have the specified padding. + Both(A), + /// Only the given side of the given axis should have the specified padding. + Side(A, AlignmentKey), +} + +key!(PaddingKey<AxisKey>, "axis or side", + "horizontal" | "h" => Both(Specific(Horizontal)), + "vertical" | "v" => Both(Specific(Vertical)), + "primary" | "p" => Both(Generic(Primary)), + "secondary" | "s" => Both(Generic(Secondary)), + + "left" => Side(Specific(Horizontal), Left), + "right" => Side(Specific(Horizontal), Right), + "top" => Side(Specific(Vertical), Top), + "bottom" => Side(Specific(Vertical), Bottom), + + "primary-origin" => Side(Generic(Primary), Align(Origin)), + "primary-end" => Side(Generic(Primary), Align(End)), + "secondary-origin" => Side(Generic(Secondary), Align(Origin)), + "secondary-end" => Side(Generic(Secondary), Align(End)), + "horizontal-origin" => Side(Specific(Horizontal), Align(Origin)), + "horizontal-end" => Side(Specific(Horizontal), Align(End)), + "vertical-origin" => Side(Specific(Vertical), Align(Origin)), + "vertical-end" => Side(Specific(Vertical), Align(End)), +); + +/// A map for storing padding at sides. +#[derive(Debug, Clone, PartialEq)] +pub struct PaddingMap(ConsistentMap<PaddingKey<AxisKey>, Size>); + +impl PaddingMap { + /// Parse a padding map from the function args. + pub fn new(args: &mut FuncArgs) -> ParseResult<PaddingMap> { + let mut map = ConsistentMap::new(); + map.add_opt(PaddingKey::All, args.get_pos_opt::<Size>()?)?; + + for arg in args.keys() { + let key = PaddingKey::from_ident(&arg.v.key)?; + let size = Size::from_expr(arg.v.value)?; + map.add(key, size)?; + } + + Ok(PaddingMap(map)) + } + + /// Apply the specified padding on the size box. + pub fn apply(&self, axes: LayoutAxes, padding: &mut SizeBox) -> LayoutResult<()> { + use PaddingKey::*; + + let map = self.0.dedup(|key, &val| { + Ok((match key { + All => All, + Both(axis) => Both(axis.to_specific(axes)), + Side(axis, alignment) => { + let axis = axis.to_specific(axes); + Side(axis, alignment.to_specific(axes, axis)) + } + }, val)) + })?; + + map.with(All, |&val| padding.set_all(val)); + map.with(Both(Horizontal), |&val| padding.set_horizontal(val)); + map.with(Both(Vertical), |&val| padding.set_vertical(val)); + + for (key, &val) in map.iter() { + if let Side(_, alignment) = key { + match alignment { + AlignmentKey::Left => padding.left = val, + AlignmentKey::Right => padding.right = val, + AlignmentKey::Top => padding.top = val, + AlignmentKey::Bottom => padding.bottom = val, + _ => {}, + } + } + } + + Ok(()) + } +} |
