2018-05-26 05:23:39 +02:00
|
|
|
// lots of this has been directly ported from one of the example files, will brush up later
|
|
|
|
|
|
|
|
// Copyright 2014 The gocui Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
package gui
|
2018-05-26 05:23:39 +02:00
|
|
|
|
|
|
|
import (
|
2018-08-05 14:00:02 +02:00
|
|
|
"strings"
|
2018-05-26 05:23:39 +02:00
|
|
|
|
2018-08-05 14:00:02 +02:00
|
|
|
"github.com/fatih/color"
|
|
|
|
"github.com/jesseduffield/gocui"
|
2018-08-14 11:05:26 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
2018-05-26 05:23:39 +02:00
|
|
|
)
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) wrappedConfirmationFunction(function func(*gocui.Gui, *gocui.View) error) func(*gocui.Gui, *gocui.View) error {
|
2018-08-05 14:00:02 +02:00
|
|
|
return func(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
if function != nil {
|
|
|
|
if err := function(g, v); err != nil {
|
2018-08-23 10:43:16 +02:00
|
|
|
return err
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.closeConfirmationPrompt(g)
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
2018-05-27 08:32:09 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) closeConfirmationPrompt(g *gocui.Gui) error {
|
2018-08-05 14:00:02 +02:00
|
|
|
view, err := g.View("confirmation")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
if err := gui.returnFocus(g, view); err != nil {
|
2018-08-05 14:00:02 +02:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
g.DeleteKeybindings("confirmation")
|
|
|
|
return g.DeleteView("confirmation")
|
2018-05-27 08:32:09 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) getMessageHeight(message string, width int) int {
|
2018-08-05 14:00:02 +02:00
|
|
|
lines := strings.Split(message, "\n")
|
|
|
|
lineCount := 0
|
|
|
|
for _, line := range lines {
|
|
|
|
lineCount += len(line)/width + 1
|
|
|
|
}
|
|
|
|
return lineCount
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, int) {
|
2018-08-05 14:00:02 +02:00
|
|
|
width, height := g.Size()
|
2018-08-09 11:49:36 +02:00
|
|
|
panelWidth := width / 2
|
2018-08-14 11:05:26 +02:00
|
|
|
panelHeight := gui.getMessageHeight(prompt, panelWidth)
|
2018-08-05 14:00:02 +02:00
|
|
|
return width/2 - panelWidth/2,
|
|
|
|
height/2 - panelHeight/2 - panelHeight%2 - 1,
|
|
|
|
width/2 + panelWidth/2,
|
|
|
|
height/2 + panelHeight/2
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, handleConfirm func(*gocui.Gui, *gocui.View) error) error {
|
2018-08-15 13:49:38 +02:00
|
|
|
gui.onNewPopupPanel()
|
2018-08-25 07:55:49 +02:00
|
|
|
confirmationView, err := gui.prepareConfirmationPanel(currentView, title, "")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
confirmationView.Editable = true
|
|
|
|
return gui.setKeyBindings(g, handleConfirm, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt string) (*gocui.View, error) {
|
|
|
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(gui.g, prompt)
|
|
|
|
confirmationView, err := gui.g.SetView("confirmation", x0, y0, x1, y1, 0)
|
|
|
|
if err != nil {
|
2018-08-05 14:00:02 +02:00
|
|
|
if err != gocui.ErrUnknownView {
|
2018-08-25 07:55:49 +02:00
|
|
|
return nil, err
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
|
|
|
confirmationView.Title = title
|
2018-08-18 08:23:19 +02:00
|
|
|
confirmationView.FgColor = gocui.ColorWhite
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
2018-08-25 07:55:49 +02:00
|
|
|
confirmationView.Clear()
|
|
|
|
|
|
|
|
if err := gui.switchFocus(gui.g, currentView, confirmationView); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return confirmationView, nil
|
2018-05-27 08:32:09 +02:00
|
|
|
}
|
|
|
|
|
2018-08-15 13:49:38 +02:00
|
|
|
func (gui *Gui) onNewPopupPanel() {
|
|
|
|
gui.g.SetViewOnBottom("commitMessage")
|
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
|
2018-08-15 13:49:38 +02:00
|
|
|
gui.onNewPopupPanel()
|
2018-08-05 14:00:02 +02:00
|
|
|
g.Update(func(g *gocui.Gui) error {
|
|
|
|
// delete the existing confirmation panel if it exists
|
|
|
|
if view, _ := g.View("confirmation"); view != nil {
|
2018-08-14 11:05:26 +02:00
|
|
|
if err := gui.closeConfirmationPrompt(g); err != nil {
|
2018-08-15 15:12:55 +02:00
|
|
|
errMessage := gui.Tr.TemplateLocalize(
|
|
|
|
"CantCloseConfirmationPrompt",
|
2018-08-16 11:31:03 +02:00
|
|
|
Teml{
|
2018-08-15 15:12:55 +02:00
|
|
|
"error": err.Error(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
gui.Log.Error(errMessage)
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
|
|
|
}
|
2018-08-25 07:55:49 +02:00
|
|
|
confirmationView, err := gui.prepareConfirmationPanel(currentView, title, prompt)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2018-08-05 14:00:02 +02:00
|
|
|
}
|
2018-08-25 07:55:49 +02:00
|
|
|
confirmationView.Editable = false
|
|
|
|
if err := gui.renderString(g, "confirmation", prompt); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return gui.setKeyBindings(g, handleConfirm, handleClose)
|
2018-08-05 14:00:02 +02:00
|
|
|
})
|
|
|
|
return nil
|
2018-06-05 10:47:57 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) handleNewline(g *gocui.Gui, v *gocui.View) error {
|
2018-08-09 15:26:31 +02:00
|
|
|
// resising ahead of time so that the top line doesn't get hidden to make
|
|
|
|
// room for the cursor on the second line
|
2018-08-14 11:05:26 +02:00
|
|
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, v.Buffer())
|
2018-08-09 15:26:31 +02:00
|
|
|
if _, err := g.SetView("confirmation", x0, y0, x1, y1+1, 0); err != nil {
|
|
|
|
if err != gocui.ErrUnknownView {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v.EditNewLine()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) setKeyBindings(g *gocui.Gui, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
|
2018-08-15 10:53:05 +02:00
|
|
|
actions := gui.Tr.TemplateLocalize(
|
|
|
|
"CloseConfirm",
|
2018-08-16 11:31:03 +02:00
|
|
|
Teml{
|
2018-08-15 10:53:05 +02:00
|
|
|
"keyBindClose": "esc",
|
|
|
|
"keyBindConfirm": "enter",
|
|
|
|
},
|
|
|
|
)
|
2018-08-25 07:55:49 +02:00
|
|
|
if err := gui.renderString(g, "options", actions); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
if err := g.SetKeybinding("confirmation", gocui.KeyEnter, gocui.ModNone, gui.wrappedConfirmationFunction(handleConfirm)); err != nil {
|
2018-08-05 14:00:02 +02:00
|
|
|
return err
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
if err := g.SetKeybinding("confirmation", gocui.KeyTab, gocui.ModNone, gui.handleNewline); err != nil {
|
2018-08-09 15:26:31 +02:00
|
|
|
return err
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
return g.SetKeybinding("confirmation", gocui.KeyEsc, gocui.ModNone, gui.wrappedConfirmationFunction(handleClose))
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
2018-05-27 08:32:09 +02:00
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) createMessagePanel(g *gocui.Gui, currentView *gocui.View, title, prompt string) error {
|
|
|
|
return gui.createConfirmationPanel(g, currentView, title, prompt, nil, nil)
|
2018-05-27 08:32:09 +02:00
|
|
|
}
|
2018-06-01 15:23:31 +02:00
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) createErrorPanel(g *gocui.Gui, message string) error {
|
2018-08-27 12:08:10 +02:00
|
|
|
gui.Log.Error(message)
|
2018-08-05 14:00:02 +02:00
|
|
|
currentView := g.CurrentView()
|
|
|
|
colorFunction := color.New(color.FgRed).SprintFunc()
|
|
|
|
coloredMessage := colorFunction(strings.TrimSpace(message))
|
2018-08-16 07:16:32 +02:00
|
|
|
return gui.createConfirmationPanel(g, currentView, gui.Tr.SLocalize("Error"), coloredMessage, nil, nil)
|
2018-06-01 15:23:31 +02:00
|
|
|
}
|
2018-08-09 15:26:31 +02:00
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) resizePopupPanel(g *gocui.Gui, v *gocui.View) error {
|
2018-08-09 15:26:31 +02:00
|
|
|
// If the confirmation panel is already displayed, just resize the width,
|
|
|
|
// otherwise continue
|
2018-08-14 11:05:26 +02:00
|
|
|
content := utils.TrimTrailingNewline(v.Buffer())
|
|
|
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, content)
|
2018-08-12 04:00:30 +02:00
|
|
|
vx0, vy0, vx1, vy1 := v.Dimensions()
|
|
|
|
if vx0 == x0 && vy0 == y0 && vx1 == x1 && vy1 == y1 {
|
2018-08-11 07:09:37 +02:00
|
|
|
return nil
|
2018-08-12 04:00:30 +02:00
|
|
|
}
|
2018-08-16 07:16:32 +02:00
|
|
|
gui.Log.Info(gui.Tr.SLocalize("resizingPopupPanel"))
|
2018-08-12 04:00:30 +02:00
|
|
|
_, err := g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
|
|
|
return err
|
2018-08-09 15:26:31 +02:00
|
|
|
}
|