diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-01 16:56:35 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-02 09:18:33 +0100 |
| commit | 37ac5d966ebaf97ac79c507028cd5b742b510b89 (patch) | |
| tree | 249d43ff0f8d880cb5d00c236993f8ff0c1f10d8 /src/library/layout | |
| parent | f547c97072881069417acd3b79b08fb7ecf40ba2 (diff) | |
More dynamic content representation
Diffstat (limited to 'src/library/layout')
| -rw-r--r-- | src/library/layout/align.rs | 26 | ||||
| -rw-r--r-- | src/library/layout/columns.rs | 24 | ||||
| -rw-r--r-- | src/library/layout/container.rs | 78 | ||||
| -rw-r--r-- | src/library/layout/flow.rs | 15 | ||||
| -rw-r--r-- | src/library/layout/grid.rs | 28 | ||||
| -rw-r--r-- | src/library/layout/pad.rs | 14 | ||||
| -rw-r--r-- | src/library/layout/page.rs | 17 | ||||
| -rw-r--r-- | src/library/layout/place.rs | 16 | ||||
| -rw-r--r-- | src/library/layout/spacing.rs | 17 | ||||
| -rw-r--r-- | src/library/layout/stack.rs | 26 | ||||
| -rw-r--r-- | src/library/layout/transform.rs | 30 |
11 files changed, 207 insertions, 84 deletions
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs index 95f5c01f..f49763b5 100644 --- a/src/library/layout/align.rs +++ b/src/library/layout/align.rs @@ -7,21 +7,25 @@ pub struct AlignNode { /// How to align the node horizontally and vertically. pub aligns: Axes<Option<RawAlign>>, /// The node to be aligned. - pub child: LayoutNode, + pub child: Content, } -#[node] +#[node(Layout)] impl AlignNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let aligns: Axes<Option<RawAlign>> = args.find()?.unwrap_or_default(); let body: Content = args.expect("body")?; - Ok(match (body, aligns) { - (Content::Block(node), _) => Content::Block(node.aligned(aligns)), - (other, Axes { x: Some(x), y: None }) => { - other.styled(ParNode::ALIGN, HorizontalAlign(x)) + + if let Axes { x: Some(x), y: None } = aligns { + if body + .to::<dyn Layout>() + .map_or(true, |node| node.level() == Level::Inline) + { + return Ok(body.styled(ParNode::ALIGN, HorizontalAlign(x))); } - (other, _) => Content::Block(other.pack().aligned(aligns)), - }) + } + + Ok(body.aligned(aligns)) } } @@ -43,7 +47,7 @@ impl Layout for AlignNode { } // Layout the child. - let mut frames = self.child.layout(world, &pod, passed.chain(&styles))?; + 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. @@ -58,4 +62,8 @@ impl Layout for AlignNode { Ok(frames) } + + fn level(&self) -> Level { + Level::Block + } } diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs index 3ba3598c..79d98e11 100644 --- a/src/library/layout/columns.rs +++ b/src/library/layout/columns.rs @@ -8,20 +8,21 @@ pub struct ColumnsNode { pub columns: NonZeroUsize, /// The child to be layouted into the columns. Most likely, this should be a /// flow or stack node. - pub child: LayoutNode, + pub child: Content, } -#[node] +#[node(Layout)] impl ColumnsNode { /// The size of the gutter space between each column. #[property(resolve)] pub const GUTTER: Rel<Length> = Ratio::new(0.04).into(); fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { - Ok(Content::block(Self { + Ok(Self { columns: args.expect("column count")?, child: args.expect("body")?, - })) + } + .pack()) } } @@ -35,7 +36,7 @@ impl Layout for ColumnsNode { // Separating the infinite space into infinite columns does not make // much sense. if !regions.first.x.is_finite() { - return self.child.layout(world, regions, styles); + return self.child.layout_block(world, regions, styles); } // Determine the width of the gutter and each column. @@ -57,7 +58,7 @@ impl Layout for ColumnsNode { }; // Layout the children. - let mut frames = self.child.layout(world, &pod, styles)?.into_iter(); + let mut frames = self.child.layout_block(world, &pod, styles)?.into_iter(); let mut finished = vec![]; let dir = styles.get(TextNode::DIR); @@ -99,15 +100,22 @@ impl Layout for ColumnsNode { Ok(finished) } + + fn level(&self) -> Level { + Level::Block + } } /// A column break. -pub struct ColbreakNode; +#[derive(Debug, Clone, Hash)] +pub struct ColbreakNode { + pub weak: bool, +} #[node] impl ColbreakNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let weak = args.named("weak")?.unwrap_or(false); - Ok(Content::Colbreak { weak }) + Ok(Self { weak }.pack()) } } diff --git a/src/library/layout/container.rs b/src/library/layout/container.rs index 9b1f8f56..60f9139b 100644 --- a/src/library/layout/container.rs +++ b/src/library/layout/container.rs @@ -1,24 +1,88 @@ use crate::library::prelude::*; /// An inline-level container that sizes content and places it into a paragraph. -pub struct BoxNode; +#[derive(Debug, Clone, Hash)] +pub struct BoxNode { + /// How to size the node horizontally and vertically. + pub sizing: Axes<Option<Rel<Length>>>, + /// The node to be sized. + pub child: Content, +} -#[node] +#[node(Layout)] impl BoxNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let width = args.named("width")?; let height = args.named("height")?; - let body: LayoutNode = args.eat()?.unwrap_or_default(); - Ok(Content::inline(body.sized(Axes::new(width, height)))) + let body = args.eat::<Content>()?.unwrap_or_default(); + Ok(body.boxed(Axes::new(width, height))) + } +} + +impl Layout for BoxNode { + fn layout( + &self, + world: Tracked<dyn World>, + regions: &Regions, + styles: StyleChain, + ) -> SourceResult<Vec<Frame>> { + // The "pod" is the region into which the child will be layouted. + let pod = { + // Resolve the sizing to a concrete size. + let size = self + .sizing + .resolve(styles) + .zip(regions.base) + .map(|(s, b)| s.map(|v| v.relative_to(b))) + .unwrap_or(regions.first); + + // Select the appropriate base and expansion for the child depending + // on whether it is automatically or relatively sized. + let is_auto = self.sizing.as_ref().map(Option::is_none); + let base = is_auto.select(regions.base, size); + let expand = regions.expand | !is_auto; + + Regions::one(size, base, expand) + }; + + // Layout the child. + let mut frames = self.child.layout_inline(world, &pod, styles)?; + + // Ensure frame size matches regions size if expansion is on. + let frame = &mut frames[0]; + let target = regions.expand.select(regions.first, frame.size()); + frame.resize(target, Align::LEFT_TOP); + + Ok(frames) + } + + fn level(&self) -> Level { + Level::Inline } } /// A block-level container that places content into a separate flow. -pub struct BlockNode; +#[derive(Debug, Clone, Hash)] +pub struct BlockNode(pub Content); -#[node] +#[node(Layout)] impl BlockNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { - Ok(Content::Block(args.eat()?.unwrap_or_default())) + Ok(Self(args.eat()?.unwrap_or_default()).pack()) + } +} + +impl Layout for BlockNode { + fn layout( + &self, + world: Tracked<dyn World>, + regions: &Regions, + styles: StyleChain, + ) -> SourceResult<Vec<Frame>> { + self.0.layout_block(world, regions, styles) + } + + fn level(&self) -> Level { + Level::Block } } diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs index 1f0a2b4a..01ee9dc9 100644 --- a/src/library/layout/flow.rs +++ b/src/library/layout/flow.rs @@ -17,11 +17,14 @@ pub enum FlowChild { /// Vertical spacing between other children. Spacing(Spacing), /// An arbitrary block-level node. - Node(LayoutNode), + Node(Content), /// A column / region break. Colbreak, } +#[node(Layout)] +impl FlowNode {} + impl Layout for FlowNode { fn layout( &self, @@ -48,6 +51,10 @@ impl Layout for FlowNode { Ok(layouter.finish()) } + + fn level(&self) -> Level { + Level::Block + } } impl Debug for FlowNode { @@ -150,7 +157,7 @@ impl FlowLayouter { pub fn layout_node( &mut self, world: Tracked<dyn World>, - node: &LayoutNode, + node: &Content, styles: StyleChain, ) -> SourceResult<()> { // Don't even try layouting into a full region. @@ -162,7 +169,7 @@ impl FlowLayouter { // aligned later. if let Some(placed) = node.downcast::<PlaceNode>() { if placed.out_of_flow() { - let frame = node.layout(world, &self.regions, styles)?.remove(0); + let frame = node.layout_block(world, &self.regions, styles)?.remove(0); self.items.push(FlowItem::Placed(frame)); return Ok(()); } @@ -180,7 +187,7 @@ impl FlowLayouter { .unwrap_or(Align::Top), ); - let frames = node.layout(world, &self.regions, styles)?; + let frames = node.layout_block(world, &self.regions, styles)?; let len = frames.len(); for (i, mut frame) in frames.into_iter().enumerate() { // Set the generic block role. diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs index a1098c6d..7e5cbbd5 100644 --- a/src/library/layout/grid.rs +++ b/src/library/layout/grid.rs @@ -8,10 +8,10 @@ pub struct GridNode { /// Defines sizing of gutter rows and columns between content. pub gutter: Axes<Vec<TrackSizing>>, /// The nodes to be arranged in a grid. - pub cells: Vec<LayoutNode>, + pub cells: Vec<Content>, } -#[node] +#[node(Layout)] impl GridNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let columns = args.named("columns")?.unwrap_or_default(); @@ -19,14 +19,15 @@ impl GridNode { let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default(); let column_gutter = args.named("column-gutter")?; let row_gutter = args.named("row-gutter")?; - Ok(Content::block(Self { + Ok(Self { tracks: Axes::new(columns, rows), gutter: Axes::new( column_gutter.unwrap_or_else(|| base_gutter.clone()), row_gutter.unwrap_or(base_gutter), ), cells: args.all()?, - })) + } + .pack()) } } @@ -50,6 +51,10 @@ impl Layout for GridNode { // Measure the columns and layout the grid row-by-row. layouter.layout() } + + fn level(&self) -> Level { + Level::Block + } } /// Defines how to size a grid cell along an axis. @@ -95,7 +100,7 @@ pub struct GridLayouter<'a> { /// The core context. world: Tracked<'a, dyn World>, /// The grid cells. - cells: &'a [LayoutNode], + cells: &'a [Content], /// The column tracks including gutter tracks. cols: Vec<TrackSizing>, /// The row tracks including gutter tracks. @@ -136,7 +141,7 @@ impl<'a> GridLayouter<'a> { world: Tracked<'a, dyn World>, tracks: Axes<&[TrackSizing]>, gutter: Axes<&[TrackSizing]>, - cells: &'a [LayoutNode], + cells: &'a [Content], regions: &Regions, styles: StyleChain<'a>, ) -> Self { @@ -301,7 +306,8 @@ impl<'a> GridLayouter<'a> { v.resolve(self.styles).relative_to(self.regions.base.y); } - let frame = node.layout(self.world, &pod, self.styles)?.remove(0); + let frame = + node.layout_block(self.world, &pod, self.styles)?.remove(0); resolved.set_max(frame.width()); } } @@ -371,7 +377,7 @@ impl<'a> GridLayouter<'a> { } let mut sizes = node - .layout(self.world, &pod, self.styles)? + .layout_block(self.world, &pod, self.styles)? .into_iter() .map(|frame| frame.height()); @@ -460,7 +466,7 @@ impl<'a> GridLayouter<'a> { .select(self.regions.base, size); let pod = Regions::one(size, base, Axes::splat(true)); - let frame = node.layout(self.world, &pod, self.styles)?.remove(0); + let frame = node.layout_block(self.world, &pod, self.styles)?.remove(0); match frame.role() { Some(Role::ListLabel | Role::ListItemBody) => { output.apply_role(Role::ListItem) @@ -508,7 +514,7 @@ impl<'a> GridLayouter<'a> { } // Push the layouted frames into the individual output frames. - let frames = node.layout(self.world, &pod, self.styles)?; + let frames = node.layout_block(self.world, &pod, self.styles)?; for (output, frame) in outputs.iter_mut().zip(frames) { match frame.role() { Some(Role::ListLabel | Role::ListItemBody) => { @@ -576,7 +582,7 @@ impl<'a> GridLayouter<'a> { /// /// Returns `None` if it's a gutter cell. #[track_caller] - fn cell(&self, x: usize, y: usize) -> Option<&'a LayoutNode> { + fn cell(&self, x: usize, y: usize) -> Option<&'a Content> { assert!(x < self.cols.len()); assert!(y < self.rows.len()); diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs index b0238d40..effdd5f8 100644 --- a/src/library/layout/pad.rs +++ b/src/library/layout/pad.rs @@ -6,10 +6,10 @@ pub struct PadNode { /// The amount of padding. pub padding: Sides<Rel<Length>>, /// The child node whose sides to pad. - pub child: LayoutNode, + pub child: Content, } -#[node] +#[node(Layout)] impl PadNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let all = args.named("rest")?.or(args.find()?); @@ -19,9 +19,9 @@ impl PadNode { let top = args.named("top")?.or(y).or(all).unwrap_or_default(); let right = args.named("right")?.or(x).or(all).unwrap_or_default(); let bottom = args.named("bottom")?.or(y).or(all).unwrap_or_default(); - let body: LayoutNode = args.expect("body")?; + let body = args.expect::<Content>("body")?; let padding = Sides::new(left, top, right, bottom); - Ok(Content::block(body.padded(padding))) + Ok(body.padded(padding)) } } @@ -35,7 +35,7 @@ impl Layout for PadNode { // Layout child into padded regions. let padding = self.padding.resolve(styles); let pod = regions.map(|size| shrink(size, padding)); - let mut frames = self.child.layout(world, &pod, styles)?; + let mut frames = self.child.layout_block(world, &pod, styles)?; for frame in &mut frames { // Apply the padding inversely such that the grown size padded @@ -51,6 +51,10 @@ impl Layout for PadNode { Ok(frames) } + + fn level(&self) -> Level { + Level::Block + } } /// Shrink a size by padding relative to the size itself. diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs index 2e5cf2f9..f5821ae6 100644 --- a/src/library/layout/page.rs +++ b/src/library/layout/page.rs @@ -5,7 +5,7 @@ use crate::library::prelude::*; /// Layouts its child onto one or multiple pages. #[derive(PartialEq, Clone, Hash)] -pub struct PageNode(pub LayoutNode); +pub struct PageNode(pub Content); #[node] impl PageNode { @@ -41,7 +41,7 @@ impl PageNode { pub const FOREGROUND: Marginal = Marginal::None; fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { - Ok(Content::Page(Self(args.expect("body")?))) + Ok(Self(args.expect("body")?).pack()) } fn set(...) { @@ -96,7 +96,7 @@ impl PageNode { // Layout the child. let regions = Regions::repeat(size, size, size.map(Abs::is_finite)); - let mut frames = child.layout(world, ®ions, styles)?; + let mut frames = child.layout_block(world, ®ions, styles)?; let header = styles.get(Self::HEADER); let footer = styles.get(Self::FOOTER); @@ -127,7 +127,7 @@ impl PageNode { ] { if let Some(content) = marginal.resolve(world, page)? { let pod = Regions::one(area, area, Axes::splat(true)); - let mut sub = content.layout(world, &pod, styles)?.remove(0); + let mut sub = content.layout_block(world, &pod, styles)?.remove(0); sub.apply_role(role); if role == Role::Background { @@ -154,13 +154,16 @@ impl Debug for PageNode { } /// A page break. -pub struct PagebreakNode; +#[derive(Debug, Copy, Clone, Hash)] +pub struct PagebreakNode { + pub weak: bool, +} #[node] impl PagebreakNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let weak = args.named("weak")?.unwrap_or(false); - Ok(Content::Pagebreak { weak }) + Ok(Self { weak }.pack()) } } @@ -201,7 +204,7 @@ impl Cast<Spanned<Value>> for Marginal { fn cast(value: Spanned<Value>) -> StrResult<Self> { match value.v { Value::None => Ok(Self::None), - Value::Str(v) => Ok(Self::Content(Content::Text(v.into()))), + Value::Str(v) => Ok(Self::Content(TextNode(v.into()).pack())), Value::Content(v) => Ok(Self::Content(v)), Value::Func(v) => Ok(Self::Func(v, value.span)), v => Err(format!( diff --git a/src/library/layout/place.rs b/src/library/layout/place.rs index 8b68c087..42ab0fba 100644 --- a/src/library/layout/place.rs +++ b/src/library/layout/place.rs @@ -3,18 +3,16 @@ use crate::library::prelude::*; /// Place a node at an absolute position. #[derive(Debug, Hash)] -pub struct PlaceNode(pub LayoutNode); +pub struct PlaceNode(pub Content); -#[node] +#[node(Layout)] impl PlaceNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let aligns = args.find()?.unwrap_or(Axes::with_x(Some(RawAlign::Start))); let dx = args.named("dx")?.unwrap_or_default(); let dy = args.named("dy")?.unwrap_or_default(); - let body: LayoutNode = args.expect("body")?; - Ok(Content::block(Self( - body.moved(Axes::new(dx, dy)).aligned(aligns), - ))) + let body = args.expect::<Content>("body")?; + Ok(Self(body.moved(Axes::new(dx, dy)).aligned(aligns)).pack()) } } @@ -35,7 +33,7 @@ impl Layout for PlaceNode { Regions::one(regions.base, regions.base, expand) }; - let mut frames = self.0.layout(world, &pod, styles)?; + 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. @@ -44,6 +42,10 @@ impl Layout for PlaceNode { Ok(frames) } + + fn level(&self) -> Level { + Level::Block + } } impl PlaceNode { diff --git a/src/library/layout/spacing.rs b/src/library/layout/spacing.rs index 28e52d73..6df5cde5 100644 --- a/src/library/layout/spacing.rs +++ b/src/library/layout/spacing.rs @@ -4,26 +4,35 @@ use crate::library::prelude::*; use crate::library::text::ParNode; /// Horizontal spacing. -pub struct HNode; +#[derive(Debug, Clone, Hash)] +pub struct HNode { + pub amount: Spacing, + pub weak: bool, +} #[node] impl HNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let amount = args.expect("spacing")?; let weak = args.named("weak")?.unwrap_or(false); - Ok(Content::Horizontal { amount, weak }) + Ok(Self { amount, weak }.pack()) } } /// Vertical spacing. -pub struct VNode; +#[derive(Debug, Clone, Hash)] +pub struct VNode { + pub amount: Spacing, + pub weak: bool, + pub generated: bool, +} #[node] impl VNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let amount = args.expect("spacing")?; let weak = args.named("weak")?.unwrap_or(false); - Ok(Content::Vertical { amount, weak, generated: false }) + Ok(Self { amount, weak, generated: false }.pack()) } } diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs index b9663dd6..9ea7965d 100644 --- a/src/library/layout/stack.rs +++ b/src/library/layout/stack.rs @@ -1,6 +1,7 @@ use super::{AlignNode, Spacing}; use crate::library::prelude::*; use crate::library::text::ParNode; +use crate::model::StyledNode; /// Arrange nodes and spacing along an axis. #[derive(Debug, Hash)] @@ -13,14 +14,15 @@ pub struct StackNode { pub children: Vec<StackChild>, } -#[node] +#[node(Layout)] impl StackNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { - Ok(Content::block(Self { + Ok(Self { dir: args.named("dir")?.unwrap_or(Dir::TTB), spacing: args.named("spacing")?, children: args.all()?, - })) + } + .pack()) } } @@ -55,6 +57,10 @@ impl Layout for StackNode { Ok(layouter.finish()) } + + fn level(&self) -> Level { + Level::Block + } } /// A child of a stack node. @@ -63,7 +69,7 @@ pub enum StackChild { /// Spacing between other nodes. Spacing(Spacing), /// An arbitrary node. - Node(LayoutNode), + Node(Content), } impl Debug for StackChild { @@ -82,7 +88,7 @@ castable! { Value::Ratio(v) => Self::Spacing(Spacing::Relative(v.into())), Value::Relative(v) => Self::Spacing(Spacing::Relative(v)), Value::Fraction(v) => Self::Spacing(Spacing::Fractional(v)), - Value::Content(v) => Self::Node(v.pack()), + Value::Content(v) => Self::Node(v), } /// Performs stack layout. @@ -169,7 +175,7 @@ impl<'a> StackLayouter<'a> { pub fn layout_node( &mut self, world: Tracked<dyn World>, - node: &LayoutNode, + node: &Content, styles: StyleChain, ) -> SourceResult<()> { if self.regions.is_full() { @@ -183,17 +189,17 @@ impl<'a> StackLayouter<'a> { .and_then(|node| node.aligns.get(self.axis)) .map(|align| align.resolve(styles)) .unwrap_or_else(|| { - if let Some(Content::Styled(styled)) = node.downcast::<Content>() { - let map = &styled.1; + if let Some(styled) = node.downcast::<StyledNode>() { + let map = &styled.map; if map.contains(ParNode::ALIGN) { - return StyleChain::with_root(&styled.1).get(ParNode::ALIGN); + return StyleChain::with_root(map).get(ParNode::ALIGN); } } self.dir.start().into() }); - let frames = node.layout(world, &self.regions, styles)?; + let frames = node.layout_block(world, &self.regions, styles)?; let len = frames.len(); for (i, mut frame) in frames.into_iter().enumerate() { // Set the generic block role. diff --git a/src/library/layout/transform.rs b/src/library/layout/transform.rs index ff42744a..061efa6b 100644 --- a/src/library/layout/transform.rs +++ b/src/library/layout/transform.rs @@ -7,18 +7,19 @@ pub struct MoveNode { /// The offset by which to move the node. pub delta: Axes<Rel<Length>>, /// The node whose contents should be moved. - pub child: LayoutNode, + pub child: Content, } -#[node] +#[node(Layout)] impl MoveNode { fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> { let dx = args.named("dx")?.unwrap_or_default(); let dy = args.named("dy")?.unwrap_or_default(); - Ok(Content::inline(Self { + Ok(Self { delta: Axes::new(dx, dy), child: args.expect("body")?, - })) + } + .pack()) } } @@ -29,7 +30,7 @@ impl Layout for MoveNode { regions: &Regions, styles: StyleChain, ) -> SourceResult<Vec<Frame>> { - let mut frames = self.child.layout(world, regions, styles)?; + let mut frames = self.child.layout_inline(world, regions, styles)?; let delta = self.delta.resolve(styles); for frame in &mut frames { @@ -39,6 +40,10 @@ impl Layout for MoveNode { Ok(frames) } + + fn level(&self) -> Level { + Level::Inline + } } /// Transform a node without affecting layout. @@ -47,7 +52,7 @@ pub struct TransformNode<const T: TransformKind> { /// Transformation to apply to the contents. pub transform: Transform, /// The node whose contents should be transformed. - pub child: LayoutNode, + pub child: Content, } /// Rotate a node without affecting layout. @@ -56,7 +61,7 @@ pub type RotateNode = TransformNode<ROTATE>; /// Scale a node without affecting layout. pub type ScaleNode = TransformNode<SCALE>; -#[node] +#[node(Layout)] impl<const T: TransformKind> TransformNode<T> { /// The origin of the transformation. #[property(resolve)] @@ -76,10 +81,7 @@ impl<const T: TransformKind> TransformNode<T> { } }; - Ok(Content::inline(Self { - transform, - child: args.expect("body")?, - })) + Ok(Self { transform, child: args.expect("body")? }.pack()) } } @@ -91,7 +93,7 @@ impl<const T: TransformKind> Layout for TransformNode<T> { styles: StyleChain, ) -> SourceResult<Vec<Frame>> { let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON); - let mut frames = self.child.layout(world, regions, styles)?; + let mut frames = self.child.layout_inline(world, regions, styles)?; for frame in &mut frames { let Axes { x, y } = origin.zip(frame.size()).map(|(o, s)| o.position(s)); @@ -104,6 +106,10 @@ impl<const T: TransformKind> Layout for TransformNode<T> { Ok(frames) } + + fn level(&self) -> Level { + Level::Inline + } } /// Kinds of transformations. |
