ui/screen/screen.go

289 lines
6.8 KiB
Go
Raw Permalink Normal View History

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 {
2024-06-14 14:15:47 +02:00
fyne.CanvasObject
2024-03-30 17:45:07 +01:00
rootElement *Element
screenHandler ScreenHandler
2024-06-14 14:15:47 +02:00
resizeCallbacks []func(fyne.Size)
moveCallbacks []func(fyne.Position)
2024-03-30 17:45:07 +01:00
}
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) {
2024-06-14 14:15:47 +02:00
if s.CanvasObject, err = s.rootElement.BuildUI(s.screenHandler); err != nil {
2024-03-30 17:45:07 +01:00
err = fmt.Errorf("failed to build screen: %w", err)
return
}
2024-06-14 14:15:47 +02:00
obj = s
2024-03-30 17:45:07 +01:00
return
}
2024-06-14 14:15:47 +02:00
func (s *Screen) Move(p fyne.Position) {
s.CanvasObject.Move(p)
for _, cb := range s.moveCallbacks {
cb(p)
}
}
func (s *Screen) Resize(sz fyne.Size) {
s.CanvasObject.Resize(sz)
for _, cb := range s.resizeCallbacks {
cb(sz)
}
}
2024-08-06 21:30:11 +02:00
func (s *Screen) MinSize() fyne.Size {
return s.CanvasObject.MinSize()
}
2024-06-14 14:15:47 +02:00
func (s *Screen) CreateRenderer() fyne.WidgetRenderer {
2024-08-06 21:30:11 +02:00
return widget.NewSimpleRenderer(s.AsContainer())
2024-06-14 14:15:47 +02:00
}
func (s *Screen) RegisterResizeCallback(cb func(fyne.Size)) {
s.resizeCallbacks = append(s.resizeCallbacks, cb)
}
func (s *Screen) RegisterMoveCallback(cb func(fyne.Position)) {
s.moveCallbacks = append(s.moveCallbacks, cb)
}
func (s *Screen) AsContainer() *fyne.Container {
return s.CanvasObject.(*fyne.Container)
}
2024-08-06 21:30:11 +02:00
type DialogScreen struct {
*Screen
}
func NewDialogScreen(
filesystem embed.FS,
name string,
screenHandler ScreenHandler,
) (src *DialogScreen, err error) {
screen, err := New(filesystem, name, screenHandler)
if err != nil {
return
}
src = &DialogScreen{screen}
return
}
func (s *DialogScreen) Initialize() (obj fyne.CanvasObject, err error) {
if s.CanvasObject, err = s.rootElement.BuildUI(s.screenHandler); err != nil {
err = fmt.Errorf("failed to build screen: %w", err)
return
}
obj = s
return
}
func (s *DialogScreen) Move(p fyne.Position) {
c := fyne.CurrentApp().Driver().CanvasForObject(s.CanvasObject)
movePos := fyne.Position{
X: p.X / c.Scale(),
Y: p.Y / c.Scale(),
}
s.CanvasObject.Move(movePos)
//fmt.Printf("%+v\n", s.CanvasObject.Position());
}
2024-03-30 17:45:07 +01:00
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) {}
}