Skip to content

Commit

Permalink
add half and fullscreen modes
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseduffield committed Feb 24, 2020
1 parent 52b5a64 commit fdb543f
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 58 deletions.
2 changes: 2 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ Default path for the config file:
createPatchOptionsMenu: '<c-p>'
nextTab: ']'
prevTab: '['
nextScreenMode: '+'
prevScreenMode: '_'
status:
checkForUpdate: 'u'
recentRepos: '<enter>'
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ keybinding:
createPatchOptionsMenu: '<c-p>'
nextTab: ']'
prevTab: '['
nextScreenMode: '+'
prevScreenMode: '_'
status:
checkForUpdate: 'u'
recentRepos: '<enter>'
Expand Down
180 changes: 122 additions & 58 deletions pkg/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ import (
"github.com/sirupsen/logrus"
)

const (
SCREEN_NORMAL int = iota
SCREEN_HALF
SCREEN_FULL
)

const StartupPopupVersion = 1

// OverlappingEdges determines if panel edges overlap
Expand Down Expand Up @@ -202,6 +208,8 @@ type guiState struct {
IsRefreshingFiles bool
RefreshingFilesMutex sync.Mutex
Searching searchingState
ScreenMode int
SideView *gocui.View
}

// for now the split view will always be on
Expand Down Expand Up @@ -236,6 +244,8 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma
},
Status: &statusPanelState{},
},
ScreenMode: SCREEN_NORMAL,
SideView: nil,
}

gui := &Gui{
Expand All @@ -257,6 +267,18 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma
return gui, nil
}

func (gui *Gui) nextScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.NextIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)

return nil
}

func (gui *Gui) prevScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.PrevIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)

return nil
}

func (gui *Gui) scrollUpView(viewName string) error {
mainView, _ := gui.g.View(viewName)
ox, oy := mainView.Origin()
Expand Down Expand Up @@ -379,6 +401,75 @@ func (gui *Gui) onFocus(v *gocui.View) error {
return nil
}

func (gui *Gui) getViewHeights() map[string]int {
currView := gui.g.CurrentView()
currentCyclebleView := gui.State.PreviousView
if currView != nil {
viewName := currView.Name()
usePreviousView := true
for _, view := range cyclableViews {
if view == viewName {
currentCyclebleView = viewName
usePreviousView = false
break
}
}
if usePreviousView {
currentCyclebleView = gui.State.PreviousView
}
}

// unfortunate result of the fact that these are separate views, have to map explicitly
if currentCyclebleView == "commitFiles" {
currentCyclebleView = "commits"
}

_, height := gui.g.Size()

if gui.State.ScreenMode == SCREEN_FULL || gui.State.ScreenMode == SCREEN_HALF {
vHeights := map[string]int{
"status": 0,
"files": 0,
"branches": 0,
"commits": 0,
"stash": 0,
"options": 0,
}
vHeights[currentCyclebleView] = height - 1
return vHeights
}

usableSpace := height - 7
extraSpace := usableSpace - (usableSpace/3)*3

if height >= 28 {
return map[string]int{
"status": 3,
"files": (usableSpace / 3) + extraSpace,
"branches": usableSpace / 3,
"commits": usableSpace / 3,
"stash": 3,
"options": 1,
}
}

defaultHeight := 3
if height < 21 {
defaultHeight = 1
}
vHeights := map[string]int{
"status": defaultHeight,
"files": defaultHeight,
"branches": defaultHeight,
"commits": defaultHeight,
"stash": defaultHeight,
"options": defaultHeight,
}
vHeights[currentCyclebleView] = height - defaultHeight*4 - 1

return vHeights
}

// 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
Expand All @@ -405,50 +496,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
return nil
}

currView := gui.g.CurrentView()
currentCyclebleView := gui.State.PreviousView
if currView != nil {
viewName := currView.Name()
usePreviouseView := true
for _, view := range cyclableViews {
if view == viewName {
currentCyclebleView = viewName
usePreviouseView = false
break
}
}
if usePreviouseView {
currentCyclebleView = gui.State.PreviousView
}
}

usableSpace := height - 7
extraSpace := usableSpace - (usableSpace/3)*3

vHeights := map[string]int{
"status": 3,
"files": (usableSpace / 3) + extraSpace,
"branches": usableSpace / 3,
"commits": usableSpace / 3,
"stash": 3,
"options": 1,
}

if height < 28 {
defaultHeight := 3
if height < 21 {
defaultHeight = 1
}
vHeights = map[string]int{
"status": defaultHeight,
"files": defaultHeight,
"branches": defaultHeight,
"commits": defaultHeight,
"stash": defaultHeight,
"options": defaultHeight,
}
vHeights[currentCyclebleView] = height - defaultHeight*4 - 1
}
vHeights := gui.getViewHeights()

optionsVersionBoundary := width - max(len(utils.Decolorise(information)), 1)

Expand All @@ -458,29 +506,45 @@ func (gui *Gui) layout(g *gocui.Gui) error {
appStatusOptionsBoundary = len(appStatus) + 2
}

panelSpacing := 1
if OverlappingEdges {
panelSpacing = 0
}

_, _ = g.SetViewOnBottom("limit")
g.DeleteView("limit")

