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 }