diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-02-14 12:08:05 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-02-14 12:08:05 +0100 |
| commit | cc9b52ddd4defa3894ee3a4b28e411fa0b0991ba (patch) | |
| tree | 56594649ee2ce36fe5b3687c72e07c50e7b6b8dd /library/src/layout/table.rs | |
| parent | e64b2379a88c169c087403c5ae90e98911c0fe7a (diff) | |
Better table lines
Diffstat (limited to 'library/src/layout/table.rs')
| -rw-r--r-- | library/src/layout/table.rs | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/library/src/layout/table.rs b/library/src/layout/table.rs index 1ceea9b9..3084c3d4 100644 --- a/library/src/layout/table.rs +++ b/library/src/layout/table.rs @@ -1,4 +1,4 @@ -use crate::layout::{AlignNode, GridNode, Sizing, TrackSizings}; +use crate::layout::{AlignNode, GridLayouter, Sizing, TrackSizings}; use crate::prelude::*; /// # Table @@ -153,13 +153,11 @@ impl Layout for TableNode { styles: StyleChain, regions: Regions, ) -> SourceResult<Fragment> { - let fill = styles.get(Self::FILL); - let stroke = styles.get(Self::STROKE).map(PartialStroke::unwrap_or_default); let inset = styles.get(Self::INSET); let align = styles.get(Self::ALIGN); let cols = self.tracks.x.len().max(1); - let cells = self + let cells: Vec<_> = self .cells .iter() .cloned() @@ -173,27 +171,81 @@ impl Layout for TableNode { child = child.styled(AlignNode::ALIGNS, alignment) } - if let Some(stroke) = stroke { - child = child.stroked(stroke); - } - - if let Some(fill) = fill.resolve(vt, x, y)? { - child = child.filled(fill); - } - Ok(child) }) .collect::<SourceResult<_>>()?; - GridNode { - tracks: self.tracks.clone(), - gutter: self.gutter.clone(), - cells, + let fill = styles.get(Self::FILL); + let stroke = styles.get(Self::STROKE).map(PartialStroke::unwrap_or_default); + + // Prepare grid layout by unifying content and gutter tracks. + let layouter = GridLayouter::new( + vt, + self.tracks.as_deref(), + self.gutter.as_deref(), + &cells, + regions, + styles, + ); + + // Measure the columns and layout the grid row-by-row. + let mut layout = layouter.layout()?; + + // Add lines and backgrounds. + for (frame, rows) in layout.fragment.iter_mut().zip(&layout.rows) { + // Render table lines. + if let Some(stroke) = stroke { + let thickness = stroke.thickness; + let half = thickness / 2.0; + + // Render horizontal lines. + for offset in points(rows.iter().map(|piece| piece.height)) { + let target = Point::with_x(frame.width() + thickness); + let hline = Geometry::Line(target).stroked(stroke); + frame.prepend(Point::new(-half, offset), Element::Shape(hline)); + } + + // Render vertical lines. + for offset in points(layout.cols.iter().copied()) { + let target = Point::with_y(frame.height() + thickness); + let vline = Geometry::Line(target).stroked(stroke); + frame.prepend(Point::new(offset, -half), Element::Shape(vline)); + } + } + + // Render cell backgrounds. + let mut dx = Abs::zero(); + for (x, &col) in layout.cols.iter().enumerate() { + let mut dy = Abs::zero(); + for row in rows { + if let Some(fill) = fill.resolve(vt, x, row.y)? { + let pos = Point::new(dx, dy); + let size = Size::new(col, row.height); + let rect = Geometry::Rect(size).filled(fill); + frame.prepend(pos, Element::Shape(rect)); + } + dy += row.height; + } + dx += col; + } } - .layout(vt, styles, regions) + + Ok(layout.fragment) } } +/// Turn an iterator extents into an iterator of offsets before, in between, and +/// after the extents, e.g. [10mm, 5mm] -> [0mm, 10mm, 15mm]. +fn points(extents: impl IntoIterator<Item = Abs>) -> impl Iterator<Item = Abs> { + let mut offset = Abs::zero(); + std::iter::once(Abs::zero()) + .chain(extents.into_iter()) + .map(move |extent| { + offset += extent; + offset + }) +} + /// A value that can be configured per cell. #[derive(Debug, Clone, PartialEq, Hash)] pub enum Celled<T> { |
