From 6536e9e069616b862ebb774c7bef1b886c069350 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 16 May 2022 16:04:40 +0200 Subject: Table fill closure --- src/library/structure/table.rs | 60 +++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/library/structure/table.rs b/src/library/structure/table.rs index b983a7ea..f39ea978 100644 --- a/src/library/structure/table.rs +++ b/src/library/structure/table.rs @@ -14,12 +14,9 @@ pub struct TableNode { #[node(showable)] impl TableNode { - /// The primary cell fill color. - #[property(shorthand(fill))] - pub const PRIMARY: Option = None; - /// The secondary cell fill color. - #[property(shorthand(fill))] - pub const SECONDARY: Option = None; + /// How to fill the cells. + #[property(referenced)] + pub const FILL: Celled> = Celled::Value(None); /// How to stroke the cells. #[property(resolve, fold)] pub const STROKE: Option = Some(RawStroke::default()); @@ -71,9 +68,8 @@ impl Show for TableNode { } } - fn realize(&self, _: &mut Context, styles: StyleChain) -> TypResult { - let primary = styles.get(Self::PRIMARY); - let secondary = styles.get(Self::SECONDARY); + fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult { + let fill = styles.get(Self::FILL); let stroke = styles.get(Self::STROKE).map(RawStroke::unwrap_or_default); let padding = styles.get(Self::PADDING); @@ -92,13 +88,13 @@ impl Show for TableNode { let x = i % cols; let y = i / cols; - if let Some(fill) = [primary, secondary][(x + y) % 2] { + if let Some(fill) = fill.resolve(ctx, x, y)? { child = child.filled(fill); } - child + Ok(child) }) - .collect(); + .collect::>()?; Ok(Content::block(GridNode { tracks: self.tracks.clone(), @@ -116,3 +112,43 @@ impl Show for TableNode { 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 { + /// A bare value, the same for all cells. + Value(T), + /// A closure mapping from cell coordinates to a value. + Func(Func, Span), +} + +impl Celled { + /// Resolve the value based on the cell position. + pub fn resolve(&self, ctx: &mut Context, x: usize, y: usize) -> TypResult { + Ok(match self { + Self::Value(value) => value.clone(), + Self::Func(func, span) => { + let args = Args::from_values(*span, [ + Value::Int(x as i64), + Value::Int(y as i64), + ]); + func.call(ctx, args)?.cast().at(*span)? + } + }) + } +} + +impl Cast> for Celled { + fn is(value: &Spanned) -> bool { + matches!(&value.v, Value::Func(_)) || T::is(&value.v) + } + + fn cast(value: Spanned) -> StrResult { + 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")), + } + } +} -- cgit v1.2.3