mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-11-22 04:42:37 +03:00
The method is only called from keybinding handlers, so the view must be focused already, otherwise the binding wouldn't have been dispatched to it.
241 lines
7.7 KiB
Go
241 lines
7.7 KiB
Go
package controllers
|
|
|
|
import (
|
|
"github.com/jesseduffield/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
type ListControllerFactory struct {
|
|
c *ControllerCommon
|
|
}
|
|
|
|
func NewListControllerFactory(c *ControllerCommon) *ListControllerFactory {
|
|
return &ListControllerFactory{
|
|
c: c,
|
|
}
|
|
}
|
|
|
|
func (self *ListControllerFactory) Create(context types.IListContext) *ListController {
|
|
return &ListController{
|
|
baseController: baseController{},
|
|
c: self.c,
|
|
context: context,
|
|
}
|
|
}
|
|
|
|
type ListController struct {
|
|
baseController
|
|
c *ControllerCommon
|
|
|
|
context types.IListContext
|
|
}
|
|
|
|
func (self *ListController) Context() types.Context {
|
|
return self.context
|
|
}
|
|
|
|
func (self *ListController) HandlePrevLine() error {
|
|
return self.handleLineChange(-1)
|
|
}
|
|
|
|
func (self *ListController) HandleNextLine() error {
|
|
return self.handleLineChange(1)
|
|
}
|
|
|
|
func (self *ListController) HandleScrollLeft() error {
|
|
return self.scrollHorizontal(self.context.GetViewTrait().ScrollLeft)
|
|
}
|
|
|
|
func (self *ListController) HandleScrollRight() error {
|
|
return self.scrollHorizontal(self.context.GetViewTrait().ScrollRight)
|
|
}
|
|
|
|
func (self *ListController) HandleScrollUp() error {
|
|
scrollHeight := self.c.UserConfig().Gui.ScrollHeight
|
|
self.context.GetViewTrait().ScrollUp(scrollHeight)
|
|
if self.context.RenderOnlyVisibleLines() {
|
|
self.context.HandleRender()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) HandleScrollDown() error {
|
|
scrollHeight := self.c.UserConfig().Gui.ScrollHeight
|
|
self.context.GetViewTrait().ScrollDown(scrollHeight)
|
|
if self.context.RenderOnlyVisibleLines() {
|
|
self.context.HandleRender()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) scrollHorizontal(scrollFunc func()) error {
|
|
scrollFunc()
|
|
|
|
self.context.HandleFocus(types.OnFocusOpts{})
|
|
if self.context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES {
|
|
self.context.HandleRender()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) handleLineChange(change int) error {
|
|
return self.handleLineChangeAux(
|
|
self.context.GetList().MoveSelectedLine, change,
|
|
)
|
|
}
|
|
|
|
func (self *ListController) HandleRangeSelectChange(change int) error {
|
|
return self.handleLineChangeAux(
|
|
self.context.GetList().ExpandNonStickyRange, change,
|
|
)
|
|
}
|
|
|
|
func (self *ListController) handleLineChangeAux(f func(int), change int) error {
|
|
list := self.context.GetList()
|
|
|
|
rangeBefore := list.IsSelectingRange()
|
|
before := list.GetSelectedLineIdx()
|
|
f(change)
|
|
rangeAfter := list.IsSelectingRange()
|
|
after := list.GetSelectedLineIdx()
|
|
|
|
// doing this check so that if we're holding the up key at the start of the list
|
|
// we're not constantly re-rendering the main view.
|
|
cursorMoved := before != after
|
|
if cursorMoved {
|
|
switch change {
|
|
case -1:
|
|
checkScrollUp(self.context.GetViewTrait(), self.c.UserConfig(),
|
|
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
|
case 1:
|
|
checkScrollDown(self.context.GetViewTrait(), self.c.UserConfig(),
|
|
self.context.ModelIndexToViewIndex(before), self.context.ModelIndexToViewIndex(after))
|
|
}
|
|
}
|
|
|
|
if cursorMoved || rangeBefore != rangeAfter {
|
|
self.context.HandleFocus(types.OnFocusOpts{})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) HandlePrevPage() error {
|
|
return self.handleLineChange(-self.context.GetViewTrait().PageDelta())
|
|
}
|
|
|
|
func (self *ListController) HandleNextPage() error {
|
|
return self.handleLineChange(self.context.GetViewTrait().PageDelta())
|
|
}
|
|
|
|
func (self *ListController) HandleGotoTop() error {
|
|
return self.handleLineChange(-self.context.GetList().Len())
|
|
}
|
|
|
|
func (self *ListController) HandleGotoBottom() error {
|
|
bottomIdx := self.context.IndexForGotoBottom()
|
|
change := bottomIdx - self.context.GetList().GetSelectedLineIdx()
|
|
return self.handleLineChange(change)
|
|
}
|
|
|
|
func (self *ListController) HandleToggleRangeSelect() error {
|
|
list := self.context.GetList()
|
|
|
|
list.ToggleStickyRange()
|
|
|
|
self.context.HandleFocus(types.OnFocusOpts{})
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) HandleRangeSelectDown() error {
|
|
return self.HandleRangeSelectChange(1)
|
|
}
|
|
|
|
func (self *ListController) HandleRangeSelectUp() error {
|
|
return self.HandleRangeSelectChange(-1)
|
|
}
|
|
|
|
func (self *ListController) HandleClick(opts gocui.ViewMouseBindingOpts) error {
|
|
newSelectedLineIdx := self.context.ViewIndexToModelIndex(opts.Y)
|
|
alreadyFocused := self.isFocused()
|
|
|
|
if err := self.pushContextIfNotFocused(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if newSelectedLineIdx > self.context.GetList().Len()-1 {
|
|
return nil
|
|
}
|
|
|
|
self.context.GetList().SetSelection(newSelectedLineIdx)
|
|
|
|
if opts.IsDoubleClick && alreadyFocused && self.context.GetOnClick() != nil {
|
|
return self.context.GetOnClick()()
|
|
}
|
|
self.context.HandleFocus(types.OnFocusOpts{})
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) pushContextIfNotFocused() error {
|
|
if !self.isFocused() {
|
|
self.c.Context().Push(self.context, types.OnFocusOpts{})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *ListController) isFocused() bool {
|
|
return self.c.Context().Current().GetKey() == self.context.GetKey()
|
|
}
|
|
|
|
func (self *ListController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
|
bindings := []*types.Binding{
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Handler: self.HandlePrevLine},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Handler: self.HandlePrevLine},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Handler: self.HandleNextLine},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItem), Handler: self.HandleNextLine},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevPage), Handler: self.HandlePrevPage, Description: self.c.Tr.PrevPage},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextPage), Handler: self.HandleNextPage, Description: self.c.Tr.NextPage},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoTop), Handler: self.HandleGotoTop, Description: self.c.Tr.GotoTop, Alternative: "<home>"},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Handler: self.HandleGotoBottom, Description: self.c.Tr.GotoBottom, Alternative: "<end>"},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoTopAlt), Handler: self.HandleGotoTop},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottomAlt), Handler: self.HandleGotoBottom},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollLeft), Handler: self.HandleScrollLeft},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollRight), Handler: self.HandleScrollRight},
|
|
}
|
|
|
|
if self.context.RangeSelectEnabled() {
|
|
bindings = append(bindings,
|
|
[]*types.Binding{
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ToggleRangeSelect), Handler: self.HandleToggleRangeSelect, Description: self.c.Tr.ToggleRangeSelect},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.RangeSelectDown), Handler: self.HandleRangeSelectDown, Description: self.c.Tr.RangeSelectDown},
|
|
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.RangeSelectUp), Handler: self.HandleRangeSelectUp, Description: self.c.Tr.RangeSelectUp},
|
|
}...,
|
|
)
|
|
}
|
|
|
|
return bindings
|
|
}
|
|
|
|
func (self *ListController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
|
return []*gocui.ViewMouseBinding{
|
|
{
|
|
ViewName: self.context.GetViewName(),
|
|
Key: gocui.MouseWheelUp,
|
|
Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandleScrollUp() },
|
|
},
|
|
{
|
|
ViewName: self.context.GetViewName(),
|
|
Key: gocui.MouseLeft,
|
|
Handler: func(opts gocui.ViewMouseBindingOpts) error { return self.HandleClick(opts) },
|
|
},
|
|
{
|
|
ViewName: self.context.GetViewName(),
|
|
Key: gocui.MouseWheelDown,
|
|
Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandleScrollDown() },
|
|
},
|
|
}
|
|
}
|