2024-03-30 17:45:07 +01:00
|
|
|
package screen
|
|
|
|
|
|
|
|
import (
|
|
|
|
"embed"
|
2024-04-19 16:44:36 +02:00
|
|
|
"errors"
|
2024-03-30 17:45:07 +01:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/fs"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"fyne.io/fyne/v2"
|
|
|
|
"fyne.io/fyne/v2/data/binding"
|
|
|
|
"fyne.io/fyne/v2/theme"
|
|
|
|
"fyne.io/fyne/v2/widget"
|
|
|
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
|
|
"gopkg.in/yaml.v2"
|
|
|
|
)
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
type ListItemTemplateFn func() fyne.CanvasObject
|
|
|
|
type ListDataItemRendererFn func(binding.DataItem, fyne.CanvasObject)
|
|
|
|
type ListItemRendererFn func(int, fyne.CanvasObject)
|
|
|
|
type ListLengthFn func() int
|
|
|
|
type ListItemHandlerFn func(widget.ListItemID)
|
|
|
|
type ClickHandlerFn func()
|
|
|
|
type CheckHandlerFn func(bool)
|
|
|
|
type DateSelectedHandlerFn func(time.Time)
|
2024-04-11 14:52:32 +02:00
|
|
|
type OptionSelectedHandlerFn func(string)
|
2024-04-03 16:07:24 +02:00
|
|
|
type ValidationChangedHandlerFn func(error)
|
|
|
|
|
|
|
|
type UIElement struct {
|
|
|
|
Object fyne.CanvasObject
|
|
|
|
Decorator fyne.CanvasObject
|
|
|
|
}
|
|
|
|
|
2024-03-30 17:45:07 +01:00
|
|
|
type ScreenHandler interface {
|
2024-04-03 16:07:24 +02:00
|
|
|
RegisterElement(string, fyne.CanvasObject, fyne.CanvasObject)
|
2024-03-30 17:45:07 +01:00
|
|
|
|
2024-04-19 16:44:36 +02:00
|
|
|
LoadAsset(string) (fs.File, error)
|
|
|
|
|
2024-03-30 17:45:07 +01:00
|
|
|
GetLocalizer() *i18n.Localizer
|
|
|
|
GetIcon(string) fyne.Resource
|
|
|
|
GetBinding(string) binding.DataItem
|
2024-04-03 16:07:24 +02:00
|
|
|
GetValidator(string) fyne.StringValidator
|
|
|
|
GetListItemTemplate(string) ListItemTemplateFn
|
|
|
|
GetListDataItemRenderer(string) ListDataItemRendererFn
|
|
|
|
GetListItemRenderer(string) ListItemRendererFn
|
|
|
|
GetListLength(string) ListLengthFn
|
2024-03-30 17:45:07 +01:00
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
GetOnListItemSelectedHandler(string) ListItemHandlerFn
|
|
|
|
GetOnListItemUnselectedHandler(string) ListItemHandlerFn
|
|
|
|
GetOnClickedHandler(string) ClickHandlerFn
|
|
|
|
GetOnCheckChangedHandler(string) CheckHandlerFn
|
|
|
|
GetOnDateSelectedHandler(string) DateSelectedHandlerFn
|
2024-04-11 14:52:32 +02:00
|
|
|
GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn
|
2024-04-03 16:07:24 +02:00
|
|
|
GetOnValidationChangedHandler(string) ValidationChangedHandlerFn
|
2024-03-30 17:45:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type Screen struct {
|
|
|
|
rootElement *Element
|
|
|
|
screenHandler ScreenHandler
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(
|
|
|
|
filesystem embed.FS,
|
|
|
|
name string,
|
|
|
|
screenHandler ScreenHandler,
|
|
|
|
) (scr *Screen, err error) {
|
|
|
|
var bytes []byte
|
|
|
|
var fh fs.File
|
|
|
|
|
|
|
|
if fh, err = filesystem.Open(name); err != nil {
|
|
|
|
err = fmt.Errorf("no screen definition found: %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if bytes, err = io.ReadAll(fh); err != nil {
|
|
|
|
err = fmt.Errorf("unable to read screen definition: %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
root := &Element{}
|
|
|
|
if err = yaml.Unmarshal(bytes, root); err != nil {
|
|
|
|
err = fmt.Errorf("failure parsing screen definition: %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
scr = &Screen{
|
|
|
|
rootElement: root,
|
|
|
|
screenHandler: screenHandler,
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTemplate(
|
|
|
|
filesystem embed.FS,
|
|
|
|
name string,
|
|
|
|
localizer *i18n.Localizer,
|
|
|
|
) (
|
|
|
|
scr *Screen,
|
|
|
|
handler *TemplateScreenHandler,
|
|
|
|
err error,
|
|
|
|
) {
|
2024-04-03 16:07:24 +02:00
|
|
|
handler = NewTemplateScreenHandler(localizer)
|
2024-03-30 17:45:07 +01:00
|
|
|
scr, err = New(filesystem, name, handler)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Screen) Initialize() (obj fyne.CanvasObject, err error) {
|
|
|
|
if obj, err = s.rootElement.BuildUI(s.screenHandler); err != nil {
|
|
|
|
err = fmt.Errorf("failed to build screen: %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type TemplateScreenHandler struct {
|
|
|
|
localizer *i18n.Localizer
|
2024-04-03 16:07:24 +02:00
|
|
|
elementsMap map[string]*UIElement
|
2024-03-30 17:45:07 +01:00
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func NewTemplateScreenHandler(
|
|
|
|
localizer *i18n.Localizer,
|
|
|
|
) *TemplateScreenHandler {
|
2024-03-30 17:45:07 +01:00
|
|
|
return &TemplateScreenHandler{
|
|
|
|
localizer: localizer,
|
2024-04-03 16:07:24 +02:00
|
|
|
elementsMap: make(map[string]*UIElement),
|
2024-03-30 17:45:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (d *TemplateScreenHandler) RegisterElement(
|
|
|
|
name string,
|
|
|
|
element fyne.CanvasObject,
|
|
|
|
decorator fyne.CanvasObject,
|
|
|
|
) {
|
|
|
|
d.elementsMap[name] = &UIElement{element, decorator}
|
2024-03-30 17:45:07 +01:00
|
|
|
}
|
|
|
|
|
2024-04-19 16:44:36 +02:00
|
|
|
func (d *TemplateScreenHandler) LoadAsset(name string) (fs.File, error) {
|
|
|
|
return nil, errors.New("not implemented")
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (d *TemplateScreenHandler) GetElement(name string) *UIElement {
|
2024-03-30 17:45:07 +01:00
|
|
|
elem, ok := d.elementsMap[name]
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return elem
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *TemplateScreenHandler) GetLocalizer() *i18n.Localizer {
|
|
|
|
return d.localizer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *TemplateScreenHandler) GetIcon(iconName string) fyne.Resource {
|
|
|
|
if strings.HasPrefix(iconName, "theme.") {
|
|
|
|
iconName := strings.SplitN(iconName, ".", 2)[1]
|
|
|
|
return theme.DefaultTheme().Icon(fyne.ThemeIconName(iconName))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TemplateScreenHandler) GetBinding(string) binding.DataItem {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetValidator(string) fyne.StringValidator {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TemplateScreenHandler) GetListItemTemplate(string) ListItemTemplateFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func() fyne.CanvasObject { return nil }
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetListDataItemRenderer(string) ListDataItemRendererFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(binding.DataItem, fyne.CanvasObject) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetListItemRenderer(string) ListItemRendererFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(int, fyne.CanvasObject) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetListLength(string) ListLengthFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func() int { return 0 }
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnListItemSelectedHandler(string) ListItemHandlerFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(widget.ListItemID) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnListItemUnselectedHandler(string) ListItemHandlerFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(widget.ListItemID) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnClickedHandler(string) ClickHandlerFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func() {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnCheckChangedHandler(string) CheckHandlerFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(bool) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnDateSelectedHandler(string) DateSelectedHandlerFn {
|
2024-03-30 17:45:07 +01:00
|
|
|
return func(time.Time) {}
|
|
|
|
}
|
2024-04-03 16:07:24 +02:00
|
|
|
|
2024-04-11 14:52:32 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn {
|
|
|
|
return func(string) {}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:07:24 +02:00
|
|
|
func (*TemplateScreenHandler) GetOnValidationChangedHandler(string) ValidationChangedHandlerFn {
|
|
|
|
return func(error) {}
|
|
|
|
}
|