summaryrefslogtreecommitdiff
path: root/library/src/layout/place.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/place.rs
parent56342bd972a13ffe21beaf2b87ab7eb1597704b4 (diff)
Split crates
Diffstat (limited to 'library/src/layout/place.rs')
-rw-r--r--library/src/layout/place.rs56
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())
+ }
+}