From cec4cb48cb8d4ba6ed3def0194f4443a1fc51cbd Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sun, 16 Aug 2020 09:18:57 +1000 Subject: [PATCH] centralise some list view code --- pkg/gui/branches_panel.go | 21 --- pkg/gui/commit_files_panel.go | 5 - pkg/gui/commits_panel.go | 13 -- pkg/gui/files_panel.go | 5 - pkg/gui/layout.go | 38 ++--- pkg/gui/list_view.go | 281 +++++++++++++++++++++------------- pkg/gui/stash_panel.go | 5 - pkg/gui/tags_panel.go | 4 - 8 files changed, 190 insertions(+), 182 deletions(-) diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 1365980be..c18f97253 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -28,10 +28,6 @@ func (gui *Gui) handleBranchSelect() error { gui.State.SplitMainPanel = false - if _, err := gui.g.SetCurrentView("branches"); err != nil { - return err - } - gui.getMainView().Title = "Log" // This really shouldn't happen: there should always be a master branch @@ -39,7 +35,6 @@ func (gui *Gui) handleBranchSelect() error { return gui.newStringTask("main", gui.Tr.SLocalize("NoBranchesThisRepo")) } branch := gui.getSelectedBranch() - gui.getBranchesView().FocusPoint(0, gui.State.Panels.Branches.SelectedLine) if gui.inDiffMode() { return gui.renderDiff() @@ -510,22 +505,6 @@ func (gui *Gui) handleCreateResetToBranchMenu(g *gocui.Gui, v *gocui.View) error return gui.createResetMenu(branch.Name) } -func (gui *Gui) onBranchesPanelSearchSelect(selectedLine int) error { - branchesView := gui.getBranchesView() - switch branchesView.Context { - case "local-branches": - gui.State.Panels.Branches.SelectedLine = selectedLine - return gui.handleBranchSelect() - case "remotes": - gui.State.Panels.Remotes.SelectedLine = selectedLine - return gui.handleRemoteSelect() - case "remote-branches": - gui.State.Panels.RemoteBranches.SelectedLine = selectedLine - return gui.handleRemoteBranchSelect() - } - return nil -} - func (gui *Gui) handleRenameBranch(g *gocui.Gui, v *gocui.View) error { branch := gui.getSelectedBranch() if branch == nil { diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index 0bddbb8e9..e2018480b 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -248,8 +248,3 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error { return enterTheFile(selectedLineIdx) } - -func (gui *Gui) onCommitFilesPanelSearchSelect(selectedLine int) error { - gui.State.Panels.CommitFiles.SelectedLine = selectedLine - return gui.handleCommitFileSelect() -} diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index d1f86d287..4dcea9876 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -715,19 +715,6 @@ func (gui *Gui) handleCreateCommitResetMenu(g *gocui.Gui, v *gocui.View) error { return gui.createResetMenu(commit.Sha) } -func (gui *Gui) onCommitsPanelSearchSelect(selectedLine int) error { - commitsView := gui.getCommitsView() - switch commitsView.Context { - case "branch-commits": - gui.State.Panels.Commits.SelectedLine = selectedLine - return gui.handleCommitSelect() - case "reflog-commits": - gui.State.Panels.ReflogCommits.SelectedLine = selectedLine - return gui.handleReflogCommitSelect() - } - return nil -} - func (gui *Gui) handleOpenSearchForCommitsPanel(g *gocui.Gui, v *gocui.View) error { // we usually lazyload these commits but now that we're searching we need to load them now if gui.State.Panels.Commits.LimitCommits { diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 3aff8c3da..37918067d 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -652,8 +652,3 @@ func (gui *Gui) handleStashChanges(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleCreateResetToUpstreamMenu(g *gocui.Gui, v *gocui.View) error { return gui.createResetMenu("@{upstream}") } - -func (gui *Gui) onFilesPanelSearchSelect(selectedLine int) error { - gui.State.Panels.Files.SelectedLine = selectedLine - return gui.focusAndSelectFile() -} diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index a9720f249..7e7772d88 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -190,7 +190,6 @@ func (gui *Gui) layout(g *gocui.Gui) error { } filesView.Highlight = true filesView.Title = gui.Tr.SLocalize("FilesTitle") - filesView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onFilesPanelSearchSelect)) filesView.ContainsList = true } @@ -202,7 +201,6 @@ func (gui *Gui) layout(g *gocui.Gui) error { branchesView.Title = gui.Tr.SLocalize("BranchesTitle") branchesView.Tabs = []string{"Local Branches", "Remotes", "Tags"} branchesView.FgColor = textColor - branchesView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onBranchesPanelSearchSelect)) branchesView.ContainsList = true } @@ -213,7 +211,6 @@ func (gui *Gui) layout(g *gocui.Gui) error { } commitFilesView.Title = gui.Tr.SLocalize("CommitFiles") commitFilesView.FgColor = textColor - commitFilesView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onCommitFilesPanelSearchSelect)) commitFilesView.ContainsList = true } @@ -225,7 +222,6 @@ func (gui *Gui) layout(g *gocui.Gui) error { commitsView.Title = gui.Tr.SLocalize("CommitsTitle") commitsView.Tabs = []string{"Commits", "Reflog"} commitsView.FgColor = textColor - commitsView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onCommitsPanelSearchSelect)) commitsView.ContainsList = true } @@ -236,7 +232,6 @@ func (gui *Gui) layout(g *gocui.Gui) error { } stashView.Title = gui.Tr.SLocalize("StashTitle") stashView.FgColor = textColor - stashView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onStashPanelSearchSelect)) stashView.ContainsList = true } @@ -352,32 +347,37 @@ func (gui *Gui) layout(g *gocui.Gui) error { lineCount int view *gocui.View context string + listView *listView } - listViews := []listViewState{ - {view: filesView, context: "", selectedLine: gui.State.Panels.Files.SelectedLine, lineCount: len(gui.State.Files)}, - {view: branchesView, context: "local-branches", selectedLine: gui.State.Panels.Branches.SelectedLine, lineCount: len(gui.State.Branches)}, - {view: branchesView, context: "remotes", selectedLine: gui.State.Panels.Remotes.SelectedLine, lineCount: len(gui.State.Remotes)}, - {view: branchesView, context: "remote-branches", selectedLine: gui.State.Panels.RemoteBranches.SelectedLine, lineCount: len(gui.State.Remotes)}, - {view: commitsView, context: "branch-commits", selectedLine: gui.State.Panels.Commits.SelectedLine, lineCount: len(gui.State.Commits)}, - {view: commitsView, context: "reflog-commits", selectedLine: gui.State.Panels.ReflogCommits.SelectedLine, lineCount: len(gui.State.FilteredReflogCommits)}, - {view: stashView, context: "", selectedLine: gui.State.Panels.Stash.SelectedLine, lineCount: len(gui.State.StashEntries)}, - {view: commitFilesView, context: "", selectedLine: gui.State.Panels.CommitFiles.SelectedLine, lineCount: len(gui.State.CommitFiles)}, + listViewStates := []listViewState{ + {view: filesView, context: "", selectedLine: gui.State.Panels.Files.SelectedLine, lineCount: len(gui.State.Files), listView: gui.filesListView()}, + {view: branchesView, context: "local-branches", selectedLine: gui.State.Panels.Branches.SelectedLine, lineCount: len(gui.State.Branches), listView: gui.branchesListView()}, + {view: branchesView, context: "remotes", selectedLine: gui.State.Panels.Remotes.SelectedLine, lineCount: len(gui.State.Remotes), listView: gui.remotesListView()}, + {view: branchesView, context: "remote-branches", selectedLine: gui.State.Panels.RemoteBranches.SelectedLine, lineCount: len(gui.State.Remotes), listView: gui.remoteBranchesListView()}, + {view: branchesView, context: "tags", selectedLine: gui.State.Panels.Tags.SelectedLine, lineCount: len(gui.State.Tags), listView: gui.tagsListView()}, + {view: commitsView, context: "branch-commits", selectedLine: gui.State.Panels.Commits.SelectedLine, lineCount: len(gui.State.Commits), listView: gui.branchCommitsListView()}, + {view: commitsView, context: "reflog-commits", selectedLine: gui.State.Panels.ReflogCommits.SelectedLine, lineCount: len(gui.State.FilteredReflogCommits), listView: gui.reflogCommitsListView()}, + {view: stashView, context: "", selectedLine: gui.State.Panels.Stash.SelectedLine, lineCount: len(gui.State.StashEntries), listView: gui.stashListView()}, + {view: commitFilesView, context: "", selectedLine: gui.State.Panels.CommitFiles.SelectedLine, lineCount: len(gui.State.CommitFiles), listView: gui.commitFilesListView()}, } // menu view might not exist so we check to be safe if menuView, err := gui.g.View("menu"); err == nil { - listViews = append(listViews, listViewState{view: menuView, context: "", selectedLine: gui.State.Panels.Menu.SelectedLine, lineCount: gui.State.MenuItemCount}) + listViewStates = append(listViewStates, listViewState{view: menuView, context: "", selectedLine: gui.State.Panels.Menu.SelectedLine, lineCount: gui.State.MenuItemCount, listView: gui.menuListView()}) } - for _, listView := range listViews { + for _, listViewState := range listViewStates { // ignore views where the context doesn't match up with the selected line we're trying to focus - if listView.context != "" && (listView.view.Context != listView.context) { + if listViewState.context != "" && (listViewState.view.Context != listViewState.context) { continue } // check if the selected line is now out of view and if so refocus it - listView.view.FocusPoint(0, listView.selectedLine) + listViewState.view.FocusPoint(0, listViewState.selectedLine) - listView.view.SelBgColor = theme.GocuiSelectedLineBgColor + listViewState.view.SelBgColor = theme.GocuiSelectedLineBgColor + + // I doubt this is expensive though it's admittedly redundant after the first render + listViewState.view.SetOnSelectItem(gui.onSelectItemWrapper(listViewState.listView.onSearchSelect)) } mainViewWidth, mainViewHeight := gui.getMainView().Size() diff --git a/pkg/gui/list_view.go b/pkg/gui/list_view.go index 84ae0ed2f..e7ff845b9 100644 --- a/pkg/gui/list_view.go +++ b/pkg/gui/list_view.go @@ -27,15 +27,27 @@ func (lv *listView) handleLineChange(change int) error { return nil } + view, err := lv.gui.g.View(lv.viewName) + if err != nil { + return err + } + lv.gui.changeSelectedLine(lv.getSelectedLineIdxPtr(), lv.getItemsLength(), change) + view.FocusPoint(0, *lv.getSelectedLineIdxPtr()) if lv.rendersToMainView { if err := lv.gui.resetOrigin(lv.gui.getMainView()); err != nil { return err } + if err := lv.gui.resetOrigin(lv.gui.getSecondaryView()); err != nil { + return err + } } - return lv.handleItemSelect() + if lv.handleItemSelect != nil { + return lv.handleItemSelect() + } + return nil } func (lv *listView) handleNextPage(g *gocui.Gui, v *gocui.View) error { @@ -81,128 +93,177 @@ func (lv *listView) handleClick(g *gocui.Gui, v *gocui.View) error { prevSelectedLineIdx := *selectedLineIdxPtr newSelectedLineIdx := v.SelectedLineIdx() + // we need to focus the view + if err := lv.gui.switchFocus(nil, v); err != nil { + return err + } + if newSelectedLineIdx > lv.getItemsLength()-1 { return lv.handleFocus() } *selectedLineIdxPtr = newSelectedLineIdx - if lv.rendersToMainView { - if err := lv.gui.resetOrigin(lv.gui.getMainView()); err != nil { - return err - } - } - prevViewName := lv.gui.currentViewName() if prevSelectedLineIdx == newSelectedLineIdx && prevViewName == lv.viewName && lv.handleClickSelectedItem != nil { return lv.handleClickSelectedItem() } - return lv.handleItemSelect() + if lv.handleItemSelect != nil { + return lv.handleItemSelect() + } + return nil +} + +func (lv *listView) onSearchSelect(selectedLineIdx int) error { + *lv.getSelectedLineIdxPtr() = selectedLineIdx + if lv.handleItemSelect != nil { + return lv.handleItemSelect() + } + return nil +} + +func (gui *Gui) menuListView() *listView { + return &listView{ + viewName: "menu", + getItemsLength: func() int { return gui.getMenuView().LinesHeight() }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Menu.SelectedLine }, + handleFocus: gui.handleMenuSelect, + handleItemSelect: gui.handleMenuSelect, + // need to add a layer of indirection here because the callback changes during runtime + handleClickSelectedItem: func() error { return gui.State.Panels.Menu.OnPress(gui.g, nil) }, + gui: gui, + rendersToMainView: false, + } +} + +func (gui *Gui) filesListView() *listView { + return &listView{ + viewName: "files", + getItemsLength: func() int { return len(gui.State.Files) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Files.SelectedLine }, + handleFocus: gui.focusAndSelectFile, + handleItemSelect: gui.focusAndSelectFile, + handleClickSelectedItem: gui.handleFilePress, + gui: gui, + rendersToMainView: false, + } +} + +func (gui *Gui) branchesListView() *listView { + return &listView{ + viewName: "branches", + context: "local-branches", + getItemsLength: func() int { return len(gui.State.Branches) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Branches.SelectedLine }, + handleFocus: gui.handleBranchSelect, + handleItemSelect: gui.handleBranchSelect, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) remotesListView() *listView { + return &listView{ + viewName: "branches", + context: "remotes", + getItemsLength: func() int { return len(gui.State.Remotes) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Remotes.SelectedLine }, + handleFocus: gui.renderRemotesWithSelection, + handleItemSelect: gui.handleRemoteSelect, + handleClickSelectedItem: gui.handleRemoteEnter, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) remoteBranchesListView() *listView { + return &listView{ + viewName: "branches", + context: "remote-branches", + getItemsLength: func() int { return len(gui.State.RemoteBranches) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.RemoteBranches.SelectedLine }, + handleFocus: gui.handleRemoteBranchSelect, + handleItemSelect: gui.handleRemoteBranchSelect, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) tagsListView() *listView { + return &listView{ + viewName: "branches", + context: "tags", + getItemsLength: func() int { return len(gui.State.Tags) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Tags.SelectedLine }, + handleFocus: gui.handleTagSelect, + handleItemSelect: gui.handleTagSelect, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) branchCommitsListView() *listView { + return &listView{ + viewName: "commits", + context: "branch-commits", + getItemsLength: func() int { return len(gui.State.Commits) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Commits.SelectedLine }, + handleFocus: gui.handleCommitSelect, + handleItemSelect: gui.handleCommitSelect, + handleClickSelectedItem: gui.handleSwitchToCommitFilesPanel, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) reflogCommitsListView() *listView { + return &listView{ + viewName: "commits", + context: "reflog-commits", + getItemsLength: func() int { return len(gui.State.FilteredReflogCommits) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.ReflogCommits.SelectedLine }, + handleFocus: gui.handleReflogCommitSelect, + handleItemSelect: gui.handleReflogCommitSelect, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) stashListView() *listView { + return &listView{ + viewName: "stash", + getItemsLength: func() int { return len(gui.State.StashEntries) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Stash.SelectedLine }, + handleFocus: gui.handleStashEntrySelect, + handleItemSelect: gui.handleStashEntrySelect, + gui: gui, + rendersToMainView: true, + } +} + +func (gui *Gui) commitFilesListView() *listView { + return &listView{ + viewName: "commitFiles", + getItemsLength: func() int { return len(gui.State.CommitFiles) }, + getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.CommitFiles.SelectedLine }, + handleFocus: gui.handleCommitFileSelect, + handleItemSelect: gui.handleCommitFileSelect, + gui: gui, + rendersToMainView: true, + } } func (gui *Gui) getListViews() []*listView { return []*listView{ - { - viewName: "menu", - getItemsLength: func() int { return gui.getMenuView().LinesHeight() }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Menu.SelectedLine }, - handleFocus: gui.handleMenuSelect, - handleItemSelect: gui.handleMenuSelect, - // need to add a layer of indirection here because the callback changes during runtime - handleClickSelectedItem: func() error { return gui.State.Panels.Menu.OnPress(gui.g, nil) }, - gui: gui, - rendersToMainView: false, - }, - { - viewName: "files", - getItemsLength: func() int { return len(gui.State.Files) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Files.SelectedLine }, - handleFocus: gui.focusAndSelectFile, - handleItemSelect: gui.focusAndSelectFile, - handleClickSelectedItem: gui.handleFilePress, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "branches", - context: "local-branches", - getItemsLength: func() int { return len(gui.State.Branches) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Branches.SelectedLine }, - handleFocus: gui.handleBranchSelect, - handleItemSelect: gui.handleBranchSelect, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "branches", - context: "remotes", - getItemsLength: func() int { return len(gui.State.Remotes) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Remotes.SelectedLine }, - handleFocus: gui.renderRemotesWithSelection, - handleItemSelect: gui.handleRemoteSelect, - handleClickSelectedItem: gui.handleRemoteEnter, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "branches", - context: "remote-branches", - getItemsLength: func() int { return len(gui.State.RemoteBranches) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.RemoteBranches.SelectedLine }, - handleFocus: gui.handleRemoteBranchSelect, - handleItemSelect: gui.handleRemoteBranchSelect, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "branches", - context: "tags", - getItemsLength: func() int { return len(gui.State.Tags) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Tags.SelectedLine }, - handleFocus: gui.handleTagSelect, - handleItemSelect: gui.handleTagSelect, - gui: gui, - rendersToMainView: true, - }, - - { - viewName: "commits", - context: "branch-commits", - getItemsLength: func() int { return len(gui.State.Commits) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Commits.SelectedLine }, - handleFocus: gui.handleCommitSelect, - handleItemSelect: gui.handleCommitSelect, - handleClickSelectedItem: gui.handleSwitchToCommitFilesPanel, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "commits", - context: "reflog-commits", - getItemsLength: func() int { return len(gui.State.FilteredReflogCommits) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.ReflogCommits.SelectedLine }, - handleFocus: gui.handleReflogCommitSelect, - handleItemSelect: gui.handleReflogCommitSelect, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "stash", - getItemsLength: func() int { return len(gui.State.StashEntries) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Stash.SelectedLine }, - handleFocus: gui.handleStashEntrySelect, - handleItemSelect: gui.handleStashEntrySelect, - gui: gui, - rendersToMainView: true, - }, - { - viewName: "commitFiles", - getItemsLength: func() int { return len(gui.State.CommitFiles) }, - getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.CommitFiles.SelectedLine }, - handleFocus: gui.handleCommitFileSelect, - handleItemSelect: gui.handleCommitFileSelect, - gui: gui, - rendersToMainView: true, - }, + gui.menuListView(), + gui.filesListView(), + gui.branchesListView(), + gui.remotesListView(), + gui.remoteBranchesListView(), + gui.tagsListView(), + gui.branchCommitsListView(), + gui.reflogCommitsListView(), + gui.stashListView(), + gui.commitFilesListView(), } } diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index f364478b4..7bbed65c2 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -149,8 +149,3 @@ func (gui *Gui) handleStashSave(stashFunc func(message string) error) error { return gui.refreshSidePanels(refreshOptions{scope: []int{STASH, FILES}}) }) } - -func (gui *Gui) onStashPanelSearchSelect(selectedLine int) error { - gui.State.Panels.Stash.SelectedLine = selectedLine - return gui.handleStashEntrySelect() -} diff --git a/pkg/gui/tags_panel.go b/pkg/gui/tags_panel.go index de80d0e93..a3d778a3d 100644 --- a/pkg/gui/tags_panel.go +++ b/pkg/gui/tags_panel.go @@ -24,10 +24,6 @@ func (gui *Gui) handleTagSelect() error { gui.State.SplitMainPanel = false - if _, err := gui.g.SetCurrentView("branches"); err != nil { - return err - } - gui.getMainView().Title = "Tag" tag := gui.getSelectedTag()