package dialogs
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"git.brettb.xyz/goinv/client/internal/ui/style"
|
|
"git.brettb.xyz/goinv/client/internal/ui/utils"
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/rivo/tview"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type MessageDialog struct {
|
|
*tview.Box
|
|
logger *zap.Logger
|
|
layout *tview.Flex
|
|
infoType *tview.InputField
|
|
textView *tview.TextView
|
|
form *tview.Form
|
|
display bool
|
|
message string
|
|
cancelHandler func()
|
|
}
|
|
|
|
type messageInfo int
|
|
|
|
const (
|
|
MessageGeneric messageInfo = iota
|
|
)
|
|
|
|
func NewMessageDialog(logger *zap.Logger, text string) *MessageDialog {
|
|
dialog := MessageDialog{
|
|
Box: tview.NewBox(),
|
|
logger: logger,
|
|
infoType: tview.NewInputField(),
|
|
display: false,
|
|
message: text,
|
|
}
|
|
|
|
dialog.infoType.SetBackgroundColor(style.ButtonBgColor)
|
|
dialog.infoType.SetFieldStyle(tcell.StyleDefault.
|
|
Background(style.ButtonBgColor).
|
|
Foreground(style.ButtonFgColor))
|
|
dialog.infoType.SetLabelStyle(tcell.StyleDefault.
|
|
Background(style.ButtonBgColor).
|
|
Foreground(style.ButtonFgColor))
|
|
|
|
dialog.textView = tview.NewTextView().
|
|
SetDynamicColors(true).
|
|
SetWrap(true).
|
|
SetTextAlign(tview.AlignLeft)
|
|
|
|
dialog.textView.SetBackgroundColor(style.DialogSubBoxBgColor)
|
|
dialog.textView.SetBorderColor(style.DialogSubBoxBorderColor)
|
|
dialog.textView.SetBorder(true)
|
|
dialog.textView.SetTextStyle(tcell.StyleDefault.
|
|
Background(style.DialogSubBoxBgColor).
|
|
Foreground(style.DialogSubBoxFgColor))
|
|
|
|
tlayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
|
tlayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
|
tlayout.AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
|
AddItem(dialog.infoType, 1, 0, false).
|
|
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
|
AddItem(dialog.textView, 0, 1, true),
|
|
0, 1, true)
|
|
tlayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
|
|
|
dialog.form = tview.NewForm().
|
|
AddButton("Cancel", nil).
|
|
SetButtonsAlign(tview.AlignRight)
|
|
|
|
dialog.form.SetFocus(0)
|
|
|
|
dialog.form.SetBackgroundColor(style.DialogBgColor)
|
|
dialog.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
|
dialog.form.SetButtonTextColor(style.ButtonFgColor)
|
|
dialog.form.SetButtonActivatedStyle(tcell.StyleDefault.
|
|
Background(style.ButtonSelectedBgColor).
|
|
Foreground(style.ButtonSelectedFgColor))
|
|
|
|
dialog.layout = tview.NewFlex().SetDirection(tview.FlexRow)
|
|
dialog.layout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
|
dialog.layout.AddItem(tlayout, 0, 1, true)
|
|
dialog.layout.AddItem(dialog.form, DialogFormHeight, 0, true)
|
|
dialog.layout.SetBorder(true)
|
|
dialog.layout.SetBorderColor(style.DialogBorderColor)
|
|
dialog.layout.SetBackgroundColor(style.DialogBgColor)
|
|
dialog.layout.SetTitleColor(style.DialogFgColor)
|
|
|
|
return &dialog
|
|
}
|
|
|
|
func (d *MessageDialog) Display() {
|
|
d.display = true
|
|
}
|
|
|
|
func (d *MessageDialog) IsDisplay() bool {
|
|
return d.display
|
|
}
|
|
|
|
func (d *MessageDialog) Hide() {
|
|
d.message = ""
|
|
d.textView.SetText("")
|
|
d.display = false
|
|
}
|
|
|
|
func (d *MessageDialog) SetTitle(title string) {
|
|
d.layout.SetTitle(strings.ToUpper(title))
|
|
}
|
|
|
|
func (d *MessageDialog) SetText(headerType messageInfo, headerMessage string, message string) {
|
|
msgTypeLabel := ""
|
|
|
|
switch headerType {
|
|
case MessageGeneric:
|
|
msgTypeLabel = "SYSTEM:"
|
|
}
|
|
|
|
if msgTypeLabel != "" {
|
|
d.infoType.SetLabel("[::b]" + msgTypeLabel)
|
|
d.infoType.SetLabelWidth(len(msgTypeLabel) + 1)
|
|
d.infoType.SetText(headerMessage)
|
|
}
|
|
|
|
d.message = message
|
|
d.textView.Clear()
|
|
|
|
if d.message == "" {
|
|
d.textView.SetBorder(false)
|
|
d.textView.SetText("")
|
|
} else {
|
|
//d.textView.SetTextColor(style.DialogFgColor)
|
|
//d.textView.SetBackgroundColor(style.DialogSubBoxBorderColor)
|
|
//d.textView.SetBorder(true)
|
|
//d.textView.SetBorderColor(style.DialogBorderColor)
|
|
//d.textView.SetTextStyle(tcell.StyleDefault.
|
|
// Background(style.DialogSubBoxBorderColor).
|
|
// Foreground(style.ButtonFgColor))
|
|
d.textView.SetBorder(true)
|
|
d.textView.SetText(message)
|
|
}
|
|
|
|
d.textView.ScrollToBeginning()
|
|
}
|
|
|
|
func (d *MessageDialog) TextScrollToEnd() {
|
|
d.textView.ScrollToEnd()
|
|
}
|
|
|
|
func (d *MessageDialog) Focus(delegate func(tview.Primitive)) {
|
|
delegate(d.form)
|
|
}
|
|
|
|
func (d *MessageDialog) HasFocus() bool {
|
|
return utils.CheckFocus(d.form, d.textView, d.Box)
|
|
}
|
|
|
|
func (d *MessageDialog) SetRect(x, y, width, height int) {
|
|
messageHeight := 0
|
|
if d.message != "" {
|
|
messageHeight = len(strings.Split(d.message, "\n"))
|
|
}
|
|
|
|
messageWidth := getMessageWidth(d.message)
|
|
|
|
headerWidth := len(d.infoType.GetText()) + len(d.infoType.GetLabel()) + 4
|
|
if messageWidth < headerWidth {
|
|
messageWidth = headerWidth
|
|
}
|
|
|
|
dWidth := width - (2 * DialogPadding)
|
|
if messageWidth+4 < dWidth {
|
|
dWidth = messageWidth + 4
|
|
}
|
|
|
|
if DialogMinWidth < width && dWidth < DialogMinWidth {
|
|
dWidth = DialogMinWidth
|
|
}
|
|
|
|
emptySpace := (width - dWidth) / 2
|
|
dX := x + emptySpace
|
|
|
|
dHeight := messageHeight + DialogFormHeight + DialogPadding + 4
|
|
if dHeight > height {
|
|
dHeight = height - DialogPadding - 1
|
|
}
|
|
|
|
textviewHeight := dHeight - DialogFormHeight - 2
|
|
hs := (height - dHeight) / 2
|
|
dY := y + hs
|
|
|
|
d.Box.SetRect(dX, dY, dWidth, dHeight)
|
|
|
|
d.layout.ResizeItem(d.textView, textviewHeight, 0)
|
|
}
|
|
|
|
func (d *MessageDialog) Draw(screen tcell.Screen) {
|
|
if !d.display {
|
|
return
|
|
}
|
|
|
|
d.Box.DrawForSubclass(screen, d)
|
|
x, y, width, height := d.Box.GetInnerRect()
|
|
d.layout.SetRect(x, y, width, height)
|
|
d.layout.Draw(screen)
|
|
}
|
|
|
|
func (d *MessageDialog) InputHandler() func(*tcell.EventKey, func(tview.Primitive)) {
|
|
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(tview.Primitive)) {
|
|
d.logger.Sugar().Debugf("message dialog event %v received", event)
|
|
if event.Key() == utils.CloseDialogKey.EventKey() || event.Key() == tcell.KeyEnter {
|
|
d.cancelHandler()
|
|
|
|
return
|
|
}
|
|
|
|
if event.Key() == utils.SwitchFocusKey.EventKey() {
|
|
if formHandler := d.form.InputHandler(); formHandler != nil {
|
|
formHandler(event, setFocus)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
if textHandler := d.textView.InputHandler(); textHandler != nil {
|
|
textHandler(event, setFocus)
|
|
|
|
return
|
|
}
|
|
})
|
|
}
|
|
|
|
func (d *MessageDialog) SetCancelFunc(handler func()) *MessageDialog {
|
|
d.cancelHandler = handler
|
|
|
|
return d
|
|
}
|