mirror of
https://github.com/mum4k/termdash.git
synced 2025-04-25 13:48:50 +08:00
add gauge threshold
This commit is contained in:
parent
9954a0543e
commit
1aba280365
@ -136,10 +136,12 @@ func (g *Gauge) Percent(p int, opts ...Option) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// width determines the required width of the gauge drawn on the provided area
|
||||
// in order to represent the current progress.
|
||||
func (g *Gauge) width(ar image.Rectangle) int {
|
||||
mult := float32(g.current) / float32(g.total)
|
||||
// width determines the X coordinate that represents point w in rectangle ar.
|
||||
// This is used to calculate the width of the gauge drawn on the provided area
|
||||
// in order to represent the current progress or to figure out the coordinate
|
||||
// for the threshold line.
|
||||
func (g *Gauge) width(ar image.Rectangle, w int) int {
|
||||
mult := float32(w) / float32(g.total)
|
||||
width := float32(ar.Dx()) * mult
|
||||
return int(width)
|
||||
}
|
||||
@ -273,7 +275,7 @@ func (g *Gauge) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error {
|
||||
progress := image.Rect(
|
||||
usable.Min.X,
|
||||
usable.Min.Y,
|
||||
usable.Min.X+g.width(usable),
|
||||
usable.Min.X+g.width(usable, g.current),
|
||||
usable.Max.Y,
|
||||
)
|
||||
if progress.Dx() > 0 {
|
||||
@ -284,6 +286,25 @@ func (g *Gauge) Draw(cvs *canvas.Canvas, meta *widgetapi.Meta) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if g.opts.threshold > 0 && g.opts.threshold < g.total {
|
||||
line := draw.HVLine{
|
||||
Start: image.Point{
|
||||
X: usable.Min.X + g.width(usable, g.opts.threshold),
|
||||
Y: cvs.Area().Min.Y,
|
||||
},
|
||||
End: image.Point{
|
||||
X: usable.Min.X + g.width(usable, g.opts.threshold),
|
||||
Y: cvs.Area().Max.Y - 1,
|
||||
},
|
||||
}
|
||||
if err := draw.HVLines(cvs, []draw.HVLine{line},
|
||||
draw.HVLineStyle(g.opts.thresholdLineStyle),
|
||||
draw.HVLineCellOpts(g.opts.thresholdCellOpts...),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return g.drawText(cvs, progress)
|
||||
}
|
||||
|
||||
|
@ -841,6 +841,100 @@ func TestGauge(t *testing.T) {
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "threshold with border percentage",
|
||||
opts: []Option{
|
||||
Char('o'),
|
||||
Threshold(20, linestyle.Double),
|
||||
},
|
||||
percent: &percentCall{p: 35},
|
||||
canvas: image.Rect(0, 0, 10, 3),
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
c := testcanvas.MustNew(ft.Area())
|
||||
|
||||
testdraw.MustRectangle(c, image.Rect(0, 0, 3, 3),
|
||||
draw.RectChar('o'),
|
||||
draw.RectCellOpts(cell.BgColor(cell.ColorGreen)),
|
||||
)
|
||||
testdraw.MustText(c, "35%", image.Point{3, 1})
|
||||
testdraw.MustHVLines(c, []draw.HVLine{{
|
||||
Start: image.Point{X: 2, Y: 0},
|
||||
End: image.Point{X: 2, Y: 2},
|
||||
}}, draw.HVLineStyle(linestyle.Double))
|
||||
testcanvas.MustApply(c, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "threshold without border absolute",
|
||||
opts: []Option{
|
||||
Char('o'),
|
||||
Threshold(3, linestyle.Light, cell.BgColor(cell.ColorRed)),
|
||||
Border(linestyle.None),
|
||||
HideTextProgress(),
|
||||
},
|
||||
absolute: &absoluteCall{done: 4, total: 10},
|
||||
canvas: image.Rect(0, 0, 10, 3),
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
c := testcanvas.MustNew(ft.Area())
|
||||
|
||||
testdraw.MustRectangle(c, image.Rect(0, 0, 3, 3),
|
||||
draw.RectChar('o'),
|
||||
draw.RectCellOpts(cell.BgColor(cell.ColorGreen)),
|
||||
)
|
||||
testdraw.MustHVLines(c, []draw.HVLine{{
|
||||
Start: image.Point{X: 3, Y: 0},
|
||||
End: image.Point{X: 3, Y: 2},
|
||||
}}, draw.HVLineStyle(linestyle.Light),
|
||||
draw.HVLineCellOpts(cell.BgColor(cell.ColorRed)))
|
||||
testcanvas.MustApply(c, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "threshold outside of bounds (negative)",
|
||||
opts: []Option{
|
||||
Char('o'),
|
||||
HideTextProgress(),
|
||||
Threshold(-1, linestyle.Light), // ignored
|
||||
},
|
||||
percent: &percentCall{p: 35},
|
||||
canvas: image.Rect(0, 0, 10, 3),
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
c := testcanvas.MustNew(ft.Area())
|
||||
|
||||
testdraw.MustRectangle(c, image.Rect(0, 0, 3, 3),
|
||||
draw.RectChar('o'),
|
||||
draw.RectCellOpts(cell.BgColor(cell.ColorGreen)),
|
||||
)
|
||||
testcanvas.MustApply(c, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "threshold outside of bounds (>=max)",
|
||||
opts: []Option{
|
||||
Char('o'),
|
||||
HideTextProgress(),
|
||||
Threshold(100, linestyle.Light), // ignored
|
||||
},
|
||||
percent: &percentCall{p: 35},
|
||||
canvas: image.Rect(0, 0, 10, 3),
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
c := testcanvas.MustNew(ft.Area())
|
||||
|
||||
testdraw.MustRectangle(c, image.Rect(0, 0, 3, 3),
|
||||
draw.RectChar('o'),
|
||||
draw.RectCellOpts(cell.BgColor(cell.ColorGreen)),
|
||||
)
|
||||
testcanvas.MustApply(c, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
@ -101,6 +101,7 @@ func main() {
|
||||
gauge.Color(cell.ColorNumber(33)),
|
||||
gauge.Border(linestyle.Light),
|
||||
gauge.BorderTitle("Absolute progress"),
|
||||
gauge.Threshold(43, linestyle.Light, cell.FgColor(cell.ColorRed)),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -124,6 +125,7 @@ func main() {
|
||||
gauge.Color(cell.ColorRed),
|
||||
gauge.FilledTextColor(cell.ColorBlack),
|
||||
gauge.EmptyTextColor(cell.ColorYellow),
|
||||
gauge.Threshold(20, linestyle.Double),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -47,6 +47,10 @@ type options struct {
|
||||
borderCellOpts []cell.Option
|
||||
borderTitle string
|
||||
borderTitleHAlign align.Horizontal
|
||||
// If set draws a vertical line representing the threshold.
|
||||
threshold int
|
||||
thresholdCellOpts []cell.Option
|
||||
thresholdLineStyle linestyle.LineStyle
|
||||
}
|
||||
|
||||
// newOptions returns options with the default values set.
|
||||
@ -201,3 +205,17 @@ func BorderTitleAlign(h align.Horizontal) Option {
|
||||
opts.borderTitleHAlign = h
|
||||
})
|
||||
}
|
||||
|
||||
// Threshold configures the Gauge to display a vertical threshold line at value
|
||||
// t. If the progress is set by a call to Percent(), t represents a percentage,
|
||||
// e.g. "40" means line is displayed at 40%. If the progress is set by a call to
|
||||
// Absolute(), the threshold is also considered an absolute number.
|
||||
// Threshold needs to be configured inside the valid values of a gauge to be
|
||||
// displayed, if it's set to <=0 or >=total it won't have any effect.
|
||||
func Threshold(t int, ls linestyle.LineStyle, cOpts ...cell.Option) Option {
|
||||
return option(func(opts *options) {
|
||||
opts.threshold = t
|
||||
opts.thresholdLineStyle = ls
|
||||
opts.thresholdCellOpts = cOpts
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user