121 lines
2.7 KiB
Go
Executable File
121 lines
2.7 KiB
Go
Executable File
package ui
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/mattn/go-runewidth"
|
|
)
|
|
|
|
type MessageDialogKind uint8
|
|
|
|
const (
|
|
MessageKindNormal MessageDialogKind = iota
|
|
MessageKindWarning
|
|
MessageKindError
|
|
)
|
|
|
|
// Index of messageDialogKindTitles is any MessageDialogKind.
|
|
var messageDialogKindTitles [3]string = [3]string{
|
|
"Message",
|
|
"Warning!",
|
|
"Error!",
|
|
}
|
|
|
|
type MessageDialog struct {
|
|
Title string
|
|
Kind MessageDialogKind
|
|
Callback func(string)
|
|
|
|
message string
|
|
messageWrapped string
|
|
|
|
buttons []*Button
|
|
selectedIdx int
|
|
|
|
baseComponent
|
|
}
|
|
|
|
func NewMessageDialog(title string, message string, kind MessageDialogKind, options []string, theme *Theme, callback func(string)) *MessageDialog {
|
|
if title == "" {
|
|
title = messageDialogKindTitles[kind] // Use default title
|
|
}
|
|
|
|
if options == nil || len(options) == 0 {
|
|
options = []string{"OK"}
|
|
}
|
|
|
|
dialog := MessageDialog{
|
|
Title: title,
|
|
Kind: kind,
|
|
Callback: callback,
|
|
|
|
baseComponent: baseComponent{theme: theme},
|
|
}
|
|
|
|
dialog.buttons = make([]*Button, len(options))
|
|
for i := range options {
|
|
dialog.buttons[i] = NewButton(options[i], theme, func() {
|
|
if dialog.Callback != nil {
|
|
dialog.Callback(dialog.buttons[dialog.selectedIdx].Text)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Set the dialog's size to its minimum size
|
|
dialog.SetSize(0, 0)
|
|
dialog.SetMessage(message)
|
|
|
|
return &dialog
|
|
}
|
|
|
|
func (d *MessageDialog) SetMessage(message string) {
|
|
d.message = message
|
|
d.messageWrapped = runewidth.Wrap(message, d.width-2)
|
|
// Update height:
|
|
_, minHeight := d.GetMinSize()
|
|
d.height = Max(d.height, minHeight)
|
|
}
|
|
|
|
func (d *MessageDialog) Draw(s tcell.Screen) {
|
|
DrawWindow(s, d.x, d.y, d.width, d.height, d.Title, d.theme)
|
|
|
|
// DrawStr will handle '\n' characters and wrap for us.
|
|
DrawStr(s, d.x+1, d.y+2, d.messageWrapped, d.theme.GetOrDefault("Window"))
|
|
|
|
col := d.width // Start from the right side
|
|
for i := range d.buttons {
|
|
width, _ := d.buttons[i].GetSize()
|
|
col -= width + 1 // Move left enough for each button (1 for padding)
|
|
d.buttons[i].SetPos(d.x+col, d.y+d.height-2)
|
|
d.buttons[i].Draw(s)
|
|
}
|
|
}
|
|
|
|
func (d *MessageDialog) SetFocused(v bool) {
|
|
d.focused = v
|
|
d.buttons[d.selectedIdx].SetFocused(v)
|
|
}
|
|
|
|
func (d *MessageDialog) SetTheme(theme *Theme) {
|
|
d.theme = theme
|
|
for i := range d.buttons {
|
|
d.buttons[i].SetTheme(theme)
|
|
}
|
|
}
|
|
|
|
func (d *MessageDialog) GetMinSize() (int, int) {
|
|
lines := strings.Count(d.messageWrapped, "\n") + 1
|
|
|
|
return Max(len(d.Title)+2, 30), 2 + lines + 2
|
|
}
|
|
|
|
func (d *MessageDialog) SetSize(width, height int) {
|
|
minWidth, minHeight := d.GetMinSize()
|
|
d.width, d.height = Max(width, minWidth), Max(height, minHeight)
|
|
}
|
|
|
|
func (d *MessageDialog) HandleEvent(event tcell.Event) bool {
|
|
return d.buttons[d.selectedIdx].HandleEvent(event)
|
|
}
|