Implement defining screens in yaml
This commit is contained in:
parent
b9d2b680bc
commit
c848c2332f
63
baseview.go
63
baseview.go
@ -1,12 +1,10 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"embed"
|
||||||
|
|
||||||
"bitbucket.org/hevanto/ui/screen"
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/data/binding"
|
"fyne.io/fyne/v2/data/binding"
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
)
|
)
|
||||||
@ -26,35 +24,8 @@ type BaseView struct {
|
|||||||
// Root CanvasObject of the view
|
// Root CanvasObject of the view
|
||||||
CanvasObject fyne.CanvasObject
|
CanvasObject fyne.CanvasObject
|
||||||
|
|
||||||
// The screen definition
|
|
||||||
screenDefinition *screen.Screen
|
|
||||||
|
|
||||||
// ----------- ScreenHandler -------------//
|
// ----------- ScreenHandler -------------//
|
||||||
|
*ScreenHandler
|
||||||
// Localizer to translate screen labels
|
|
||||||
localizer *i18n.Localizer
|
|
||||||
|
|
||||||
// Map of screen elements that got an id assigned
|
|
||||||
screenElementMap map[string]fyne.CanvasObject
|
|
||||||
|
|
||||||
// Map of list item template
|
|
||||||
listItemTemplates map[string]func() fyne.CanvasObject
|
|
||||||
|
|
||||||
// Map of list data item renderers
|
|
||||||
listDataItemRenderers map[string]func(binding.DataItem, fyne.CanvasObject)
|
|
||||||
|
|
||||||
// Map of list item renderers
|
|
||||||
listItemRenderers map[string]func(int, fyne.CanvasObject)
|
|
||||||
|
|
||||||
// Map of list length functions
|
|
||||||
listLenghts map[string]func() int
|
|
||||||
|
|
||||||
// Handlers
|
|
||||||
onSelectedHandlers map[string]func(widget.ListItemID)
|
|
||||||
onUnselectedHandlers map[string]func(widget.ListItemID)
|
|
||||||
onClickedHandlers map[string]func()
|
|
||||||
onCheckChangedHandlers map[string]func(bool)
|
|
||||||
onDateSelectedHandlers map[string]func(time.Time)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBaseView creates a new baseview
|
// NewBaseView creates a new baseview
|
||||||
@ -80,6 +51,28 @@ func NewBaseView(
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewBaseViewWithScreen(
|
||||||
|
concreteView View,
|
||||||
|
controller Controller,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) *BaseView {
|
||||||
|
v := NewBaseView(concreteView, controller)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
v.ScreenHandler, err = NewScreenHandler(
|
||||||
|
filesystem,
|
||||||
|
screenName,
|
||||||
|
controller,
|
||||||
|
localizer)
|
||||||
|
if err != nil {
|
||||||
|
LogWindowError(v, LoadScreen, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// ID returns tie id of the view
|
// ID returns tie id of the view
|
||||||
func (v BaseView) ID() string {
|
func (v BaseView) ID() string {
|
||||||
return v.id
|
return v.id
|
||||||
@ -106,8 +99,8 @@ func (v *BaseView) Initialize() fyne.CanvasObject {
|
|||||||
if err := v.Ctrl.Initialize(); err != nil {
|
if err := v.Ctrl.Initialize(); err != nil {
|
||||||
LogWindowError(v, Initialize, err)
|
LogWindowError(v, Initialize, err)
|
||||||
}
|
}
|
||||||
if v.screenDefinition != nil {
|
if v.ScreenHandler != nil && v.ScreenDefinition() != nil {
|
||||||
obj, err := v.screenDefinition.Initialize()
|
obj, err := v.ScreenDefinition().Initialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogWindowError(v, Initialize, err)
|
LogWindowError(v, Initialize, err)
|
||||||
return nil
|
return nil
|
||||||
@ -133,3 +126,7 @@ func (v *BaseView) OnShow() {
|
|||||||
func (v *BaseView) OnHide() {
|
func (v *BaseView) OnHide() {
|
||||||
LogWindowEvent(v, OnHide)
|
LogWindowEvent(v, OnHide)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *BaseView) GetBinding(bindingName string) binding.DataItem {
|
||||||
|
return v.Ctrl.GetBinding(bindingName)
|
||||||
|
}
|
||||||
|
@ -1,177 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"bitbucket.org/hevanto/ui/screen"
|
|
||||||
"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"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewBaseViewWithScreen(
|
|
||||||
concreteView View,
|
|
||||||
filesystem embed.FS,
|
|
||||||
screenName string,
|
|
||||||
localizer *i18n.Localizer,
|
|
||||||
controller Controller,
|
|
||||||
) *BaseView {
|
|
||||||
v := NewBaseView(concreteView, controller)
|
|
||||||
def, err := screen.New(filesystem, screenName, v)
|
|
||||||
if err != nil {
|
|
||||||
LogWindowError(v, LoadScreen, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
v.screenDefinition = def
|
|
||||||
v.localizer = localizer
|
|
||||||
v.screenElementMap = make(map[string]fyne.CanvasObject)
|
|
||||||
v.listItemTemplates = make(map[string]func() fyne.CanvasObject)
|
|
||||||
v.listDataItemRenderers = make(map[string]func(binding.DataItem, fyne.CanvasObject))
|
|
||||||
v.listItemRenderers = make(map[string]func(int, fyne.CanvasObject))
|
|
||||||
v.listLenghts = make(map[string]func() int)
|
|
||||||
v.onSelectedHandlers = make(map[string]func(widget.ListItemID))
|
|
||||||
v.onUnselectedHandlers = make(map[string]func(widget.ListItemID))
|
|
||||||
v.onClickedHandlers = make(map[string]func())
|
|
||||||
v.onCheckChangedHandlers = make(map[string]func(bool))
|
|
||||||
v.onDateSelectedHandlers = make(map[string]func(time.Time))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterElement(id string, elem fyne.CanvasObject) {
|
|
||||||
v.screenElementMap[id] = elem
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterListItemTemplate(name string, fn func() fyne.CanvasObject) {
|
|
||||||
v.listItemTemplates[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterListDataItemRenderer(name string, fn func(binding.DataItem, fyne.CanvasObject)) {
|
|
||||||
v.listDataItemRenderers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterListItemRenderer(name string, fn func(int, fyne.CanvasObject)) {
|
|
||||||
v.listItemRenderers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterListLength(name string, fn func() int) {
|
|
||||||
v.listLenghts[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterOnSelectedHandler(name string, fn func(widget.ListItemID)) {
|
|
||||||
v.onSelectedHandlers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterOnUnselectedHandler(name string, fn func(widget.ListItemID)) {
|
|
||||||
v.onUnselectedHandlers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterOnClickHandler(name string, fn func()) {
|
|
||||||
v.onClickedHandlers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterOnCheckChangedHandler(name string, fn func(bool)) {
|
|
||||||
v.onCheckChangedHandlers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) RegisterOnDateSelectedHandler(name string, fn func(time.Time)) {
|
|
||||||
v.onDateSelectedHandlers[name] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetElement(id string) fyne.CanvasObject {
|
|
||||||
if elem, ok := v.screenElementMap[id]; ok {
|
|
||||||
return elem
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetLocalizer() *i18n.Localizer {
|
|
||||||
return v.localizer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) 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 (v *BaseView) GetBinding(bindingName string) binding.DataItem {
|
|
||||||
return v.Ctrl.GetBinding(bindingName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetListItemTemplate(name string) func() fyne.CanvasObject {
|
|
||||||
fn, ok := v.listItemTemplates[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetListDataItemRenderer(name string) func(binding.DataItem, fyne.CanvasObject) {
|
|
||||||
fn, ok := v.listDataItemRenderers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetListItemRenderer(name string) func(int, fyne.CanvasObject) {
|
|
||||||
fn, ok := v.listItemRenderers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetListLength(name string) func() int {
|
|
||||||
fn, ok := v.listLenghts[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetOnSelectedHandler(name string) func(widget.ListItemID) {
|
|
||||||
fn, ok := v.onSelectedHandlers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetOnUnselectedHandler(name string) func(widget.ListItemID) {
|
|
||||||
fn, ok := v.onUnselectedHandlers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetClickedHandler(name string) func() {
|
|
||||||
fn, ok := v.onClickedHandlers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetCheckChangedHandler(name string) func(bool) {
|
|
||||||
fn, ok := v.onCheckChangedHandlers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BaseView) GetDateSelectedHandler(name string) func(time.Time) {
|
|
||||||
fn, ok := v.onDateSelectedHandlers[name]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
@ -1,15 +1,25 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import "fyne.io/fyne/v2/data/binding"
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/data/binding"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ScreenController interface {
|
||||||
|
GetBinding(string) binding.DataItem
|
||||||
|
GetValidator(string) fyne.StringValidator
|
||||||
|
}
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
|
ScreenController
|
||||||
|
|
||||||
Initialize() error
|
Initialize() error
|
||||||
RefreshData() error
|
RefreshData() error
|
||||||
|
|
||||||
GetBinding(string) binding.DataItem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialogController interface {
|
type DialogController interface {
|
||||||
|
ScreenController
|
||||||
|
|
||||||
Initialize(data binding.DataItem) error
|
Initialize(data binding.DataItem) error
|
||||||
RefreshData() error
|
RefreshData() error
|
||||||
}
|
}
|
||||||
|
204
dialog.go
204
dialog.go
@ -1,6 +1,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
@ -8,13 +9,22 @@ import (
|
|||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DialogName string
|
type DialogName string
|
||||||
type DialogKind string
|
type DialogKind string
|
||||||
|
|
||||||
type OnConfirmFn func(bool, error, ...interface{})
|
type OnConfirmFn func(bool, error, ...interface{})
|
||||||
type NewDialogFn func(DialogName, DialogKind, fyne.Window, OnConfirmFn, ...binding.DataItem) Dialog
|
type NewDialogFn func(
|
||||||
|
DialogName,
|
||||||
|
DialogKind,
|
||||||
|
fyne.Window,
|
||||||
|
OnConfirmFn,
|
||||||
|
binding.DataItem,
|
||||||
|
*embed.FS,
|
||||||
|
string,
|
||||||
|
*i18n.Localizer) Dialog
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DlgGeneric DialogKind = "Generic"
|
DlgGeneric DialogKind = "Generic"
|
||||||
@ -47,12 +57,16 @@ type BaseDialog struct {
|
|||||||
CanvasObj fyne.CanvasObject
|
CanvasObj fyne.CanvasObject
|
||||||
Data binding.DataItem
|
Data binding.DataItem
|
||||||
focusItem fyne.Focusable
|
focusItem fyne.Focusable
|
||||||
|
|
||||||
|
Ctrl DialogController
|
||||||
|
*ScreenHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBaseDialog(
|
func NewBaseDialog(
|
||||||
concreteDialog Dialog,
|
concreteDialog Dialog,
|
||||||
name DialogName,
|
name DialogName,
|
||||||
kind DialogKind,
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
) *BaseDialog {
|
) *BaseDialog {
|
||||||
@ -63,13 +77,40 @@ func NewBaseDialog(
|
|||||||
dlgKind: kind,
|
dlgKind: kind,
|
||||||
window: parent,
|
window: parent,
|
||||||
onConfirm: confirm,
|
onConfirm: confirm,
|
||||||
|
Ctrl: controller,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewBaseDialogWithScreen(
|
||||||
|
concreteDialog Dialog,
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) *BaseDialog {
|
||||||
|
d := NewBaseDialog(
|
||||||
|
concreteDialog, name, kind, controller,
|
||||||
|
parent, confirm)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
d.ScreenHandler, err = NewScreenHandler(
|
||||||
|
filesystem, screenName, controller, localizer)
|
||||||
|
if err != nil {
|
||||||
|
LogWindowError(d, LoadScreen, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
func NewBaseDialogWithData(
|
func NewBaseDialogWithData(
|
||||||
concreteDialog Dialog,
|
concreteDialog Dialog,
|
||||||
name DialogName,
|
name DialogName,
|
||||||
kind DialogKind,
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
data binding.DataItem,
|
data binding.DataItem,
|
||||||
@ -82,9 +123,36 @@ func NewBaseDialogWithData(
|
|||||||
window: parent,
|
window: parent,
|
||||||
onConfirm: confirm,
|
onConfirm: confirm,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Ctrl: controller,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewBaseDialogWithDataAndScreen(
|
||||||
|
concreteDialog Dialog,
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
data binding.DataItem,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) *BaseDialog {
|
||||||
|
d := NewBaseDialogWithData(
|
||||||
|
concreteDialog, name, kind, controller,
|
||||||
|
parent, confirm, data)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
d.ScreenHandler, err = NewScreenHandler(
|
||||||
|
filesystem, screenName, controller, localizer)
|
||||||
|
if err != nil {
|
||||||
|
LogWindowError(d, LoadScreen, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
func (d BaseDialog) Window() fyne.Window {
|
func (d BaseDialog) Window() fyne.Window {
|
||||||
return d.window
|
return d.window
|
||||||
}
|
}
|
||||||
@ -114,6 +182,7 @@ func (d BaseDialog) OnConfirmFn() OnConfirmFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaseDialog) Show(parent ...fyne.Window) {
|
func (d *BaseDialog) Show(parent ...fyne.Window) {
|
||||||
|
|
||||||
d.concreteDialog.OnShow()
|
d.concreteDialog.OnShow()
|
||||||
d.dlg = dialog.NewCustomConfirm(
|
d.dlg = dialog.NewCustomConfirm(
|
||||||
d.concreteDialog.Title(),
|
d.concreteDialog.Title(),
|
||||||
@ -146,6 +215,17 @@ func (d BaseDialog) Title() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaseDialog) Initialize() fyne.CanvasObject {
|
func (d *BaseDialog) Initialize() fyne.CanvasObject {
|
||||||
|
if err := d.Ctrl.Initialize(d.Data); err != nil {
|
||||||
|
LogWindowError(d, Initialize, err)
|
||||||
|
}
|
||||||
|
if d.ScreenHandler != nil && d.ScreenDefinition() != nil {
|
||||||
|
obj, err := d.ScreenDefinition().Initialize()
|
||||||
|
if err != nil {
|
||||||
|
LogWindowError(d, Initialize, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
d.CanvasObj = obj
|
||||||
|
}
|
||||||
return d.CanvasObj
|
return d.CanvasObj
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,35 +264,80 @@ func NewFormDialog(
|
|||||||
concreteDialog Dialog,
|
concreteDialog Dialog,
|
||||||
name DialogName,
|
name DialogName,
|
||||||
kind DialogKind,
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
itemsFn FormDialogItemsFn,
|
itemsFn FormDialogItemsFn,
|
||||||
) *FormDialog {
|
) *FormDialog {
|
||||||
return &FormDialog{
|
return &FormDialog{
|
||||||
BaseDialog: NewBaseDialog(concreteDialog, name, kind, parent, confirm),
|
BaseDialog: NewBaseDialog(
|
||||||
|
concreteDialog, name, kind, controller, parent, confirm),
|
||||||
itemsFn: itemsFn,
|
itemsFn: itemsFn,
|
||||||
confirmLabel: "OK",
|
confirmLabel: "OK",
|
||||||
dismissLabel: "Cancel",
|
dismissLabel: "Cancel",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewFormDialogWithScreen(
|
||||||
|
concreteDialog Dialog,
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) *FormDialog {
|
||||||
|
return &FormDialog{
|
||||||
|
BaseDialog: NewBaseDialogWithScreen(
|
||||||
|
concreteDialog, name, kind, controller, parent, confirm,
|
||||||
|
filesystem, screenName, localizer),
|
||||||
|
confirmLabel: "OK",
|
||||||
|
dismissLabel: "Cancel",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewformDialogWithData(
|
func NewformDialogWithData(
|
||||||
concreteDialog Dialog,
|
concreteDialog Dialog,
|
||||||
name DialogName,
|
name DialogName,
|
||||||
kind DialogKind,
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
itemsFn FormDialogItemsFn,
|
itemsFn FormDialogItemsFn,
|
||||||
data binding.DataItem,
|
data binding.DataItem,
|
||||||
) *FormDialog {
|
) *FormDialog {
|
||||||
return &FormDialog{
|
return &FormDialog{
|
||||||
BaseDialog: NewBaseDialogWithData(concreteDialog, name, kind, parent, confirm, data),
|
BaseDialog: NewBaseDialogWithData(
|
||||||
|
concreteDialog, name, kind, controller, parent, confirm, data),
|
||||||
itemsFn: itemsFn,
|
itemsFn: itemsFn,
|
||||||
confirmLabel: "OK",
|
confirmLabel: "OK",
|
||||||
dismissLabel: "Cancel",
|
dismissLabel: "Cancel",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewFormDialogWithDataAndScreen(
|
||||||
|
concreteDialog Dialog,
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
controller DialogController,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
data binding.DataItem,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) *FormDialog {
|
||||||
|
return &FormDialog{
|
||||||
|
BaseDialog: NewBaseDialogWithDataAndScreen(
|
||||||
|
concreteDialog, name, kind, controller, parent, confirm, data,
|
||||||
|
filesystem, screenName, localizer),
|
||||||
|
confirmLabel: "OK",
|
||||||
|
dismissLabel: "Cancel",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *FormDialog) SetButtonLabels(
|
func (d *FormDialog) SetButtonLabels(
|
||||||
confirm string,
|
confirm string,
|
||||||
dismiss string,
|
dismiss string,
|
||||||
@ -221,7 +346,25 @@ func (d *FormDialog) SetButtonLabels(
|
|||||||
d.dismissLabel = dismiss
|
d.dismissLabel = dismiss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *FormDialog) Initialize() fyne.CanvasObject {
|
||||||
|
if d.itemsFn == nil {
|
||||||
|
form := d.BaseDialog.Initialize().(*fyne.Container)
|
||||||
|
d.itemsFn = func() []*widget.FormItem {
|
||||||
|
res := make([]*widget.FormItem, 0, len(form.Objects)/2)
|
||||||
|
for i := 0; i < len(form.Objects); i += 2 {
|
||||||
|
res = append(res, widget.NewFormItem(
|
||||||
|
form.Objects[i].(*widget.Label).Text,
|
||||||
|
form.Objects[i+1]))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *FormDialog) Show(parent ...fyne.Window) {
|
func (d *FormDialog) Show(parent ...fyne.Window) {
|
||||||
|
d.concreteDialog.Initialize()
|
||||||
d.items = d.itemsFn()
|
d.items = d.itemsFn()
|
||||||
|
|
||||||
d.concreteDialog.OnShow()
|
d.concreteDialog.OnShow()
|
||||||
@ -263,7 +406,8 @@ func RegisterDialog(name DialogName, kind DialogKind, fn NewDialogFn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDialog(
|
func NewDialog(
|
||||||
name DialogName, kind DialogKind,
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
) Dialog {
|
) Dialog {
|
||||||
@ -272,14 +416,37 @@ func NewDialog(
|
|||||||
}
|
}
|
||||||
if kindCatalog, ok := dialogCatalog[name]; ok {
|
if kindCatalog, ok := dialogCatalog[name]; ok {
|
||||||
if fn, ok := kindCatalog[kind]; ok {
|
if fn, ok := kindCatalog[kind]; ok {
|
||||||
return fn(name, kind, parent, confirm)
|
return fn(name, kind, parent, confirm, nil, nil, "", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDialogWithScreen(
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) Dialog {
|
||||||
|
if dialogCatalog == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if kindCatalog, ok := dialogCatalog[name]; ok {
|
||||||
|
if fn, ok := kindCatalog[kind]; ok {
|
||||||
|
return fn(
|
||||||
|
name, kind, parent, confirm, nil,
|
||||||
|
&filesystem, screenName, localizer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDialogWithData(
|
func NewDialogWithData(
|
||||||
name DialogName, kind DialogKind,
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
parent fyne.Window,
|
parent fyne.Window,
|
||||||
confirm OnConfirmFn,
|
confirm OnConfirmFn,
|
||||||
data binding.DataItem,
|
data binding.DataItem,
|
||||||
@ -289,7 +456,30 @@ func NewDialogWithData(
|
|||||||
}
|
}
|
||||||
if kindCatalog, ok := dialogCatalog[name]; ok {
|
if kindCatalog, ok := dialogCatalog[name]; ok {
|
||||||
if fn, ok := kindCatalog[kind]; ok {
|
if fn, ok := kindCatalog[kind]; ok {
|
||||||
return fn(name, kind, parent, confirm, data)
|
return fn(name, kind, parent, confirm, data, nil, "", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDialogWithDataAndScreen(
|
||||||
|
name DialogName,
|
||||||
|
kind DialogKind,
|
||||||
|
parent fyne.Window,
|
||||||
|
confirm OnConfirmFn,
|
||||||
|
data binding.DataItem,
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) Dialog {
|
||||||
|
if dialogCatalog == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if kindCatalog, ok := dialogCatalog[name]; ok {
|
||||||
|
if fn, ok := kindCatalog[kind]; ok {
|
||||||
|
return fn(
|
||||||
|
name, kind, parent, confirm, data,
|
||||||
|
&filesystem, screenName, localizer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -9,45 +9,85 @@ import (
|
|||||||
"fyne.io/fyne/v2/container"
|
"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
|
type Container string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// HScroll Container
|
||||||
|
//
|
||||||
|
// Available yaml options:
|
||||||
|
// - content: The content of the container
|
||||||
HScroll Container = "HScroll"
|
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"
|
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 {
|
switch cnt {
|
||||||
case HScroll:
|
case HScroll:
|
||||||
c, err = cnt.buildHScrollContainer(e, s)
|
container, err = cnt.buildHScrollContainer(e, s)
|
||||||
case Scroll:
|
case Scroll:
|
||||||
c, err = cnt.buildScrollContainer(e, s)
|
container, err = cnt.buildScrollContainer(e, s)
|
||||||
case VScroll:
|
case VScroll:
|
||||||
c, err = cnt.buildVScrollContainer(e, s)
|
container, err = cnt.buildVScrollContainer(e, s)
|
||||||
default:
|
default:
|
||||||
err = errors.New("invalid container")
|
err = errors.New("invalid container")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if e.Decorators != nil {
|
|
||||||
|
|
||||||
|
decorator = container
|
||||||
|
if e.Decorators != nil {
|
||||||
for _, dec := range e.Decorators {
|
for _, dec := range e.Decorators {
|
||||||
switch dec {
|
switch dec {
|
||||||
case "Border":
|
case "Border":
|
||||||
c = uiwidget.NewWidgetBorder(c)
|
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Hidden {
|
if e.Hidden {
|
||||||
c.Hide()
|
decorator.Hide()
|
||||||
}
|
}
|
||||||
return
|
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 {
|
if e.Content == nil {
|
||||||
err = errors.New("HScroll: no content defined")
|
err = errors.New("HScroll: no content defined")
|
||||||
return
|
return
|
||||||
@ -62,7 +102,10 @@ func (ctn Container) buildHScrollContainer(e *Element, s ScreenHandler) (c fyne.
|
|||||||
return
|
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 {
|
if e.Content == nil {
|
||||||
err = errors.New("Scroll: no content defined")
|
err = errors.New("Scroll: no content defined")
|
||||||
return
|
return
|
||||||
@ -77,7 +120,10 @@ func (ctn Container) buildScrollContainer(e *Element, s ScreenHandler) (c fyne.C
|
|||||||
return
|
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 {
|
if e.Content == nil {
|
||||||
err = errors.New("VScroll: no content defined")
|
err = errors.New("VScroll: no content defined")
|
||||||
return
|
return
|
||||||
|
@ -7,11 +7,13 @@ import (
|
|||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Size represents the yaml description of a ui size
|
||||||
type Size struct {
|
type Size struct {
|
||||||
Width float32 `yaml:"width"`
|
Width float32 `yaml:"width"`
|
||||||
Height float32 `yaml:"height"`
|
Height float32 `yaml:"height"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Element represents the yaml description of a ui element
|
||||||
type Element struct {
|
type Element struct {
|
||||||
ID string `yaml:"id"`
|
ID string `yaml:"id"`
|
||||||
|
|
||||||
@ -57,6 +59,12 @@ type Element struct {
|
|||||||
Time *string `yaml:"time"`
|
Time *string `yaml:"time"`
|
||||||
TimeFormat *string `yaml:"timeFormat"`
|
TimeFormat *string `yaml:"timeFormat"`
|
||||||
|
|
||||||
|
// Entry Properties
|
||||||
|
MultiLine bool `yaml:"multiLine"`
|
||||||
|
Placeholder string `yaml:"placeholder"`
|
||||||
|
PlaceholderLocalized bool `yaml:"placeholderLocalized"`
|
||||||
|
Validator string `yaml:"validator"`
|
||||||
|
|
||||||
// List Properties
|
// List Properties
|
||||||
ItemTemplate string `yaml:"itemTemplate"`
|
ItemTemplate string `yaml:"itemTemplate"`
|
||||||
ItemRenderer string `yaml:"itemRenderer"`
|
ItemRenderer string `yaml:"itemRenderer"`
|
||||||
@ -70,38 +78,44 @@ type Element struct {
|
|||||||
FixVertical bool `yaml:"fixVertical"`
|
FixVertical bool `yaml:"fixVertical"`
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
OnClicked string `yaml:"onClicked"`
|
OnClicked string `yaml:"onClicked"`
|
||||||
OnUpClicked string `yaml:"onUpClicked"`
|
OnUpClicked string `yaml:"onUpClicked"`
|
||||||
OnDownClicked string `yaml:"onDownClicked"`
|
OnDownClicked string `yaml:"onDownClicked"`
|
||||||
OnChanged string `yaml:"onChanged"`
|
OnChanged string `yaml:"onChanged"`
|
||||||
OnSelected string `yaml:"onSelected"`
|
OnSelected string `yaml:"onSelected"`
|
||||||
OnUnselected string `yaml:"onUnselected"`
|
OnUnselected string `yaml:"onUnselected"`
|
||||||
OnDateSelected string `yaml:"onDateSelected"`
|
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) {
|
func (e *Element) BuildUI(s ScreenHandler) (obj fyne.CanvasObject, err error) {
|
||||||
|
var baseObject fyne.CanvasObject
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e.ID != "" && obj != nil {
|
if e.ID != "" && baseObject != nil {
|
||||||
s.RegisterElement(e.ID, obj)
|
s.RegisterElement(e.ID, baseObject, obj)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if e.Container != "" {
|
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)
|
err = fmt.Errorf("failed to build container element: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if e.Layout != "" {
|
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)
|
err = fmt.Errorf("failed to build layout element: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if e.Widget != "" {
|
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)
|
err = fmt.Errorf("failed to build widget element: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -115,4 +129,7 @@ func (e *Element) localize(s ScreenHandler) {
|
|||||||
if e.Localized {
|
if e.Localized {
|
||||||
e.Text = i18n.T(s.GetLocalizer(), e.Text)
|
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"
|
"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
|
type Layout string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Border Layout = "Border"
|
// Border Layout
|
||||||
Form Layout = "Form"
|
//
|
||||||
Grid Layout = "Grid"
|
// Available yaml options
|
||||||
HBox Layout = "HBox"
|
// - 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"
|
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 {
|
switch l {
|
||||||
case Border:
|
case Border:
|
||||||
c, err = l.buildBorderLayout(e, s)
|
layout, err = l.buildBorderLayout(e, s)
|
||||||
case Form:
|
case Form:
|
||||||
c, err = l.buildFormLayout(e, s)
|
layout, err = l.buildFormLayout(e, s)
|
||||||
case Grid:
|
case Grid:
|
||||||
c, err = l.buildGridLayout(e, s)
|
layout, err = l.buildGridLayout(e, s)
|
||||||
case HBox:
|
case HBox:
|
||||||
c, err = l.buildHBoxLayout(e, s)
|
layout, err = l.buildHBoxLayout(e, s)
|
||||||
case MinSize:
|
case MinSize:
|
||||||
c, err = l.buildMinSizeLayout(e, s)
|
layout, err = l.buildMinSizeLayout(e, s)
|
||||||
case Stack:
|
case Stack:
|
||||||
c, err = l.buildStackLayout(e, s)
|
layout, err = l.buildStackLayout(e, s)
|
||||||
case VBox:
|
case VBox:
|
||||||
c, err = l.buildVBoxLayout(e, s)
|
layout, err = l.buildVBoxLayout(e, s)
|
||||||
default:
|
default:
|
||||||
err = errors.New("invalid layout")
|
err = errors.New("invalid layout")
|
||||||
}
|
}
|
||||||
@ -46,22 +113,26 @@ func (l Layout) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decorator = layout
|
||||||
if e.Decorators != nil {
|
if e.Decorators != nil {
|
||||||
for _, dec := range e.Decorators {
|
for _, dec := range e.Decorators {
|
||||||
switch dec {
|
switch dec {
|
||||||
case "Border":
|
case "Border":
|
||||||
c = uiwidget.NewWidgetBorder(c)
|
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Hidden {
|
if e.Hidden {
|
||||||
c.Hide()
|
decorator.Hide()
|
||||||
}
|
}
|
||||||
return
|
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 top, left, right, bottom fyne.CanvasObject
|
||||||
var center []fyne.CanvasObject
|
var center []fyne.CanvasObject
|
||||||
|
|
||||||
@ -109,7 +180,10 @@ func (l Layout) buildBorderLayout(e *Element, s ScreenHandler) (c *fyne.Containe
|
|||||||
return
|
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)
|
children := make([]fyne.CanvasObject, 0, len(e.Children)*2)
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
if child.Label == nil {
|
if child.Label == nil {
|
||||||
@ -149,7 +223,10 @@ func (l Layout) buildFormLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
|||||||
return
|
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))
|
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
var obj fyne.CanvasObject
|
var obj fyne.CanvasObject
|
||||||
@ -179,7 +256,10 @@ func (l Layout) buildGridLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
|||||||
return
|
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))
|
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
var obj fyne.CanvasObject
|
var obj fyne.CanvasObject
|
||||||
@ -193,7 +273,10 @@ func (l Layout) buildHBoxLayout(e *Element, s ScreenHandler) (c *fyne.Container,
|
|||||||
return
|
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))
|
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
var obj fyne.CanvasObject
|
var obj fyne.CanvasObject
|
||||||
@ -216,7 +299,10 @@ func (l Layout) buildMinSizeLayout(e *Element, s ScreenHandler) (c *fyne.Contain
|
|||||||
return
|
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))
|
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
var obj fyne.CanvasObject
|
var obj fyne.CanvasObject
|
||||||
@ -230,7 +316,10 @@ func (l Layout) buildStackLayout(e *Element, s ScreenHandler) (c *fyne.Container
|
|||||||
return
|
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))
|
children := make([]fyne.CanvasObject, 0, len(e.Children))
|
||||||
for _, child := range e.Children {
|
for _, child := range e.Children {
|
||||||
var obj fyne.CanvasObject
|
var obj fyne.CanvasObject
|
||||||
|
@ -5,15 +5,19 @@ import (
|
|||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ListItemTemplate is a template for a list item.
|
||||||
|
// It implements the fyne.CanvasObject interface and TemplateScreenHandler
|
||||||
type ListItemTemplate struct {
|
type ListItemTemplate struct {
|
||||||
fyne.CanvasObject
|
fyne.CanvasObject
|
||||||
*TemplateScreenHandler
|
*TemplateScreenHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRenderer implements the fyne.CanvasObject interface
|
||||||
func (i *ListItemTemplate) CreateRenderer() fyne.WidgetRenderer {
|
func (i *ListItemTemplate) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(i.CanvasObject)
|
return widget.NewSimpleRenderer(i.CanvasObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewListItemTemplate creates a new ListItemTemplate
|
||||||
func NewListItemTemplate(
|
func NewListItemTemplate(
|
||||||
obj fyne.CanvasObject,
|
obj fyne.CanvasObject,
|
||||||
screenHandler *TemplateScreenHandler,
|
screenHandler *TemplateScreenHandler,
|
||||||
|
@ -16,22 +16,39 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"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 {
|
type ScreenHandler interface {
|
||||||
RegisterElement(string, fyne.CanvasObject)
|
RegisterElement(string, fyne.CanvasObject, fyne.CanvasObject)
|
||||||
|
|
||||||
GetLocalizer() *i18n.Localizer
|
GetLocalizer() *i18n.Localizer
|
||||||
GetIcon(string) fyne.Resource
|
GetIcon(string) fyne.Resource
|
||||||
GetBinding(string) binding.DataItem
|
GetBinding(string) binding.DataItem
|
||||||
GetListItemTemplate(string) func() fyne.CanvasObject
|
GetValidator(string) fyne.StringValidator
|
||||||
GetListDataItemRenderer(string) func(binding.DataItem, fyne.CanvasObject)
|
GetListItemTemplate(string) ListItemTemplateFn
|
||||||
GetListItemRenderer(string) func(int, fyne.CanvasObject)
|
GetListDataItemRenderer(string) ListDataItemRendererFn
|
||||||
GetListLength(string) func() int
|
GetListItemRenderer(string) ListItemRendererFn
|
||||||
|
GetListLength(string) ListLengthFn
|
||||||
|
|
||||||
GetOnSelectedHandler(string) func(widget.ListItemID)
|
GetOnListItemSelectedHandler(string) ListItemHandlerFn
|
||||||
GetOnUnselectedHandler(string) func(widget.ListItemID)
|
GetOnListItemUnselectedHandler(string) ListItemHandlerFn
|
||||||
GetClickedHandler(string) func()
|
GetOnClickedHandler(string) ClickHandlerFn
|
||||||
GetCheckChangedHandler(string) func(bool)
|
GetOnCheckChangedHandler(string) CheckHandlerFn
|
||||||
GetDateSelectedHandler(string) func(time.Time)
|
GetOnDateSelectedHandler(string) DateSelectedHandlerFn
|
||||||
|
GetOnValidationChangedHandler(string) ValidationChangedHandlerFn
|
||||||
}
|
}
|
||||||
|
|
||||||
type Screen struct {
|
type Screen struct {
|
||||||
@ -79,7 +96,7 @@ func NewTemplate(
|
|||||||
handler *TemplateScreenHandler,
|
handler *TemplateScreenHandler,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
handler = NewDummyScreenHandler(localizer)
|
handler = NewTemplateScreenHandler(localizer)
|
||||||
scr, err = New(filesystem, name, handler)
|
scr, err = New(filesystem, name, handler)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -94,21 +111,27 @@ func (s *Screen) Initialize() (obj fyne.CanvasObject, err error) {
|
|||||||
|
|
||||||
type TemplateScreenHandler struct {
|
type TemplateScreenHandler struct {
|
||||||
localizer *i18n.Localizer
|
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{
|
return &TemplateScreenHandler{
|
||||||
localizer: localizer,
|
localizer: localizer,
|
||||||
elementsMap: make(map[string]fyne.CanvasObject),
|
elementsMap: make(map[string]*UIElement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *TemplateScreenHandler) RegisterElement(name string, element fyne.CanvasObject) {
|
func (d *TemplateScreenHandler) RegisterElement(
|
||||||
d.elementsMap[name] = element
|
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]
|
elem, ok := d.elementsMap[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
@ -132,38 +155,46 @@ func (*TemplateScreenHandler) GetBinding(string) binding.DataItem {
|
|||||||
return nil
|
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 }
|
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) {}
|
return func(binding.DataItem, fyne.CanvasObject) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetListItemRenderer(string) func(int, fyne.CanvasObject) {
|
func (*TemplateScreenHandler) GetListItemRenderer(string) ListItemRendererFn {
|
||||||
return func(int, fyne.CanvasObject) {}
|
return func(int, fyne.CanvasObject) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetListLength(string) func() int {
|
func (*TemplateScreenHandler) GetListLength(string) ListLengthFn {
|
||||||
return func() int { return 0 }
|
return func() int { return 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetOnSelectedHandler(string) func(widget.ListItemID) {
|
func (*TemplateScreenHandler) GetOnListItemSelectedHandler(string) ListItemHandlerFn {
|
||||||
return func(widget.ListItemID) {}
|
return func(widget.ListItemID) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetOnUnselectedHandler(string) func(widget.ListItemID) {
|
func (*TemplateScreenHandler) GetOnListItemUnselectedHandler(string) ListItemHandlerFn {
|
||||||
return func(widget.ListItemID) {}
|
return func(widget.ListItemID) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetClickedHandler(string) func() {
|
func (*TemplateScreenHandler) GetOnClickedHandler(string) ClickHandlerFn {
|
||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetCheckChangedHandler(string) func(bool) {
|
func (*TemplateScreenHandler) GetOnCheckChangedHandler(string) CheckHandlerFn {
|
||||||
return func(bool) {}
|
return func(bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TemplateScreenHandler) GetDateSelectedHandler(string) func(time.Time) {
|
func (*TemplateScreenHandler) GetOnDateSelectedHandler(string) DateSelectedHandlerFn {
|
||||||
return func(time.Time) {}
|
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"
|
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
|
type Widget string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Button Widget = "Button"
|
// Button Widget
|
||||||
Calendar Widget = "Calendar"
|
//
|
||||||
Check Widget = "Check"
|
// Available yaml options:
|
||||||
H1 Widget = "H1"
|
// - text: The text for the button
|
||||||
H2 Widget = "H2"
|
// - localized: If the text represents a localization key
|
||||||
H3 Widget = "H3"
|
// - icon: The icon for the button
|
||||||
H4 Widget = "H4"
|
// - disabled: Wether the button is disabled or not
|
||||||
H5 Widget = "H5"
|
// - options: Additional options for the button
|
||||||
H6 Widget = "H6"
|
// - alignment: The alignment of the button
|
||||||
Label Widget = "Label"
|
// - iconPlacement: The icon placement of the button
|
||||||
List Widget = "List"
|
// - importance: The importance of the button
|
||||||
Separator Widget = "Separator"
|
// - onclicked: The function to call when the button is clicked
|
||||||
Spacer Widget = "Spacer"
|
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"
|
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)
|
e.localize(s)
|
||||||
|
|
||||||
switch w {
|
switch w {
|
||||||
case Button:
|
case Button:
|
||||||
c, err = w.buildButtonWidget(e, s)
|
widget, err = w.buildButtonWidget(e, s)
|
||||||
case Calendar:
|
case Calendar:
|
||||||
c, err = w.buildCalendarWidget(e, s)
|
widget, err = w.buildCalendarWidget(e, s)
|
||||||
case Check:
|
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:
|
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:
|
case Label:
|
||||||
c, err = w.buildLabelWidget(e, s)
|
widget, err = w.buildLabelWidget(e, s)
|
||||||
case List:
|
case List:
|
||||||
c, err = w.buildListWidget(e, s)
|
widget, err = w.buildListWidget(e, s)
|
||||||
case Separator:
|
case Separator:
|
||||||
c, err = w.buildSeparatorWidget(e, s)
|
widget, err = w.buildSeparatorWidget(e, s)
|
||||||
case Spacer:
|
case Spacer:
|
||||||
c, err = w.buildSpacerWidget(e, s)
|
widget, err = w.buildSpacerWidget(e, s)
|
||||||
case UpDownLabel:
|
case UpDownLabel:
|
||||||
c, err = w.buildUpDownLabelWidget(e, s)
|
widget, err = w.buildUpDownLabelWidget(e, s)
|
||||||
default:
|
default:
|
||||||
err = errors.New("invalid widget")
|
err = errors.New("invalid widget")
|
||||||
}
|
}
|
||||||
@ -61,28 +230,32 @@ func (w Widget) Build(e *Element, s ScreenHandler) (c fyne.CanvasObject, err err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decorator = widget
|
||||||
if e.Decorators != nil {
|
if e.Decorators != nil {
|
||||||
for _, dec := range e.Decorators {
|
for _, dec := range e.Decorators {
|
||||||
switch dec {
|
switch dec {
|
||||||
case "Border":
|
case "Border":
|
||||||
c = uiwidget.NewWidgetBorder(c)
|
decorator = uiwidget.NewWidgetBorder(decorator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Hidden {
|
if e.Hidden {
|
||||||
c.Hide()
|
decorator.Hide()
|
||||||
}
|
}
|
||||||
return
|
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
|
var btn *widget.Button
|
||||||
if e.Icon != "" {
|
if e.Icon != "" {
|
||||||
btn = widget.NewButtonWithIcon(
|
btn = widget.NewButtonWithIcon(
|
||||||
e.Text, s.GetIcon(e.Icon), s.GetClickedHandler(e.OnClicked))
|
e.Text, s.GetIcon(e.Icon), s.GetOnClickedHandler(e.OnClicked))
|
||||||
} else {
|
} 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 {
|
for opt, val := range e.Options {
|
||||||
@ -103,7 +276,10 @@ func (w Widget) buildButtonWidget(e *Element, s ScreenHandler) (c fyne.CanvasObj
|
|||||||
return
|
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()
|
t := time.Now()
|
||||||
if e.Time != nil {
|
if e.Time != nil {
|
||||||
timeFormat := time.DateOnly
|
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
|
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
|
var chk *widget.Check
|
||||||
if e.Binding != "" {
|
if e.Binding != "" {
|
||||||
chk = widget.NewCheckWithData(
|
chk = widget.NewCheckWithData(
|
||||||
e.Text, s.GetBinding(e.Binding).(binding.Bool))
|
e.Text, s.GetBinding(e.Binding).(binding.Bool))
|
||||||
} else {
|
} else {
|
||||||
chk = widget.NewCheck(
|
chk = widget.NewCheck(
|
||||||
e.Text, s.GetCheckChangedHandler(e.OnChanged))
|
e.Text, s.GetOnCheckChangedHandler(e.OnChanged))
|
||||||
chk.SetChecked(e.Checked)
|
chk.SetChecked(e.Checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +317,40 @@ func (w Widget) buildCheckWidget(e *Element, s ScreenHandler) (c fyne.CanvasObje
|
|||||||
return
|
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
|
var rt *widget.RichText
|
||||||
|
|
||||||
level := 1
|
level := 1
|
||||||
@ -174,7 +386,18 @@ func (w Widget) buildHeaderLabelWidget(e *Element, s ScreenHandler) (c fyne.Canv
|
|||||||
return
|
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
|
var lbl *widget.Label
|
||||||
|
|
||||||
if e.Binding != "" {
|
if e.Binding != "" {
|
||||||
@ -201,7 +424,10 @@ func (w Widget) buildLabelWidget(e *Element, s ScreenHandler) (c fyne.CanvasObje
|
|||||||
return
|
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
|
var lst *widget.List
|
||||||
|
|
||||||
if e.Binding != "" {
|
if e.Binding != "" {
|
||||||
@ -217,22 +443,28 @@ func (w Widget) buildListWidget(e *Element, s ScreenHandler) (c fyne.CanvasObjec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.OnSelected != "" {
|
if e.OnSelected != "" {
|
||||||
lst.OnSelected = s.GetOnSelectedHandler(e.OnSelected)
|
lst.OnSelected = s.GetOnListItemSelectedHandler(e.OnSelected)
|
||||||
}
|
}
|
||||||
if e.OnUnselected != "" {
|
if e.OnUnselected != "" {
|
||||||
lst.OnUnselected = s.GetOnUnselectedHandler(e.OnUnselected)
|
lst.OnUnselected = s.GetOnListItemUnselectedHandler(e.OnUnselected)
|
||||||
}
|
}
|
||||||
c = lst
|
c = lst
|
||||||
return
|
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()
|
sep := widget.NewSeparator()
|
||||||
c = sep
|
c = sep
|
||||||
return
|
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{
|
spc := &layout.Spacer{
|
||||||
FixHorizontal: e.FixHorizontal,
|
FixHorizontal: e.FixHorizontal,
|
||||||
FixVertical: e.FixVertical,
|
FixVertical: e.FixVertical,
|
||||||
@ -241,11 +473,14 @@ func (w Widget) buildSpacerWidget(e *Element, _ ScreenHandler) (c fyne.CanvasObj
|
|||||||
return
|
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(
|
btn := uiwidget.NewUpDownLabelWithData(
|
||||||
s.GetBinding(e.Binding).(binding.String),
|
s.GetBinding(e.Binding).(binding.String),
|
||||||
s.GetClickedHandler(e.OnUpClicked),
|
s.GetOnClickedHandler(e.OnUpClicked),
|
||||||
s.GetClickedHandler(e.OnDownClicked))
|
s.GetOnClickedHandler(e.OnDownClicked))
|
||||||
c = btn
|
c = btn
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
351
screenhandler.go
Normal file
351
screenhandler.go
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/hevanto/ui/screen"
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/data/binding"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ScreenHandler represents the handler for a screen.
|
||||||
|
//
|
||||||
|
// It provides:
|
||||||
|
// - The screen definition
|
||||||
|
// - The localizer
|
||||||
|
// - The screen controller
|
||||||
|
// - Exported elements
|
||||||
|
// - List item templates and renderers
|
||||||
|
// - User interaction handlers
|
||||||
|
type ScreenHandler struct {
|
||||||
|
screenDefinition *screen.Screen
|
||||||
|
localizer *i18n.Localizer
|
||||||
|
ctrl ScreenController
|
||||||
|
|
||||||
|
// Map of screen elements that got an id assigned
|
||||||
|
exportedElements map[string]*screen.UIElement
|
||||||
|
|
||||||
|
listItemTemplates map[string]screen.ListItemTemplateFn
|
||||||
|
listItemRenderers map[string]screen.ListItemRendererFn
|
||||||
|
listDataItemRenderers map[string]screen.ListDataItemRendererFn
|
||||||
|
listLengths map[string]screen.ListLengthFn
|
||||||
|
|
||||||
|
onListItemSelectedHandlers map[string]screen.ListItemHandlerFn
|
||||||
|
onListItemUnselectedHandlers map[string]screen.ListItemHandlerFn
|
||||||
|
onClickedHandlers map[string]screen.ClickHandlerFn
|
||||||
|
onCheckChangedHandlers map[string]screen.CheckHandlerFn
|
||||||
|
onDateSelectedHandlers map[string]screen.DateSelectedHandlerFn
|
||||||
|
onValidationChangedHandlers map[string]screen.ValidationChangedHandlerFn
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewScreenHandler initializes a new ScreenHandler with the provided filesystem, screen name, ScreenController, and localizer.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// - filesystem: the embedded filesystem to access screen resources.
|
||||||
|
// - screenName: the name of the screen to load.
|
||||||
|
// - ctrl: the ScreenController for the screen.
|
||||||
|
// - localizer: the i18n.Localizer for localization.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// - h: the initialized ScreenHandler.
|
||||||
|
// - err: an error if loading the screen fails.
|
||||||
|
func NewScreenHandler(
|
||||||
|
filesystem embed.FS,
|
||||||
|
screenName string,
|
||||||
|
ctrl ScreenController,
|
||||||
|
localizer *i18n.Localizer,
|
||||||
|
) (h *ScreenHandler, err error) {
|
||||||
|
h = new(ScreenHandler)
|
||||||
|
|
||||||
|
h.ctrl = ctrl
|
||||||
|
h.localizer = localizer
|
||||||
|
|
||||||
|
def, err := screen.New(filesystem, screenName, h)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failure loading screen: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.screenDefinition = def
|
||||||
|
|
||||||
|
h.exportedElements = make(map[string]*screen.UIElement)
|
||||||
|
h.listItemTemplates = make(map[string]screen.ListItemTemplateFn)
|
||||||
|
h.listItemRenderers = make(map[string]screen.ListItemRendererFn)
|
||||||
|
h.listDataItemRenderers = make(map[string]screen.ListDataItemRendererFn)
|
||||||
|
h.listLengths = make(map[string]screen.ListLengthFn)
|
||||||
|
h.onListItemSelectedHandlers = make(map[string]screen.ListItemHandlerFn)
|
||||||
|
h.onListItemUnselectedHandlers = make(map[string]screen.ListItemHandlerFn)
|
||||||
|
h.onClickedHandlers = make(map[string]screen.ClickHandlerFn)
|
||||||
|
h.onCheckChangedHandlers = make(map[string]screen.CheckHandlerFn)
|
||||||
|
h.onDateSelectedHandlers = make(map[string]screen.DateSelectedHandlerFn)
|
||||||
|
h.onValidationChangedHandlers = make(map[string]screen.ValidationChangedHandlerFn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScreenDefinition returns the screen definition for the ScreenHandler.
|
||||||
|
func (h *ScreenHandler) ScreenDefinition() *screen.Screen {
|
||||||
|
return h.screenDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterElement registers an element with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// This function is called for every element in the screen definition fow which
|
||||||
|
// an ID is defined.
|
||||||
|
func (h *ScreenHandler) RegisterElement(
|
||||||
|
id string,
|
||||||
|
elem fyne.CanvasObject,
|
||||||
|
decorator fyne.CanvasObject,
|
||||||
|
) {
|
||||||
|
h.exportedElements[id] = &screen.UIElement{Object: elem, Decorator: decorator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterListItemTemplate registers a ListItemTemplate with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the templates for the lists used in the
|
||||||
|
// screen definition.
|
||||||
|
func (h *ScreenHandler) RegisterListItemTemplate(
|
||||||
|
name string,
|
||||||
|
fn screen.ListItemTemplateFn,
|
||||||
|
) {
|
||||||
|
h.listItemTemplates[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterListDataItemRenderer registers a ListDataItemRenderer with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the renderers for the lists used in the
|
||||||
|
// screen definition.
|
||||||
|
func (h *ScreenHandler) RegisterListDataItemRenderer(
|
||||||
|
name string,
|
||||||
|
fn screen.ListDataItemRendererFn,
|
||||||
|
) {
|
||||||
|
h.listDataItemRenderers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterListItemRenderer registers a ListItemRenderer with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the renderers for the lists used in the
|
||||||
|
// screen definition.
|
||||||
|
func (h *ScreenHandler) RegisterListItemRenderer(
|
||||||
|
name string,
|
||||||
|
fn screen.ListItemRendererFn,
|
||||||
|
) {
|
||||||
|
h.listItemRenderers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterListLength registers a ListLength with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the lengths for the lists used in the
|
||||||
|
// screen definition.
|
||||||
|
func (h *ScreenHandler) RegisterListLength(
|
||||||
|
name string,
|
||||||
|
fn screen.ListLengthFn,
|
||||||
|
) {
|
||||||
|
h.listLengths[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnListItemSelectedHandler registers a OnListItemSelectedHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnListItemSelectedHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.ListItemHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onListItemSelectedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnListItemUnselectedHandler registers a OnListItemUnselectedHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnListItemUnselectedHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.ListItemHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onListItemUnselectedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnClickHandler registers a OnClickHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnClickHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.ClickHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onClickedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnCheckChangedHandler registers a OnCheckChangedHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnCheckChangedHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.CheckHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onCheckChangedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnDateSelectedHandler registers a OnDateSelectedHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnDateSelectedHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.DateSelectedHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onDateSelectedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterOnValidationChangedHandler registers a OnValidationChangedHandler with the ScreenHandler.
|
||||||
|
//
|
||||||
|
// Use this function to register the handler functions used in the screen
|
||||||
|
// definition.
|
||||||
|
func (h *ScreenHandler) RegisterOnValidationChangedHandler(
|
||||||
|
name string,
|
||||||
|
fn screen.ValidationChangedHandlerFn,
|
||||||
|
) {
|
||||||
|
h.onValidationChangedHandlers[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBinding returns the binding with the given name.
|
||||||
|
//
|
||||||
|
// This function forwards the call to the controller. In the controller the
|
||||||
|
// required bindings should be mapped to the screen elements.
|
||||||
|
func (h *ScreenHandler) GetBinding(name string) binding.DataItem {
|
||||||
|
return h.ctrl.GetBinding(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValidator returns the validator with the given name.
|
||||||
|
//
|
||||||
|
// This function forwards the call to the controller. In the controller the
|
||||||
|
// required validators should be mapped to the screen elements.
|
||||||
|
func (h *ScreenHandler) GetValidator(name string) fyne.StringValidator {
|
||||||
|
return h.ctrl.GetValidator(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetElement returns the UIElement with the given ID.
|
||||||
|
//
|
||||||
|
// This function allows you to retrieve the exported elements (given an ID in
|
||||||
|
// the screen definition). The UIElement contains the object and the decorator.
|
||||||
|
// Should no decorator be present, both point to the same widget. If a decorator
|
||||||
|
// is present it's advices to do hide and show operations on the decorator, and
|
||||||
|
// all other operators on the object.
|
||||||
|
func (h *ScreenHandler) GetElement(id string) *screen.UIElement {
|
||||||
|
if elem, ok := h.exportedElements[id]; ok {
|
||||||
|
return elem
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocalizer returns the i18n.Localizer used for localization.
|
||||||
|
func (h *ScreenHandler) GetLocalizer() *i18n.Localizer {
|
||||||
|
return h.localizer
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIcon returns the icon with the given name.
|
||||||
|
//
|
||||||
|
// This handler only implements the default theme icons. If you wish to support
|
||||||
|
// other items, wrap this ScreenHandler and implement the loading of the icons
|
||||||
|
// yourself.
|
||||||
|
func (h *ScreenHandler) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetListItemTemplate returns the ListItemTemplate with the given name.
|
||||||
|
func (h *ScreenHandler) GetListItemTemplate(name string) screen.ListItemTemplateFn {
|
||||||
|
fn, ok := h.listItemTemplates[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetListDataItemRenderer returns the ListDataItemRenderer with the given name.
|
||||||
|
func (h *ScreenHandler) GetListDataItemRenderer(name string) screen.ListDataItemRendererFn {
|
||||||
|
fn, ok := h.listDataItemRenderers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetListItemRenderer returns the ListItemRenderer with the given name.
|
||||||
|
func (h *ScreenHandler) GetListItemRenderer(name string) screen.ListItemRendererFn {
|
||||||
|
fn, ok := h.listItemRenderers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetListLength returns the ListLength with the given name.
|
||||||
|
func (h *ScreenHandler) GetListLength(name string) screen.ListLengthFn {
|
||||||
|
fn, ok := h.listLengths[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnListItemSelectedHandler returns the OnListItemSelectedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnListItemSelectedHandler(name string) screen.ListItemHandlerFn {
|
||||||
|
fn, ok := h.onListItemSelectedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnListItemUnselectedHandler returns the OnListItemUnselectedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnListItemUnselectedHandler(name string) screen.ListItemHandlerFn {
|
||||||
|
fn, ok := h.onListItemUnselectedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnClickedHandler returns the OnClickedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnClickedHandler(name string) screen.ClickHandlerFn {
|
||||||
|
fn, ok := h.onClickedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnCheckChangedHandler returns the OnCheckChangedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnCheckChangedHandler(name string) screen.CheckHandlerFn {
|
||||||
|
fn, ok := h.onCheckChangedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnDateSelectedHandler returns the OnDateSelectedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnDateSelectedHandler(name string) screen.DateSelectedHandlerFn {
|
||||||
|
fn, ok := h.onDateSelectedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnValidationChangedHandler returns the OnValidationChangedHandler with the given name.
|
||||||
|
func (h *ScreenHandler) GetOnValidationChangedHandler(name string) screen.ValidationChangedHandlerFn {
|
||||||
|
fn, ok := h.onValidationChangedHandlers[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
@ -7,6 +7,8 @@ import (
|
|||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Implement screen reading from file!
|
||||||
|
|
||||||
type TabbedView struct {
|
type TabbedView struct {
|
||||||
*BaseView
|
*BaseView
|
||||||
|
|
||||||
|
@ -2,14 +2,26 @@ package uilayout
|
|||||||
|
|
||||||
import "fyne.io/fyne/v2"
|
import "fyne.io/fyne/v2"
|
||||||
|
|
||||||
|
// MinSize implements a min size layout.
|
||||||
|
//
|
||||||
|
// The MinSize layout will ensure that the container is rendered at a size that
|
||||||
|
// is at least as large as the minimum size provided.
|
||||||
type MinSize struct {
|
type MinSize struct {
|
||||||
minSize fyne.Size
|
minSize fyne.Size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMinSizeLayout creates a new MinSize layout with the specified minimum size.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// - minSize: the minimum size for the layout.
|
||||||
|
//
|
||||||
|
// Returns *MinSize: a pointer to the newly created MinSize layout.
|
||||||
func NewMinSizeLayout(minSize fyne.Size) *MinSize {
|
func NewMinSizeLayout(minSize fyne.Size) *MinSize {
|
||||||
return &MinSize{minSize: minSize}
|
return &MinSize{minSize: minSize}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MinSize calculates the minimum size of the layout on the current screen. The
|
||||||
|
// reported size will be at least as large as the configured minimum size.
|
||||||
func (l *MinSize) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
func (l *MinSize) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
||||||
size := l.minSize
|
size := l.minSize
|
||||||
for _, o := range objects {
|
for _, o := range objects {
|
||||||
@ -24,6 +36,7 @@ func (l *MinSize) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
|||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layout implements the Layout interface.
|
||||||
func (l *MinSize) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
|
func (l *MinSize) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
|
||||||
pos := fyne.NewPos(0, 0)
|
pos := fyne.NewPos(0, 0)
|
||||||
for _, o := range objects {
|
for _, o := range objects {
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LabelOpts defines the options for a label.
|
||||||
type LabelOpts interface {
|
type LabelOpts interface {
|
||||||
ApplyTo(*widget.Label)
|
ApplyTo(*widget.Label)
|
||||||
}
|
}
|
||||||
@ -19,10 +20,12 @@ type allignmentOpt struct {
|
|||||||
Alignment fyne.TextAlign
|
Alignment fyne.TextAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlignmentOpt returns a LabelOpts with the specified alignment.
|
||||||
func AlignmentOpt(alignment fyne.TextAlign) LabelOpts {
|
func AlignmentOpt(alignment fyne.TextAlign) LabelOpts {
|
||||||
return &allignmentOpt{alignment}
|
return &allignmentOpt{alignment}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTo sets the alignment of a label to the specified alignment.
|
||||||
func (a *allignmentOpt) ApplyTo(lbl *widget.Label) {
|
func (a *allignmentOpt) ApplyTo(lbl *widget.Label) {
|
||||||
lbl.Alignment = a.Alignment
|
lbl.Alignment = a.Alignment
|
||||||
}
|
}
|
||||||
@ -31,10 +34,12 @@ type wrappingOpt struct {
|
|||||||
Wrapping fyne.TextWrap
|
Wrapping fyne.TextWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WrappingOpt creates a LabelOpts with the specified text wrapping option.
|
||||||
func WrappingOpt(wrapping fyne.TextWrap) LabelOpts {
|
func WrappingOpt(wrapping fyne.TextWrap) LabelOpts {
|
||||||
return &wrappingOpt{wrapping}
|
return &wrappingOpt{wrapping}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTo applies the wrapping option to the label.
|
||||||
func (w *wrappingOpt) ApplyTo(lbl *widget.Label) {
|
func (w *wrappingOpt) ApplyTo(lbl *widget.Label) {
|
||||||
lbl.Wrapping = w.Wrapping
|
lbl.Wrapping = w.Wrapping
|
||||||
}
|
}
|
||||||
@ -43,10 +48,12 @@ type textStyleOpt struct {
|
|||||||
Style fyne.TextStyle
|
Style fyne.TextStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextStyleOpt returns the label options for the given text style.
|
||||||
func TextStyleOpt(style fyne.TextStyle) LabelOpts {
|
func TextStyleOpt(style fyne.TextStyle) LabelOpts {
|
||||||
return &textStyleOpt{style}
|
return &textStyleOpt{style}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTo applies the text style option to the label.
|
||||||
func (t *textStyleOpt) ApplyTo(lbl *widget.Label) {
|
func (t *textStyleOpt) ApplyTo(lbl *widget.Label) {
|
||||||
lbl.TextStyle = t.Style
|
lbl.TextStyle = t.Style
|
||||||
}
|
}
|
||||||
@ -55,10 +62,12 @@ type truncationOpt struct {
|
|||||||
Truncation fyne.TextTruncation
|
Truncation fyne.TextTruncation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TruncationOpt returns the label options for the given text truncation option.
|
||||||
func TruncationOpt(truncation fyne.TextTruncation) LabelOpts {
|
func TruncationOpt(truncation fyne.TextTruncation) LabelOpts {
|
||||||
return &truncationOpt{truncation}
|
return &truncationOpt{truncation}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTo applies the text truncation option to the label.
|
||||||
func (t *truncationOpt) ApplyTo(lbl *widget.Label) {
|
func (t *truncationOpt) ApplyTo(lbl *widget.Label) {
|
||||||
lbl.Truncation = t.Truncation
|
lbl.Truncation = t.Truncation
|
||||||
}
|
}
|
||||||
@ -67,14 +76,23 @@ type importanceOpt struct {
|
|||||||
Importance widget.Importance
|
Importance widget.Importance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImportanceOpt returns the label options for the given text importance option.
|
||||||
func ImportanceOpt(importance widget.Importance) LabelOpts {
|
func ImportanceOpt(importance widget.Importance) LabelOpts {
|
||||||
return &importanceOpt{importance}
|
return &importanceOpt{importance}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTo applies the text importance option to the label.
|
||||||
func (i *importanceOpt) ApplyTo(lbl *widget.Label) {
|
func (i *importanceOpt) ApplyTo(lbl *widget.Label) {
|
||||||
lbl.Importance = i.Importance
|
lbl.Importance = i.Importance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLabel creates a new label widget with the given text and options.
|
||||||
|
//
|
||||||
|
// Arguments
|
||||||
|
// - text: the text to be displayed on the label.
|
||||||
|
// - opts: optional configuration options for the label.
|
||||||
|
//
|
||||||
|
// Returns *widget.Label: a pointer to the newly created label widget.
|
||||||
func NewLabel(text string, opts ...LabelOpts) *widget.Label {
|
func NewLabel(text string, opts ...LabelOpts) *widget.Label {
|
||||||
lbl := widget.NewLabel(text)
|
lbl := widget.NewLabel(text)
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
@ -83,6 +101,13 @@ func NewLabel(text string, opts ...LabelOpts) *widget.Label {
|
|||||||
return lbl
|
return lbl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLabelWithData creates a new Label widget with the provided data and options.
|
||||||
|
//
|
||||||
|
// Arguments
|
||||||
|
// - data: The string data to be displayed on the label.
|
||||||
|
// - opts: Additional options to customize the label.
|
||||||
|
//
|
||||||
|
// Returns *widget.Label: a pointer to the newly created Label widget.
|
||||||
func NewLabelWithData(data binding.String, opts ...LabelOpts) *widget.Label {
|
func NewLabelWithData(data binding.String, opts ...LabelOpts) *widget.Label {
|
||||||
lbl := widget.NewLabelWithData(data)
|
lbl := widget.NewLabelWithData(data)
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
@ -91,6 +116,14 @@ func NewLabelWithData(data binding.String, opts ...LabelOpts) *widget.Label {
|
|||||||
return lbl
|
return lbl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewUpDownLabelWithData creates a new label widget with up and down buttons.
|
||||||
|
//
|
||||||
|
// Arguments
|
||||||
|
// - data: the string data to display in the label.
|
||||||
|
// - upHandler: the function to call when the up button is clicked.
|
||||||
|
// - downHandler: the function to call when the down button is clicked.
|
||||||
|
//
|
||||||
|
// Returns fyne.CanvasObject: the created widget.
|
||||||
func NewUpDownLabelWithData(
|
func NewUpDownLabelWithData(
|
||||||
data binding.String,
|
data binding.String,
|
||||||
upHandler func(),
|
upHandler func(),
|
||||||
@ -115,11 +148,25 @@ func NewUpDownLabelWithData(
|
|||||||
return c1
|
return c1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH creates a RichText widget formatted as a header of the provided level.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - level: an integer representing the level of the text.
|
||||||
|
// - text: a string containing the text to display.
|
||||||
|
//
|
||||||
|
// Returns a pointer to a RichText widget.
|
||||||
func NewH(level int, text string) *widget.RichText {
|
func NewH(level int, text string) *widget.RichText {
|
||||||
return widget.NewRichTextFromMarkdown(
|
return widget.NewRichTextFromMarkdown(
|
||||||
fmt.Sprintf("%s %s", strings.Repeat("#", level), text))
|
fmt.Sprintf("%s %s", strings.Repeat("#", level), text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewHWithData creates a new RichText widget formatted as a header of the provided level.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - level: an integer representing the level of the text.
|
||||||
|
// - data: a string binding containing the text to display.
|
||||||
|
//
|
||||||
|
// Returns a pointer to a RichText widget.
|
||||||
func NewHWithData(level int, data binding.String) *widget.RichText {
|
func NewHWithData(level int, data binding.String) *widget.RichText {
|
||||||
txt, _ := data.Get()
|
txt, _ := data.Get()
|
||||||
w := NewH(level, txt)
|
w := NewH(level, txt)
|
||||||
@ -130,50 +177,62 @@ func NewHWithData(level int, data binding.String) *widget.RichText {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH1 creates a new RichText widget with header level 1.
|
||||||
func NewH1(text string) *widget.RichText {
|
func NewH1(text string) *widget.RichText {
|
||||||
return NewH(1, text)
|
return NewH(1, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH1WithData creates a new RichText widget with header level 1.
|
||||||
func NewH1WithData(data binding.String) *widget.RichText {
|
func NewH1WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(1, data)
|
return NewHWithData(1, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH2 creates a new RichText widget with header level 2.
|
||||||
func NewH2(text string) *widget.RichText {
|
func NewH2(text string) *widget.RichText {
|
||||||
return NewH(2, text)
|
return NewH(2, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH2WithData creates a new RichText widget with header level 2.
|
||||||
func NewH2WithData(data binding.String) *widget.RichText {
|
func NewH2WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(2, data)
|
return NewHWithData(2, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH3 creates a new RichText widget with header level 3.
|
||||||
func NewH3(text string) *widget.RichText {
|
func NewH3(text string) *widget.RichText {
|
||||||
return NewH(3, text)
|
return NewH(3, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH3WithData creates a new RichText widget with header level 3.
|
||||||
func NewH3WithData(data binding.String) *widget.RichText {
|
func NewH3WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(3, data)
|
return NewHWithData(3, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH4 creates a new RichText widget with header level 4.
|
||||||
func NewH4(text string) *widget.RichText {
|
func NewH4(text string) *widget.RichText {
|
||||||
return NewH(4, text)
|
return NewH(4, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH4WithData creates a new RichText widget with header level 4.
|
||||||
func NewH4WithData(data binding.String) *widget.RichText {
|
func NewH4WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(4, data)
|
return NewHWithData(4, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH5 creates a new RichText widget with header level 5.
|
||||||
func NewH5(text string) *widget.RichText {
|
func NewH5(text string) *widget.RichText {
|
||||||
return NewH(5, text)
|
return NewH(5, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH5WithData creates a new RichText widget with header level 5.
|
||||||
func NewH5WithData(data binding.String) *widget.RichText {
|
func NewH5WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(5, data)
|
return NewHWithData(5, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH6 creates a new RichText widget with header level 6.
|
||||||
func NewH6(text string) *widget.RichText {
|
func NewH6(text string) *widget.RichText {
|
||||||
return NewH(6, text)
|
return NewH(6, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewH6WithData creates a new RichText widget with header level 6.
|
||||||
func NewH6WithData(data binding.String) *widget.RichText {
|
func NewH6WithData(data binding.String) *widget.RichText {
|
||||||
return NewHWithData(6, data)
|
return NewHWithData(6, data)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ import (
|
|||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewWidgetBorder creates a new widget border for the given fyne.CanvasObject.
|
||||||
|
// It does so by wrapping the object in a Stack layout with a border drawn
|
||||||
|
// above the widget.
|
||||||
func NewWidgetBorder(widget fyne.CanvasObject) fyne.CanvasObject {
|
func NewWidgetBorder(widget fyne.CanvasObject) fyne.CanvasObject {
|
||||||
b := canvas.NewRectangle(color.Transparent)
|
b := canvas.NewRectangle(color.Transparent)
|
||||||
b.StrokeColor = theme.InputBorderColor()
|
b.StrokeColor = theme.InputBorderColor()
|
||||||
|
Loading…
Reference in New Issue
Block a user