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 = applyDecorators(e, cnv) 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 }