You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

238 lines
6.0 KiB

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
}