core/linechart/linechart.go

Functions Structs

Functions

func AddSeries

AddSeries adds a named data series with the given color.

If a series with the same label already exists, this is a no-op.

Safe to call from any goroutine.

func (w *Widget) AddSeries(label string, color widget.Color) {
	w.mu.Lock()
	defer w.mu.Unlock()

	for _, s := range w.series {
		if s.Label == label {
			return
		}
	}

	w.series = append(w.series, Series{
		Label:	label,
		Color:	color,
		Points:	make([]DataPoint, 0, w.cfg.maxPoints),
	})
	w.syncToSignal()
	w.SetNeedsRedraw(true)
}

func BackgroundColor

BackgroundColor sets the chart background fill color.

func BackgroundColor(color widget.Color) Option {
	return func(c *config) {
		c.background = color
	}
}

func Children

Children returns nil because a line chart is a leaf widget.

func (w *Widget) Children() []widget.Widget {
	return nil
}

func ClearSeries

ClearSeries removes all data points from the named series.

Safe to call from any goroutine.

func (w *Widget) ClearSeries(label string) {
	w.mu.Lock()
	defer w.mu.Unlock()

	for i := range w.series {
		if w.series[i].Label == label {
			w.series[i].Points = w.series[i].Points[:0]
			w.syncToSignal()
			w.SetNeedsRedraw(true)
			return
		}
	}
}

func Draw

Draw renders the chart to the canvas.

func (w *Widget) Draw(_ widget.Context, canvas widget.Canvas) {
	bounds := w.Bounds()
	if bounds.IsEmpty() {
		return
	}

	// Build PaintState from current data.
	chartState := w.buildPaintState()
	w.painter.PaintChart(canvas, bounds, chartState)
}

func Event

Event handles an input event and returns true if consumed.

LineChart is a display-only widget and does not consume events.

func (w *Widget) Event(_ widget.Context, _ event.Event) bool {
	return false
}

func GridColor

GridColor sets the color used for grid lines.

func GridColor(color widget.Color) Option {
	return func(c *config) {
		c.gridColor = color
	}
}

func Layout

Layout calculates the chart's preferred size within the given constraints.

func (w *Widget) Layout(_ widget.Context, constraints geometry.Constraints) geometry.Size {
	width := constraints.MaxWidth
	if width <= 0 || width == geometry.Infinity {
		width = defaultWidth + w.padding*2
	}
	height := defaultHeight + w.padding*2
	return constraints.Constrain(geometry.Sz(width, height))
}

func MaxPoints

MaxPoints sets the rolling window size (number of data points displayed).

Default is 60.

func MaxPoints(n int) Option {
	return func(c *config) {
		if n > 0 {
			c.maxPoints = n
		}
	}
}

func Mount

Mount creates signal bindings for push-based invalidation.

Implements [widget.Lifecycle].

func (w *Widget) Mount(ctx widget.Context) {
	sched := ctx.Scheduler()
	if sched == nil {
		return
	}
	if w.cfg.readonlySeriesSignal != nil {
		b := state.BindToScheduler(w.cfg.readonlySeriesSignal, w, sched)
		w.AddBinding(b)
	} else if w.cfg.seriesSignal != nil {
		b := state.BindToScheduler(w.cfg.seriesSignal, w, sched)
		w.AddBinding(b)
	}
}

func New

New creates a new line chart Widget with the given options.

 

The returned widget is visible and enabled by default.

The default Y range is [0, 100] with a rolling window of 60 points.

func New(opts ...Option) *Widget {
	w := &Widget{
		padding:	defaultPadding,
		painter:	DefaultPainter{},
	}
	w.SetVisible(true)
	w.SetEnabled(true)

	// Default config.
	w.cfg.maxPoints = defaultMaxPoints
	w.cfg.yMin = defaultYMin
	w.cfg.yMax = defaultYMax
	w.cfg.background = defaultBackground
	w.cfg.gridColor = defaultGridColor

	for _, opt := range opts {
		opt(&w.cfg)
	}

	// Apply painter from config if set.
	if w.cfg.painter != nil {
		w.painter = w.cfg.painter
	}

	// Copy initial static series into mutable state.
	if len(w.cfg.series) > 0 {
		w.series = make([]Series, len(w.cfg.series))
		copy(w.series, w.cfg.series)
	}

	return w
}

