objects/dialog.go

102 lines
2.9 KiB
Go
Raw Normal View History

2024-05-18 11:25:06 -06:00
package objects
import "image"
import "git.tebibyte.media/tomo/tomo"
import "git.tebibyte.media/tomo/tomo/event"
import "git.tebibyte.media/tomo/objects/layouts"
// DialogKind defines the semantic role of a dialog window.
type DialogKind int; const (
DialogInformation DialogKind = iota
DialogQuestion
DialogWarning
DialogError
)
// Dialog is a modal dialog window.
type Dialog struct {
tomo.Window
controlRow *Container
2024-05-18 11:25:06 -06:00
}
type clickable interface {
OnClick (func ()) event.Cookie
}
// NewDialog creates a new dialog window given a dialog kind.
func NewDialog (kind DialogKind, parent tomo.Window, title, message string, options ...tomo.Object) (*Dialog, error) {
2024-05-18 11:25:06 -06:00
if title == "" {
switch kind {
case DialogInformation: title = "Information"
case DialogQuestion: title = "Question"
case DialogWarning: title = "Warning"
case DialogError: title = "Error"
}
}
dialog := &Dialog { }
if parent == nil {
window, err := tomo.NewWindow(image.Rectangle { })
if err != nil { return nil, err }
dialog.Window = window
} else {
window, err := parent.NewModal(image.Rectangle { })
if err != nil { return nil, err }
dialog.Window = window
}
2024-05-26 15:21:58 -06:00
var iconId tomo.Icon
2024-05-18 11:25:06 -06:00
switch kind {
2024-05-26 15:21:58 -06:00
case DialogInformation: iconId = tomo.IconDialogInformation
case DialogQuestion: iconId = tomo.IconDialogQuestion
case DialogWarning: iconId = tomo.IconDialogWarning
case DialogError: iconId = tomo.IconDialogError
2024-05-18 11:25:06 -06:00
}
dialog.SetTitle(title)
2024-08-23 19:39:39 -06:00
dialog.SetIcon(iconId)
2024-05-26 15:21:58 -06:00
icon := NewIcon(iconId, tomo.IconSizeLarge)
2024-05-18 11:25:06 -06:00
messageText := NewLabel(message)
2024-07-21 09:48:28 -06:00
messageText.SetAttr(tomo.AAlign(tomo.AlignStart, tomo.AlignMiddle))
2024-05-18 11:25:06 -06:00
for _, option := range options {
if option, ok := option.(clickable); ok {
option.OnClick(dialog.Close)
}
}
dialog.controlRow = NewInnerContainer(layouts.ContractHorizontal, options...)
dialog.controlRow.SetAlign(tomo.AlignEnd, tomo.AlignEnd)
2024-05-18 11:25:06 -06:00
dialog.SetRoot(NewOuterContainer (
2024-06-22 16:44:26 -06:00
layouts.Column { true, false },
2024-05-18 11:25:06 -06:00
NewInnerContainer(layouts.ContractHorizontal, icon, messageText),
dialog.controlRow))
return dialog, nil
}
// NewDialogOk creates a new dialog window with an OK option.
func NewDialogOk (kind DialogKind, parent tomo.Window, title, message string, onOk func ()) (*Dialog, error) {
2024-05-18 11:25:06 -06:00
okButton := NewButton("OK")
2024-05-27 13:22:18 -06:00
okButton.SetIcon(tomo.IconDialogOkay)
2024-05-18 11:25:06 -06:00
okButton.OnClick(func () {
if onOk != nil { onOk() }
})
okButton.SetFocused(true)
return NewDialog(kind, parent, title, message, okButton)
2024-05-18 11:25:06 -06:00
}
// NewDialogOkCancel creates a new dialog window with OK and Cancel options.
func NewDialogOkCancel (kind DialogKind, parent tomo.Window, title, message string, onOk func ()) (*Dialog, error) {
2024-05-18 11:25:06 -06:00
cancelButton := NewButton("Cancel")
2024-05-27 13:22:18 -06:00
cancelButton.SetIcon(tomo.IconDialogCancel)
2024-05-18 11:25:06 -06:00
okButton := NewButton("OK")
2024-05-27 13:22:18 -06:00
okButton.SetIcon(tomo.IconDialogOkay)
2024-05-18 11:25:06 -06:00
okButton.OnClick(func () {
if onOk != nil { onOk() }
})
okButton.SetFocused(true)
return NewDialog(kind, parent, title, message, cancelButton, okButton)
2024-05-18 11:25:06 -06:00
}