From e73937c2bd5c10ba7389392784a1e90af57cc490 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 18 May 2020 22:00:07 +1000 Subject: [PATCH] more work on new layout functionality --- pkg/gui/arrangement.go | 43 ++++++++++++++++++++++++++++++----------- pkg/gui/dimensions.go | 10 ++++++++++ pkg/gui/layout.go | 28 +++++++++++++++------------ pkg/gui/view_helpers.go | 5 +++++ 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/pkg/gui/arrangement.go b/pkg/gui/arrangement.go index 6ce9b7907..589bf6c3c 100644 --- a/pkg/gui/arrangement.go +++ b/pkg/gui/arrangement.go @@ -1,27 +1,40 @@ package gui -func (gui *Gui) getViewDimensions() map[string]dimensions { - width, height := gui.g.Size() +func (gui *Gui) mainSectionChildren() []*box { + currentViewName := gui.currentViewName() + + // if we're not in split mode we can just show the one main panel. Likewise if + // the main panel is focused and we're in full-screen mode + if !gui.State.SplitMainPanel || (gui.State.ScreenMode == SCREEN_FULL && currentViewName == "main") { + return []*box{ + { + viewName: "main", + weight: 1, + }, + } + } main := "main" secondary := "secondary" - if gui.State.Panels.LineByLine != nil && gui.State.Panels.LineByLine.SecondaryFocused { + if gui.secondaryViewFocused() { + // when you think you've focused the secondary view, we've actually just swapped them around in the layout main, secondary = secondary, main } - mainSectionChildren := []*box{ + return []*box{ { viewName: main, weight: 1, }, - } - - if gui.State.SplitMainPanel { - mainSectionChildren = append(mainSectionChildren, &box{ + { viewName: secondary, weight: 1, - }) + }, } +} + +func (gui *Gui) getMidSectionWeights() (int, int) { + currentViewName := gui.currentViewName() // we originally specified this as a ratio i.e. .20 would correspond to a weight of 1 against 4 sidePanelWidthRatio := gui.Config.GetUserConfig().GetFloat64("gui.sidePanelWidth") @@ -32,7 +45,7 @@ func (gui *Gui) getViewDimensions() map[string]dimensions { if gui.State.SplitMainPanel { mainSectionWeight = 5 // need to shrink side panel to make way for main panels if side-by-side } - currentViewName := gui.currentViewName() + if currentViewName == "main" { if gui.State.ScreenMode == SCREEN_HALF || gui.State.ScreenMode == SCREEN_FULL { sideSectionWeight = 0 @@ -45,6 +58,14 @@ func (gui *Gui) getViewDimensions() map[string]dimensions { } } + return sideSectionWeight, mainSectionWeight +} + +func (gui *Gui) getViewDimensions() map[string]dimensions { + width, height := gui.g.Size() + + sideSectionWeight, mainSectionWeight := gui.getMidSectionWeights() + sidePanelsDirection := COLUMN portraitMode := width <= 84 && height > 50 if portraitMode { @@ -73,7 +94,7 @@ func (gui *Gui) getViewDimensions() map[string]dimensions { }, direction: COLUMN, weight: mainSectionWeight, - children: mainSectionChildren, + children: gui.mainSectionChildren(), }, }, }, diff --git a/pkg/gui/dimensions.go b/pkg/gui/dimensions.go index fbf9891f3..912af50d2 100644 --- a/pkg/gui/dimensions.go +++ b/pkg/gui/dimensions.go @@ -14,6 +14,16 @@ const ( COLUMN ) +// to give a high-level explanation of what's going on here. We layout our views by arranging a bunch of boxes in the window. +// If a box has children, it needs to specify how it wants to arrange those children: ROW or COLUMN. +// If a box represents a view, you can put the view name in the viewName field. +// When determining how to divvy-up the available height (for row children) or width (for column children), we first +// give the boxes with a static `size` the space that they want. Then we apportion +// the remaining space based on the weights of the dynamic boxes (you can't define +// both size and weight at the same time: you gotta pick one). If there are two +// boxes, one with weight 1 and the other with weight 2, the first one gets 33% +// of the available space and the second one gets the remaining 66% + type box struct { // direction decides how the children boxes are laid out. ROW means the children will each form a row i.e. that they will be stacked on top of eachother. direction int // ROW or COLUMN diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index ceb858973..f9178262c 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -71,23 +71,27 @@ func (gui *Gui) onFocus(v *gocui.View) error { return nil } +func (gui *Gui) informationStr() string { + if gui.inDiffMode() { + return utils.ColoredString(fmt.Sprintf("%s %s %s", gui.Tr.SLocalize("showingGitDiff"), "git diff "+gui.diffStr(), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgMagenta) + } else if gui.inFilterMode() { + return utils.ColoredString(fmt.Sprintf("%s '%s' %s", gui.Tr.SLocalize("filteringBy"), gui.State.FilterPath, utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgRed, color.Bold) + } else if len(gui.State.CherryPickedCommits) > 0 { + return utils.ColoredString(fmt.Sprintf("%d commits copied", len(gui.State.CherryPickedCommits)), color.FgCyan) + } else if gui.g.Mouse { + donate := color.New(color.FgMagenta, color.Underline).Sprint(gui.Tr.SLocalize("Donate")) + return donate + " " + gui.Config.GetVersion() + } else { + return gui.Config.GetVersion() + } +} + // layout is called for every screen re-render e.g. when the screen is resized func (gui *Gui) layout(g *gocui.Gui) error { g.Highlight = true width, height := g.Size() - information := gui.Config.GetVersion() - if gui.g.Mouse { - donate := color.New(color.FgMagenta, color.Underline).Sprint(gui.Tr.SLocalize("Donate")) - information = donate + " " + information - } - if gui.inDiffMode() { - information = utils.ColoredString(fmt.Sprintf("%s %s %s", gui.Tr.SLocalize("showingGitDiff"), "git diff "+gui.diffStr(), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgMagenta) - } else if gui.inFilterMode() { - information = utils.ColoredString(fmt.Sprintf("%s '%s' %s", gui.Tr.SLocalize("filteringBy"), gui.State.FilterPath, utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgRed, color.Bold) - } else if len(gui.State.CherryPickedCommits) > 0 { - information = utils.ColoredString(fmt.Sprintf("%d commits copied", len(gui.State.CherryPickedCommits)), color.FgCyan) - } + information := gui.informationStr() minimumHeight := 9 minimumWidth := 10 diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 5f742e9cd..56386c872 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -567,3 +567,8 @@ func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View) return f() } } + +// secondaryViewFocused tells us whether it appears that the secondary view is focused. The view is actually never focused for real: we just swap the main and secondary views and then you're still focused on the main view so that we can give you access to all its keybindings for free. I will probably regret this design decision soon enough. +func (gui *Gui) secondaryViewFocused() bool { + return gui.State.Panels.LineByLine != nil && gui.State.Panels.LineByLine.SecondaryFocused +}