diff --git a/.gitignore b/.gitignore index 97e9bcb..d984289 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ # Exclude MacOS attribute files. .DS_Store + +# Exclude IDE files. +.idea/ \ No newline at end of file diff --git a/widgets/heatmap/heatmap.go b/widgets/heatmap/heatmap.go index 9b00c0a..b262489 100644 --- a/widgets/heatmap/heatmap.go +++ b/widgets/heatmap/heatmap.go @@ -20,7 +20,6 @@ import ( "fmt" "image" "math" - "sort" "sync" "github.com/mum4k/termdash/cell" @@ -89,36 +88,31 @@ func NewHeatMap(opts ...Option) (*HeatMap, error) { }, nil } -// SetColumns sets the HeatMap's values, min and max values. -func (hp *HeatMap) SetColumns(values map[string][]int64) { +// SetColumns sets the HeatMap's X-Labels, values, min and max values. +func (hp *HeatMap) SetColumns(xLabels []string, values map[string][]int64) error { hp.mu.Lock() defer hp.mu.Unlock() - var minMaxValues []int64 - - // The iteration order of map is uncertain, so the keys must be sorted explicitly. - var names []string - for name := range values { - names = append(names, name) + if len(xLabels) != len(values) { + return errors.New("the number of x-axis labels does not match the amount of column data") } - sort.Strings(names) // Clear XLabels and columns. - if len(hp.XLabels) > 0 { - hp.XLabels = hp.XLabels[:0] - } - hp.columns = make(map[string]*columnValues) - - for _, name := range names { - cv := newColumnValues(values[name]) - hp.columns[name] = cv - hp.XLabels = append(hp.XLabels, name) + hp.XLabels = hp.XLabels[:0] + hp.columns = make(map[string]*columnValues, len(xLabels)) + hp.XLabels = append(hp.XLabels, xLabels...) + var minMaxValues []int64 + for _, label := range xLabels { + cv := newColumnValues(values[label]) + hp.columns[label] = cv minMaxValues = append(minMaxValues, cv.Min) minMaxValues = append(minMaxValues, cv.Max) } hp.MinValue, hp.MaxValue = minMax(minMaxValues) + + return nil } // SetYLabels sets HeatMap's Y-Labels. @@ -127,10 +121,7 @@ func (hp *HeatMap) SetYLabels(labels []string) { defer hp.mu.Unlock() // Clear YLabels. - if len(hp.YLabels) > 0 { - hp.YLabels = hp.YLabels[:0] - } - + hp.YLabels = hp.YLabels[:0] hp.YLabels = append(hp.YLabels, labels...) // Reverse the array. diff --git a/widgets/heatmap/heatmapdemo/heatmapdemo.go b/widgets/heatmap/heatmapdemo/heatmapdemo.go index f67295a..b749a96 100644 --- a/widgets/heatmap/heatmapdemo/heatmapdemo.go +++ b/widgets/heatmap/heatmapdemo/heatmapdemo.go @@ -15,3 +15,79 @@ // Binary heatmapdemo displays a heatmap widget. // Exist when 'q' is pressed. package main + +import ( + "context" + "github.com/mum4k/termdash" + "github.com/mum4k/termdash/container" + "github.com/mum4k/termdash/linestyle" + "github.com/mum4k/termdash/terminal/termbox" + "github.com/mum4k/termdash/terminal/terminalapi" + "github.com/mum4k/termdash/widgets/heatmap" +) + +func main() { + xLabels := []string{ + "12:00", + "12:05", + "12:10", + "12:15", + "12:20", + } + yLabels := []string{ + "10", + "20", + "30", + "40", + "50", + "60", + "70", + "80", + "90", + "100", + } + values := map[string][]int64{ + "12:00": {10, 20, 30, 40, 50, 50, 40, 30, 20, 10}, + "12:05": {50, 40, 30, 20, 10, 10, 20, 30, 40, 50}, + "12:10": {10, 20, 30, 40, 50, 50, 40, 30, 20, 10}, + "12:15": {50, 40, 30, 20, 10, 10, 20, 30, 40, 50}, + "12:20": {10, 20, 30, 40, 50, 50, 40, 30, 0, 0}, + } + + t, err := termbox.New() + if err != nil { + panic(err) + } + defer t.Close() + + hp, err := heatmap.NewHeatMap() + if err != nil { + panic(err) + } + if err := hp.SetColumns(xLabels, values); err != nil { + panic(err) + } + hp.SetYLabels(yLabels) + + c, err := container.New( + t, + container.Border(linestyle.Light), + container.BorderTitle("PRESS Q TO QUIT"), + container.PlaceWidget(hp), + ) + if err != nil { + panic(err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + quitter := func(k *terminalapi.Keyboard) { + if k.Key == 'q' || k.Key == 'Q' { + cancel() + } + } + + if err := termdash.Run(ctx, t, c, termdash.KeyboardSubscriber(quitter)); err != nil { + panic(err) + } +}