diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2021-04-04 23:51:59 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2021-04-06 19:34:32 +1000 |
commit | 4fe512ff3a299102c2bd78bc83b8644582127aae (patch) | |
tree | 5a34eacc1c137a8c98624ba29b757c0a717cf694 /pkg/gui/layout.go | |
parent | 4197921465a6cb67d5fdd5b63de653493a5ebd41 (diff) |
test
type safe view access
Diffstat (limited to 'pkg/gui/layout.go')
-rw-r--r-- | pkg/gui/layout.go | 311 |
1 files changed, 188 insertions, 123 deletions
diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 6d1c956d3..d319873c7 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -31,29 +31,22 @@ func (gui *Gui) layout(g *gocui.Gui) error { minimumHeight := 9 minimumWidth := 10 - if height < minimumHeight || width < minimumWidth { - v, err := g.SetView("limit", 0, 0, width-1, height-1, 0) - if err != nil { - if err.Error() != UNKNOWN_VIEW_ERROR_MSG { - return err - } - v.Title = gui.Tr.NotEnoughSpace - v.Wrap = true - _, _ = g.SetViewOnTop("limit") + var err error + gui.Views.Limit, err = g.SetView("limit", 0, 0, width-1, height-1, 0) + if err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err } - return nil + gui.Views.Limit.Title = gui.Tr.NotEnoughSpace + gui.Views.Limit.Wrap = true } + gui.Views.Limit.Visible = height < minimumHeight || width < minimumWidth informationStr := gui.informationStr() appStatus := gui.statusManager.getStatusString() viewDimensions := gui.getWindowDimensions(informationStr, appStatus) - _, _ = g.SetViewOnBottom("limit") - _ = g.DeleteView("limit") - - textColor := theme.GocuiDefaultTextColor - // reading more lines into main view buffers upon resize prevMainView, err := gui.g.View("main") if err == nil { @@ -79,17 +72,17 @@ func (gui *Gui) layout(g *gocui.Gui) error { // to render content as soon as it appears, because lazyloaded content (via a pty task) // cares about the size of the view. view, err := g.SetView(viewName, 0, 0, width, height, 0) - if err != nil { - return view, err + if view != nil { + view.Visible = false } - return g.SetViewOnBottom(viewName) + return view, err } frameOffset := 1 if frame { frameOffset = 0 } - return g.SetView( + view, err := g.SetView( viewName, dimensionsObj.X0-frameOffset, dimensionsObj.Y0-frameOffset, @@ -97,172 +90,150 @@ func (gui *Gui) layout(g *gocui.Gui) error { dimensionsObj.Y1+frameOffset, 0, ) + + if view != nil { + view.Visible = true + } + + return view, err } - v, err := setViewFromDimensions("main", "main", true) + gui.Views.Main, err = setViewFromDimensions("main", "main", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - v.Title = gui.Tr.DiffTitle - v.Wrap = true - v.FgColor = textColor - v.IgnoreCarriageReturns = true + gui.Views.Main.Title = gui.Tr.DiffTitle + gui.Views.Main.Wrap = true + gui.Views.Main.FgColor = theme.GocuiDefaultTextColor + gui.Views.Main.IgnoreCarriageReturns = true } - secondaryView, err := setViewFromDimensions("secondary", "secondary", true) + gui.Views.Secondary, err = setViewFromDimensions("secondary", "secondary", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - secondaryView.Title = gui.Tr.DiffTitle - secondaryView.Wrap = true - secondaryView.FgColor = textColor - secondaryView.IgnoreCarriageReturns = true + gui.Views.Secondary.Title = gui.Tr.DiffTitle + gui.Views.Secondary.Wrap = true + gui.Views.Secondary.FgColor = theme.GocuiDefaultTextColor + gui.Views.Secondary.IgnoreCarriageReturns = true } - hiddenViewOffset := 9999 - - if v, err := setViewFromDimensions("status", "status", true); err != nil { + if gui.Views.Status, err = setViewFromDimensions("status", "status", true); err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - v.Title = gui.Tr.StatusTitle - v.FgColor = textColor + gui.Views.Status.Title = gui.Tr.StatusTitle + gui.Views.Status.FgColor = theme.GocuiDefaultTextColor } - filesView, err := setViewFromDimensions("files", "files", true) + gui.Views.Files, err = setViewFromDimensions("files", "files", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - filesView.Highlight = true - filesView.Title = gui.Tr.FilesTitle - filesView.FgColor = textColor - filesView.ContainsList = true + gui.Views.Files.Highlight = true + gui.Views.Files.Title = gui.Tr.FilesTitle + gui.Views.Files.FgColor = theme.GocuiDefaultTextColor + gui.Views.Files.ContainsList = true } - branchesView, err := setViewFromDimensions("branches", "branches", true) + gui.Views.Branches, err = setViewFromDimensions("branches", "branches", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - branchesView.Title = gui.Tr.BranchesTitle - branchesView.FgColor = textColor - branchesView.ContainsList = true + gui.Views.Branches.Title = gui.Tr.BranchesTitle + gui.Views.Branches.FgColor = theme.GocuiDefaultTextColor + gui.Views.Branches.ContainsList = true } - commitFilesView, err := setViewFromDimensions("commitFiles", gui.State.Contexts.CommitFiles.GetWindowName(), true) + gui.Views.CommitFiles, err = setViewFromDimensions("commitFiles", gui.State.Contexts.CommitFiles.GetWindowName(), true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - commitFilesView.Title = gui.Tr.CommitFiles - commitFilesView.FgColor = textColor - commitFilesView.ContainsList = true - _, _ = gui.g.SetViewOnBottom("commitFiles") + gui.Views.CommitFiles.Title = gui.Tr.CommitFiles + gui.Views.CommitFiles.FgColor = theme.GocuiDefaultTextColor + gui.Views.CommitFiles.ContainsList = true } + // if the commit files view is the view to be displayed for its window, we'll display it + gui.Views.CommitFiles.Visible = gui.getViewNameForWindow(gui.State.Contexts.CommitFiles.GetWindowName()) == "commitFiles" - commitsView, err := setViewFromDimensions("commits", "commits", true) + gui.Views.Commits, err = setViewFromDimensions("commits", "commits", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - commitsView.Title = gui.Tr.CommitsTitle - commitsView.FgColor = textColor - commitsView.ContainsList = true + gui.Views.Commits.Title = gui.Tr.CommitsTitle + gui.Views.Commits.FgColor = theme.GocuiDefaultTextColor + gui.Views.Commits.ContainsList = true } - stashView, err := setViewFromDimensions("stash", "stash", true) + gui.Views.Stash, err = setViewFromDimensions("stash", "stash", true) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - stashView.Title = gui.Tr.StashTitle - stashView.FgColor = textColor - stashView.ContainsList = true - } - - if gui.getCommitMessageView() == nil { - // doesn't matter where this view starts because it will be hidden - if commitMessageView, err := g.SetView("commitMessage", hiddenViewOffset, hiddenViewOffset, hiddenViewOffset+10, hiddenViewOffset+10, 0); err != nil { - if err.Error() != UNKNOWN_VIEW_ERROR_MSG { - return err - } - _, _ = g.SetViewOnBottom("commitMessage") - commitMessageView.Title = gui.Tr.CommitMessage - commitMessageView.FgColor = textColor - commitMessageView.Editable = true - commitMessageView.Editor = gocui.EditorFunc(gui.commitMessageEditor) - } + gui.Views.Stash.Title = gui.Tr.StashTitle + gui.Views.Stash.FgColor = theme.GocuiDefaultTextColor + gui.Views.Stash.ContainsList = true } - if check, _ := g.View("credentials"); check == nil { - // doesn't matter where this view starts because it will be hidden - if credentialsView, err := g.SetView("credentials", hiddenViewOffset, hiddenViewOffset, hiddenViewOffset+10, hiddenViewOffset+10, 0); err != nil { - if err.Error() != UNKNOWN_VIEW_ERROR_MSG { - return err - } - _, _ = g.SetViewOnBottom("credentials") - credentialsView.Title = gui.Tr.CredentialsUsername - credentialsView.FgColor = textColor - credentialsView.Editable = true - } - } - - if v, err := setViewFromDimensions("options", "options", false); err != nil { + if gui.Views.Options, err = setViewFromDimensions("options", "options", false); err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - v.Frame = false - v.FgColor = theme.OptionsColor + gui.Views.Options.Frame = false + gui.Views.Options.FgColor = theme.OptionsColor } // this view takes up one character. Its only purpose is to show the slash when searching - if searchPrefixView, err := setViewFromDimensions("searchPrefix", "searchPrefix", false); err != nil { + if gui.Views.SearchPrefix, err = setViewFromDimensions("searchPrefix", "searchPrefix", false); err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - searchPrefixView.BgColor = gocui.ColorDefault - searchPrefixView.FgColor = gocui.ColorGreen - searchPrefixView.Frame = false - gui.setViewContent(searchPrefixView, SEARCH_PREFIX) + gui.Views.SearchPrefix.BgColor = gocui.ColorDefault + gui.Views.SearchPrefix.FgColor = gocui.ColorGreen + gui.Views.SearchPrefix.Frame = false + gui.setViewContent(gui.Views.SearchPrefix, SEARCH_PREFIX) } - if searchView, err := setViewFromDimensions("search", "search", false); err != nil { + if gui.Views.Search, err = setViewFromDimensions("search", "search", false); err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - searchView.BgColor = gocui.ColorDefault - searchView.FgColor = gocui.ColorGreen - searchView.Frame = false - searchView.Editable = true + gui.Views.Search.BgColor = gocui.ColorDefault + gui.Views.Search.FgColor = gocui.ColorGreen + gui.Views.Search.Frame = false + gui.Views.Search.Editable = true } - if appStatusView, err := setViewFromDimensions("appStatus", "appStatus", false); err != nil { + if gui.Views.AppStatus, err = setViewFromDimensions("appStatus", "appStatus", false); err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - appStatusView.BgColor = gocui.ColorDefault - appStatusView.FgColor = gocui.ColorCyan - appStatusView.Frame = false - _, _ = g.SetViewOnBottom("appStatus") + gui.Views.AppStatus.BgColor = gocui.ColorDefault + gui.Views.AppStatus.FgColor = gocui.ColorCyan + gui.Views.AppStatus.Frame = false + gui.Views.AppStatus.Visible = false } - informationView, err := setViewFromDimensions("information", "information", false) + gui.Views.Information, err = setViewFromDimensions("information", "information", false) if err != nil { if err.Error() != UNKNOWN_VIEW_ERROR_MSG { return err } - informationView.BgColor = gocui.ColorDefault - informationView.FgColor = gocui.ColorGreen - informationView.Frame = false + gui.Views.Information.BgColor = gocui.ColorDefault + gui.Views.Information.FgColor = gocui.ColorGreen + gui.Views.Information.Frame = false gui.renderString("information", INFO_SECTION_PADDING+informationStr) } if gui.State.OldInformation != informationStr { - gui.setViewContent(informationView, informationStr) + gui.setViewContent(gui.Views.Information, informationStr) gui.State.OldInformation = informationStr } @@ -289,7 +260,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { } // ignore contexts whose view is owned by another context right now - if view.Context != listContext.GetKey() { + if ContextKey(view.Context) != listContext.GetKey() { continue } @@ -302,9 +273,9 @@ func (gui *Gui) layout(g *gocui.Gui) error { view.SetOnSelectItem(gui.onSelectItemWrapper(listContext.onSearchSelect)) } - gui.getMainView().SetOnSelectItem(gui.onSelectItemWrapper(gui.handlelineByLineNavigateTo)) + gui.Views.Main.SetOnSelectItem(gui.onSelectItemWrapper(gui.handlelineByLineNavigateTo)) - mainViewWidth, mainViewHeight := gui.getMainView().Size() + mainViewWidth, mainViewHeight := gui.Views.Main.Size() if mainViewWidth != gui.State.PrevMainWidth || mainViewHeight != gui.State.PrevMainHeight { gui.State.PrevMainWidth = mainViewWidth gui.State.PrevMainHeight = mainViewHeight @@ -320,28 +291,24 @@ func (gui *Gui) layout(g *gocui.Gui) error { return gui.resizeCurrentPopupPanel() } +func (gui *Gui) setHiddenView(viewName string) (*gocui.View, error) { + // arbitrarily giving the view enough size so that we don't get an error, but + // it's expected that the view will be given the correct size before being shown + return gui.g.SetView(viewName, 0, 0, 10, 10, 0) +} + func (gui *Gui) onInitialViewsCreationForRepo() error { gui.setInitialViewContexts() // hide any popup views. This only applies when we've just switched repos for _, viewName := range gui.popupViewNames() { - _, _ = gui.g.SetViewOnBottom(viewName) - } - - // the status panel is not actually a list context at the moment, so it is excluded - // here. Arguably that's quite convenient because it means we're back to starting - // in the files panel when landing in a new repo, but when returning from a submodule - // we'll be back in the submodules context. This still seems awkward though, and it's - // definitely going to break when (if) we make the status context a list context - initialContext := gui.currentSideContext() - if initialContext == nil { - if gui.State.Modes.Filtering.Active() { - initialContext = gui.State.Contexts.BranchCommits - } else { - initialContext = gui.State.Contexts.Files + view, err := gui.g.View(viewName) + if err == nil { + view.Visible = false } } + initialContext := gui.currentSideContext() if err := gui.pushContext(initialContext); err != nil { return err } @@ -350,6 +317,49 @@ func (gui *Gui) onInitialViewsCreationForRepo() error { } func (gui *Gui) onInitialViewsCreation() error { + // creating some views which are hidden at the start but we need to exist so that we can set an initial ordering + if err := gui.createHiddenViews(); err != nil { + return err + } + + // now we order the views (in order of bottom first) + layerOneViews := []*gocui.View{ + // first layer. Ordering within this layer does not matter because there are + // no overlapping views + gui.Views.Status, + gui.Views.Files, + gui.Views.Branches, + gui.Views.Commits, + gui.Views.Stash, + gui.Views.CommitFiles, + gui.Views.Main, + gui.Views.Secondary, + + // bottom line + gui.Views.Options, + gui.Views.AppStatus, + gui.Views.Information, + gui.Views.Search, + gui.Views.SearchPrefix, + + // popups. Ordering within this layer does not matter because there should + // only be one popup shown at a time + gui.Views.CommitMessage, + gui.Views.Credentials, + gui.Views.Menu, + gui.Views.Confirmation, + gui.Views.Suggestions, + + // this guy will cover everything else when it appears + gui.Views.Limit, + } + + for _, view := range layerOneViews { + if _, err := gui.g.SetViewOnTop(view.Name()); err != nil { + return err + } + } + gui.g.Mutexes.ViewsMutex.Lock() // add tabs to views for _, view := range gui.g.Views() { @@ -378,3 +388,58 @@ func (gui *Gui) onInitialViewsCreation() error { return nil } + +func (gui *Gui) createHiddenViews() error { + // doesn't matter where this view starts because it will be hidden + var err error + if gui.Views.CommitMessage, err = gui.setHiddenView("commitMessage"); err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err + } + gui.Views.CommitMessage.Visible = false + gui.Views.CommitMessage.Title = gui.Tr.CommitMessage + gui.Views.CommitMessage.FgColor = theme.GocuiDefaultTextColor + gui.Views.CommitMessage.Editable = true + gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor) + } + + // doesn't matter where this view starts because it will be hidden + if gui.Views.Credentials, err = gui.setHiddenView("credentials"); err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err + } + gui.Views.Credentials.Visible = false + gui.Views.Credentials.Title = gui.Tr.CredentialsUsername + gui.Views.Credentials.FgColor = theme.GocuiDefaultTextColor + gui.Views.Credentials.Editable = true + } + + // not worrying about setting attributes because that will be done when the view is actually shown + gui.Views.Confirmation, err = gui.setHiddenView("confirmation") + if err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err + } + gui.Views.Confirmation.Visible = false + } + + // not worrying about setting attributes because that will be done when the view is actually shown + gui.Views.Suggestions, err = gui.setHiddenView("suggestions") + if err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err + } + gui.Views.Suggestions.Visible = false + } + + // not worrying about setting attributes because that will be done when the view is actually shown + gui.Views.Menu, err = gui.setHiddenView("menu") + if err != nil { + if err.Error() != UNKNOWN_VIEW_ERROR_MSG { + return err + } + gui.Views.Menu.Visible = false + } + + return nil +} |