diff --git a/examples/nuvumeter/main.go b/examples/nuvumeter/main.go index 80cc483..9910b66 100644 --- a/examples/nuvumeter/main.go +++ b/examples/nuvumeter/main.go @@ -1,6 +1,8 @@ package main import ( + "time" + "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/data/binding" @@ -16,6 +18,7 @@ func main() { levelPB := numeter.NewVUMeterWithData(level) level.Set(0.95) levelPB.TextFormatter = func() string { return " " } + levelPB.Peakhold = 3 * time.Second progress := widget.NewProgressBarWithData(level) setLevel := binding.NewFloat() setLevel.Set(75.0) @@ -26,6 +29,7 @@ func main() { vLevelPB := numeter.NewVUMeterWithData(level) vLevelPB.VUMeterDirection = numeter.VUMeterVertical + levelPB.Peakhold = 3 * time.Second levelPB.TextFormatter = func() string { return " " } contain := container.New(layout.NewVBoxLayout(), levelPB, progress, slider) w.SetContent(container.New(layout.NewHBoxLayout(), contain, vLevelPB)) diff --git a/pkg/numeter/numeter.go b/pkg/numeter/numeter.go index b57d5b3..1560830 100644 --- a/pkg/numeter/numeter.go +++ b/pkg/numeter/numeter.go @@ -1,9 +1,11 @@ package numeter import ( + "fmt" "image" "image/color" "math" + "time" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" @@ -14,6 +16,8 @@ import ( type vuRenderer struct { currentframe *canvas.Raster + lastPeakTime time.Time + lastPeakVal float64 meter *vuMeter } @@ -59,6 +63,34 @@ func vuSet(i *image.RGBA, w int, h int, o VUMeterDirectionEnum, val float64, col } } +func drawPeakBar(i *image.RGBA, w int, h int, o VUMeterDirectionEnum, val float64, colGrn color.Color, colAmber color.Color, colRed color.Color) { + valPixel := int(math.Round(float64(w) * val)) + c := colGrn + if o == VUMeterVertical { + valPixel = int(math.Round(float64(h) * val)) + if float64(valPixel)/float64(h) > 0.75 { + c = colAmber + } + if float64(valPixel)/float64(h) > 0.85 { + c = colRed + } + for x := 0; x < w; x++ { + i.Set(x, valPixel-h, c) + } + } else { + valPixel = int(math.Round(float64(w) * val)) + if float64(valPixel)/float64(w) > 0.75 { + c = colAmber + } + if float64(valPixel)/float64(w) > 0.85 { + c = colRed + } + for y := 0; y < h; y++ { + i.Set(valPixel, y, c) + } + } +} + func (v *vuRenderer) Render(w int, h int) image.Image { i := image.NewRGBA(image.Rect(0, 0, w, h)) g := color.RGBA{0, 0x1f, 0, 0xff} @@ -70,6 +102,20 @@ func (v *vuRenderer) Render(w int, h int) image.Image { r = color.RGBA{0xff, 0, 0, 0xff} val := (v.meter.Value - v.meter.Min) / (v.meter.Max - v.meter.Min) * 100 vuSet(i, w, h, v.meter.VUMeterDirection, val, g, a, r) + if v.meter.Value > v.lastPeakVal { + fmt.Printf("New peak: %f, expires at %s\n", v.meter.Value, time.Now().Add(v.meter.Peakhold)) + v.lastPeakTime = time.Now() + v.lastPeakVal = v.meter.Value + } + if v.lastPeakTime.Add(v.meter.Peakhold).Before(time.Now()) { + fmt.Printf("Previous peak good, bar at %f\n", v.lastPeakVal) + drawPeakBar(i, w, h, v.meter.VUMeterDirection, v.lastPeakVal, g, a, r) + } + if v.lastPeakTime.Add(v.meter.Peakhold).After(time.Now()) { + fmt.Printf("Previous peak expired, holding at %f\n", v.meter.Value) + v.lastPeakVal = v.meter.Value + v.lastPeakTime = time.Now() + } return i } @@ -113,6 +159,7 @@ type vuMeter struct { TextFormatter func() string Value, Min, Max, OptimumValueMin, OptimumValueMax float64 + Peakhold time.Duration VUMeterDirection VUMeterDirectionEnum binder basicBinder @@ -120,9 +167,11 @@ type vuMeter struct { func NewVUMeterRenderer(m *vuMeter) *vuRenderer { c := canvas.NewRaster(func(w int, h int) image.Image { return image.NewNRGBA(image.Rect(0, 0, 200, 200)) }) - renderer := vuRenderer{c, m} + renderer := vuRenderer{c, time.Now(), 0, m} c.Generator = renderer.Render renderer.currentframe = c + renderer.lastPeakTime = time.Now() + renderer.lastPeakVal = 0 return &renderer } @@ -182,6 +231,7 @@ func NewVUMeter(value float64) *vuMeter { meter.Max = 100 meter.ExtendBaseWidget(meter) meter.VUMeterDirection = VUMeterHorizontal + meter.Peakhold = 0 return meter }