Files
filepass/internal/tui/scroll.go
2026-04-18 04:31:10 +09:00

89 lines
1.4 KiB
Go

package tui
// visibleRange returns [start, end) indices of rows that should be rendered.
func visibleRange(total, selected, scrollOff, viewHeight int) (int, int) {
if total <= 0 {
return 0, 0
}
maxVis := viewHeight
if maxVis <= 0 {
maxVis = total // unconstrained
}
if maxVis >= total {
return 0, total
}
// Reserve lines for scroll indicators.
hasAbove := scrollOff > 0
hasBelow := scrollOff+maxVis < total
if hasAbove {
maxVis--
}
if hasBelow {
maxVis--
}
if maxVis < 1 {
maxVis = 1
}
start := scrollOff
end := start + maxVis
if selected < start {
start = selected
end = start + maxVis
}
if selected >= end {
end = selected + 1
start = end - maxVis
}
if start < 0 {
start = 0
end = min(maxVis, total)
}
if end > total {
end = total
start = max(0, end-maxVis)
}
return start, end
}
// syncScroll adjusts scrollOff so selected stays inside the viewport.
func syncScroll(selected, total, viewHeight, scrollOff int) int {
if total <= 0 {
return 0
}
maxVis := viewHeight
if maxVis <= 0 || maxVis >= total {
return 0
}
if selected < 0 {
selected = 0
}
if selected >= total {
selected = total - 1
}
if scrollOff < 0 {
scrollOff = 0
}
if scrollOff > total-1 {
scrollOff = total - 1
}
if selected < scrollOff {
scrollOff = selected
}
if selected >= scrollOff+maxVis {
scrollOff = selected - maxVis + 1
}
if scrollOff < 0 {
scrollOff = 0
}
return scrollOff
}