From eb5e54e9fd649e556d8c639ff87fedbfe02ff8e9 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Thu, 20 Aug 2020 08:52:51 +1000 Subject: [PATCH] use interface for panel state rather than pointer --- pkg/gui/files_panel.go | 2 +- pkg/gui/gui.go | 55 +++++++----- pkg/gui/layout.go | 2 +- pkg/gui/list_context.go | 194 ++++++++++++++++++++-------------------- pkg/gui/view_helpers.go | 31 ++++--- 5 files changed, 151 insertions(+), 133 deletions(-) diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 0015c563c..929f54f6b 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -420,7 +420,7 @@ func (gui *Gui) refreshStateFiles() error { } } - gui.refreshSelectedLine(&gui.State.Panels.Files.SelectedLine, len(gui.State.Files)) + gui.refreshSelectedLine(gui.State.Panels.Files, len(gui.State.Files)) return nil } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 68d5b9de2..6eab2314c 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -101,10 +101,23 @@ type Gui struct { ViewTabContextMap map[string][]tabContext } -type hasSelectedLine struct { +type listPanelState struct { SelectedLine int } +func (h *listPanelState) SetSelectedLineIdx(value int) { + h.SelectedLine = value +} + +func (h *listPanelState) GetSelectedLineIdx() int { + return h.SelectedLine +} + +type IListPanelState interface { + SetSelectedLineIdx(int) + GetSelectedLineIdx() int +} + // for now the staging panel state, unlike the other panel states, is going to be // non-mutative, so that we don't accidentally end up // with mismatches of data. We might change this in the future @@ -130,47 +143,47 @@ type mergingPanelState struct { } type filePanelState struct { - hasSelectedLine + listPanelState } // TODO: consider splitting this out into the window and the branches view type branchPanelState struct { - hasSelectedLine + listPanelState } type remotePanelState struct { - hasSelectedLine + listPanelState } type remoteBranchesState struct { - hasSelectedLine + listPanelState } type tagsPanelState struct { - hasSelectedLine + listPanelState } type commitPanelState struct { - hasSelectedLine + listPanelState LimitCommits bool } type reflogCommitPanelState struct { - hasSelectedLine + listPanelState } type stashPanelState struct { - hasSelectedLine + listPanelState } type menuPanelState struct { - hasSelectedLine + listPanelState OnPress func(g *gocui.Gui, v *gocui.View) error } type commitFilesPanelState struct { - hasSelectedLine + listPanelState } type panelStates struct { @@ -271,16 +284,16 @@ func (gui *Gui) resetState() { CherryPickedCommits: make([]*commands.Commit, 0), StashEntries: make([]*commands.StashEntry, 0), Panels: &panelStates{ - Files: &filePanelState{hasSelectedLine{SelectedLine: -1}}, - Branches: &branchPanelState{hasSelectedLine{SelectedLine: 0}}, - Remotes: &remotePanelState{hasSelectedLine{SelectedLine: 0}}, - RemoteBranches: &remoteBranchesState{hasSelectedLine{SelectedLine: -1}}, - Tags: &tagsPanelState{hasSelectedLine{SelectedLine: -1}}, - Commits: &commitPanelState{hasSelectedLine: hasSelectedLine{SelectedLine: -1}, LimitCommits: true}, - ReflogCommits: &reflogCommitPanelState{hasSelectedLine{SelectedLine: 0}}, // TODO: might need to make -1 - CommitFiles: &commitFilesPanelState{hasSelectedLine{SelectedLine: -1}}, - Stash: &stashPanelState{hasSelectedLine{SelectedLine: -1}}, - Menu: &menuPanelState{hasSelectedLine: hasSelectedLine{SelectedLine: 0}, OnPress: nil}, + Files: &filePanelState{listPanelState{SelectedLine: -1}}, + Branches: &branchPanelState{listPanelState{SelectedLine: 0}}, + Remotes: &remotePanelState{listPanelState{SelectedLine: 0}}, + RemoteBranches: &remoteBranchesState{listPanelState{SelectedLine: -1}}, + Tags: &tagsPanelState{listPanelState{SelectedLine: -1}}, + Commits: &commitPanelState{listPanelState: listPanelState{SelectedLine: -1}, LimitCommits: true}, + ReflogCommits: &reflogCommitPanelState{listPanelState{SelectedLine: 0}}, // TODO: might need to make -1 + CommitFiles: &commitFilesPanelState{listPanelState{SelectedLine: -1}}, + Stash: &stashPanelState{listPanelState{SelectedLine: -1}}, + Menu: &menuPanelState{listPanelState: listPanelState{SelectedLine: 0}, OnPress: nil}, Merging: &mergingPanelState{ ConflictIndex: 0, ConflictTop: true, diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index ccda11ac6..0c1a6d07a 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -309,7 +309,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { continue } // check if the selected line is now out of view and if so refocus it - listContextState.view.FocusPoint(0, *listContextState.listContext.GetSelectedLineIdxPtr()) + listContextState.view.FocusPoint(0, listContextState.listContext.GetPanelState().GetSelectedLineIdx()) listContextState.view.SelBgColor = theme.GocuiSelectedLineBgColor diff --git a/pkg/gui/list_context.go b/pkg/gui/list_context.go index 1419454fe..12644cb49 100644 --- a/pkg/gui/list_context.go +++ b/pkg/gui/list_context.go @@ -6,15 +6,15 @@ import ( ) type ListContext struct { - ViewName string - ContextKey string - GetItemsLength func() int - GetSelectedLineIdxPtr func() *int - GetDisplayStrings func() [][]string - OnFocus func() error - OnFocusLost func() error - OnClickSelectedItem func() error - GetItems func() []ListItem + ViewName string + ContextKey string + GetItemsLength func() int + GetDisplayStrings func() [][]string + OnFocus func() error + OnFocusLost func() error + OnClickSelectedItem func() error + GetItems func() []ListItem + GetPanelState func() IListPanelState Gui *Gui RendersToMainView bool @@ -32,7 +32,7 @@ func (lc *ListContext) GetSelectedItem() ListItem { return nil } - selectedLineIdx := *lc.GetSelectedLineIdxPtr() + selectedLineIdx := lc.GetPanelState().GetSelectedLineIdx() if selectedLineIdx > len(items)-1 { return nil @@ -62,7 +62,7 @@ func (lc *ListContext) OnRender() error { } if lc.GetDisplayStrings != nil { - lc.Gui.refreshSelectedLine(lc.GetSelectedLineIdxPtr(), lc.GetItemsLength()) + lc.Gui.refreshSelectedLine(lc.GetPanelState(), lc.GetItemsLength()) lc.Gui.renderDisplayStrings(view, lc.GetDisplayStrings()) } @@ -131,8 +131,8 @@ func (lc *ListContext) handleLineChange(change int) error { return err } - lc.Gui.changeSelectedLine(lc.GetSelectedLineIdxPtr(), lc.GetItemsLength(), change) - view.FocusPoint(0, *lc.GetSelectedLineIdxPtr()) + lc.Gui.changeSelectedLine(lc.GetPanelState(), lc.GetItemsLength(), change) + view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx()) if lc.RendersToMainView { if err := lc.Gui.resetOrigin(lc.Gui.getMainView()); err != nil { @@ -185,8 +185,7 @@ func (lc *ListContext) handleClick(g *gocui.Gui, v *gocui.View) error { return nil } - selectedLineIdxPtr := lc.GetSelectedLineIdxPtr() - prevSelectedLineIdx := *selectedLineIdxPtr + prevSelectedLineIdx := lc.GetPanelState().GetSelectedLineIdx() newSelectedLineIdx := v.SelectedLineIdx() // we need to focus the view @@ -198,7 +197,7 @@ func (lc *ListContext) handleClick(g *gocui.Gui, v *gocui.View) error { return nil } - *selectedLineIdxPtr = newSelectedLineIdx + lc.GetPanelState().SetSelectedLineIdx(newSelectedLineIdx) prevViewName := lc.Gui.currentViewName() if prevSelectedLineIdx == newSelectedLineIdx && prevViewName == lc.ViewName && lc.OnClickSelectedItem != nil { @@ -208,23 +207,22 @@ func (lc *ListContext) handleClick(g *gocui.Gui, v *gocui.View) error { } func (lc *ListContext) onSearchSelect(selectedLineIdx int) error { - *lc.GetSelectedLineIdxPtr() = selectedLineIdx + lc.GetPanelState().SetSelectedLineIdx(selectedLineIdx) return lc.HandleFocus() } func (gui *Gui) menuListContext() *ListContext { return &ListContext{ - ViewName: "menu", - ContextKey: "menu", - GetItemsLength: func() int { return gui.getMenuView().LinesHeight() }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Menu.SelectedLine }, - OnFocus: gui.handleMenuSelect, + ViewName: "menu", + ContextKey: "menu", + GetItemsLength: func() int { return gui.getMenuView().LinesHeight() }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Menu }, + OnFocus: gui.handleMenuSelect, // need to add a layer of indirection here because the callback changes during runtime OnClickSelectedItem: func() error { return gui.State.Panels.Menu.OnPress(gui.g, nil) }, Gui: gui, RendersToMainView: false, Kind: PERSISTENT_POPUP, - // GetItems: // no GetDisplayStrings field because we do a custom render on menu creation } @@ -232,15 +230,15 @@ func (gui *Gui) menuListContext() *ListContext { func (gui *Gui) filesListContext() *ListContext { return &ListContext{ - ViewName: "files", - ContextKey: "files", - GetItemsLength: func() int { return len(gui.State.Files) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Files.SelectedLine }, - OnFocus: gui.focusAndSelectFile, - OnClickSelectedItem: gui.handleFilePress, - Gui: gui, - RendersToMainView: false, - Kind: SIDE_CONTEXT, + ViewName: "files", + ContextKey: "files", + GetItemsLength: func() int { return len(gui.State.Files) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Files }, + OnFocus: gui.focusAndSelectFile, + OnClickSelectedItem: gui.handleFilePress, + Gui: gui, + RendersToMainView: false, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetFileListDisplayStrings(gui.State.Files, gui.State.Diff.Ref) }, @@ -249,14 +247,14 @@ func (gui *Gui) filesListContext() *ListContext { func (gui *Gui) branchesListContext() *ListContext { return &ListContext{ - ViewName: "branches", - ContextKey: "local-branches", - GetItemsLength: func() int { return len(gui.State.Branches) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Branches.SelectedLine }, - OnFocus: gui.handleBranchSelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "branches", + ContextKey: "local-branches", + GetItemsLength: func() int { return len(gui.State.Branches) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Branches }, + OnFocus: gui.handleBranchSelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref) }, @@ -265,15 +263,15 @@ func (gui *Gui) branchesListContext() *ListContext { func (gui *Gui) remotesListContext() *ListContext { return &ListContext{ - ViewName: "branches", - ContextKey: "remotes", - GetItemsLength: func() int { return len(gui.State.Remotes) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Remotes.SelectedLine }, - OnFocus: gui.handleRemoteSelect, - OnClickSelectedItem: gui.handleRemoteEnter, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "branches", + ContextKey: "remotes", + GetItemsLength: func() int { return len(gui.State.Remotes) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Remotes }, + OnFocus: gui.handleRemoteSelect, + OnClickSelectedItem: gui.handleRemoteEnter, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Diff.Ref) }, @@ -282,14 +280,14 @@ func (gui *Gui) remotesListContext() *ListContext { func (gui *Gui) remoteBranchesListContext() *ListContext { return &ListContext{ - ViewName: "branches", - ContextKey: "remote-branches", - GetItemsLength: func() int { return len(gui.State.RemoteBranches) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.RemoteBranches.SelectedLine }, - OnFocus: gui.handleRemoteBranchSelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "branches", + ContextKey: "remote-branches", + GetItemsLength: func() int { return len(gui.State.RemoteBranches) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.RemoteBranches }, + OnFocus: gui.handleRemoteBranchSelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Diff.Ref) }, @@ -298,14 +296,14 @@ func (gui *Gui) remoteBranchesListContext() *ListContext { func (gui *Gui) tagsListContext() *ListContext { return &ListContext{ - ViewName: "branches", - ContextKey: "tags", - GetItemsLength: func() int { return len(gui.State.Tags) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Tags.SelectedLine }, - OnFocus: gui.handleTagSelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "branches", + ContextKey: "tags", + GetItemsLength: func() int { return len(gui.State.Tags) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Tags }, + OnFocus: gui.handleTagSelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Diff.Ref) }, @@ -314,15 +312,15 @@ func (gui *Gui) tagsListContext() *ListContext { func (gui *Gui) branchCommitsListContext() *ListContext { return &ListContext{ - ViewName: "commits", - ContextKey: "branch-commits", - GetItemsLength: func() int { return len(gui.State.Commits) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Commits.SelectedLine }, - OnFocus: gui.handleCommitSelect, - OnClickSelectedItem: gui.handleSwitchToCommitFilesPanel, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "commits", + ContextKey: "branch-commits", + GetItemsLength: func() int { return len(gui.State.Commits) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Commits }, + OnFocus: gui.handleCommitSelect, + OnClickSelectedItem: gui.handleSwitchToCommitFilesPanel, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetCommitListDisplayStrings(gui.State.Commits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap(), gui.State.Diff.Ref) }, @@ -331,14 +329,14 @@ func (gui *Gui) branchCommitsListContext() *ListContext { func (gui *Gui) reflogCommitsListContext() *ListContext { return &ListContext{ - ViewName: "commits", - ContextKey: "reflog-commits", - GetItemsLength: func() int { return len(gui.State.FilteredReflogCommits) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.ReflogCommits.SelectedLine }, - OnFocus: gui.handleReflogCommitSelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "commits", + ContextKey: "reflog-commits", + GetItemsLength: func() int { return len(gui.State.FilteredReflogCommits) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.ReflogCommits }, + OnFocus: gui.handleReflogCommitSelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetReflogCommitListDisplayStrings(gui.State.FilteredReflogCommits, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref) }, @@ -347,14 +345,14 @@ func (gui *Gui) reflogCommitsListContext() *ListContext { func (gui *Gui) stashListContext() *ListContext { return &ListContext{ - ViewName: "stash", - ContextKey: "stash", - GetItemsLength: func() int { return len(gui.State.StashEntries) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Stash.SelectedLine }, - OnFocus: gui.handleStashEntrySelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "stash", + ContextKey: "stash", + GetItemsLength: func() int { return len(gui.State.StashEntries) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.Stash }, + OnFocus: gui.handleStashEntrySelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetStashEntryListDisplayStrings(gui.State.StashEntries, gui.State.Diff.Ref) }, @@ -363,14 +361,14 @@ func (gui *Gui) stashListContext() *ListContext { func (gui *Gui) commitFilesListContext() *ListContext { return &ListContext{ - ViewName: "commitFiles", - ContextKey: "commitFiles", - GetItemsLength: func() int { return len(gui.State.CommitFiles) }, - GetSelectedLineIdxPtr: func() *int { return &gui.State.Panels.CommitFiles.SelectedLine }, - OnFocus: gui.handleCommitFileSelect, - Gui: gui, - RendersToMainView: true, - Kind: SIDE_CONTEXT, + ViewName: "commitFiles", + ContextKey: "commitFiles", + GetItemsLength: func() int { return len(gui.State.CommitFiles) }, + GetPanelState: func() IListPanelState { return gui.State.Panels.CommitFiles }, + OnFocus: gui.handleCommitFileSelect, + Gui: gui, + RendersToMainView: true, + Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { return presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles, gui.State.Diff.Ref) }, diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 2c8f9066b..4b60c4c26 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -289,25 +289,32 @@ func (gui *Gui) resizePopupPanel(v *gocui.View) error { return err } -func (gui *Gui) changeSelectedLine(line *int, total int, change int) { +func (gui *Gui) changeSelectedLine(panelState IListPanelState, total int, change int) { // TODO: find out why we're doing this - if *line == -1 { + line := panelState.GetSelectedLineIdx() + + if line == -1 { return } - if *line+change < 0 { - *line = 0 - } else if *line+change >= total { - *line = total - 1 + var newLine int + if line+change < 0 { + newLine = 0 + } else if line+change >= total { + newLine = total - 1 } else { - *line += change + newLine = line + change } + + panelState.SetSelectedLineIdx(newLine) } -func (gui *Gui) refreshSelectedLine(line *int, total int) { - if *line == -1 && total > 0 { - *line = 0 - } else if total-1 < *line { - *line = total - 1 +func (gui *Gui) refreshSelectedLine(panelState IListPanelState, total int) { + line := panelState.GetSelectedLineIdx() + + if line == -1 && total > 0 { + panelState.SetSelectedLineIdx(0) + } else if total-1 < line { + panelState.SetSelectedLineIdx(total - 1) } }