Added score display
This commit is contained in:
233
uiwidget/scoredisplay.go
Normal file
233
uiwidget/scoredisplay.go
Normal file
@ -0,0 +1,233 @@
|
||||
package uiwidget
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type ScoreDisplayResources struct {
|
||||
Empty fyne.Resource
|
||||
Digits [10]fyne.Resource
|
||||
}
|
||||
|
||||
func NewScoreDisplayResources(
|
||||
empty fyne.Resource,
|
||||
digits [10]fyne.Resource,
|
||||
) *ScoreDisplayResources {
|
||||
return &ScoreDisplayResources{
|
||||
Empty: empty,
|
||||
Digits: digits,
|
||||
}
|
||||
}
|
||||
|
||||
type ScoreDisplay struct {
|
||||
widget.BaseWidget
|
||||
|
||||
Score int
|
||||
|
||||
scoreBinding binding.Int
|
||||
numDigits int
|
||||
digits []*canvas.Image
|
||||
resources *ScoreDisplayResources
|
||||
layout *ScoreDisplayLayout
|
||||
cont *fyne.Container
|
||||
relSize *fyne.Size
|
||||
fixedSize *fyne.Size
|
||||
}
|
||||
|
||||
func NewScoreDisplay(
|
||||
score int,
|
||||
numDigits int,
|
||||
resources *ScoreDisplayResources,
|
||||
relSize *fyne.Size,
|
||||
fizedSize *fyne.Size,
|
||||
) *ScoreDisplay {
|
||||
sd := new(ScoreDisplay)
|
||||
sd.Score = score
|
||||
sd.numDigits = numDigits
|
||||
sd.resources = resources
|
||||
sd.digits = make([]*canvas.Image, numDigits)
|
||||
for i := 0; i < numDigits; i++ {
|
||||
sd.digits[i] = canvas.NewImageFromResource(resources.Empty)
|
||||
}
|
||||
sd.relSize = relSize
|
||||
sd.fixedSize = fizedSize
|
||||
sd.ExtendBaseWidget(sd)
|
||||
sd.updateScore()
|
||||
return sd
|
||||
}
|
||||
|
||||
func NewScoreDisplayWithData(
|
||||
scoreBinding binding.Int,
|
||||
numDigits int,
|
||||
resources *ScoreDisplayResources,
|
||||
relSize *fyne.Size,
|
||||
fixedSize *fyne.Size,
|
||||
) *ScoreDisplay {
|
||||
sd := new(ScoreDisplay)
|
||||
sd.scoreBinding = scoreBinding
|
||||
sd.numDigits = numDigits
|
||||
sd.resources = resources
|
||||
sd.digits = make([]*canvas.Image, numDigits)
|
||||
for i := 0; i < numDigits; i++ {
|
||||
sd.digits[i] = canvas.NewImageFromResource(resources.Empty)
|
||||
}
|
||||
sd.relSize = relSize
|
||||
sd.fixedSize = fixedSize
|
||||
sd.ExtendBaseWidget(sd)
|
||||
sd.scoreBinding.AddListener(sd)
|
||||
return sd
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) CreateRenderer() fyne.WidgetRenderer {
|
||||
sd.layout = NewScoreDisplayLayout(sd.relSize, sd.fixedSize)
|
||||
sd.cont = container.New(sd.layout)
|
||||
for i := sd.numDigits; i > 0; i-- {
|
||||
digit := sd.digits[i-1]
|
||||
sd.cont.Add(digit)
|
||||
}
|
||||
|
||||
return widget.NewSimpleRenderer(sd.cont)
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) Refresh() {
|
||||
sd.updateScore()
|
||||
sd.BaseWidget.Refresh()
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) Size() fyne.Size {
|
||||
if sd.layout == nil {
|
||||
if sd.fixedSize != nil {
|
||||
return *sd.fixedSize
|
||||
} else if sd.relSize != nil {
|
||||
canvas := fyne.CurrentApp().Driver().AllWindows()[0].Canvas()
|
||||
if canvas == nil {
|
||||
return fyne.NewSize(0, 0)
|
||||
}
|
||||
size := fyne.NewSize(
|
||||
canvas.Size().Width*sd.relSize.Width,
|
||||
canvas.Size().Height*sd.relSize.Height,
|
||||
)
|
||||
return size
|
||||
} else {
|
||||
return fyne.NewSize(0, 0)
|
||||
}
|
||||
|
||||
}
|
||||
return sd.layout.CurrentSize()
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) MinSize() fyne.Size {
|
||||
return sd.Size()
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) DataChanged() {
|
||||
var err error
|
||||
|
||||
sd.Score, err = sd.scoreBinding.Get()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sd.Refresh()
|
||||
}
|
||||
|
||||
func (sd *ScoreDisplay) updateScore() {
|
||||
aspect := float32(0)
|
||||
score := sd.Score
|
||||
for i := 0; i < sd.numDigits; i++ {
|
||||
digit := score % 10
|
||||
score /= 10
|
||||
if i != 0 && digit == 0 && score == 0 {
|
||||
sd.digits[i].Resource = sd.resources.Empty
|
||||
} else {
|
||||
sd.digits[i].Resource = sd.resources.Digits[digit]
|
||||
}
|
||||
sd.digits[i].ScaleMode = canvas.ImageScaleSmooth
|
||||
sd.digits[i].FillMode = canvas.ImageFillContain
|
||||
sd.digits[i].Resize(fyne.NewSize(200, 300))
|
||||
aspect += sd.digits[i].Aspect()
|
||||
}
|
||||
if sd.layout != nil {
|
||||
sd.layout.setAspect(aspect)
|
||||
}
|
||||
}
|
||||
|
||||
type ScoreDisplayLayout struct {
|
||||
canvas fyne.Canvas
|
||||
relSize *fyne.Size
|
||||
fixedSize *fyne.Size
|
||||
aspect float32
|
||||
currentSize fyne.Size
|
||||
}
|
||||
|
||||
func NewScoreDisplayLayout(relSize *fyne.Size, fixedSize *fyne.Size) *ScoreDisplayLayout {
|
||||
return &ScoreDisplayLayout{
|
||||
relSize: relSize,
|
||||
fixedSize: fixedSize,
|
||||
aspect: float32(0),
|
||||
}
|
||||
}
|
||||
|
||||
func (sdl *ScoreDisplayLayout) setAspect(a float32) {
|
||||
sdl.aspect = a
|
||||
}
|
||||
|
||||
func (sdl *ScoreDisplayLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
||||
if sdl.fixedSize != nil {
|
||||
return *sdl.fixedSize
|
||||
}
|
||||
return sdl.calculateSize(objects)
|
||||
}
|
||||
|
||||
func (sdl *ScoreDisplayLayout) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
|
||||
size := sdl.calculateSize(objects)
|
||||
sdl.currentSize = size
|
||||
|
||||
numObjects := len(objects)
|
||||
objSize := fyne.NewSize(
|
||||
size.Width/float32(numObjects),
|
||||
size.Height)
|
||||
|
||||
pos := fyne.NewPos(0, 0)
|
||||
for _, o := range objects {
|
||||
o.Resize(objSize)
|
||||
o.Move(pos)
|
||||
pos = pos.Add(fyne.NewPos(objSize.Width, 0))
|
||||
}
|
||||
}
|
||||
|
||||
func (sdl *ScoreDisplayLayout) CurrentSize() fyne.Size {
|
||||
return sdl.currentSize
|
||||
}
|
||||
|
||||
func (sdl *ScoreDisplayLayout) calculateSize(objects []fyne.CanvasObject) fyne.Size {
|
||||
size := fyne.NewSize(0, 0)
|
||||
if sdl.relSize != nil {
|
||||
if sdl.canvas == nil && len(objects) > 0 {
|
||||
sdl.canvas = fyne.CurrentApp().Driver().CanvasForObject(objects[0])
|
||||
}
|
||||
if sdl.canvas != nil {
|
||||
size = fyne.NewSize(
|
||||
sdl.canvas.Size().Width*sdl.relSize.Width,
|
||||
sdl.canvas.Size().Height*sdl.relSize.Height,
|
||||
)
|
||||
}
|
||||
} else if sdl.fixedSize != nil {
|
||||
size = *sdl.fixedSize
|
||||
sdl.currentSize = size
|
||||
}
|
||||
|
||||
if sdl.aspect > 0 {
|
||||
curAspect := size.Width / size.Height
|
||||
if curAspect > sdl.aspect {
|
||||
size.Width = size.Height * sdl.aspect
|
||||
} else {
|
||||
size.Height = size.Width / sdl.aspect
|
||||
}
|
||||
sdl.currentSize = size
|
||||
}
|
||||
return size
|
||||
}
|
Reference in New Issue
Block a user