ui/screen/canvas.go
2024-06-17 15:58:12 +02:00

185 lines
3.3 KiB
Go

package screen
import (
"errors"
"fmt"
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/data/binding"
)
type Canvas string
const (
Image Canvas = "Image"
Rectangle Canvas = "Rectangle"
Text Canvas = "Text"
)
func (c Canvas) Build(
e *Element,
s ScreenHandler,
) (
cnv fyne.CanvasObject,
decorator fyne.CanvasObject,
err error,
) {
e.localize(s)
switch c {
case Image:
cnv, err = c.BuildImageCanvas(e, s)
case Rectangle:
cnv, err = c.BuildRectangleCanvas(e, s)
case Text:
cnv, err = c.BuildTextCanvas(e, s)
default:
err = errors.New("invalid canvas")
}
if err != nil {
return
}
decorator = applyPadding(e, cnv)
decorator = applyDecorators(e, decorator)
decorator = applyMargins(e, decorator)
if e.Hidden {
decorator.Hide()
}
return
}
func (c *Canvas) BuildImageCanvas(
e *Element,
s ScreenHandler,
) (obj fyne.CanvasObject, err error) {
var img *canvas.Image
if e.ImageName != "" {
img, err = AssetToImage(s, e.ImageName)
if err != nil {
err = fmt.Errorf("failed to load image: %w", err)
return
}
} else {
img = &canvas.Image{}
}
if e.Translucency != nil {
img.Translucency = *e.Translucency
}
for opt, val := range e.Options {
switch opt {
case "scaleMode":
img.ScaleMode = getImageScale(val)
case "fillMode":
img.FillMode = getImageFill(val)
}
}
obj = img
return
}
func (c Canvas) BuildRectangleCanvas(
e *Element,
s ScreenHandler,
) (obj fyne.CanvasObject, err error) {
fClr := color.RGBA{R: 255, G: 255, B: 255, A: 255}
if e.FillColor != nil {
fClr = color.RGBA{
R: e.FillColor.Red,
G: e.FillColor.Green,
B: e.FillColor.Blue,
A: e.FillColor.Alpha,
}
}
rect := canvas.NewRectangle(fClr)
if e.StrokeColor != nil {
rect.StrokeColor = color.RGBA{
R: e.StrokeColor.Red,
G: e.StrokeColor.Green,
B: e.StrokeColor.Blue,
A: e.StrokeColor.Alpha,
}
}
rect.StrokeWidth = 0
rect.CornerRadius = 0
if e.StrokeWidth != nil {
rect.StrokeWidth = *e.StrokeWidth
}
if e.CornerRadius != nil {
rect.CornerRadius = *e.CornerRadius
}
obj = rect
return
}
func (c Canvas) BuildTextCanvas(
e *Element,
s ScreenHandler,
) (obj fyne.CanvasObject, err error) {
txtClr := color.RGBA{R: 255, G: 255, B: 255, A: 255}
if e.TextColor != nil {
txtClr = color.RGBA{
R: e.TextColor.Red,
G: e.TextColor.Green,
B: e.TextColor.Blue,
A: e.TextColor.Alpha,
}
}
txt := canvas.NewText(e.Text, txtClr)
if e.Binding != "" {
bnd := s.GetBinding(e.Binding).(binding.String)
bnd.AddListener(binding.NewDataListener(func() {
txt.Text, _ = bnd.Get()
txt.Refresh()
}))
}
if e.TextSize != nil {
txt.TextSize = *e.TextSize
}
for opt, val := range e.Options {
switch opt {
case "alignment":
txt.Alignment = getTextAlignment(val)
case "textStyle":
txt.TextStyle = getTextStyle(val)
}
}
obj = txt
return
}
func getImageFill(v any) canvas.ImageFill {
switch v.(string) {
case "Stretch":
return canvas.ImageFillStretch
case "Contain":
return canvas.ImageFillContain
case "Original":
return canvas.ImageFillOriginal
}
return canvas.ImageFillStretch
}
func getImageScale(v any) canvas.ImageScale {
switch v.(string) {
case "Smooth":
return canvas.ImageScaleSmooth
case "Pixels":
return canvas.ImageScalePixels
case "Fastest":
return canvas.ImageScaleFastest
}
return canvas.ImageScaleSmooth
}