textColor := theme.GocuiDefaultTextColor
leftSideWidth := width / 3
var leftSideWidth int
switch gui.State.ScreenMode {
case SCREEN_NORMAL:
leftSideWidth = width / 3
case SCREEN_HALF:
leftSideWidth = width / 2
case SCREEN_FULL:
currentView := gui.g.CurrentView()
if currentView != nil && currentView.Name() == "main" {
leftSideWidth = 0
} else {
leftSideWidth = width - 1
}
}

panelSplitX := width - 1
mainPanelLeft := leftSideWidth + 1
mainPanelRight := width - 1
secondaryPanelLeft := width - 1
secondaryPanelTop := 0
mainPanelBottom := height - 2
if gui.State.SplitMainPanel {
if width < 220 {
if gui.State.ScreenMode == SCREEN_FULL {
mainPanelLeft = 0
panelSplitX = width/2 - 4
mainPanelRight = panelSplitX
secondaryPanelLeft = panelSplitX + 1
} else if width < 220 {
mainPanelBottom = height/2 - 1
secondaryPanelTop = mainPanelBottom + 1
secondaryPanelLeft = leftSideWidth + 1
} else {
units := 5
leftSideWidth = width / units
mainPanelLeft = leftSideWidth + 1
panelSplitX = (1 + ((units - 1) / 2)) * width / units
mainPanelRight = panelSplitX
secondaryPanelLeft = panelSplitX + 1
Expand Down Expand Up @@ -510,7 +574,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
}

v, err := g.SetView(main, leftSideWidth+panelSpacing, 0, mainPanelRight, mainPanelBottom, gocui.LEFT)
v, err := g.SetView(main, mainPanelLeft, 0, mainPanelRight, mainPanelBottom, gocui.LEFT)
if err != nil {
if err.Error() != "unknown view" {
return err
Expand All @@ -519,16 +583,15 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.Wrap = true
v.FgColor = textColor
v.IgnoreCarriageReturns = true
v.SetOnSelectItem(gui.onSelectItemWrapper(func(selectedLine int) error {
return nil
}))
}

hiddenViewOffset := 0
hiddenViewOffset := 9999

hiddenSecondaryPanelOffset := 0
if !gui.State.SplitMainPanel {
hiddenViewOffset = 9999
hiddenSecondaryPanelOffset = hiddenViewOffset
}
secondaryView, err := g.SetView(secondary, secondaryPanelLeft+hiddenViewOffset, hiddenViewOffset+secondaryPanelTop, width-1+hiddenViewOffset, height-2+hiddenViewOffset, gocui.LEFT)
secondaryView, err := g.SetView(secondary, secondaryPanelLeft+hiddenSecondaryPanelOffset, hiddenSecondaryPanelOffset+secondaryPanelTop, width-1+hiddenSecondaryPanelOffset, height-2+hiddenSecondaryPanelOffset, gocui.LEFT)
if err != nil {
if err.Error() != "unknown view" {
return err
Expand Down Expand Up @@ -577,6 +640,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.Title = gui.Tr.SLocalize("CommitFiles")
v.FgColor = textColor
v.SetOnSelectItem(gui.onSelectItemWrapper(gui.onCommitFilesPanelSearchSelect))
v.ContainsList = true
}

commitsView, err := g.SetViewBeneath("commits", "branches", vHeights["commits"])
Expand Down
14 changes: 14 additions & 0 deletions pkg/gui/keybindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,20 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleEditConfig,
Description: gui.Tr.SLocalize("EditConfig"),
},
{
ViewName: "",
Key: gui.getKey("universal.nextScreenMode"),
Modifier: gocui.ModNone,
Handler: gui.nextScreenMode,
Description: gui.Tr.SLocalize("nextScreenMode"),
},
{
ViewName: "",
Key: gui.getKey("universal.prevScreenMode"),
Modifier: gocui.ModNone,
Handler: gui.prevScreenMode,
Description: gui.Tr.SLocalize("prevScreenMode"),
},
{
ViewName: "status",
Key: gui.getKey("universal.openFile"),
Expand Down
6 changes: 6 additions & 0 deletions pkg/i18n/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,12 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "viewResetToUpstreamOptions",
Other: "view upstream reset options",
}, &i18n.Message{
ID: "nextScreenMode",
Other: "next screen mode (normal/half/fullscreen)",
}, &i18n.Message{
ID: "prevScreenMode",
Other: "prev screen mode",
},
)
}
26 changes: 26 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,29 @@ func ModuloWithWrap(n, max int) int {
return n
}
}

// NextIntInCycle returns the next int in a slice, returning to the first index if we've reached the end
func NextIntInCycle(sl []int, current int) int {
for i, val := range sl {
if val == current {
if i == len(sl)-1 {
return sl[0]
}
return sl[i+1]
}
}
return sl[0]
}

// PrevIntInCycle returns the prev int in a slice, returning to the first index if we've reached the end
func PrevIntInCycle(sl []int, current int) int {
for i, val := range sl {
if val == current {
if i > 0 {
return sl[i-1]
}
return sl[len(sl)-1]
}
}
return sl[len(sl)-1]
}

0 comments on commit fdb543f

Please sign in to comment.