diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-03 11:44:53 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-03 13:35:39 +0100 |
| commit | 37a7afddfaffd44cb9bc013c9506599267e08983 (patch) | |
| tree | 20e7d62d3c5418baff01a21d0406b91bf3096214 /library/src/layout/align.rs | |
| parent | 56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff) | |
Split crates
Diffstat (limited to 'library/src/layout/align.rs')
| -rw-r--r-- | library/src/layout/align.rs | 62 |
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) + } +} |
