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.
 

203 lines
4.9 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 ConfirmDialog struct {
*tview.Box
logger *zap.Logger
layout *tview.Flex
textview *tview.TextView
form *tview.Form
x int
y int
width int
height int
message string
display bool
cancelHandler func()
selectHandler func()
}
func NewConfirmDialog(logger *zap.Logger) *ConfirmDialog {
dialog := &ConfirmDialog{
Box: tview.NewBox(),
logger: logger,
display: false,
}
dialog.textview = tview.NewTextView().
SetDynamicColors(true).
SetWrap(true).
SetTextAlign(tview.AlignLeft)
dialog.textview.SetBackgroundColor(style.DialogBgColor)
dialog.textview.SetTextColor(style.DialogFgColor)
dialog.form = tview.NewForm().
AddButton("Cancel", nil).
AddButton(" OK ", nil).
SetButtonsAlign(tview.AlignRight)
dialog.form.SetBackgroundColor(style.DialogBgColor)
dialog.form.SetButtonBackgroundColor(style.ButtonBgColor)
dialog.form.SetButtonTextColor(style.ButtonFgColor)
activatedStyle := tcell.StyleDefault.
Background(style.ButtonSelectedBgColor).
Foreground(style.ButtonSelectedFgColor)
dialog.form.SetButtonActivatedStyle(activatedStyle)
dialog.layout = tview.NewFlex().SetDirection(tview.FlexRow)
dialog.layout.SetBorder(true)
dialog.layout.SetBorderColor(style.DialogBorderColor)
dialog.layout.SetBackgroundColor(style.DialogBgColor)
return dialog
}
func (d *ConfirmDialog) Display() {
d.display = true
d.form.SetFocus(1)
}
func (d *ConfirmDialog) IsDisplay() bool {
return d.display
}
func (d *ConfirmDialog) Hide() {
d.textview.SetText("")
d.message = ""
d.display = false
}
func (d *ConfirmDialog) SetTitle(title string) {
d.layout.SetTitle(strings.ToUpper(title))
d.layout.SetTitleColor(style.DialogFgColor)
}
func (d *ConfirmDialog) SetText(message string) {
d.message = message
d.textview.Clear()
msg := "\n" + message
d.textview.SetText(msg)
d.textview.ScrollToBeginning()
d.setRect()
}
func (d *ConfirmDialog) Focus(delegate func(tview.Primitive)) {
delegate(d.form)
}
func (d *ConfirmDialog) HasFocus() bool {
return d.form.HasFocus()
}
func (d *ConfirmDialog) SetRect(x, y, width, height int) {
d.x = x + DialogPadding
d.y = y + DialogPadding
d.width = width - (2 * DialogPadding) //nolint:gomnd
d.height = height - (2 * DialogPadding) //nolint:gomnd
d.setRect()
}
func (d *ConfirmDialog) setRect() {
maxHeight := d.height
maxWidth := d.width
messageHeight := len(strings.Split(d.message, "\n"))
messageWidth := getMessageWidth(d.message)
layoutHeight := messageHeight + 2 //nolint:gomnd
if maxHeight > layoutHeight+DialogFormHeight {
d.height = layoutHeight + DialogFormHeight + 2 //nolint:gomnd
} else {
d.height = maxHeight
layoutHeight = d.height - DialogFormHeight - 2 //nolint:gomnd
}
if maxHeight > d.height {
emptyHeight := (maxHeight - d.height) / 2 //nolint:gomnd
d.y += emptyHeight
}
if d.width > DialogMinWidth {
if messageWidth < DialogMinWidth {
d.width = DialogMinWidth + 2 //nolint:gomnd
} else if messageWidth < d.width {
d.width = messageWidth + 2 //nolint:gomnd
}
}
if maxWidth > d.width {
emptyWidth := (maxWidth - d.width) / 2 //nolint:gomnd
d.x += emptyWidth
}
msgLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
msgLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
msgLayout.AddItem(d.textview, 0, 1, true)
msgLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
d.layout.Clear()
d.layout.AddItem(msgLayout, layoutHeight, 0, true)
d.layout.AddItem(d.form, DialogFormHeight, 0, true)
d.Box.SetRect(d.x, d.y, d.width, d.height)
}
// Draw draws this primitive onto the screen.
func (d *ConfirmDialog) 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 *ConfirmDialog) InputHandler() func(*tcell.EventKey, func(tview.Primitive)) {
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(tview.Primitive)) {
d.logger.Sugar().Debugf("confirm dialog event %v received", event)
if event.Key() == utils.CloseDialogKey.EventKey() {
d.cancelHandler()
return
}
if formHandler := d.form.InputHandler(); formHandler != nil {
formHandler(event, setFocus)
return
}
})
}
func (d *ConfirmDialog) SetCancelFunc(handler func()) *ConfirmDialog {
d.cancelHandler = handler
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2)
cancelButton.SetSelectedFunc(handler)
return d
}
func (d *ConfirmDialog) SetSelectedFunc(handler func()) *ConfirmDialog {
d.selectHandler = handler
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
enterButton.SetSelectedFunc(handler)
return d
}