ui/dialog.go

297 lines
5.6 KiB
Go
Raw Normal View History

2024-03-30 17:45:07 +01:00
package ui
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"github.com/google/uuid"
)
type DialogName string
type DialogKind string
type OnConfirmFn func(bool, error, ...interface{})
type NewDialogFn func(DialogName, DialogKind, fyne.Window, OnConfirmFn, ...binding.DataItem) Dialog
const (
DlgGeneric DialogKind = "Generic"
)
type Dialog interface {
View
Window() fyne.Window
View() View
SetInitialFocusItem(focusItem fyne.Focusable)
Show(parent ...fyne.Window)
OnClose(bool)
DialogName() DialogName
DialogKind() DialogKind
OnConfirmFn() OnConfirmFn
}
type BaseDialog struct {
id string
concreteDialog Dialog
dlgName DialogName
dlgKind DialogKind
dlg dialog.Dialog
window fyne.Window
onConfirm OnConfirmFn
CanvasObj fyne.CanvasObject
Data binding.DataItem
focusItem fyne.Focusable
}
func NewBaseDialog(
concreteDialog Dialog,
name DialogName,
kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
) *BaseDialog {
return &BaseDialog{
id: uuid.NewString(),
concreteDialog: concreteDialog,
dlgName: name,
dlgKind: kind,
window: parent,
onConfirm: confirm,
}
}
func NewBaseDialogWithData(
concreteDialog Dialog,
name DialogName,
kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
data binding.DataItem,
) *BaseDialog {
return &BaseDialog{
id: uuid.NewString(),
concreteDialog: concreteDialog,
dlgName: name,
dlgKind: kind,
window: parent,
onConfirm: confirm,
Data: data,
}
}
func (d BaseDialog) Window() fyne.Window {
return d.window
}
func (d *BaseDialog) View() View {
return d
}
func (d BaseDialog) Equals(other View) bool {
return d.id == other.ID()
}
func (d *BaseDialog) SetInitialFocusItem(focusItem fyne.Focusable) {
d.focusItem = focusItem
}
func (d BaseDialog) DialogName() DialogName {
return d.dlgName
}
func (d BaseDialog) DialogKind() DialogKind {
return d.dlgKind
}
func (d BaseDialog) OnConfirmFn() OnConfirmFn {
return d.onConfirm
}
func (d *BaseDialog) Show(parent ...fyne.Window) {
d.concreteDialog.OnShow()
d.dlg = dialog.NewCustomConfirm(
d.concreteDialog.Title(),
"OK", "Cancel",
d.concreteDialog.Initialize(),
d.concreteDialog.OnClose,
d.window,
)
d.dlg.Show()
d.dlg.Resize(fyne.NewSize(640, 480))
if d.focusItem != nil {
window := d.window
if parent != nil {
window = parent[0]
}
window.Canvas().Focus(d.focusItem)
}
}
func (d BaseDialog) ID() string {
return d.id
}
func (d *BaseDialog) SetID(id string) {
d.id = id
}
func (d BaseDialog) Title() string {
return ""
}
func (d *BaseDialog) Initialize() fyne.CanvasObject {
return d.CanvasObj
}
func (d *BaseDialog) Refresh() {
if d.CanvasObj != nil {
d.CanvasObj.Refresh()
}
}
func (d *BaseDialog) OnShow() {
LogWindowEvent(d, OnShow)
}
func (d *BaseDialog) OnHide() {
LogWindowEvent(d, OnHide)
}
func (d *BaseDialog) OnClose(confirmed bool) {
LogWindowEventMessage(d, OnClose, fmt.Sprintf("confirmed: %v", confirmed))
d.OnHide()
}
type FormDialogItemsFn func() []*widget.FormItem
type FormDialog struct {
*BaseDialog
confirmLabel string
dismissLabel string
itemsFn FormDialogItemsFn
items []*widget.FormItem
}
func NewFormDialog(
concreteDialog Dialog,
name DialogName,
kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
itemsFn FormDialogItemsFn,
) *FormDialog {
return &FormDialog{
BaseDialog: NewBaseDialog(concreteDialog, name, kind, parent, confirm),
itemsFn: itemsFn,
confirmLabel: "OK",
dismissLabel: "Cancel",
}
}
func NewformDialogWithData(
concreteDialog Dialog,
name DialogName,
kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
itemsFn FormDialogItemsFn,
data binding.DataItem,
) *FormDialog {
return &FormDialog{
BaseDialog: NewBaseDialogWithData(concreteDialog, name, kind, parent, confirm, data),
itemsFn: itemsFn,
confirmLabel: "OK",
dismissLabel: "Cancel",
}
}
func (d *FormDialog) SetButtonLabels(
confirm string,
dismiss string,
) {
d.confirmLabel = confirm
d.dismissLabel = dismiss
}
func (d *FormDialog) Show(parent ...fyne.Window) {
d.items = d.itemsFn()
d.concreteDialog.OnShow()
d.dlg = dialog.NewForm(
d.concreteDialog.Title(),
d.confirmLabel,
d.dismissLabel,
d.items,
d.concreteDialog.OnClose,
d.window,
)
d.dlg.Show()
d.dlg.Resize(fyne.NewSize(640, 480))
if d.focusItem != nil {
window := d.window
if parent != nil {
window = parent[0]
}
window.Canvas().Focus(d.focusItem)
}
}
func (d *FormDialog) Refresh() {
for _, itm := range d.items {
itm.Widget.Refresh()
}
}
var dialogCatalog map[DialogName]map[DialogKind]NewDialogFn
func RegisterDialog(name DialogName, kind DialogKind, fn NewDialogFn) {
if dialogCatalog == nil {
dialogCatalog = make(map[DialogName]map[DialogKind]NewDialogFn)
}
if _, ok := dialogCatalog[name]; !ok {
dialogCatalog[name] = make(map[DialogKind]NewDialogFn)
}
dialogCatalog[name][kind] = fn
}
func NewDialog(
name DialogName, kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
) Dialog {
if dialogCatalog == nil {
return nil
}
if kindCatalog, ok := dialogCatalog[name]; ok {
if fn, ok := kindCatalog[kind]; ok {
return fn(name, kind, parent, confirm)
}
}
return nil
}
func NewDialogWithData(
name DialogName, kind DialogKind,
parent fyne.Window,
confirm OnConfirmFn,
data binding.DataItem,
) 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)
}
}
return nil
}