2019-01-23 21:12:10 -07:00
|
|
|
// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
|
2022-08-28 10:46:41 -06:00
|
|
|
// Use of this source code is governed by a GPLv3 license that can
|
2019-01-23 21:12:10 -07:00
|
|
|
// be found in the LICENSE file.
|
|
|
|
|
|
|
|
package widgets
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
|
|
|
|
2022-08-28 10:37:35 -06:00
|
|
|
. "git.tebitea.media/sashakoshka/termui/v3"
|
2019-01-23 21:12:10 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
|
|
|
|
type Sparkline struct {
|
|
|
|
Data []float64
|
|
|
|
Title string
|
|
|
|
TitleStyle Style
|
|
|
|
LineColor Color
|
|
|
|
MaxVal float64
|
|
|
|
MaxHeight int // TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
// SparklineGroup is a renderable widget which groups together the given sparklines.
|
|
|
|
type SparklineGroup struct {
|
|
|
|
Block
|
|
|
|
Sparklines []*Sparkline
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSparkline returns a unrenderable single sparkline that needs to be added to a SparklineGroup
|
|
|
|
func NewSparkline() *Sparkline {
|
|
|
|
return &Sparkline{
|
|
|
|
TitleStyle: Theme.Sparkline.Title,
|
|
|
|
LineColor: Theme.Sparkline.Line,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSparklineGroup(sls ...*Sparkline) *SparklineGroup {
|
|
|
|
return &SparklineGroup{
|
|
|
|
Block: *NewBlock(),
|
|
|
|
Sparklines: sls,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *SparklineGroup) Draw(buf *Buffer) {
|
|
|
|
self.Block.Draw(buf)
|
|
|
|
|
|
|
|
sparklineHeight := self.Inner.Dy() / len(self.Sparklines)
|
|
|
|
|
|
|
|
for i, sl := range self.Sparklines {
|
|
|
|
heightOffset := (sparklineHeight * (i + 1))
|
|
|
|
barHeight := sparklineHeight
|
|
|
|
if i == len(self.Sparklines)-1 {
|
|
|
|
heightOffset = self.Inner.Dy()
|
|
|
|
barHeight = self.Inner.Dy() - (sparklineHeight * i)
|
|
|
|
}
|
|
|
|
if sl.Title != "" {
|
|
|
|
barHeight--
|
|
|
|
}
|
|
|
|
|
|
|
|
maxVal := sl.MaxVal
|
|
|
|
if maxVal == 0 {
|
|
|
|
maxVal, _ = GetMaxFloat64FromSlice(sl.Data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw line
|
|
|
|
for j := 0; j < len(sl.Data) && j < self.Inner.Dx(); j++ {
|
|
|
|
data := sl.Data[j]
|
|
|
|
height := int((data / maxVal) * float64(barHeight))
|
|
|
|
sparkChar := BARS[len(BARS)-1]
|
|
|
|
for k := 0; k < height; k++ {
|
|
|
|
buf.SetCell(
|
|
|
|
NewCell(sparkChar, NewStyle(sl.LineColor)),
|
|
|
|
image.Pt(j+self.Inner.Min.X, self.Inner.Min.Y-1+heightOffset-k),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
if height == 0 {
|
2019-01-24 09:42:13 -07:00
|
|
|
sparkChar = BARS[1]
|
2019-01-23 21:12:10 -07:00
|
|
|
buf.SetCell(
|
|
|
|
NewCell(sparkChar, NewStyle(sl.LineColor)),
|
|
|
|
image.Pt(j+self.Inner.Min.X, self.Inner.Min.Y-1+heightOffset),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if sl.Title != "" {
|
|
|
|
// draw title
|
|
|
|
buf.SetString(
|
|
|
|
TrimString(sl.Title, self.Inner.Dx()),
|
|
|
|
sl.TitleStyle,
|
|
|
|
image.Pt(self.Inner.Min.X, self.Inner.Min.Y-1+heightOffset-barHeight),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|