From c3d1a79a89d335bb539db78bf55fae067886c8f5 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 24 Jun 2024 18:45:30 +0200 Subject: [PATCH 01/10] Fix clicking outside of the commit description panel or suggestions panel We forgot to handle the "suggestions" and "commitDescription" view names. Instead of listing all the names of views that can appear in popups though, let's use the context kind for this, which feels more robust. This is a change in behavior: previously, clicking outside of the search or filter prompt would close the prompt, now it no longer does (because search has a persistent popup kind, but it wasn't listed in the list of view names before). --- pkg/gui/controllers/helpers/confirmation_helper.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 8f7c60b5a..4fed9ab0b 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -454,12 +454,12 @@ func (self *ConfirmationHelper) ResizeCommitMessagePanels() { _, _ = self.c.GocuiGui().SetView(self.c.Views().CommitDescription.Name(), x0, y0+summaryViewHeight, x1, y1+summaryViewHeight, 0) } -func (self *ConfirmationHelper) IsPopupPanel(viewName string) bool { - return viewName == "commitMessage" || viewName == "confirmation" || viewName == "menu" +func (self *ConfirmationHelper) IsPopupPanel(context types.Context) bool { + return context.GetKind() == types.PERSISTENT_POPUP || context.GetKind() == types.TEMPORARY_POPUP } func (self *ConfirmationHelper) IsPopupPanelFocused() bool { - return self.IsPopupPanel(self.c.CurrentContext().GetViewName()) + return self.IsPopupPanel(self.c.CurrentContext()) } func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string { From 22dc7fece98b37c359f6305ee9ac5271bb2c5f54 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Jun 2024 09:34:46 +0200 Subject: [PATCH 02/10] Have only one of commit message and description on the context stack at a time This is how we do it for confirmation with suggestions too, so be consistent. It will make things easier later in this branch if we only have one context per "panel" on the stack, even if the panel consists of two views. Concretely this means: - only push the message context onto the stack when opening the panel (this requires making the description view visible manually; we do the same for suggestions) - when switching between message and description, use ReplaceContext rather than PushContext --- pkg/gui/context/commit_message_context.go | 2 ++ .../commit_description_controller.go | 2 +- .../controllers/commit_message_controller.go | 2 +- .../custom_patch_options_menu_action.go | 2 +- pkg/gui/controllers/helpers/commits_helper.go | 26 +++---------------- 5 files changed, 9 insertions(+), 25 deletions(-) diff --git a/pkg/gui/context/commit_message_context.go b/pkg/gui/context/commit_message_context.go index f69b7ef74..402f9b12e 100644 --- a/pkg/gui/context/commit_message_context.go +++ b/pkg/gui/context/commit_message_context.go @@ -116,6 +116,8 @@ func (self *CommitMessageContext) SetPanelState( "togglePanelKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.Universal.TogglePanel), "commitMenuKeybinding": keybindings.Label(self.c.UserConfig.Keybinding.CommitMessage.CommitMenu), }) + + self.c.Views().CommitDescription.Visible = true } func (self *CommitMessageContext) RenderCommitLength() { diff --git a/pkg/gui/controllers/commit_description_controller.go b/pkg/gui/controllers/commit_description_controller.go index 0c078382b..80608fff5 100644 --- a/pkg/gui/controllers/commit_description_controller.go +++ b/pkg/gui/controllers/commit_description_controller.go @@ -53,7 +53,7 @@ func (self *CommitDescriptionController) context() *context.CommitMessageContext } func (self *CommitDescriptionController) switchToCommitMessage() error { - return self.c.PushContext(self.c.Contexts().CommitMessage) + return self.c.ReplaceContext(self.c.Contexts().CommitMessage) } func (self *CommitDescriptionController) close() error { diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index 4012dc950..5c37b4da9 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -85,7 +85,7 @@ func (self *CommitMessageController) handleNextCommit() error { } func (self *CommitMessageController) switchToCommitDescription() error { - if err := self.c.PushContext(self.c.Contexts().CommitDescription); err != nil { + if err := self.c.ReplaceContext(self.c.Contexts().CommitDescription); err != nil { return err } return nil diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index f24607597..867e4528a 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -214,7 +214,7 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error { PreserveMessage: false, OnConfirm: func(summary string, description string) error { return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { - _ = self.c.Helpers().Commits.PopCommitMessageContexts() + _ = self.c.Helpers().Commits.CloseCommitMessagePanel() self.c.LogAction(self.c.Tr.Actions.MovePatchIntoNewCommit) err := self.c.Git().Patch.PullPatchIntoNewCommit(self.c.Model().Commits, commitIndex, summary, description) if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil { diff --git a/pkg/gui/controllers/helpers/commits_helper.go b/pkg/gui/controllers/helpers/commits_helper.go index 216f55f8e..be3a36e8d 100644 --- a/pkg/gui/controllers/helpers/commits_helper.go +++ b/pkg/gui/controllers/helpers/commits_helper.go @@ -154,7 +154,7 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp self.UpdateCommitPanelView(opts.InitialMessage) - return self.pushCommitMessageContexts() + return self.c.PushContext(self.c.Contexts().CommitMessage) } func (self *CommitsHelper) OnCommitSuccess() { @@ -190,28 +190,10 @@ func (self *CommitsHelper) CloseCommitMessagePanel() error { self.c.Contexts().CommitMessage.SetHistoryMessage("") - return self.PopCommitMessageContexts() -} + self.c.Views().CommitMessage.Visible = false + self.c.Views().CommitDescription.Visible = false -func (self *CommitsHelper) PopCommitMessageContexts() error { - return self.c.RemoveContexts(self.commitMessageContexts()) -} - -func (self *CommitsHelper) pushCommitMessageContexts() error { - for _, context := range self.commitMessageContexts() { - if err := self.c.PushContext(context); err != nil { - return err - } - } - - return nil -} - -func (self *CommitsHelper) commitMessageContexts() []types.Context { - return []types.Context{ - self.c.Contexts().CommitDescription, - self.c.Contexts().CommitMessage, - } + return self.c.PopContext() } func (self *CommitsHelper) OpenCommitMenu(suggestionFunc func(string) []*types.Suggestion) error { From 34d7afc0e91014732d79a4164fe0b00769f8b713 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 24 Jun 2024 18:14:51 +0200 Subject: [PATCH 03/10] Remove unused functions --- pkg/gui/controllers/helpers/confirmation_helper.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 4fed9ab0b..2364a4f57 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -5,8 +5,6 @@ import ( "fmt" "strings" - "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/theme" @@ -118,12 +116,6 @@ func wrapMessageToWidth(wrap bool, message string, width int) []string { return wrappedLines } -func (self *ConfirmationHelper) getPopupPanelDimensions(wrap bool, prompt string) (int, int, int, int) { - panelWidth := self.getPopupPanelWidth() - panelHeight := getMessageHeight(wrap, prompt, panelWidth) - return self.getPopupPanelDimensionsAux(panelWidth, panelHeight) -} - func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) { return self.getPopupPanelDimensionsAux(panelWidth, contentHeight) } @@ -361,12 +353,6 @@ func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error { return nil } -func (self *ConfirmationHelper) ResizePopupPanel(v *gocui.View, content string) error { - x0, y0, x1, y1 := self.getPopupPanelDimensions(v.Wrap, content) - _, err := self.c.GocuiGui().SetView(v.Name(), x0, y0, x1, y1, 0) - return err -} - func (self *ConfirmationHelper) resizeMenu() { // we want the unfiltered length here so that if we're filtering we don't // resize the window From ccc620e5fc0891000d329d244b61eec6ff8017d3 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 24 Jun 2024 18:21:21 +0200 Subject: [PATCH 04/10] Remove duplicate function ResizeConfirmationPanel and resizeConfirmationPanel were identical, get rid of one of them. --- .../helpers/confirmation_helper.go | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 2364a4f57..b3f1eca49 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -169,7 +169,7 @@ func (self *ConfirmationHelper) prepareConfirmationPanel( suggestionsView.Subtitle = "" } - self.ResizeConfirmationPanel() + self.resizeConfirmationPanel() return nil } @@ -219,7 +219,7 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ textArea := confirmationView.TextArea textArea.Clear() textArea.TypeString(opts.Prompt) - self.ResizeConfirmationPanel() + self.resizeConfirmationPanel() confirmationView.RenderTextArea() } else { self.c.ResetViewOrigin(confirmationView) @@ -317,27 +317,6 @@ func (self *ConfirmationHelper) getSelectedSuggestionValue() string { return "" } -func (self *ConfirmationHelper) ResizeConfirmationPanel() { - suggestionsViewHeight := 0 - if self.c.Views().Suggestions.Visible { - suggestionsViewHeight = 11 - } - panelWidth := self.getPopupPanelWidth() - prompt := self.c.Views().Confirmation.Buffer() - wrap := true - if self.c.Views().Confirmation.Editable { - prompt = self.c.Views().Confirmation.TextArea.GetContent() - wrap = false - } - panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight - x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight) - confirmationViewBottom := y1 - suggestionsViewHeight - _, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0) - - suggestionsViewTop := confirmationViewBottom + 1 - _, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0) -} - func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error { c := self.c.CurrentContext() From b795d91fa8112534db96311eb86d339066dedb07 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 27 Jun 2024 10:18:07 +0200 Subject: [PATCH 05/10] Remove redundant resizeConfirmationPanel() call at panel creating time We resize the panel in layout, so there's no need to do that after creation. --- pkg/gui/controllers/helpers/confirmation_helper.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index b3f1eca49..d564eeabc 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -169,7 +169,6 @@ func (self *ConfirmationHelper) prepareConfirmationPanel( suggestionsView.Subtitle = "" } - self.resizeConfirmationPanel() return nil } From 32cfe7a5c3d325e035f0768d0ff2a37cdec2aff6 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 28 Jun 2024 08:14:05 +0200 Subject: [PATCH 06/10] Bump gocui --- go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/jesseduffield/gocui/gui.go | 18 +++++++++++++++--- vendor/modules.txt | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 69546555d..bc8009a98 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d - github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d + github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e diff --git a/go.sum b/go.sum index dae59e807..e575afcad 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= -github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d h1:I6rViLB+ZW5SnS8P7ZE0FdY6lMfx803qZ9ZYEYCvfro= -github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8= +github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b h1:oxCq0DvR2GMGf4UaoaASb0nQK/fJMQW3c3PNCLWCjS8= +github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go index e2593b985..0c64e6925 100644 --- a/vendor/github.com/jesseduffield/gocui/gui.go +++ b/vendor/github.com/jesseduffield/gocui/gui.go @@ -307,14 +307,26 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er } if v, err := g.View(name); err == nil { - if v.x0 != x0 || v.x1 != x1 || v.y0 != y0 || v.y1 != y1 { - v.clearViewLines() - } + sizeChanged := v.x0 != x0 || v.x1 != x1 || v.y0 != y0 || v.y1 != y1 v.x0 = x0 v.y0 = y0 v.x1 = x1 v.y1 = y1 + + if sizeChanged { + v.clearViewLines() + + if v.Editable { + cursorX, cursorY := v.TextArea.GetCursorXY() + newViewCursorX, newOriginX := updatedCursorAndOrigin(0, v.InnerWidth(), cursorX) + newViewCursorY, newOriginY := updatedCursorAndOrigin(0, v.InnerHeight(), cursorY) + + _ = v.SetCursor(newViewCursorX, newViewCursorY) + _ = v.SetOrigin(newOriginX, newOriginY) + } + } + return v, nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index c7d601a93..6b34633e2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -172,7 +172,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem github.com/jesseduffield/go-git/v5/utils/merkletrie/index github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/noder -# github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d +# github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b ## explicit; go 1.12 github.com/jesseduffield/gocui # github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 From bb016485212b322a11debaa4a64494f5904e06b5 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Jun 2024 18:18:55 +0200 Subject: [PATCH 07/10] Remove redundant calls to resize editable panels at creating time The only purpose of this was to scroll the editable text correctly (see https://github.com/jesseduffield/lazygit/pull/2146); now that gocui takes care of that, we no longer need to do this. --- pkg/gui/controllers.go | 1 - pkg/gui/controllers/helpers/confirmation_helper.go | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index d6ac5a268..ba39fef5a 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -404,7 +404,6 @@ func (gui *Gui) getCommitMessageSetTextareaTextFn(getView func() *gocui.View) fu view := getView() view.ClearTextArea() view.TextArea.TypeString(text) - gui.helpers.Confirmation.ResizeCommitMessagePanels() view.RenderTextArea() } } diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index d564eeabc..9fa2ce8a8 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -218,7 +218,6 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ textArea := confirmationView.TextArea textArea.Clear() textArea.TypeString(opts.Prompt) - self.resizeConfirmationPanel() confirmationView.RenderTextArea() } else { self.c.ResetViewOrigin(confirmationView) From 1d502d3245c543f20b4b72d00f555bb41438e374 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 27 Jun 2024 10:23:08 +0200 Subject: [PATCH 08/10] Remove return value from ResizeCurrentPopupPanel It always returned nil, so there's no point in returning an error. --- pkg/gui/controllers/helpers/confirmation_helper.go | 4 +--- pkg/gui/layout.go | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 9fa2ce8a8..2a1a821c2 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -315,7 +315,7 @@ func (self *ConfirmationHelper) getSelectedSuggestionValue() string { return "" } -func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error { +func (self *ConfirmationHelper) ResizeCurrentPopupPanel() { c := self.c.CurrentContext() switch c { @@ -326,8 +326,6 @@ func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error { case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription: self.ResizeCommitMessagePanels() } - - return nil } func (self *ConfirmationHelper) resizeMenu() { diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 861bb0bd1..077ee3c84 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -173,9 +173,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { // if you run `lazygit --logs` // this will let you see these branches as prettified json // gui.c.Log.Info(utils.AsJson(gui.State.Model.Branches[0:4])) - if err := gui.helpers.Confirmation.ResizeCurrentPopupPanel(); err != nil { - return err - } + gui.helpers.Confirmation.ResizeCurrentPopupPanel() gui.renderContextOptionsMap() From 1ab1fb3599c9aa891e9ff0c8ca52f1a22b8af141 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Jun 2024 19:25:46 +0200 Subject: [PATCH 09/10] Resize all open popup panels in layout, not just the topmost one Probably not the most import feature in the world, but when resizing the terminal window while multiple popup panels were open at the same time, we would only resize the topmost one. The main reason for changing this is because it makes the next commit easier to implement. --- pkg/gui/context.go | 9 +++++++++ .../helpers/confirmation_helper.go | 20 +++++++++---------- pkg/gui/gui_common.go | 4 ++++ pkg/gui/layout.go | 2 +- pkg/gui/types/common.go | 1 + 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/pkg/gui/context.go b/pkg/gui/context.go index 28ecf2405..5dc6df6a0 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -391,3 +391,12 @@ func (self *ContextMgr) ContextForKey(key types.ContextKey) types.Context { return nil } + +func (self *ContextMgr) PopupContexts() []types.Context { + self.RLock() + defer self.RUnlock() + + return lo.Filter(self.ContextStack, func(context types.Context, _ int) bool { + return context.GetKind() == types.TEMPORARY_POPUP || context.GetKind() == types.PERSISTENT_POPUP + }) +} diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 2a1a821c2..83e4102ac 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -315,16 +315,16 @@ func (self *ConfirmationHelper) getSelectedSuggestionValue() string { return "" } -func (self *ConfirmationHelper) ResizeCurrentPopupPanel() { - c := self.c.CurrentContext() - - switch c { - case self.c.Contexts().Menu: - self.resizeMenu() - case self.c.Contexts().Confirmation, self.c.Contexts().Suggestions: - self.resizeConfirmationPanel() - case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription: - self.ResizeCommitMessagePanels() +func (self *ConfirmationHelper) ResizeCurrentPopupPanels() { + for _, c := range self.c.CurrentPopupContexts() { + switch c { + case self.c.Contexts().Menu: + self.resizeMenu() + case self.c.Contexts().Confirmation, self.c.Contexts().Suggestions: + self.resizeConfirmationPanel() + case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription: + self.ResizeCommitMessagePanels() + } } } diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index 434f4b38b..8a537f2ca 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -73,6 +73,10 @@ func (self *guiCommon) CurrentSideContext() types.Context { return self.gui.State.ContextMgr.CurrentSide() } +func (self *guiCommon) CurrentPopupContexts() []types.Context { + return self.gui.State.ContextMgr.PopupContexts() +} + func (self *guiCommon) IsCurrentContext(c types.Context) bool { return self.gui.State.ContextMgr.IsCurrent(c) } diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 077ee3c84..3bf6a7c35 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -173,7 +173,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { // if you run `lazygit --logs` // this will let you see these branches as prettified json // gui.c.Log.Info(utils.AsJson(gui.State.Model.Branches[0:4])) - gui.helpers.Confirmation.ResizeCurrentPopupPanel() + gui.helpers.Confirmation.ResizeCurrentPopupPanels() gui.renderContextOptionsMap() diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 61c27de49..c6885d717 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -67,6 +67,7 @@ type IGuiCommon interface { CurrentContext() Context CurrentStaticContext() Context CurrentSideContext() Context + CurrentPopupContexts() []Context IsCurrentContext(Context) bool // TODO: replace the above context-based methods with just using Context() e.g. replace PushContext() with Context().Push() Context() IContextMgr From 4b6479b25f8fcbacb360ee18ef3359cfeee8bd8c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Jun 2024 08:02:56 +0200 Subject: [PATCH 10/10] Stagger popup panels When opening a popup panel on top of another one, offset the new one a little bit down and to the right. --- .../helpers/confirmation_helper.go | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 83e4102ac..c0fb5bafb 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -116,15 +116,23 @@ func wrapMessageToWidth(wrap bool, message string, width int) []string { return wrappedLines } -func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) { - return self.getPopupPanelDimensionsAux(panelWidth, contentHeight) +func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int, parentPopupContext types.Context) (int, int, int, int) { + return self.getPopupPanelDimensionsAux(panelWidth, contentHeight, parentPopupContext) } -func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) { +func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panelHeight int, parentPopupContext types.Context) (int, int, int, int) { width, height := self.c.GocuiGui().Size() if panelHeight > height*3/4 { panelHeight = height * 3 / 4 } + if parentPopupContext != nil { + // If there's already a popup on the screen, offset the new one from its + // parent so that it's clearly distinguished from the parent + x0, y0, _, _ := parentPopupContext.GetView().Dimensions() + x0 += 2 + y0 += 1 + return x0, y0, x0 + panelWidth, y0 + panelHeight + 1 + } return width/2 - panelWidth/2, height/2 - panelHeight/2 - panelHeight%2 - 1, width/2 + panelWidth/2, @@ -316,19 +324,22 @@ func (self *ConfirmationHelper) getSelectedSuggestionValue() string { } func (self *ConfirmationHelper) ResizeCurrentPopupPanels() { + var parentPopupContext types.Context for _, c := range self.c.CurrentPopupContexts() { switch c { case self.c.Contexts().Menu: - self.resizeMenu() + self.resizeMenu(parentPopupContext) case self.c.Contexts().Confirmation, self.c.Contexts().Suggestions: - self.resizeConfirmationPanel() + self.resizeConfirmationPanel(parentPopupContext) case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription: - self.ResizeCommitMessagePanels() + self.ResizeCommitMessagePanels(parentPopupContext) } + + parentPopupContext = c } } -func (self *ConfirmationHelper) resizeMenu() { +func (self *ConfirmationHelper) resizeMenu(parentPopupContext types.Context) { // we want the unfiltered length here so that if we're filtering we don't // resize the window itemCount := self.c.Contexts().Menu.UnfilteredLen() @@ -336,7 +347,7 @@ func (self *ConfirmationHelper) resizeMenu() { panelWidth := self.getPopupPanelWidth() contentWidth := panelWidth - 2 // minus 2 for the frame promptLinesCount := self.layoutMenuPrompt(contentWidth) - x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount) + x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount, parentPopupContext) menuBottom := y1 - offset _, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0) @@ -379,7 +390,7 @@ func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int { return len(promptLines) } -func (self *ConfirmationHelper) resizeConfirmationPanel() { +func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types.Context) { suggestionsViewHeight := 0 if self.c.Views().Suggestions.Visible { suggestionsViewHeight = 11 @@ -392,7 +403,7 @@ func (self *ConfirmationHelper) resizeConfirmationPanel() { wrap = false } panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight - x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight) + x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext) confirmationViewBottom := y1 - suggestionsViewHeight _, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0) @@ -400,7 +411,7 @@ func (self *ConfirmationHelper) resizeConfirmationPanel() { _, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0) } -func (self *ConfirmationHelper) ResizeCommitMessagePanels() { +func (self *ConfirmationHelper) ResizeCommitMessagePanels(parentPopupContext types.Context) { panelWidth := self.getPopupPanelWidth() content := self.c.Views().CommitDescription.TextArea.GetContent() summaryViewHeight := 3 @@ -409,7 +420,7 @@ func (self *ConfirmationHelper) ResizeCommitMessagePanels() { if panelHeight < minHeight { panelHeight = minHeight } - x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight) + x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext) _, _ = self.c.GocuiGui().SetView(self.c.Views().CommitMessage.Name(), x0, y0, x1, y0+summaryViewHeight-1, 0) _, _ = self.c.GocuiGui().SetView(self.c.Views().CommitDescription.Name(), x0, y0+summaryViewHeight, x1, y1+summaryViewHeight, 0)