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/place.rs | |
| parent | 56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff) | |
Split crates
Diffstat (limited to 'library/src/layout/place.rs')
| -rw-r--r-- | library/src/layout/place.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs new file mode 100644 index 00000000..7d760ab6 --- /dev/null +++ b/library/src/layout/place.rs @@ -0,0 +1,56 @@ +use super::AlignNode; +use crate::prelude::*; + +/// Place content at an absolute position. +#[derive(Debug, Hash)] +pub struct PlaceNode(pub Content); + +#[node(LayoutBlock)] +impl PlaceNode { + fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { + let aligns = args.find()?.unwrap_or(Axes::with_x(Some(GenAlign::Start))); + let dx = args.named("dx")?.unwrap_or_default(); + let dy = args.named("dy")?.unwrap_or_default(); + let body = args.expect::<Content>("body")?; + Ok(Self(body.moved(Axes::new(dx, dy)).aligned(aligns)).pack()) + } +} + +impl LayoutBlock for PlaceNode { + fn layout_block( + &self, + world: Tracked<dyn World>, + regions: &Regions, + styles: StyleChain, + ) -> SourceResult<Vec<Frame>> { + let out_of_flow = self.out_of_flow(); + + // The pod is the base area of the region because for absolute + // placement we don't really care about the already used area. + let pod = { + let finite = regions.base.map(Abs::is_finite); + let expand = finite & (regions.expand | out_of_flow); + Regions::one(regions.base, regions.base, expand) + }; + + let mut frames = self.0.layout_block(world, &pod, styles)?; + + // If expansion is off, zero all sizes so that we don't take up any + // space in our parent. Otherwise, respect the expand settings. + let target = regions.expand.select(regions.first, Size::zero()); + frames[0].resize(target, Align::LEFT_TOP); + + Ok(frames) + } +} + +impl PlaceNode { + /// Whether this node wants to be placed relative to its its parent's base + /// origin. Instead of relative to the parent's current flow/cursor + /// position. + pub fn out_of_flow(&self) -> bool { + self.0 + .downcast::<AlignNode>() + .map_or(false, |node| node.aligns.y.is_some()) + } +} |
