forked from Archives/fx
129 lines
2.2 KiB
Go
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)
|
|
}
|
|
}
|