summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-12-09 13:29:04 +0100
committerLaurenz <laurmaedje@gmail.com>2019-12-09 13:29:04 +0100
commit7e980224354880cfda1797136a1ff886d6642662 (patch)
treec0137dcca82526faa71fd1d980a90c68dac798c8 /src/library
parent64f938b449b7ff5e53b6a06ed943bf9dedc1014b (diff)
Bad stack layouter 🚑
Diffstat (limited to 'src/library')
-rw-r--r--src/library/boxed.rs15
-rw-r--r--src/library/direction.rs60
-rw-r--r--src/library/keys.rs9
-rw-r--r--src/library/maps.rs38
-rw-r--r--src/library/mod.rs12
5 files changed, 113 insertions, 21 deletions
diff --git a/src/library/boxed.rs b/src/library/boxed.rs
index 3ec9d001..d3d5b591 100644
--- a/src/library/boxed.rs
+++ b/src/library/boxed.rs
@@ -6,7 +6,7 @@ function! {
#[derive(Debug, PartialEq)]
pub struct Boxed {
body: SyntaxTree,
- map: ExtentMap,
+ map: ExtentMap<PSize>,
}
parse(args, body, ctx) {
@@ -17,7 +17,18 @@ function! {
}
layout(self, mut ctx) {
- self.map.apply(ctx.axes, &mut ctx.spaces[0].dimensions)?;
+ use SpecificAxisKind::*;
+
+ let space = &mut ctx.spaces[0];
+ self.map.apply_with(ctx.axes, |axis, p| {
+ let entity = match axis {
+ Horizontal => { space.expand.0 = true; &mut space.dimensions.x },
+ Vertical => { space.expand.1 = true; &mut space.dimensions.y },
+ };
+
+ *entity = p.concretize(*entity)
+ });
+
vec![AddMultiple(layout_tree(&self.body, ctx)?)]
}
}
diff --git a/src/library/direction.rs b/src/library/direction.rs
new file mode 100644
index 00000000..3b9956d1
--- /dev/null
+++ b/src/library/direction.rs
@@ -0,0 +1,60 @@
+use crate::func::prelude::*;
+use super::maps::ConsistentMap;
+use super::keys::AxisKey;
+
+function! {
+ /// `direction`: Sets the directions for the layouting axes.
+ #[derive(Debug, PartialEq)]
+ pub struct Direction {
+ body: Option<SyntaxTree>,
+ map: ConsistentMap<AxisKey, Axis>,
+ }
+
+ parse(args, body, ctx) {
+ let mut map = ConsistentMap::new();
+
+ map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Axis>()?)?;
+ map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Axis>()?)?;
+
+ for arg in args.keys() {
+ let axis = AxisKey::from_ident(&arg.v.key)?;
+ let value = Axis::from_expr(arg.v.value)?;
+
+ map.add(axis, value)?;
+ }
+
+ Direction {
+ body: parse!(optional: body, ctx),
+ map,
+ }
+ }
+
+ layout(self, mut ctx) {
+ let axes = ctx.axes;
+
+ let map = self.map.dedup(|key, &direction| {
+ Ok((match key {
+ AxisKey::Primary => GenericAxisKind::Primary,
+ AxisKey::Secondary => GenericAxisKind::Secondary,
+ AxisKey::Horizontal => axes.horizontal(),
+ AxisKey::Vertical => axes.vertical(),
+ }, direction))
+ })?;
+
+ map.with(GenericAxisKind::Primary, |&val| ctx.axes.primary = val);
+ map.with(GenericAxisKind::Secondary, |&val| ctx.axes.secondary = val);
+
+ if ctx.axes.primary.is_horizontal() == ctx.axes.secondary.is_horizontal() {
+ error!(
+ "aligned primary and secondary axes: `{}`, `{}`",
+ format!("{:?}", ctx.axes.primary).to_lowercase(),
+ format!("{:?}", ctx.axes.secondary).to_lowercase(),
+ );
+ }
+
+ match &self.body {
+ Some(body) => vec![AddMultiple(layout_tree(&body, ctx)?)],
+ None => vec![Command::SetAxes(ctx.axes)],
+ }
+ }
+}
diff --git a/src/library/keys.rs b/src/library/keys.rs
index e74027ec..c7e34839 100644
--- a/src/library/keys.rs
+++ b/src/library/keys.rs
@@ -66,7 +66,7 @@ kind!(AxisKey, "axis",
"secondary" => AxisKey::Secondary,
);
-/// An argument key which identifies a target alignment.
+/// An argument key which describes a target alignment.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum AlignmentKey {
Left,
@@ -172,3 +172,10 @@ kind!(PaddingKey<AxisKey>, "axis or side",
"vertical-origin" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Origin),
"vertical-end" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::End),
);
+
+kind!(Axis, "direction",
+ "ltr" => Axis::LeftToRight,
+ "rtl" => Axis::RightToLeft,
+ "ttb" => Axis::TopToBottom,
+ "btt" => Axis::BottomToTop,
+);
diff --git a/src/library/maps.rs b/src/library/maps.rs
index 01bde38b..c89d46cb 100644
--- a/src/library/maps.rs
+++ b/src/library/maps.rs
@@ -72,14 +72,14 @@ impl<K, V> ConsistentMap<K, V> where K: Hash + Eq {
/// A map for storing extents along axes.
#[derive(Debug, Clone, PartialEq)]
-pub struct ExtentMap(ConsistentMap<AxisKey, Size>);
+pub struct ExtentMap<E: ExpressionKind + Copy>(ConsistentMap<AxisKey, E>);
-impl ExtentMap {
+impl<E: ExpressionKind + Copy> ExtentMap<E> {
/// Parse an extent map from the function args.
///
/// If `enforce` is true other arguments will create an error, otherwise
/// they are left intact.
- pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<ExtentMap> {
+ pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<ExtentMap<E>> {
let mut map = ConsistentMap::new();
for arg in args.keys() {
@@ -96,22 +96,38 @@ impl ExtentMap {
}
};
- let size = Size::from_expr(arg.v.value)?;
- map.add(key, size)?;
+ let e = E::from_expr(arg.v.value)?;
+ map.add(key, e)?;
}
Ok(ExtentMap(map))
}
- /// Map from any axis key to the specific axis kind.
- pub fn apply(&self, axes: LayoutAxes, dimensions: &mut Size2D) -> LayoutResult<()> {
- let map = self.0.dedup(|key, &val| Ok((key.specific(axes), val)))?;
-
- map.with(SpecificAxisKind::Horizontal, |&val| dimensions.x = val);
- map.with(SpecificAxisKind::Vertical, |&val| dimensions.y = val);
+ /// Apply the extents on the dimensions.
+ pub fn apply<F>(
+ &self,
+ axes: LayoutAxes,
+ dimensions: &mut Size2D,
+ size: F
+ ) -> LayoutResult<()> where F: Fn(&E) -> Size {
+ let map = self.dedup(axes)?;
+ map.with(SpecificAxisKind::Horizontal, |val| dimensions.x = size(val));
+ map.with(SpecificAxisKind::Vertical, |val| dimensions.y = size(val));
+ Ok(())
+ }
+ /// Map from any axis key to the specific axis kind.
+ pub fn apply_with<F>(&self, axes: LayoutAxes, mut f: F) -> LayoutResult<()>
+ where F: FnMut(SpecificAxisKind, &E) {
+ for (&key, value) in self.dedup(axes)?.iter() {
+ f(key, value);
+ }
Ok(())
}
+
+ fn dedup(&self, axes: LayoutAxes) -> LayoutResult<ConsistentMap<SpecificAxisKind, E>> {
+ self.0.dedup(|key, &val| Ok((key.specific(axes), val)))
+ }
}
/// A map for storing padding at sides.
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 293f9589..4439f137 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -8,6 +8,7 @@ use maps::*;
pub_use_mod!(align);
pub_use_mod!(boxed);
+pub_use_mod!(direction);
pub mod maps;
pub mod keys;
@@ -19,6 +20,7 @@ pub fn std() -> Scope {
std.add::<Align>("align");
std.add::<Boxed>("box");
+ std.add::<Direction>("direction");
std.add::<PageSize>("page.size");
std.add::<PageMargins>("page.margins");
@@ -78,7 +80,7 @@ function! {
/// `page.size`: Set the size of pages.
#[derive(Debug, PartialEq)]
pub struct PageSize {
- map: ExtentMap,
+ map: ExtentMap<Size>,
}
parse(args, body) {
@@ -90,7 +92,7 @@ function! {
layout(self, ctx) {
let mut style = ctx.style.page;
- self.map.apply(ctx.axes, &mut style.dimensions)?;
+ self.map.apply(ctx.axes, &mut style.dimensions, |&s| s)?;
vec![SetPageStyle(style)]
}
}
@@ -150,11 +152,7 @@ function! {
layout(self, ctx) {
let axis = self.axis.generic(ctx.axes);
- let spacing = match self.spacing {
- FSize::Absolute(size) => size,
- FSize::Scaled(scale) => scale * ctx.style.text.font_size,
- };
-
+ let spacing = self.spacing.concretize(ctx.style.text.font_size);
vec![AddSpacing(spacing, SpacingKind::Hard, axis)]
}
}