Implement defining screens in yaml
This commit is contained in:
@ -9,45 +9,85 @@ import (
|
||||
"fyne.io/fyne/v2/container"
|
||||
)
|
||||
|
||||
// The constants for the Containers
|
||||
//
|
||||
// Available yaml options for all containers:
|
||||
// - id: The ID for exporting the container to code
|
||||
// - decorators: The decorators to wrap the container into
|
||||
// - hidden: Wether the container is hidden or not
|
||||
type Container string
|
||||
|
||||
const (
|
||||
// HScroll Container
|
||||
//
|
||||
// Available yaml options:
|
||||
// - content: The content of the container
|
||||
HScroll Container = "HScroll"
|
||||
Scroll Container = "Scroll"
|
||||
|
||||
// Scroll Container
|
||||
//
|
||||
// Available yaml options:
|
||||
// - content: The content of the container
|
||||
Scroll Container = "Scroll"
|
||||
|
||||
// VScroll Container
|
||||
//
|
||||
// Available yaml options:
|
||||
// - content: The content of the container
|
||||
VScroll Container = "VScroll"
|
||||
)
|
||||
|
||||
func (cnt Container) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
// Build builds the container and decorator for the given Container and Element,
|
||||
// using the provided ScreenHandler to fetch functions, data bindings, etc.
|
||||
//
|
||||
// Parameters:
|
||||
// - e *Element - the element to build the container for
|
||||
// - s ScreenHandler - the screen handler for the container
|
||||
//
|
||||
// Returns the CanvasObject for the widget, the CanvasObject for the decorator
|
||||
// I fno decorators are specified, the widget and decorator will be the same.
|
||||
func (cnt Container) Build(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (
|
||||
container fyne.CanvasObject,
|
||||
decorator fyne.CanvasObject,
|
||||
err error,
|
||||
) {
|
||||
switch cnt {
|
||||
case HScroll:
|
||||
c, err = cnt.buildHScrollContainer(e, s)
|
||||
container, err = cnt.buildHScrollContainer(e, s)
|
||||
case Scroll:
|
||||
c, err = cnt.buildScrollContainer(e, s)
|
||||
container, err = cnt.buildScrollContainer(e, s)
|
||||
case VScroll:
|
||||
c, err = cnt.buildVScrollContainer(e, s)
|
||||
container, err = cnt.buildVScrollContainer(e, s)
|
||||
default:
|
||||
err = errors.New("invalid container")
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if e.Decorators != nil {
|
||||
|
||||
decorator = container
|
||||
if e.Decorators != nil {
|
||||
for _, dec := range e.Decorators {
|
||||
switch dec {
|
||||
case "Border":
|
||||
c = uiwidget.NewWidgetBorder(c)
|
||||
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.Hidden {
|
||||
c.Hide()
|
||||
decorator.Hide()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ctn Container) buildHScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (ctn Container) buildHScrollContainer(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
if e.Content == nil {
|
||||
err = errors.New("HScroll: no content defined")
|
||||
return
|
||||
@ -62,7 +102,10 @@ func (ctn Container) buildHScrollContainer(e *Element, s ScreenHandler) (c fyne.
|
||||
return
|
||||
}
|
||||
|
||||
func (ctn Container) buildScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (ctn Container) buildScrollContainer(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
if e.Content == nil {
|
||||
err = errors.New("Scroll: no content defined")
|
||||
return
|
||||
@ -77,7 +120,10 @@ func (ctn Container) buildScrollContainer(e *Element, s ScreenHandler) (c fyne.C
|
||||
return
|
||||
}
|
||||
|
||||
func (ctn Container) buildVScrollContainer(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (ctn Container) buildVScrollContainer(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
if e.Content == nil {
|
||||
err = errors.New("VScroll: no content defined")
|
||||
return
|
||||
|
@ -7,11 +7,13 @@ import (
|
||||
"fyne.io/fyne/v2"
|
||||
)
|
||||
|
||||
// Size represents the yaml description of a ui size
|
||||
type Size struct {
|
||||
Width float32 `yaml:"width"`
|
||||
Height float32 `yaml:"height"`
|
||||
}
|
||||
|
||||
// Element represents the yaml description of a ui element
|
||||
type Element struct {
|
||||
ID string `yaml:"id"`
|
||||
|
||||
@ -57,6 +59,12 @@ type Element struct {
|
||||
Time *string `yaml:"time"`
|
||||
TimeFormat *string `yaml:"timeFormat"`
|
||||
|
||||
// Entry Properties
|
||||
MultiLine bool `yaml:"multiLine"`
|
||||
Placeholder string `yaml:"placeholder"`
|
||||
PlaceholderLocalized bool `yaml:"placeholderLocalized"`
|
||||
Validator string `yaml:"validator"`
|
||||
|
||||
// List Properties
|
||||
ItemTemplate string `yaml:"itemTemplate"`
|
||||
ItemRenderer string `yaml:"itemRenderer"`
|
||||
@ -70,38 +78,44 @@ type Element struct {
|
||||
FixVertical bool `yaml:"fixVertical"`
|
||||
|
||||
// Handlers
|
||||
OnClicked string `yaml:"onClicked"`
|
||||
OnUpClicked string `yaml:"onUpClicked"`
|
||||
OnDownClicked string `yaml:"onDownClicked"`
|
||||
OnChanged string `yaml:"onChanged"`
|
||||
OnSelected string `yaml:"onSelected"`
|
||||
OnUnselected string `yaml:"onUnselected"`
|
||||
OnDateSelected string `yaml:"onDateSelected"`
|
||||
OnClicked string `yaml:"onClicked"`
|
||||
OnUpClicked string `yaml:"onUpClicked"`
|
||||
OnDownClicked string `yaml:"onDownClicked"`
|
||||
OnChanged string `yaml:"onChanged"`
|
||||
OnSelected string `yaml:"onSelected"`
|
||||
OnUnselected string `yaml:"onUnselected"`
|
||||
OnDateSelected string `yaml:"onDateSelected"`
|
||||
OnValidationChanged string `yaml:"onValidationChanged"`
|
||||
}
|
||||
|
||||
// BuildUI generates the UI for the Element.
|
||||
//
|
||||
// It takes a ScreenHandler parameter and returns a fyne.CanvasObject and an error.
|
||||
func (e *Element) BuildUI(s ScreenHandler) (obj fyne.CanvasObject, err error) {
|
||||
var baseObject fyne.CanvasObject
|
||||
|
||||
defer func() {
|
||||
if e.ID != "" && obj != nil {
|
||||
s.RegisterElement(e.ID, obj)
|
||||
if e.ID != "" && baseObject != nil {
|
||||
s.RegisterElement(e.ID, baseObject, obj)
|
||||
}
|
||||
}()
|
||||
|
||||
if e.Container != "" {
|
||||
if obj, err = e.Container.Build(e, s); err != nil {
|
||||
if baseObject, obj, err = e.Container.Build(e, s); err != nil {
|
||||
err = fmt.Errorf("failed to build container element: %w", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if e.Layout != "" {
|
||||
if obj, err = e.Layout.Build(e, s); err != nil {
|
||||
if baseObject, obj, err = e.Layout.Build(e, s); err != nil {
|
||||
err = fmt.Errorf("failed to build layout element: %w", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if e.Widget != "" {
|
||||
if obj, err = e.Widget.Build(e, s); err != nil {
|
||||
if baseObject, obj, err = e.Widget.Build(e, s); err != nil {
|
||||
err = fmt.Errorf("failed to build widget element: %w", err)
|
||||
return
|
||||
}
|
||||
@ -115,4 +129,7 @@ func (e *Element) localize(s ScreenHandler) {
|
||||
if e.Localized {
|
||||
e.Text = i18n.T(s.GetLocalizer(), e.Text)
|
||||
}
|
||||
if e.PlaceholderLocalized {
|
||||
e.Placeholder = i18n.T(s.GetLocalizer(), e.Placeholder)
|
||||
}
|
||||
}
|
||||
|
135
screen/layout.go
135
screen/layout.go
@ -11,34 +11,101 @@ import (
|
||||
"fyne.io/fyne/v2/layout"
|
||||
)
|
||||
|
||||
// The constants for the Layouts
|
||||
//
|
||||
// Available yaml options for all layouts:
|
||||
// - id: The ID for exporting the layout to code
|
||||
// - decorators: The decorators to wrap the layout into
|
||||
// - hidden: Wether the layout is hidden or not
|
||||
type Layout string
|
||||
|
||||
const (
|
||||
Border Layout = "Border"
|
||||
Form Layout = "Form"
|
||||
Grid Layout = "Grid"
|
||||
HBox Layout = "HBox"
|
||||
// Border Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - top: The top pane (contains 1 widget)
|
||||
// - bottom: The bottom pane (contains 1 widget)
|
||||
// - left: The left pane (contains 1 widget)
|
||||
// - right: The right pane (contains 1 widget)
|
||||
// - center: The center pane (contains multiple widgets)
|
||||
Border Layout = "Border"
|
||||
|
||||
// Form Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - children: The children of the form
|
||||
// - label: The label of the form element
|
||||
// - field: The field of the form element
|
||||
Form Layout = "Form"
|
||||
|
||||
// Grid Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - columns: The number of columns (GridWithColumns)
|
||||
// - rows: The number of rows (GridWithRows)
|
||||
// - rowColumns: The number of rows and columns (AdaptiveGrid)
|
||||
// - elementSize: The size of the elements (GridWrap)
|
||||
// - children: The children of the grid
|
||||
Grid Layout = "Grid"
|
||||
|
||||
// HBox Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - children: The children of the HBox
|
||||
HBox Layout = "HBox"
|
||||
|
||||
// MinSize Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - minSize: The minimum size of the layout
|
||||
// - children: The children of the MinSize
|
||||
MinSize Layout = "MinSize"
|
||||
Stack Layout = "Stack"
|
||||
VBox Layout = "VBox"
|
||||
|
||||
// Stack Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - children: The children of the Stack
|
||||
Stack Layout = "Stack"
|
||||
|
||||
// VBox Layout
|
||||
//
|
||||
// Available yaml options
|
||||
// - children: The children of the VBox
|
||||
VBox Layout = "VBox"
|
||||
)
|
||||
|
||||
func (l Layout) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
// Build builds the layout based on the given Layout and Element
|
||||
// using the provided ScreenHandler to fetch functions, data bindings, etc.
|
||||
//
|
||||
// Parameters:
|
||||
// - e: The Element to build the Layout for
|
||||
// - s: The ScreenHandler to use to fetch functions, data bindings, etc.
|
||||
// Returns the CanvasObject for the Layout, the CanvasObject for the decorator
|
||||
// and an error if any.
|
||||
// If no decorators are specified, the widget and decorator will be the same.
|
||||
func (l Layout) Build(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (
|
||||
layout fyne.CanvasObject,
|
||||
decorator fyne.CanvasObject,
|
||||
err error,
|
||||
) {
|
||||
switch l {
|
||||
case Border:
|
||||
c, err = l.buildBorderLayout(e, s)
|
||||
layout, err = l.buildBorderLayout(e, s)
|
||||
case Form:
|
||||
c, err = l.buildFormLayout(e, s)
|
||||
layout, err = l.buildFormLayout(e, s)
|
||||
case Grid:
|
||||
c, err = l.buildGridLayout(e, s)
|
||||
layout, err = l.buildGridLayout(e, s)
|
||||
case HBox:
|
||||
c, err = l.buildHBoxLayout(e, s)
|
||||
layout, err = l.buildHBoxLayout(e, s)
|
||||
case MinSize:
|
||||
c, err = l.buildMinSizeLayout(e, s)
|
||||
layout, err = l.buildMinSizeLayout(e, s)
|
||||
case Stack:
|
||||
c, err = l.buildStackLayout(e, s)
|
||||
layout, err = l.buildStackLayout(e, s)
|
||||
case VBox:
|
||||
c, err = l.buildVBoxLayout(e, s)
|
||||
layout, err = l.buildVBoxLayout(e, s)
|
||||
default:
|
||||
err = errors.New("invalid layout")
|
||||
}
|
||||
@ -46,22 +113,26 @@ func (l Layout) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err err
|
||||
return
|
||||
}
|
||||
|
||||
decorator = layout
|
||||
if e.Decorators != nil {
|
||||
for _, dec := range e.Decorators {
|
||||
switch dec {
|
||||
case "Border":
|
||||
c = uiwidget.NewWidgetBorder(c)
|
||||
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.Hidden {
|
||||
c.Hide()
|
||||
decorator.Hide()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildBorderLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildBorderLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
var top, left, right, bottom fyne.CanvasObject
|
||||
var center []fyne.CanvasObject
|
||||
|
||||
@ -109,7 +180,10 @@ func (l Layout) buildBorderLayout(e *Element, s ScreenHandler) (c *fyne.Containe
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildFormLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildFormLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children)*2)
|
||||
for _, child := range e.Children {
|
||||
if child.Label == nil {
|
||||
@ -149,7 +223,10 @@ func (l Layout) buildFormLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildGridLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildGridLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||
for _, child := range e.Children {
|
||||
var obj fyne.CanvasObject
|
||||
@ -179,7 +256,10 @@ func (l Layout) buildGridLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildHBoxLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||
for _, child := range e.Children {
|
||||
var obj fyne.CanvasObject
|
||||
@ -193,7 +273,10 @@ func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildMinSizeLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildMinSizeLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||
for _, child := range e.Children {
|
||||
var obj fyne.CanvasObject
|
||||
@ -216,7 +299,10 @@ func (l Layout) buildMinSizeLayout(e *Element, s ScreenHandler) (c *fyne.Contain
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildStackLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||
for _, child := range e.Children {
|
||||
var obj fyne.CanvasObject
|
||||
@ -230,7 +316,10 @@ func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container
|
||||
return
|
||||
}
|
||||
|
||||
func (l Layout) buildVBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container, err error) {
|
||||
func (l Layout) buildVBoxLayout(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c *fyne.Container, err error) {
|
||||
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||
for _, child := range e.Children {
|
||||
var obj fyne.CanvasObject
|
||||
|
@ -5,15 +5,19 @@ import (
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// ListItemTemplate is a template for a list item.
|
||||
// It implements the fyne.CanvasObject interface and TemplateScreenHandler
|
||||
type ListItemTemplate struct {
|
||||
fyne.CanvasObject
|
||||
*TemplateScreenHandler
|
||||
}
|
||||
|
||||
// CreateRenderer implements the fyne.CanvasObject interface
|
||||
func (i *ListItemTemplate) CreateRenderer() fyne.WidgetRenderer {
|
||||
return widget.NewSimpleRenderer(i.CanvasObject)
|
||||
}
|
||||
|
||||
// NewListItemTemplate creates a new ListItemTemplate
|
||||
func NewListItemTemplate(
|
||||
obj fyne.CanvasObject,
|
||||
screenHandler *TemplateScreenHandler,
|
||||
|
@ -16,22 +16,39 @@ import (
|
||||
"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 ValidationChangedHandlerFn func(error)
|
||||
|
||||
type UIElement struct {
|
||||
Object fyne.CanvasObject
|
||||
Decorator fyne.CanvasObject
|
||||
}
|
||||
|
||||
type ScreenHandler interface {
|
||||
RegisterElement(string, fyne.CanvasObject)
|
||||
RegisterElement(string, fyne.CanvasObject, 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
|
||||
GetValidator(string) fyne.StringValidator
|
||||
GetListItemTemplate(string) ListItemTemplateFn
|
||||
GetListDataItemRenderer(string) ListDataItemRendererFn
|
||||
GetListItemRenderer(string) ListItemRendererFn
|
||||
GetListLength(string) ListLengthFn
|
||||
|
||||
GetOnSelectedHandler(string) func(widget.ListItemID)
|
||||
GetOnUnselectedHandler(string) func(widget.ListItemID)
|
||||
GetClickedHandler(string) func()
|
||||
GetCheckChangedHandler(string) func(bool)
|
||||
GetDateSelectedHandler(string) func(time.Time)
|
||||
GetOnListItemSelectedHandler(string) ListItemHandlerFn
|
||||
GetOnListItemUnselectedHandler(string) ListItemHandlerFn
|
||||
GetOnClickedHandler(string) ClickHandlerFn
|
||||
GetOnCheckChangedHandler(string) CheckHandlerFn
|
||||
GetOnDateSelectedHandler(string) DateSelectedHandlerFn
|
||||
GetOnValidationChangedHandler(string) ValidationChangedHandlerFn
|
||||
}
|
||||
|
||||
type Screen struct {
|
||||
@ -79,7 +96,7 @@ func NewTemplate(
|
||||
handler *TemplateScreenHandler,
|
||||
err error,
|
||||
) {
|
||||
handler = NewDummyScreenHandler(localizer)
|
||||
handler = NewTemplateScreenHandler(localizer)
|
||||
scr, err = New(filesystem, name, handler)
|
||||
return
|
||||
}
|
||||
@ -94,21 +111,27 @@ func (s *Screen) Initialize() (obj fyne.CanvasObject, err error) {
|
||||
|
||||
type TemplateScreenHandler struct {
|
||||
localizer *i18n.Localizer
|
||||
elementsMap map[string]fyne.CanvasObject
|
||||
elementsMap map[string]*UIElement
|
||||
}
|
||||
|
||||
func NewDummyScreenHandler(localizer *i18n.Localizer) *TemplateScreenHandler {
|
||||
func NewTemplateScreenHandler(
|
||||
localizer *i18n.Localizer,
|
||||
) *TemplateScreenHandler {
|
||||
return &TemplateScreenHandler{
|
||||
localizer: localizer,
|
||||
elementsMap: make(map[string]fyne.CanvasObject),
|
||||
elementsMap: make(map[string]*UIElement),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *TemplateScreenHandler) RegisterElement(name string, element fyne.CanvasObject) {
|
||||
d.elementsMap[name] = element
|
||||
func (d *TemplateScreenHandler) RegisterElement(
|
||||
name string,
|
||||
element fyne.CanvasObject,
|
||||
decorator fyne.CanvasObject,
|
||||
) {
|
||||
d.elementsMap[name] = &UIElement{element, decorator}
|
||||
}
|
||||
|
||||
func (d *TemplateScreenHandler) GetElement(name string) fyne.CanvasObject {
|
||||
func (d *TemplateScreenHandler) GetElement(name string) *UIElement {
|
||||
elem, ok := d.elementsMap[name]
|
||||
if !ok {
|
||||
return nil
|
||||
@ -132,38 +155,46 @@ func (*TemplateScreenHandler) GetBinding(string) binding.DataItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetListItemTemplate(string) func() fyne.CanvasObject {
|
||||
func (*TemplateScreenHandler) GetValidator(string) fyne.StringValidator {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetListItemTemplate(string) ListItemTemplateFn {
|
||||
return func() fyne.CanvasObject { return nil }
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetListDataItemRenderer(string) func(binding.DataItem, fyne.CanvasObject) {
|
||||
func (*TemplateScreenHandler) GetListDataItemRenderer(string) ListDataItemRendererFn {
|
||||
return func(binding.DataItem, fyne.CanvasObject) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetListItemRenderer(string) func(int, fyne.CanvasObject) {
|
||||
func (*TemplateScreenHandler) GetListItemRenderer(string) ListItemRendererFn {
|
||||
return func(int, fyne.CanvasObject) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetListLength(string) func() int {
|
||||
func (*TemplateScreenHandler) GetListLength(string) ListLengthFn {
|
||||
return func() int { return 0 }
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetOnSelectedHandler(string) func(widget.ListItemID) {
|
||||
func (*TemplateScreenHandler) GetOnListItemSelectedHandler(string) ListItemHandlerFn {
|
||||
return func(widget.ListItemID) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetOnUnselectedHandler(string) func(widget.ListItemID) {
|
||||
func (*TemplateScreenHandler) GetOnListItemUnselectedHandler(string) ListItemHandlerFn {
|
||||
return func(widget.ListItemID) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetClickedHandler(string) func() {
|
||||
func (*TemplateScreenHandler) GetOnClickedHandler(string) ClickHandlerFn {
|
||||
return func() {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetCheckChangedHandler(string) func(bool) {
|
||||
func (*TemplateScreenHandler) GetOnCheckChangedHandler(string) CheckHandlerFn {
|
||||
return func(bool) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetDateSelectedHandler(string) func(time.Time) {
|
||||
func (*TemplateScreenHandler) GetOnDateSelectedHandler(string) DateSelectedHandlerFn {
|
||||
return func(time.Time) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetOnValidationChangedHandler(string) ValidationChangedHandlerFn {
|
||||
return func(error) {}
|
||||
}
|
||||
|
319
screen/widget.go
319
screen/widget.go
@ -13,47 +13,216 @@ import (
|
||||
xwidget "fyne.io/x/fyne/widget"
|
||||
)
|
||||
|
||||
// The constants for the Widgets
|
||||
//
|
||||
// Available yaml options for all widgets:
|
||||
// - id: The ID for exporting the widget to code
|
||||
// - decorators: The decorators to wrap the widget into
|
||||
// - hidden: Wether the widget is hidden or not
|
||||
type Widget string
|
||||
|
||||
const (
|
||||
Button Widget = "Button"
|
||||
Calendar Widget = "Calendar"
|
||||
Check Widget = "Check"
|
||||
H1 Widget = "H1"
|
||||
H2 Widget = "H2"
|
||||
H3 Widget = "H3"
|
||||
H4 Widget = "H4"
|
||||
H5 Widget = "H5"
|
||||
H6 Widget = "H6"
|
||||
Label Widget = "Label"
|
||||
List Widget = "List"
|
||||
Separator Widget = "Separator"
|
||||
Spacer Widget = "Spacer"
|
||||
// Button Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the button
|
||||
// - localized: If the text represents a localization key
|
||||
// - icon: The icon for the button
|
||||
// - disabled: Wether the button is disabled or not
|
||||
// - options: Additional options for the button
|
||||
// - alignment: The alignment of the button
|
||||
// - iconPlacement: The icon placement of the button
|
||||
// - importance: The importance of the button
|
||||
// - onclicked: The function to call when the button is clicked
|
||||
Button Widget = "Button"
|
||||
|
||||
// Calendar Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - time: The current time to use for the calendar
|
||||
// - timeFormat: The format to use to interpret the time field (default time.DateOnly)
|
||||
// - onDateSelected: The function to call when a date is selected
|
||||
Calendar Widget = "Calendar"
|
||||
|
||||
// Checkbox Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the checkbox
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the checkbox
|
||||
// - checked: The checked state of the checkbox
|
||||
// - disabled: Wether the button is disabled or not
|
||||
// - onChanged: The function to call when the checkbox is changed
|
||||
Check Widget = "Check"
|
||||
|
||||
// Entry Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the entry
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the entry
|
||||
// - placeholder: The placeholder for the entry
|
||||
// - placeholderLocalized: If the placeholder represents a localization key
|
||||
// - multiLine: If the entry is multiline
|
||||
// - disabled: Wether the button is disabled or not
|
||||
// - validator: The validator for the entry
|
||||
// - onValidationChanged: The function to call when the validation changes
|
||||
Entry Widget = "Entry"
|
||||
|
||||
// H1 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H1
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H1
|
||||
// - options: The options for the H1
|
||||
// - wrapping: The wrapping option for the H1
|
||||
// - truncation: The truncation option for the H1
|
||||
H1 Widget = "H1"
|
||||
|
||||
// H2 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H2
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H2
|
||||
// - options: The options for the H2
|
||||
// - wrapping: The wrapping option for the H2
|
||||
// - truncation: The truncation option for the H2
|
||||
H2 Widget = "H2"
|
||||
|
||||
// H3 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H3
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H3
|
||||
// - options: The options for the H3
|
||||
// - wrapping: The wrapping option for the H3
|
||||
// - truncation: The truncation option for the H3
|
||||
H3 Widget = "H3"
|
||||
|
||||
// H4 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H4
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H4
|
||||
// - options: The options for the H4
|
||||
// - wrapping: The wrapping option for the H4
|
||||
// - truncation: The truncation option for the H4
|
||||
H4 Widget = "H4"
|
||||
|
||||
// H5 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H5
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H5
|
||||
// - options: The options for the H5
|
||||
// - wrapping: The wrapping option for the H5
|
||||
// - truncation: The truncation option for the H5
|
||||
H5 Widget = "H5"
|
||||
|
||||
// H6 Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the H6
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the H6
|
||||
// - options: The options for the H6
|
||||
// - wrapping: The wrapping option for the H6
|
||||
// - truncation: The truncation option for the H6
|
||||
H6 Widget = "H6"
|
||||
|
||||
// Icon Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - icon: The icon for the icon
|
||||
Icon Widget = "Icon"
|
||||
|
||||
// Label Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - text: The text for the label
|
||||
// - localized: If the text represents a localization key
|
||||
// - binding: The databinding for the label
|
||||
// - options: The options for the label
|
||||
// - allignment: The alignment option for the label
|
||||
// - wrapping: The wrapping option for the label
|
||||
// - textStyle: The text style option for the label
|
||||
// - truncation: The truncation option for the label
|
||||
Label Widget = "Label"
|
||||
|
||||
// List Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - binding: The databinding for the list
|
||||
// - listLength: The length of the list
|
||||
// - itemTemplate: The item template for the list
|
||||
// - itemRenderer: The item renderer for the list
|
||||
// - onSelect: The on select function for the list
|
||||
// - onUnselect: The on unselect function for the list
|
||||
List Widget = "List"
|
||||
|
||||
// Separator Widget
|
||||
Separator Widget = "Separator"
|
||||
|
||||
// Spacer Widget
|
||||
Spacer Widget = "Spacer"
|
||||
|
||||
// UpDownLabel Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
// - binding: The databinding for the up down label
|
||||
// - onUpClicked: The on up clicked function for the up down label
|
||||
// - onDownClicked: The on down clicked function for the up down label
|
||||
UpDownLabel Widget = "UpDownLabel"
|
||||
)
|
||||
|
||||
func (w Widget) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
// Build builds a fyne.CanvasObject for the given Widget and Element,
|
||||
// using the provided ScreenHandler to fetch functions, data bindings, etc.
|
||||
//
|
||||
// Arguments:
|
||||
// - e: The Element to build the Widget for.
|
||||
// - s: The ScreenHandler to use to fetch functions, data bindings, etc.
|
||||
//
|
||||
// Returns the CanvasObject for the widget, the CanvasObject for the decorator,
|
||||
// and an error if any.
|
||||
// If no decorators are specified, the widget and decorator will be the same.
|
||||
func (w Widget) Build(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (
|
||||
widget fyne.CanvasObject,
|
||||
decorator fyne.CanvasObject,
|
||||
err error,
|
||||
) {
|
||||
e.localize(s)
|
||||
|
||||
switch w {
|
||||
case Button:
|
||||
c, err = w.buildButtonWidget(e, s)
|
||||
widget, err = w.buildButtonWidget(e, s)
|
||||
case Calendar:
|
||||
c, err = w.buildCalendarWidget(e, s)
|
||||
widget, err = w.buildCalendarWidget(e, s)
|
||||
case Check:
|
||||
c, err = w.buildCheckWidget(e, s)
|
||||
widget, err = w.buildCheckWidget(e, s)
|
||||
case Entry:
|
||||
widget, err = w.buildEntryWidget(e, s)
|
||||
case H1, H2, H3, H4, H5, H6:
|
||||
c, err = w.buildHeaderLabelWidget(e, s)
|
||||
widget, err = w.buildHeaderLabelWidget(e, s)
|
||||
case Icon:
|
||||
widget, err = w.buildIconWidget(e, s)
|
||||
case Label:
|
||||
c, err = w.buildLabelWidget(e, s)
|
||||
widget, err = w.buildLabelWidget(e, s)
|
||||
case List:
|
||||
c, err = w.buildListWidget(e, s)
|
||||
widget, err = w.buildListWidget(e, s)
|
||||
case Separator:
|
||||
c, err = w.buildSeparatorWidget(e, s)
|
||||
widget, err = w.buildSeparatorWidget(e, s)
|
||||
case Spacer:
|
||||
c, err = w.buildSpacerWidget(e, s)
|
||||
widget, err = w.buildSpacerWidget(e, s)
|
||||
case UpDownLabel:
|
||||
c, err = w.buildUpDownLabelWidget(e, s)
|
||||
widget, err = w.buildUpDownLabelWidget(e, s)
|
||||
default:
|
||||
err = errors.New("invalid widget")
|
||||
}
|
||||
@ -61,28 +230,32 @@ func (w Widget) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err err
|
||||
return
|
||||
}
|
||||
|
||||
decorator = widget
|
||||
if e.Decorators != nil {
|
||||
for _, dec := range e.Decorators {
|
||||
switch dec {
|
||||
case "Border":
|
||||
c = uiwidget.NewWidgetBorder(c)
|
||||
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.Hidden {
|
||||
c.Hide()
|
||||
decorator.Hide()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildButtonWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildButtonWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var btn *widget.Button
|
||||
if e.Icon != "" {
|
||||
btn = widget.NewButtonWithIcon(
|
||||
e.Text, s.GetIcon(e.Icon), s.GetClickedHandler(e.OnClicked))
|
||||
e.Text, s.GetIcon(e.Icon), s.GetOnClickedHandler(e.OnClicked))
|
||||
} else {
|
||||
btn = widget.NewButton(e.Text, s.GetClickedHandler(e.OnClicked))
|
||||
btn = widget.NewButton(e.Text, s.GetOnClickedHandler(e.OnClicked))
|
||||
}
|
||||
|
||||
for opt, val := range e.Options {
|
||||
@ -103,7 +276,10 @@ func (w Widget) buildButtonWidget(e *Element, s ScreenHandler) (c fyne.CanvasObj
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildCalendarWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildCalendarWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
t := time.Now()
|
||||
if e.Time != nil {
|
||||
timeFormat := time.DateOnly
|
||||
@ -116,18 +292,21 @@ func (w Widget) buildCalendarWidget(e *Element, s ScreenHandler) (c fyne.CanvasO
|
||||
}
|
||||
}
|
||||
|
||||
c = xwidget.NewCalendar(t, s.GetDateSelectedHandler(e.OnDateSelected))
|
||||
c = xwidget.NewCalendar(t, s.GetOnDateSelectedHandler(e.OnDateSelected))
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildCheckWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildCheckWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var chk *widget.Check
|
||||
if e.Binding != "" {
|
||||
chk = widget.NewCheckWithData(
|
||||
e.Text, s.GetBinding(e.Binding).(binding.Bool))
|
||||
} else {
|
||||
chk = widget.NewCheck(
|
||||
e.Text, s.GetCheckChangedHandler(e.OnChanged))
|
||||
e.Text, s.GetOnCheckChangedHandler(e.OnChanged))
|
||||
chk.SetChecked(e.Checked)
|
||||
}
|
||||
|
||||
@ -138,7 +317,40 @@ func (w Widget) buildCheckWidget(e *Element, s ScreenHandler) (c fyne.CanvasObje
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildHeaderLabelWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildEntryWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var ent *widget.Entry
|
||||
if e.MultiLine {
|
||||
ent = widget.NewMultiLineEntry()
|
||||
} else {
|
||||
ent = widget.NewEntry()
|
||||
}
|
||||
if e.Binding != "" {
|
||||
ent.Bind(s.GetBinding(e.Binding).(binding.String))
|
||||
} else {
|
||||
ent.Text = e.Text
|
||||
}
|
||||
ent.PlaceHolder = e.Placeholder
|
||||
if e.Validator != "" {
|
||||
ent.Validator = s.GetValidator(e.Validator)
|
||||
}
|
||||
if e.OnValidationChanged != "" {
|
||||
ent.SetOnValidationChanged(s.GetOnValidationChangedHandler(e.OnValidationChanged))
|
||||
}
|
||||
|
||||
if e.Disabled {
|
||||
ent.Disable()
|
||||
}
|
||||
c = ent
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildHeaderLabelWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var rt *widget.RichText
|
||||
|
||||
level := 1
|
||||
@ -174,7 +386,18 @@ func (w Widget) buildHeaderLabelWidget(e *Element, s ScreenHandler) (c fyne.Canv
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildLabelWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildIconWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
c = widget.NewIcon(s.GetIcon(e.Icon))
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildLabelWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var lbl *widget.Label
|
||||
|
||||
if e.Binding != "" {
|
||||
@ -201,7 +424,10 @@ func (w Widget) buildLabelWidget(e *Element, s ScreenHandler) (c fyne.CanvasObje
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildListWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildListWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var lst *widget.List
|
||||
|
||||
if e.Binding != "" {
|
||||
@ -217,22 +443,28 @@ func (w Widget) buildListWidget(e *Element, s ScreenHandler) (c fyne.CanvasObjec
|
||||
}
|
||||
|
||||
if e.OnSelected != "" {
|
||||
lst.OnSelected = s.GetOnSelectedHandler(e.OnSelected)
|
||||
lst.OnSelected = s.GetOnListItemSelectedHandler(e.OnSelected)
|
||||
}
|
||||
if e.OnUnselected != "" {
|
||||
lst.OnUnselected = s.GetOnUnselectedHandler(e.OnUnselected)
|
||||
lst.OnUnselected = s.GetOnListItemUnselectedHandler(e.OnUnselected)
|
||||
}
|
||||
c = lst
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildSeparatorWidget(_ *Element, _ ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildSeparatorWidget(
|
||||
_ *Element,
|
||||
_ ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
sep := widget.NewSeparator()
|
||||
c = sep
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildSpacerWidget(e *Element, _ ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildSpacerWidget(
|
||||
e *Element,
|
||||
_ ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
spc := &layout.Spacer{
|
||||
FixHorizontal: e.FixHorizontal,
|
||||
FixVertical: e.FixVertical,
|
||||
@ -241,11 +473,14 @@ func (w Widget) buildSpacerWidget(e *Element, _ ScreenHandler) (c fyne.CanvasObj
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildUpDownLabelWidget(e *Element, s ScreenHandler) (c fyne.CanvasObject, err error) {
|
||||
func (w Widget) buildUpDownLabelWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
btn := uiwidget.NewUpDownLabelWithData(
|
||||
s.GetBinding(e.Binding).(binding.String),
|
||||
s.GetClickedHandler(e.OnUpClicked),
|
||||
s.GetClickedHandler(e.OnDownClicked))
|
||||
s.GetOnClickedHandler(e.OnUpClicked),
|
||||
s.GetOnClickedHandler(e.OnDownClicked))
|
||||
c = btn
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user