diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-11-25 16:56:29 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-11-25 16:56:29 +0100 |
| commit | 11e44516fae84f907ea992311fcfdc3636101f14 (patch) | |
| tree | ff9b6a04c3accd5c0f75f1ceb60e578c389a2606 /src/library/align.rs | |
| parent | 761931405c68efe0a35d96524df797dda7155723 (diff) | |
Merge some modules 🥞
Diffstat (limited to 'src/library/align.rs')
| -rw-r--r-- | src/library/align.rs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/src/library/align.rs b/src/library/align.rs deleted file mode 100644 index 4f4a1750..00000000 --- a/src/library/align.rs +++ /dev/null @@ -1,185 +0,0 @@ -use crate::prelude::*; -use std::fmt::{self, Display, Formatter}; - -/// `align`: Align content along the layouting axes. -/// -/// # Positional arguments -/// - At most two of `left`, `right`, `top`, `bottom`, `center`. -/// -/// When `center` is used as a positional argument, it is automatically inferred -/// which axis it should apply to depending on further arguments, defaulting -/// to the axis, text is set along. -/// -/// # Keyword arguments -/// - `horizontal`: Any of `left`, `right` or `center`. -/// - `vertical`: Any of `top`, `bottom` or `center`. -/// -/// There may not be two alignment specifications for the same axis. -pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value { - let snapshot = ctx.state.clone(); - let body = args.find::<SynTree>(); - let first = args.get::<_, Spanned<AlignArg>>(ctx, 0); - let second = args.get::<_, Spanned<AlignArg>>(ctx, 1); - let hor = args.get::<_, Spanned<AlignArg>>(ctx, "horizontal"); - let ver = args.get::<_, Spanned<AlignArg>>(ctx, "vertical"); - args.done(ctx); - - let iter = first - .into_iter() - .chain(second.into_iter()) - .map(|align| (align.v.axis(), align)) - .chain(hor.into_iter().map(|align| (Some(SpecAxis::Horizontal), align))) - .chain(ver.into_iter().map(|align| (Some(SpecAxis::Vertical), align))); - - let align = dedup_aligns(ctx, iter); - let ends_par = align.main != ctx.state.align.main; - ctx.state.align = align; - - if ends_par { - ctx.end_par_group(); - ctx.start_par_group(); - } - - if let Some(body) = body { - body.eval(ctx); - ctx.state = snapshot; - } - - Value::None -} - -/// Deduplicate alignments and deduce to which axes they apply. -fn dedup_aligns( - ctx: &mut EvalContext, - iter: impl Iterator<Item = (Option<SpecAxis>, Spanned<AlignArg>)>, -) -> BoxAlign { - let mut alignments = ctx.state.align; - let mut had = Gen::uniform(false); - let mut had_center = false; - - for (axis, Spanned { v: align, span }) in iter { - // Check whether we know which axis this alignment belongs to. - if let Some(axis) = axis { - // We know the axis. - let gen_axis = axis.switch(ctx.state.flow); - let gen_align = align.switch(ctx.state.flow); - - if align.axis().map_or(false, |a| a != axis) { - ctx.diag(error!( - span, - "invalid alignment `{}` for {} axis", align, axis, - )); - } else if had.get(gen_axis) { - ctx.diag(error!(span, "duplicate alignment for {} axis", axis)); - } else { - *alignments.get_mut(gen_axis) = gen_align; - *had.get_mut(gen_axis) = true; - } - } else { - // We don't know the axis: This has to be a `center` alignment for a - // positional argument. - debug_assert_eq!(align, AlignArg::Center); - - if had.main && had.cross { - ctx.diag(error!(span, "duplicate alignment")); - } else if had_center { - // Both this and the previous one are unspecified `center` - // alignments. Both axes should be centered. - alignments = BoxAlign::new(Align::Center, Align::Center); - had = Gen::uniform(true); - } else { - had_center = true; - } - } - - // If we we know one alignment, we can handle the unspecified `center` - // alignment. - if had_center && (had.main || had.cross) { - if had.main { - alignments.cross = Align::Center; - had.cross = true; - } else { - alignments.main = Align::Center; - had.main = true; - } - had_center = false; - } - } - - // If center has not been flushed by now, it is the only argument and then - // we default to applying it to the cross axis. - if had_center { - alignments.cross = Align::Center; - } - - alignments -} - -/// An alignment argument. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -enum AlignArg { - Left, - Right, - Top, - Bottom, - Center, -} - -impl AlignArg { - /// The specific axis this alignment refers to. - /// - /// Returns `None` if this is `Center` since the axis is unknown. - pub fn axis(self) -> Option<SpecAxis> { - match self { - Self::Left => Some(SpecAxis::Horizontal), - Self::Right => Some(SpecAxis::Horizontal), - Self::Top => Some(SpecAxis::Vertical), - Self::Bottom => Some(SpecAxis::Vertical), - Self::Center => None, - } - } -} - -impl Switch for AlignArg { - type Other = Align; - - fn switch(self, flow: Flow) -> Self::Other { - let get = |dir: Dir, at_positive_start| { - if dir.is_positive() == at_positive_start { - Align::Start - } else { - Align::End - } - }; - - let flow = flow.switch(flow); - match self { - Self::Left => get(flow.horizontal, true), - Self::Right => get(flow.horizontal, false), - Self::Top => get(flow.vertical, true), - Self::Bottom => get(flow.vertical, false), - Self::Center => Align::Center, - } - } -} - -convert_ident!(AlignArg, "alignment", |v| match v { - "left" => Some(Self::Left), - "right" => Some(Self::Right), - "top" => Some(Self::Top), - "bottom" => Some(Self::Bottom), - "center" => Some(Self::Center), - _ => None, -}); - -impl Display for AlignArg { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(match self { - Self::Left => "left", - Self::Right => "right", - Self::Top => "top", - Self::Bottom => "bottom", - Self::Center => "center", - }) - } -} |
