summaryrefslogtreecommitdiff
path: root/library/src/layout/align.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-11-03 11:44:53 +0100
committerLaurenz <laurmaedje@gmail.com>2022-11-03 13:35:39 +0100
commit37a7afddfaffd44cb9bc013c9506599267e08983 (patch)
tree20e7d62d3c5418baff01a21d0406b91bf3096214 /library/src/layout/align.rs
parent56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff)
Split crates
Diffstat (limited to 'library/src/layout/align.rs')
-rw-r--r--library/src/layout/align.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs
new file mode 100644
index 00000000..5e1b3555
--- /dev/null
+++ b/library/src/layout/align.rs
@@ -0,0 +1,62 @@
+use crate::prelude::*;
+use crate::text::{HorizontalAlign, ParNode};
+
+/// Align content along the layouting axes.
+#[derive(Debug, Hash)]
+pub struct AlignNode {
+ /// How to align the content horizontally and vertically.
+ pub aligns: Axes<Option<GenAlign>>,
+ /// The content to be aligned.
+ pub child: Content,
+}
+
+#[node(LayoutBlock)]
+impl AlignNode {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
+ let aligns: Axes<Option<GenAlign>> = args.find()?.unwrap_or_default();
+ let body: Content = args.expect("body")?;
+
+ if let Axes { x: Some(x), y: None } = aligns {
+ if !body.has::<dyn LayoutBlock>() {
+ return Ok(body.styled(ParNode::ALIGN, HorizontalAlign(x)));
+ }
+ }
+
+ Ok(body.aligned(aligns))
+ }
+}
+
+impl LayoutBlock for AlignNode {
+ fn layout_block(
+ &self,
+ world: Tracked<dyn World>,
+ regions: &Regions,
+ styles: StyleChain,
+ ) -> SourceResult<Vec<Frame>> {
+ // The child only needs to expand along an axis if there's no alignment.
+ let mut pod = regions.clone();
+ pod.expand &= self.aligns.as_ref().map(Option::is_none);
+
+ // Align paragraphs inside the child.
+ let mut passed = StyleMap::new();
+ if let Some(align) = self.aligns.x {
+ passed.set(ParNode::ALIGN, HorizontalAlign(align));
+ }
+
+ // Layout the child.
+ let mut frames = self.child.layout_block(world, &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 aligns = self
+ .aligns
+ .map(|align| align.resolve(styles))
+ .unwrap_or(Axes::new(Align::Left, Align::Top));
+
+ frame.resize(target, aligns);
+ }
+
+ Ok(frames)
+ }
+}