1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-14 11:23:09 +02:00
lazygit/pkg/gui/controllers/scroll_off_margin.go
Stefan Haller 341b9725d4 Add ScrollOffMargin user config
When set to a non-zero value, views will scroll when the selection gets this
close to the top or bottom of the view.
2023-08-15 11:40:40 +02:00

71 lines
2.9 KiB
Go

package controllers
import (
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// To be called after pressing up-arrow; checks whether the cursor entered the
// top scroll-off margin, and so the view needs to be scrolled up one line
func checkScrollUp(view types.IViewTrait, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) {
viewPortStart, viewPortHeight := view.ViewPortYBounds()
linesToScroll := calculateLinesToScrollUp(
viewPortStart, viewPortHeight, scrollOffMargin, lineIdxBefore, lineIdxAfter)
if linesToScroll != 0 {
view.ScrollUp(linesToScroll)
}
}
// To be called after pressing down-arrow; checks whether the cursor entered the
// bottom scroll-off margin, and so the view needs to be scrolled down one line
func checkScrollDown(view types.IViewTrait, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) {
viewPortStart, viewPortHeight := view.ViewPortYBounds()
linesToScroll := calculateLinesToScrollDown(
viewPortStart, viewPortHeight, scrollOffMargin, lineIdxBefore, lineIdxAfter)
if linesToScroll != 0 {
view.ScrollDown(linesToScroll)
}
}
func calculateLinesToScrollUp(viewPortStart int, viewPortHeight int, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) int {
// Cap the margin to half the view height. This allows setting the config to
// a very large value to keep the cursor always in the middle of the screen.
// Use +.5 so that if the height is even, the top margin is one line higher
// than the bottom margin.
scrollOffMargin = utils.Min(scrollOffMargin, int((float64(viewPortHeight)+.5)/2))
// Scroll only if the "before" position was visible (this could be false if
// the scroll wheel was used to scroll the selected line out of view) ...
if lineIdxBefore >= viewPortStart && lineIdxBefore < viewPortStart+viewPortHeight {
marginEnd := viewPortStart + scrollOffMargin
// ... and the "after" position is within the top margin (or before it)
if lineIdxAfter < marginEnd {
return marginEnd - lineIdxAfter
}
}
return 0
}
func calculateLinesToScrollDown(viewPortStart int, viewPortHeight int, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) int {
// Cap the margin to half the view height. This allows setting the config to
// a very large value to keep the cursor always in the middle of the screen.
// Use -.5 so that if the height is even, the bottom margin is one line lower
// than the top margin.
scrollOffMargin = utils.Min(scrollOffMargin, int((float64(viewPortHeight)-.5)/2))
// Scroll only if the "before" position was visible (this could be false if
// the scroll wheel was used to scroll the selected line out of view) ...
if lineIdxBefore >= viewPortStart && lineIdxBefore < viewPortStart+viewPortHeight {
marginStart := viewPortStart + viewPortHeight - scrollOffMargin - 1
// ... and the "after" position is within the bottom margin (or after it)
if lineIdxAfter > marginStart {
return lineIdxAfter - marginStart
}
}
return 0
}