seeking, layout update
This commit is contained in:
@@ -160,6 +160,7 @@ func (pc *PlayerControls) OnSeek(f func(float64)) {
|
||||
f(pos)
|
||||
}
|
||||
}
|
||||
pc.waveform.OnSeeked = f
|
||||
}
|
||||
|
||||
func (pc *PlayerControls) OnSeekPrevious(f func()) {
|
||||
@@ -208,10 +209,10 @@ func (pc *PlayerControls) UpdatePlayTime(curTime, totalTime float64) {
|
||||
pc.curTimeLabel.SetText(ct)
|
||||
updated = true
|
||||
}
|
||||
pc.waveform.SetProgress(v)
|
||||
if updated {
|
||||
// Only update slider once a second when time label changes
|
||||
pc.slider.SetValue(v)
|
||||
pc.waveform.SetProgress(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,50 +3,89 @@ package widgets
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
)
|
||||
|
||||
type WaveformSeekbar struct {
|
||||
widget.BaseWidget
|
||||
|
||||
imgColorL color.Color
|
||||
imgColorR color.Color
|
||||
imgProgress float64
|
||||
OnSeeked func(float64)
|
||||
|
||||
img *canvas.Image
|
||||
imgColorL color.Color
|
||||
imgColorR color.Color
|
||||
imgProgressPixel int
|
||||
|
||||
img *canvas.Image
|
||||
cursor *myTheme.ThemedRectangle
|
||||
}
|
||||
|
||||
func NewWaveformSeekbar() *WaveformSeekbar {
|
||||
w := &WaveformSeekbar{
|
||||
img: canvas.NewImageFromImage(nil),
|
||||
img: &canvas.Image{
|
||||
ScaleMode: canvas.ImageScaleFastest,
|
||||
},
|
||||
cursor: myTheme.NewThemedRectangle(theme.ColorNameForeground),
|
||||
}
|
||||
w.cursor.Hide()
|
||||
w.ExtendBaseWidget(w)
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) UpdateImage(img *backend.WaveformImage) {
|
||||
w.img.Image = img
|
||||
prm, fg := w.getThemeColors()
|
||||
w.recolorImage(prm, fg, w.imgProgressPixel)
|
||||
w.Refresh()
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) Refresh() {
|
||||
w.cursor.Resize(fyne.NewSize(1.5, w.Size().Height-4))
|
||||
w.cursor.Refresh()
|
||||
prm, fg := w.getThemeColors()
|
||||
w.recolorImage(prm, fg, w.imgProgress)
|
||||
w.img.Refresh()
|
||||
//w.BaseWidget.Refresh()
|
||||
if w.recolorImage(prm, fg, w.imgProgressPixel) {
|
||||
w.img.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
var _ desktop.Hoverable = (*WaveformSeekbar)(nil)
|
||||
|
||||
func (w *WaveformSeekbar) MouseIn(e *desktop.MouseEvent) {
|
||||
w.cursor.Move(fyne.NewPos(e.Position.X, 2))
|
||||
w.cursor.Show()
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) MouseMoved(e *desktop.MouseEvent) {
|
||||
w.cursor.Move(fyne.NewPos(e.Position.X, 2))
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) MouseOut() {
|
||||
w.cursor.Hide()
|
||||
}
|
||||
|
||||
var _ fyne.Tappable = (*WaveformSeekbar)(nil)
|
||||
|
||||
func (w *WaveformSeekbar) Tapped(e *fyne.PointEvent) {
|
||||
if w.OnSeeked != nil {
|
||||
w.OnSeeked(float64(e.Position.X / w.Size().Width))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) CreateRenderer() fyne.WidgetRenderer {
|
||||
return widget.NewSimpleRenderer(
|
||||
container.New(layout.NewCustomPaddedLayout(4, 4, 0, 0), w.img),
|
||||
container.NewStack(
|
||||
container.New(layout.NewCustomPaddedLayout(4, 4, 0, 0), w.img),
|
||||
container.NewWithoutLayout(w.cursor),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -54,8 +93,10 @@ func (w *WaveformSeekbar) CreateRenderer() fyne.WidgetRenderer {
|
||||
// (ratio from 0 to 1)
|
||||
func (w *WaveformSeekbar) SetProgress(v float64) {
|
||||
prm, fg := w.getThemeColors()
|
||||
w.recolorImage(prm, fg, v)
|
||||
w.Refresh()
|
||||
thresholdPixel := int(math.Round(1024.0 /*pixel width of waveform*/ * v))
|
||||
if w.recolorImage(prm, fg, thresholdPixel) {
|
||||
w.img.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) getThemeColors() (primary, foreground color.Color) {
|
||||
@@ -66,12 +107,12 @@ func (w *WaveformSeekbar) getThemeColors() (primary, foreground color.Color) {
|
||||
return primary, foreground
|
||||
}
|
||||
|
||||
func (w *WaveformSeekbar) recolorImage(cL, cR color.Color, progress float64) {
|
||||
func (w *WaveformSeekbar) recolorImage(cL, cR color.Color, progress int) (updated bool) {
|
||||
if w.img.Image == nil {
|
||||
return
|
||||
return false
|
||||
}
|
||||
if w.imgColorL == cL && w.imgColorR == cR && w.imgProgress == progress {
|
||||
return
|
||||
if w.imgColorL == cL && w.imgColorR == cR && w.imgProgressPixel == progress {
|
||||
return false
|
||||
}
|
||||
|
||||
_r, _g, _b, _ := cL.RGBA()
|
||||
@@ -84,12 +125,9 @@ func (w *WaveformSeekbar) recolorImage(cL, cR color.Color, progress float64) {
|
||||
// and not iterate the whole thing every time
|
||||
img := w.img.Image.(*image.NRGBA)
|
||||
bnds := img.Rect.Bounds()
|
||||
thresholdPixel := int(float64(bnds.Dx()) * progress)
|
||||
log.Println("progress = ", progress, " bounds Dx = ", bnds.Dx())
|
||||
log.Println("thresholdPixel = ", thresholdPixel)
|
||||
for x := 0; x < bnds.Dx(); x++ {
|
||||
for y := 0; y < bnds.Dy(); y++ {
|
||||
if x < thresholdPixel {
|
||||
if x < progress {
|
||||
setPixelRGB(img, x, y, rL, gL, bL)
|
||||
} else {
|
||||
setPixelRGB(img, x, y, rR, gR, bR)
|
||||
@@ -98,7 +136,8 @@ func (w *WaveformSeekbar) recolorImage(cL, cR color.Color, progress float64) {
|
||||
}
|
||||
|
||||
w.imgColorL, w.imgColorR = cL, cR
|
||||
w.imgProgress = progress
|
||||
w.imgProgressPixel = progress
|
||||
return true
|
||||
}
|
||||
|
||||
func setPixelRGB(img *image.NRGBA, x, y int, r, g, b byte) {
|
||||
|
||||
Reference in New Issue
Block a user