summaryrefslogtreecommitdiff
path: root/src/library/structure/table.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/structure/table.rs')
-rw-r--r--src/library/structure/table.rs160
1 files changed, 0 insertions, 160 deletions
diff --git a/src/library/structure/table.rs b/src/library/structure/table.rs
deleted file mode 100644
index 8a4eb302..00000000
--- a/src/library/structure/table.rs
+++ /dev/null
@@ -1,160 +0,0 @@
-use crate::library::layout::{BlockSpacing, GridNode, TrackSizing};
-use crate::library::prelude::*;
-
-/// A table of items.
-#[derive(Debug, Hash)]
-pub struct TableNode {
- /// Defines sizing for content rows and columns.
- pub tracks: Axes<Vec<TrackSizing>>,
- /// Defines sizing of gutter rows and columns between content.
- pub gutter: Axes<Vec<TrackSizing>>,
- /// The content to be arranged in the table.
- pub cells: Vec<Content>,
-}
-
-#[node(Show)]
-impl TableNode {
- /// How to fill the cells.
- #[property(referenced)]
- pub const FILL: Celled<Option<Paint>> = Celled::Value(None);
- /// How to stroke the cells.
- #[property(resolve, fold)]
- pub const STROKE: Option<RawStroke> = Some(RawStroke::default());
- /// How much to pad the cells's content.
- pub const PADDING: Rel<Length> = Abs::pt(5.0).into();
-
- /// The spacing above the table.
- #[property(resolve, shorthand(around))]
- pub const ABOVE: Option<BlockSpacing> = Some(Ratio::one().into());
- /// The spacing below the table.
- #[property(resolve, shorthand(around))]
- pub const BELOW: Option<BlockSpacing> = Some(Ratio::one().into());
-
- fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
- let columns = args.named("columns")?.unwrap_or_default();
- let rows = args.named("rows")?.unwrap_or_default();
- 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(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())
- }
-}
-
-impl Show for TableNode {
- fn unguard_parts(&self, sel: Selector) -> Content {
- Self {
- tracks: self.tracks.clone(),
- gutter: self.gutter.clone(),
- cells: self.cells.iter().map(|cell| cell.unguard(sel)).collect(),
- }
- .pack()
- }
-
- fn field(&self, name: &str) -> Option<Value> {
- match name {
- "cells" => Some(Value::Array(
- self.cells.iter().cloned().map(Value::Content).collect(),
- )),
- _ => None,
- }
- }
-
- fn realize(
- &self,
- world: Tracked<dyn World>,
- styles: StyleChain,
- ) -> SourceResult<Content> {
- let fill = styles.get(Self::FILL);
- let stroke = styles.get(Self::STROKE).map(RawStroke::unwrap_or_default);
- let padding = styles.get(Self::PADDING);
-
- let cols = self.tracks.x.len().max(1);
- let cells = self
- .cells
- .iter()
- .cloned()
- .enumerate()
- .map(|(i, child)| {
- let mut child = child.padded(Sides::splat(padding));
-
- if let Some(stroke) = stroke {
- child = child.stroked(stroke);
- }
-
- let x = i % cols;
- let y = i / cols;
- if let Some(fill) = fill.resolve(world, x, y)? {
- child = child.filled(fill);
- }
-
- Ok(child)
- })
- .collect::<SourceResult<_>>()?;
-
- Ok(GridNode {
- tracks: self.tracks.clone(),
- gutter: self.gutter.clone(),
- cells,
- }
- .pack())
- }
-
- fn finalize(
- &self,
- _: Tracked<dyn World>,
- styles: StyleChain,
- realized: Content,
- ) -> SourceResult<Content> {
- Ok(realized.spaced(styles.get(Self::ABOVE), styles.get(Self::BELOW)))
- }
-}
-
-/// A value that can be configured per cell.
-#[derive(Debug, Clone, PartialEq, Hash)]
-pub enum Celled<T> {
- /// A bare value, the same for all cells.
- Value(T),
- /// A closure mapping from cell coordinates to a value.
- Func(Func, Span),
-}
-
-impl<T: Cast + Clone> Celled<T> {
- /// Resolve the value based on the cell position.
- pub fn resolve(
- &self,
- world: Tracked<dyn World>,
- x: usize,
- y: usize,
- ) -> SourceResult<T> {
- Ok(match self {
- Self::Value(value) => value.clone(),
- Self::Func(func, span) => {
- let args = Args::new(*span, [Value::Int(x as i64), Value::Int(y as i64)]);
- func.call_detached(world, args)?.cast().at(*span)?
- }
- })
- }
-}
-
-impl<T: Cast> Cast<Spanned<Value>> for Celled<T> {
- fn is(value: &Spanned<Value>) -> bool {
- matches!(&value.v, Value::Func(_)) || T::is(&value.v)
- }
-
- fn cast(value: Spanned<Value>) -> StrResult<Self> {
- match value.v {
- Value::Func(v) => Ok(Self::Func(v, value.span)),
- v => T::cast(v)
- .map(Self::Value)
- .map_err(|msg| with_alternative(msg, "function")),
- }
- }
-}