2022-01-29 10:09:20 +02:00
package context
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type ListContextTrait struct {
base types . IBaseContext
2022-01-30 05:46:46 +02:00
list types . IList
2022-01-29 10:09:20 +02:00
viewTrait * ViewTrait
takeFocus func ( ) error
GetDisplayStrings func ( startIdx int , length int ) [ ] [ ] string
OnFocus func ( ... types . OnFocusOpts ) error
OnRenderToMain func ( ... types . OnFocusOpts ) error
OnFocusLost func ( ) error
// if this is true, we'll call GetDisplayStrings for just the visible part of the
// view and re-render that. This is useful when you need to render different
// content based on the selection (e.g. for showing the selected commit)
RenderSelection bool
c * types . ControllerCommon
}
func ( self * ListContextTrait ) GetPanelState ( ) types . IListPanelState {
2022-01-30 05:46:46 +02:00
return self . list
2022-01-29 10:09:20 +02:00
}
func ( self * ListContextTrait ) FocusLine ( ) {
// we need a way of knowing whether we've rendered to the view yet.
2022-01-30 05:46:46 +02:00
self . viewTrait . FocusPoint ( self . list . GetSelectedLineIdx ( ) )
2022-01-29 10:09:20 +02:00
if self . RenderSelection {
min , max := self . viewTrait . ViewPortYBounds ( )
displayStrings := self . GetDisplayStrings ( min , max )
content := utils . RenderDisplayStrings ( displayStrings )
self . viewTrait . SetViewPortContent ( content )
}
2022-01-30 05:46:46 +02:00
self . viewTrait . SetFooter ( formatListFooter ( self . list . GetSelectedLineIdx ( ) , self . list . GetItemsLength ( ) ) )
2022-01-29 10:09:20 +02:00
}
func formatListFooter ( selectedLineIdx int , length int ) string {
return fmt . Sprintf ( "%d of %d" , selectedLineIdx + 1 , length )
}
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
func ( self * ListContextTrait ) HandleRender ( ) error {
if self . GetDisplayStrings != nil {
2022-01-30 05:46:46 +02:00
self . list . RefreshSelectedIdx ( )
content := utils . RenderDisplayStrings ( self . GetDisplayStrings ( 0 , self . list . GetItemsLength ( ) ) )
2022-01-29 10:09:20 +02:00
self . viewTrait . SetContent ( content )
self . c . Render ( )
}
return nil
}
func ( self * ListContextTrait ) HandleFocusLost ( ) error {
if self . OnFocusLost != nil {
return self . OnFocusLost ( )
}
self . viewTrait . SetOriginX ( 0 )
return nil
}
func ( self * ListContextTrait ) HandleFocus ( opts ... types . OnFocusOpts ) error {
self . FocusLine ( )
if self . OnFocus != nil {
if err := self . OnFocus ( opts ... ) ; err != nil {
return err
}
}
if self . OnRenderToMain != nil {
if err := self . OnRenderToMain ( opts ... ) ; err != nil {
return err
}
}
return nil
}
func ( self * ListContextTrait ) HandlePrevLine ( ) error {
return self . handleLineChange ( - 1 )
}
func ( self * ListContextTrait ) HandleNextLine ( ) error {
return self . handleLineChange ( 1 )
}
func ( self * ListContextTrait ) HandleScrollLeft ( ) error {
return self . scroll ( self . viewTrait . ScrollLeft )
}
func ( self * ListContextTrait ) HandleScrollRight ( ) error {
return self . scroll ( self . viewTrait . ScrollRight )
}
func ( self * ListContextTrait ) scroll ( scrollFunc func ( ) ) error {
scrollFunc ( )
return self . HandleFocus ( )
}
func ( self * ListContextTrait ) handleLineChange ( change int ) error {
2022-01-30 05:46:46 +02:00
before := self . list . GetSelectedLineIdx ( )
self . list . MoveSelectedLine ( change )
after := self . list . GetSelectedLineIdx ( )
2022-01-29 10:09:20 +02:00
2022-01-30 05:46:46 +02:00
// 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.
2022-01-29 10:09:20 +02:00
if before != after {
return self . HandleFocus ( )
}
return nil
}
func ( self * ListContextTrait ) HandlePrevPage ( ) error {
return self . handleLineChange ( - self . viewTrait . PageDelta ( ) )
}
func ( self * ListContextTrait ) HandleNextPage ( ) error {
return self . handleLineChange ( self . viewTrait . PageDelta ( ) )
}
func ( self * ListContextTrait ) HandleGotoTop ( ) error {
2022-01-30 05:46:46 +02:00
return self . handleLineChange ( - self . list . GetItemsLength ( ) )
2022-01-29 10:09:20 +02:00
}
func ( self * ListContextTrait ) HandleGotoBottom ( ) error {
2022-01-30 05:46:46 +02:00
return self . handleLineChange ( self . list . GetItemsLength ( ) )
2022-01-29 10:09:20 +02:00
}
func ( self * ListContextTrait ) HandleClick ( onClick func ( ) error ) error {
2022-01-30 05:46:46 +02:00
prevSelectedLineIdx := self . list . GetSelectedLineIdx ( )
2022-01-29 10:09:20 +02:00
// because we're handling a click, we need to determine the new line idx based
// on the view itself.
newSelectedLineIdx := self . viewTrait . SelectedLineIdx ( )
currentContextKey := self . c . CurrentContext ( ) . GetKey ( )
alreadyFocused := currentContextKey == self . base . GetKey ( )
// we need to focus the view
if ! alreadyFocused {
if err := self . takeFocus ( ) ; err != nil {
return err
}
}
2022-01-30 05:46:46 +02:00
if newSelectedLineIdx > self . list . GetItemsLength ( ) - 1 {
2022-01-29 10:09:20 +02:00
return nil
}
2022-01-30 05:46:46 +02:00
self . list . SetSelectedLineIdx ( newSelectedLineIdx )
2022-01-29 10:09:20 +02:00
if prevSelectedLineIdx == newSelectedLineIdx && alreadyFocused && onClick != nil {
return onClick ( )
}
return self . HandleFocus ( )
}
func ( self * ListContextTrait ) OnSearchSelect ( selectedLineIdx int ) error {
2022-01-30 05:46:46 +02:00
self . list . SetSelectedLineIdx ( selectedLineIdx )
2022-01-29 10:09:20 +02:00
return self . HandleFocus ( )
}
func ( self * ListContextTrait ) HandleRenderToMain ( ) error {
if self . OnRenderToMain != nil {
return self . OnRenderToMain ( )
}
return nil
}
2022-02-05 01:31:07 +02:00
func ( self * ListContextTrait ) keybindings ( opts types . KeybindingsOpts ) [ ] * types . Binding {
2022-01-29 10:09:20 +02:00
return [ ] * types . Binding {
2022-02-05 01:31:07 +02:00
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . PrevItemAlt ) , Modifier : gocui . ModNone , Handler : self . HandlePrevLine } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . PrevItem ) , Modifier : gocui . ModNone , Handler : self . HandlePrevLine } ,
2022-01-29 10:09:20 +02:00
{ Tag : "navigation" , Key : gocui . MouseWheelUp , Modifier : gocui . ModNone , Handler : self . HandlePrevLine } ,
2022-02-05 01:31:07 +02:00
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . NextItemAlt ) , Modifier : gocui . ModNone , Handler : self . HandleNextLine } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . NextItem ) , Modifier : gocui . ModNone , Handler : self . HandleNextLine } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . PrevPage ) , Modifier : gocui . ModNone , Handler : self . HandlePrevPage , Description : self . c . Tr . LcPrevPage } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . NextPage ) , Modifier : gocui . ModNone , Handler : self . HandleNextPage , Description : self . c . Tr . LcNextPage } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . GotoTop ) , Modifier : gocui . ModNone , Handler : self . HandleGotoTop , Description : self . c . Tr . LcGotoTop } ,
2022-01-29 10:09:20 +02:00
{ Key : gocui . MouseLeft , Modifier : gocui . ModNone , Handler : func ( ) error { return self . HandleClick ( nil ) } } ,
{ Tag : "navigation" , Key : gocui . MouseWheelDown , Modifier : gocui . ModNone , Handler : self . HandleNextLine } ,
2022-02-05 01:31:07 +02:00
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . ScrollLeft ) , Modifier : gocui . ModNone , Handler : self . HandleScrollLeft } ,
{ Tag : "navigation" , Key : opts . GetKey ( opts . Config . Universal . ScrollRight ) , Modifier : gocui . ModNone , Handler : self . HandleScrollRight } ,
2022-01-29 10:09:20 +02:00
{
2022-02-05 01:31:07 +02:00
Key : opts . GetKey ( opts . Config . Universal . StartSearch ) ,
2022-01-29 10:09:20 +02:00
Handler : func ( ) error { self . c . OpenSearch ( ) ; return nil } ,
Description : self . c . Tr . LcStartSearch ,
Tag : "navigation" ,
} ,
{
2022-02-05 01:31:07 +02:00
Key : opts . GetKey ( opts . Config . Universal . GotoBottom ) ,
2022-01-29 10:09:20 +02:00
Description : self . c . Tr . LcGotoBottom ,
Handler : self . HandleGotoBottom ,
Tag : "navigation" ,
} ,
}
}