This document captures design and implementation notes for Sparkline.
For end-user usage and examples, see Sparkline.
LineChart / Canvas for richer charts)src/XenoAtom.Terminal.UI/Controls/Sparkline.cssrc/XenoAtom.Terminal.UI/Styling/SparklineStyle.cssrc/XenoAtom.Terminal.UI.Tests/VisualizationTests.cs (sparkline rendering)samples/ControlsDemo/Demos/SparklineDemo.csSparkline : Visual (sealed)Values : BindableList<double>
Minimum : double? (bindable)
Maximum : double? (bindable)
There are no events and no input handling.
The sparkline measures as a one-row fixed-size visual:
Values.CountImplementation details:
MeasureCore returns SizeHints.Fixed(constraints.Clamp(new Size(max(0, Values.Count), 1))).The sparkline renders into Bounds (single row) and uses SparklineStyle for:
SparklineStyle.Glyphs)SparklineStyle.Resolve(theme))Scaling uses a min/max range:
Minimum and/or Maximum are not provided, they are computed from Values by scanning the list onceNaN and infinities are ignored during min/max computation and samplingmax <= min, the code forces max = min + 1.0 to avoid division by zeroWhen Bounds.Width is smaller than Values.Count, the sparkline down-samples values into buckets.
For each output column x:
start = (x * count) / widthend = ((x + 1) * count) / widthend <= start, clamp end = min(count, start + 1)Using the bucket maximum preserves spikes: a single high sample will still show up in the downsampled output.
When Bounds.Width is larger than Values.Count, the integer mapping causes some buckets to repeat the same input
indices, effectively stretching the series horizontally.
Each sampled value is normalized to a [0..1] range and mapped to 8 levels:
t = (sample - min) / (max - min) clamped to [0..1]level = round(t * 7) (0..7)rune = glyphs.GetLevel(level)Note: the default glyph set (Blocks8) uses non-ASCII block glyphs in code. Specs and docs should avoid embedding those
glyph characters directly; refer to glyph set names instead.
SparklineStyle controls:
Glyphs : SparklineGlyphs (default: Blocks8)Style : Style? overrideSparklineStyle.Resolve(theme) returns:
Style if explicitly providedtheme.ForegroundTextStyle() with theme.Accent as the foreground when availableThe sparkline does not fill background cells; it only sets the single rune per output column with the resolved style.
VisualizationTests.Sparkline_Renders_Block_Glyphs validates that rendering produces block glyph output by checking for
the presence of the expected code points (e.g., U+2581..U+2588) when using the default glyph set.
SparklineStyle.Sparkline).