package tk
import (
)
type TextView interface {
Widget
ScrollBy(delta int)
MutateState(f func(*TextViewState))
CopyState() TextViewState
}
type TextViewSpec struct {
Bindings Bindings
Scrollable bool
State TextViewState
}
type TextViewState struct {
Lines []string
First int
}
type textView struct {
StateMutex sync.RWMutex
TextViewSpec
}
func ( TextViewSpec) TextView {
if .Bindings == nil {
.Bindings = DummyBindings{}
}
return &textView{TextViewSpec: }
}
func ( *textView) (, int) *term.Buffer {
, := .getStateForRender()
:= .Scrollable && ( > 0 || + < len())
:=
if {
--
}
:= term.NewBufferBuilder()
for := ; < + && < len(); ++ {
if > {
.Newline()
}
.Write(wcwidth.Trim([], ))
}
:= .Buffer()
if {
:= VScrollbar{
Total: len(), Low: , High: + }
.ExtendRight(.Render(1, ))
}
return
}
func ( *textView) ( int) ( []string, int) {
.MutateState(func( *TextViewState) {
if .First > len(.Lines)- && len(.Lines)- >= 0 {
.First = len(.Lines) -
}
, = .Lines, .First
})
return
}
func ( *textView) ( term.Event) bool {
if .Bindings.Handle(, ) {
return true
}
if .Scrollable {
switch {
case term.K(ui.Up):
.ScrollBy(-1)
return true
case term.K(ui.Down):
.ScrollBy(1)
return true
}
}
return false
}
func ( *textView) ( int) {
.MutateState(func( *TextViewState) {
.First +=
if .First < 0 {
.First = 0
}
if .First >= len(.Lines) {
.First = len(.Lines) - 1
}
})
}
func ( *textView) ( func(*TextViewState)) {
.StateMutex.Lock()
defer .StateMutex.Unlock()
(&.State)
}
func ( *textView) () TextViewState {
.StateMutex.RLock()
defer .StateMutex.RUnlock()
return .State
}