fx/viewport.go
2022-04-17 22:57:12 +02:00

129 lines
2.2 KiB
Go

package main
import (
"math"
)
func (m *model) AtTop() bool {
return m.offset <= 0
}
func (m *model) AtBottom() bool {
return m.offset >= m.maxYOffset()
}
func (m *model) PastBottom() bool {
return m.offset > m.maxYOffset()
}
func (m *model) ScrollPercent() float64 {
if m.height >= len(m.lines) {
return 1.0
}
y := float64(m.offset)
h := float64(m.height)
t := float64(len(m.lines) - 1)
v := y / (t - h)
return math.Max(0.0, math.Min(1.0, v))
}
func (m *model) maxYOffset() int {
return max(0, len(m.lines)-m.height)
}
func (m *model) visibleLines() (lines []string) {
if len(m.lines) > 0 {
top := max(0, m.offset)
bottom := clamp(m.offset+m.height, top, len(m.lines))
lines = m.lines[top:bottom]
}
return lines
}
func (m *model) SetOffset(n int) {
m.offset = clamp(n, 0, m.maxYOffset())
}
func (m *model) ViewDown() {
if m.AtBottom() {
return
}
m.SetOffset(m.offset + m.height)
}
func (m *model) ViewUp() {
if m.AtTop() {
return
}
m.SetOffset(m.offset - m.height)
}
func (m *model) HalfViewDown() {
if m.AtBottom() {
return
}
m.SetOffset(m.offset + m.height/2)
}
func (m *model) HalfViewUp() {
if m.AtTop() {
return
}
m.SetOffset(m.offset - m.height/2)
}
func (m *model) LineDown(n int) {
if m.AtBottom() || n == 0 {
return
}
// Make sure the Number of lines by which we're going to scroll isn't
// greater than the Number of lines we actually have left before we reach
// the bottom.
m.SetOffset(m.offset + n)
}
func (m *model) LineUp(n int) {
if m.AtTop() || n == 0 {
return
}
// Make sure the Number of lines by which we're going to scroll isn't
// greater than the Number of lines we are from the top.
m.SetOffset(m.offset - n)
}
func (m *model) GotoTop() {
if m.AtTop() {
return
}
m.SetOffset(0)
}
func (m *model) GotoBottom() {
m.SetOffset(m.maxYOffset())
}
func (m *model) scrollDownToCursor() {
at := m.cursorLineNumber()
if m.offset <= at { // cursor is lower
m.LineDown(max(0, at-(m.offset+m.height-1))) // minus one is due to cursorLineNumber() starts from 0
} else {
m.SetOffset(at)
}
}
func (m *model) scrollUpToCursor() {
at := m.cursorLineNumber()
if at < m.offset+m.height { // cursor is above
m.LineUp(max(0, m.offset-at))
} else {
m.SetOffset(at)
}
}