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 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) type OptionSelectedHandlerFn func(string) type ValidationChangedHandlerFn func(error) type UIElement struct { Object fyne.CanvasObject Decorator fyne.CanvasObject } type ScreenHandler interface { RegisterElement(string, fyne.CanvasObject, fyne.CanvasObject) GetLocalizer() *i18n.Localizer GetIcon(string) fyne.Resource GetBinding(string) binding.DataItem GetValidator(string) fyne.StringValidator GetListItemTemplate(string) ListItemTemplateFn GetListDataItemRenderer(string) ListDataItemRendererFn GetListItemRenderer(string) ListItemRendererFn GetListLength(string) ListLengthFn GetOnListItemSelectedHandler(string) ListItemHandlerFn GetOnListItemUnselectedHandler(string) ListItemHandlerFn GetOnClickedHandler(string) ClickHandlerFn GetOnCheckChangedHandler(string) CheckHandlerFn GetOnDateSelectedHandler(string) DateSelectedHandlerFn GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn GetOnValidationChangedHandler(string) ValidationChangedHandlerFn } 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 = NewTemplateScreenHandler(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]*UIElement } func NewTemplateScreenHandler( localizer *i18n.Localizer, ) *TemplateScreenHandler { return &TemplateScreenHandler{ localizer: localizer, elementsMap: make(map[string]*UIElement), } } func (d *TemplateScreenHandler) RegisterElement( name string, element fyne.CanvasObject, decorator fyne.CanvasObject, ) { d.elementsMap[name] = &UIElement{element, decorator} } func (d *TemplateScreenHandler) GetElement(name string) *UIElement { 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) GetValidator(string) fyne.StringValidator { return nil } func (*TemplateScreenHandler) GetListItemTemplate(string) ListItemTemplateFn { return func() fyne.CanvasObject { return nil } } func (*TemplateScreenHandler) GetListDataItemRenderer(string) ListDataItemRendererFn { return func(binding.DataItem, fyne.CanvasObject) {} } func (*TemplateScreenHandler) GetListItemRenderer(string) ListItemRendererFn { return func(int, fyne.CanvasObject) {} } func (*TemplateScreenHandler) GetListLength(string) ListLengthFn { return func() int { return 0 } } func (*TemplateScreenHandler) GetOnListItemSelectedHandler(string) ListItemHandlerFn { return func(widget.ListItemID) {} } func (*TemplateScreenHandler) GetOnListItemUnselectedHandler(string) ListItemHandlerFn { return func(widget.ListItemID) {} } func (*TemplateScreenHandler) GetOnClickedHandler(string) ClickHandlerFn { return func() {} } func (*TemplateScreenHandler) GetOnCheckChangedHandler(string) CheckHandlerFn { return func(bool) {} } func (*TemplateScreenHandler) GetOnDateSelectedHandler(string) DateSelectedHandlerFn { return func(time.Time) {} } func (*TemplateScreenHandler) GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn { return func(string) {} } func (*TemplateScreenHandler) GetOnValidationChangedHandler(string) ValidationChangedHandlerFn { return func(error) {} }