Skip to content

Commit 42e4232

Browse files
authored
Keep cursor at top/bottom when navigating by page (#5019)
When pressing '.' (next page) or ',' (previous page), the selection now stays at the bottom or top of the viewport respectively, instead of being centered which caused items to scroll off. (If the selection is not already on the last/first line of the view, '.'/',' moves it there without scrolling.) This implements a special case for page navigation as suggested by the maintainer in issue #5017, keeping the cursor position consistent with user expectations for page-based navigation. Fixes #5017
2 parents 9c0cbd8 + 8114943 commit 42e4232

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

pkg/gui/controllers/list_controller.go

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
101101
rangeAfter := list.IsSelectingRange()
102102
after := list.GetSelectedLineIdx()
103103

104-
if err := self.pushContextIfNotFocused(); err != nil {
105-
return err
106-
}
107-
108104
// doing this check so that if we're holding the up key at the start of the list
109105
// we're not constantly re-rendering the main view.
110106
cursorMoved := before != after
@@ -127,11 +123,59 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
127123
}
128124

129125
func (self *ListController) HandlePrevPage() error {
130-
return self.handleLineChange(-self.context.GetViewTrait().PageDelta())
126+
return self.handlePageChange(-self.context.GetViewTrait().PageDelta())
131127
}
132128

133129
func (self *ListController) HandleNextPage() error {
134-
return self.handleLineChange(self.context.GetViewTrait().PageDelta())
130+
return self.handlePageChange(self.context.GetViewTrait().PageDelta())
131+
}
132+
133+
func (self *ListController) handlePageChange(delta int) error {
134+
list := self.context.GetList()
135+
view := self.context.GetViewTrait()
136+
137+
before := list.GetSelectedLineIdx()
138+
139+
viewPortStart, viewPortHeight := view.ViewPortYBounds()
140+
beforeViewIdx := self.context.ModelIndexToViewIndex(before)
141+
afterViewIdx := beforeViewIdx + delta
142+
newModelIndex := self.context.ViewIndexToModelIndex(afterViewIdx)
143+
144+
if delta < 0 {
145+
// Previous page: keep selection at top of viewport
146+
indexAtTopOfPage := self.context.ViewIndexToModelIndex(viewPortStart)
147+
if before != indexAtTopOfPage {
148+
// If the selection isn't already at the top of the page, move it there without scrolling
149+
list.MoveSelectedLine(indexAtTopOfPage - before)
150+
} else {
151+
// Otherwise, move the selection by one page and scroll
152+
list.MoveSelectedLine(newModelIndex - before)
153+
154+
linesToScroll := afterViewIdx - viewPortStart
155+
if linesToScroll < 0 {
156+
view.ScrollUp(-linesToScroll)
157+
}
158+
}
159+
} else {
160+
// Next page: keep selection at bottom of viewport
161+
indexAtBottomOfPage := self.context.ViewIndexToModelIndex(viewPortStart + viewPortHeight - 1)
162+
if before != indexAtBottomOfPage {
163+
// If the selection isn't already at the bottom of the page, move it there without scrolling
164+
list.MoveSelectedLine(indexAtBottomOfPage - before)
165+
} else {
166+
// Otherwise, move the selection by one page and scroll
167+
list.MoveSelectedLine(newModelIndex - before)
168+
169+
linesToScroll := afterViewIdx - (viewPortStart + viewPortHeight - 1)
170+
if linesToScroll > 0 {
171+
view.ScrollDown(linesToScroll)
172+
}
173+
}
174+
}
175+
176+
self.context.HandleFocus(types.OnFocusOpts{})
177+
178+
return nil
135179
}
136180

137181
func (self *ListController) HandleGotoTop() error {

0 commit comments

Comments
 (0)