summaryrefslogtreecommitdiff
path: root/src/library/layout/align.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-02-28 15:50:48 +0100
committerLaurenz <laurmaedje@gmail.com>2022-02-28 23:54:34 +0100
commit3ca5b238238e1128aa7bbfbd5db9e632045d8600 (patch)
tree2471f4b340a15695b7f4d518c0b39fabaea676c4 /src/library/layout/align.rs
parentb63c21c91d99a1554a019dc275f955d3e6a34271 (diff)
Reorganize library
Diffstat (limited to 'src/library/layout/align.rs')
-rw-r--r--src/library/layout/align.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs
new file mode 100644
index 00000000..7fbe0d01
--- /dev/null
+++ b/src/library/layout/align.rs
@@ -0,0 +1,71 @@
+use crate::library::prelude::*;
+use crate::library::text::ParNode;
+
+/// Align a node along the layouting axes.
+#[derive(Debug, Hash)]
+pub struct AlignNode {
+ /// How to align the node horizontally and vertically.
+ pub aligns: Spec<Option<Align>>,
+ /// The node to be aligned.
+ pub child: LayoutNode,
+}
+
+#[class]
+impl AlignNode {
+ fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
+ let aligns: Spec<_> = args.find()?.unwrap_or_default();
+ let body: LayoutNode = args.expect("body")?;
+ Ok(Template::block(body.aligned(aligns)))
+ }
+}
+
+impl Layout for AlignNode {
+ fn layout(
+ &self,
+ ctx: &mut Context,
+ regions: &Regions,
+ styles: StyleChain,
+ ) -> TypResult<Vec<Arc<Frame>>> {
+ // The child only needs to expand along an axis if there's no alignment.
+ let mut pod = regions.clone();
+ pod.expand &= self.aligns.map_is_none();
+
+ // Align paragraphs inside the child.
+ let mut passed = StyleMap::new();
+ if let Some(align) = self.aligns.x {
+ passed.set(ParNode::ALIGN, align);
+ }
+
+ // Layout the child.
+ let mut frames = self.child.layout(ctx, &pod, passed.chain(&styles))?;
+ for (region, frame) in regions.iter().zip(&mut frames) {
+ // Align in the target size. The target size depends on whether we
+ // should expand.
+ let target = regions.expand.select(region, frame.size);
+ let default = Spec::new(Align::Left, Align::Top);
+ let aligns = self.aligns.unwrap_or(default);
+ Arc::make_mut(frame).resize(target, aligns);
+ }
+
+ Ok(frames)
+ }
+}
+
+dynamic! {
+ Align: "alignment",
+}
+
+dynamic! {
+ Spec<Align>: "2d alignment",
+}
+
+castable! {
+ Spec<Option<Align>>,
+ Expected: "1d or 2d alignment",
+ @align: Align => {
+ let mut aligns = Spec::default();
+ aligns.set(align.axis(), Some(*align));
+ aligns
+ },
+ @aligns: Spec<Align> => aligns.map(Some),
+}