package screen import ( "embed" "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" ) type ScreenHandler interface { RegisterElement(string, fyne.CanvasObject) GetLocalizer() *i18n.Localizer GetIcon(string) fyne.Resource GetBinding(string) binding.DataItem GetListItemTemplate(string) func() fyne.CanvasObject GetListDataItemRenderer(string) func(binding.DataItem, fyne.CanvasObject) GetListItemRenderer(string) func(int, fyne.CanvasObject) GetListLength(string) func() int GetOnSelectedHandler(string) func(widget.ListItemID) GetOnUnselectedHandler(string) func(widget.ListItemID) GetClickedHandler(string) func() GetCheckChangedHandler(string) func(bool) GetDateSelectedHandler(string) func(time.Time) } 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, ) { handler = NewDummyScreenHandler(localizer) 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 elementsMap map[string]fyne.CanvasObject } func NewDummyScreenHandler(localizer *i18n.Localizer) *TemplateScreenHandler { return &TemplateScreenHandler{ localizer: localizer, elementsMap: make(map[string]fyne.CanvasObject), } } func (d *TemplateScreenHandler) RegisterElement(name string, element fyne.CanvasObject) { d.elementsMap[name] = element } func (d *TemplateScreenHandler) GetElement(name string) fyne.CanvasObject { 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 } func (*TemplateScreenHandler) GetListItemTemplate(string) func() fyne.CanvasObject { return func() fyne.CanvasObject { return nil } } func (*TemplateScreenHandler) GetListDataItemRenderer(string) func(binding.DataItem, fyne.CanvasObject) { return func(binding.DataItem, fyne.CanvasObject) {} } func (*TemplateScreenHandler) GetListItemRenderer(string) func(int, fyne.CanvasObject) { return func(int, fyne.CanvasObject) {} } func (*TemplateScreenHandler) GetListLength(string) func() int { return func() int { return 0 } } func (*TemplateScreenHandler) GetOnSelectedHandler(string) func(widget.ListItemID) { return func(widget.ListItemID) {} } func (*TemplateScreenHandler) GetOnUnselectedHandler(string) func(widget.ListItemID) { return func(widget.ListItemID) {} } func (*TemplateScreenHandler) GetClickedHandler(string) func() { return func() {} } func (*TemplateScreenHandler) GetCheckChangedHandler(string) func(bool) { return func(bool) {} } func (*TemplateScreenHandler) GetDateSelectedHandler(string) func(time.Time) { return func(time.Time) {} }