Scroll views up if needed to show all their content

There are many situations where this can arise. Some examples are:
- the terminal window is small, and you are showing a view that shows more
  content than fits into the view port, and the view is scrolled all the way
  down; now you resize the terminal window to a taller size. Previously, the
  scroll position of the view would stay the same, so it would add blank space
  at the bottom; now it will scroll to fill that blank space with content
- expandFocusedSidePanel is on, you go to the bottom of a list view, now switch
  to a different panel, then scroll that (now unfocused) panel all the way down
  with the scroll wheel; now you focus that panel again. It becomes larger
  because of the accordion behavior, but would show blank space at the bottom.

And probably others that I can't remember right now. I only remember that I
always found it confusing to look at a view that had blank space at the bottom
even though it had more content to scroll into view.
This commit is contained in:
Stefan Haller 2024-08-18 20:51:38 +02:00
parent 0aa351443f
commit 6114f69ee5
4 changed files with 28 additions and 0 deletions

View file

@ -212,3 +212,7 @@ func (self *BaseContext) NeedsRerenderOnHeightChange() bool {
func (self *BaseContext) Title() string {
return ""
}
func (self *BaseContext) TotalContentHeight() int {
return self.view.ViewLinesHeight()
}

View file

@ -140,3 +140,11 @@ func (self *ListContextTrait) RangeSelectEnabled() bool {
func (self *ListContextTrait) RenderOnlyVisibleLines() bool {
return self.renderOnlyVisibleLines
}
func (self *ListContextTrait) TotalContentHeight() int {
result := self.list.Len()
if self.getNonModelItems != nil {
result += len(self.getNonModelItems())
}
return result
}

View file

@ -73,6 +73,19 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
mustRerender := false
newHeight := dimensionsObj.Y1 - dimensionsObj.Y0 + 2*frameOffset
maxOriginY := context.TotalContentHeight()
if !view.CanScrollPastBottom {
maxOriginY -= newHeight - 1
}
if oldOriginY := view.OriginY(); oldOriginY > maxOriginY {
view.ScrollUp(oldOriginY - maxOriginY)
// the view might not have scrolled actually (if it was at the limit
// already), so we need to check if it did
if oldOriginY != view.OriginY() && context.NeedsRerenderOnHeightChange() {
mustRerender = true
}
}
if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES {
// view.Width() returns the width -1 for some reason
oldWidth := view.Width() + 1

View file

@ -71,6 +71,9 @@ type IBaseContext interface {
// determined independently.
HasControlledBounds() bool
// the total height of the content that the view is currently showing
TotalContentHeight() int
// to what extent the view needs to be rerendered when its width changes
NeedsRerenderOnWidthChange() NeedsRerenderOnWidthChangeLevel