diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-02-28 15:50:48 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-02-28 23:54:34 +0100 |
| commit | 3ca5b238238e1128aa7bbfbd5db9e632045d8600 (patch) | |
| tree | 2471f4b340a15695b7f4d518c0b39fabaea676c4 /src/library/elements/table.rs | |
| parent | b63c21c91d99a1554a019dc275f955d3e6a34271 (diff) | |
Reorganize library
Diffstat (limited to 'src/library/elements/table.rs')
| -rw-r--r-- | src/library/elements/table.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/library/elements/table.rs b/src/library/elements/table.rs new file mode 100644 index 00000000..555dcc44 --- /dev/null +++ b/src/library/elements/table.rs @@ -0,0 +1,100 @@ +use crate::library::layout::{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: Spec<Vec<TrackSizing>>, + /// Defines sizing of gutter rows and columns between content. + pub gutter: Spec<Vec<TrackSizing>>, + /// The nodes to be arranged in the table. + pub children: Vec<Template>, +} + +#[class] +impl TableNode { + /// The primary cell fill color. + pub const PRIMARY: Option<Paint> = None; + /// The secondary cell fill color. + pub const SECONDARY: Option<Paint> = None; + /// How the stroke the cells. + pub const STROKE: Option<Paint> = Some(Color::BLACK.into()); + /// The stroke's thickness. + pub const THICKNESS: Length = Length::pt(1.0); + /// How much to pad the cells's content. + pub const PADDING: Linear = Length::pt(5.0).into(); + + fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> { + 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(Template::show(Self { + tracks: Spec::new(columns, rows), + gutter: Spec::new( + column_gutter.unwrap_or_else(|| base_gutter.clone()), + row_gutter.unwrap_or(base_gutter), + ), + children: args.all()?, + })) + } + + fn set(args: &mut Args, styles: &mut StyleMap) -> TypResult<()> { + let fill = args.named("fill")?; + styles.set_opt(Self::PRIMARY, args.named("primary")?.or(fill)); + styles.set_opt(Self::SECONDARY, args.named("secondary")?.or(fill)); + styles.set_opt(Self::STROKE, args.named("stroke")?); + styles.set_opt(Self::THICKNESS, args.named("thickness")?); + styles.set_opt(Self::PADDING, args.named("padding")?); + Ok(()) + } +} + +impl Show for TableNode { + fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> { + if let Some(template) = styles.show( + self, + ctx, + self.children.iter().map(|child| Value::Template(child.clone())), + )? { + return Ok(template); + } + + let primary = styles.get(Self::PRIMARY); + let secondary = styles.get(Self::SECONDARY); + let thickness = styles.get(Self::THICKNESS); + let stroke = styles.get(Self::STROKE).map(|paint| Stroke { paint, thickness }); + let padding = styles.get(Self::PADDING); + + let cols = self.tracks.x.len().max(1); + let children = self + .children + .iter() + .cloned() + .enumerate() + .map(|(i, child)| { + let mut child = child.pack().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) = [primary, secondary][(x + y) % 2] { + child = child.filled(fill); + } + + child + }) + .collect(); + + Ok(Template::block(GridNode { + tracks: self.tracks.clone(), + gutter: self.gutter.clone(), + children, + })) + } +} |