func Padding

Padding sets the padding around the chart area.

Returns the widget for method chaining.

func (w *Widget) Padding(v float32) *Widget {
	w.padding = v
	return w
}

func PainterOpt

PainterOpt sets the painter used to render the chart.

Each design system provides its own painter. If not set,

[DefaultPainter] is used.

func PainterOpt(p Painter) Option {
	return func(c *config) {
		c.painter = p
	}
}

func PushValue

PushValue appends a data point to the named series. If the series has

reached MaxPoints, the oldest point is removed (rolling window).

Safe to call from any goroutine.

func (w *Widget) PushValue(label string, value float64) {
	w.mu.Lock()
	defer w.mu.Unlock()

	for i := range w.series {
		if w.series[i].Label != label {
			continue
		}

		pts := w.series[i].Points
		if len(pts) >= w.cfg.maxPoints {
			// Shift left: drop oldest point.
			copy(pts, pts[1:])
			pts[len(pts)-1] = DataPoint{Value: value}
		} else {
			pts = append(pts, DataPoint{Value: value})
		}
		w.series[i].Points = pts
		w.syncToSignal()
		w.SetNeedsRedraw(true)
		return
	}
}

func SeriesCount

SeriesCount returns the number of series. Safe to call from any goroutine.

func (w *Widget) SeriesCount() int {
	w.mu.Lock()
	defer w.mu.Unlock()
	return len(w.series)
}

func SeriesData

SeriesData sets the initial static series data.

func SeriesData(s []Series) Option {
	return func(c *config) {
		c.series = s
	}
}

func SeriesFn

SeriesFn sets a dynamic function that returns the current series data.

When set, this takes precedence over the static data but not over

a signal set via [SeriesSignal].

func SeriesFn(fn func() []Series) Option {
	return func(c *config) {
		c.seriesFn = fn
	}
}

func SeriesReadonlySignal

SeriesReadonlySignal binds the chart's series data to a read-only signal.

This is useful for computed signals. When set, this takes highest precedence.

func SeriesReadonlySignal(sig state.ReadonlySignal[[]Series]) Option {
	return func(c *config) {
		c.readonlySeriesSignal = sig
	}
}

func SeriesSignal

SeriesSignal binds the chart's series data to a reactive signal.

This is a TWO-WAY binding: the widget reads series from the signal,

and when PushValue modifies series, the signal is updated.

func SeriesSignal(sig state.Signal[[]Series]) Option {
	return func(c *config) {
		c.seriesSignal = sig
	}
}

func ShowGrid

ShowGrid enables or disables grid lines. Default is false.

func ShowGrid(v bool) Option {
	return func(c *config) {
		c.showGrid = v
	}
}

func ShowLabels

ShowLabels enables or disables Y axis labels. Default is false.

func ShowLabels(v bool) Option {
	return func(c *config) {
		c.showLabels = v
	}
}

func Unmount

Unmount is called when the chart is removed from the widget tree.

Implements [widget.Lifecycle].

func (w *Widget) Unmount() {
	// Bindings are cleaned up automatically by WidgetBase.CleanupBindings().
}

func YRange

YRange sets the Y axis range [yMin, yMax].

Default is [0, 100].

func YRange(yMin, yMax float64) Option {
	return func(c *config) {
		c.yMin = yMin
		c.yMax = yMax
	}
}

Structs

type DataPoint struct

DataPoint represents a single data value in a series.

type DataPoint struct {
	Value float64
}

type Series struct

Series represents a named collection of data points with a display color.

type Series struct {
	Label	string
	Color	widget.Color
	Points	[]DataPoint
}

type Widget struct

Widget implements a real-time line chart for visualizing time-series data.

 

A line chart is created with [New] using functional options:

 

chart := linechart.New(

linechart.MaxPoints(60),

linechart.YRange(0, 100),

linechart.ShowGrid(true),

)

 

Data is pushed with [Widget.AddSeries] and [Widget.PushValue], which are

safe to call from any goroutine.

type Widget struct {
	widget.WidgetBase
	cfg	config
	painter	Painter

	// mu protects series data for concurrent PushValue calls.
	mu	sync.Mutex
	series	[]Series

	// Styling overrides set via fluent methods.
	padding	float32
}