forked from tslocum/cview
Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
cd2edc8176 |
|
@ -63,6 +63,7 @@ func main() {
|
|||
TextView1,
|
||||
TextView2,
|
||||
InputField,
|
||||
TextArea,
|
||||
Slider,
|
||||
Form,
|
||||
Table,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/cview"
|
||||
)
|
||||
|
||||
// TextArea demonstrates the TextArea.
|
||||
func TextArea(nextSlide func()) (title string, info string, content cview.Primitive) {
|
||||
t := cview.NewTextArea()
|
||||
t.SetBorder(true)
|
||||
t.SetTitle("Multi-line text input")
|
||||
return "TextArea", "", Center(44, 16, t)
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package cview
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
// TextArea is a multi-line text input.
|
||||
type TextArea struct {
|
||||
*TextView
|
||||
|
||||
setFocus func(Primitive)
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// NewTextArea returns a new TextArea object.
|
||||
func NewTextArea() *TextArea {
|
||||
t := &TextArea{
|
||||
TextView: NewTextView(),
|
||||
}
|
||||
|
||||
t.TextView.SetShowCursor(true)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (t *TextArea) Draw(screen tcell.Screen) {
|
||||
if !t.GetVisible() {
|
||||
return
|
||||
}
|
||||
|
||||
t.Box.Draw(screen)
|
||||
t.TextView.Draw(screen)
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
func (t *TextArea) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
||||
if t.setFocus == nil {
|
||||
t.setFocus = setFocus
|
||||
}
|
||||
|
||||
add := func(r rune) bool {
|
||||
t.Write([]byte(string(r)))
|
||||
return true
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyRune {
|
||||
add(event.Rune())
|
||||
return
|
||||
} else if event.Key() == tcell.KeyEnter {
|
||||
add('\n')
|
||||
return
|
||||
} else if event.Key() == tcell.KeyBackspace2 {
|
||||
b := t.GetBytes(false)
|
||||
t.SetBytes(b[:len(b)-1])
|
||||
return
|
||||
}
|
||||
|
||||
t.TextView.InputHandler()(event, setFocus)
|
||||
})
|
||||
}
|
||||
|
||||
// MouseHandler returns the mouse handler for this primitive.
|
||||
func (t *TextArea) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
return t.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
if t.setFocus == nil {
|
||||
t.setFocus = setFocus
|
||||
}
|
||||
|
||||
x, y := event.Position()
|
||||
if !t.InRect(x, y) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return t.TextView.MouseHandler()(action, event, setFocus)
|
||||
})
|
||||
}
|
43
textview.go
43
textview.go
|
@ -196,6 +196,9 @@ type TextView struct {
|
|||
// If set to true, region tags can be used to define regions.
|
||||
regions bool
|
||||
|
||||
// If set to true, a cursor is drawn.
|
||||
showCursor bool
|
||||
|
||||
// A temporary flag which, when true, will automatically bring the current
|
||||
// highlight(s) into the visible screen.
|
||||
scrollToHighlights bool
|
||||
|
@ -731,6 +734,14 @@ func (t *TextView) GetRegionText(regionID string) string {
|
|||
return escapePattern.ReplaceAllString(buffer.String(), `[$1$2]`)
|
||||
}
|
||||
|
||||
// SetShowCursor sets a flag controlling whether a cursor is drawn.
|
||||
func (t *TextView) SetShowCursor(showCursor bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.showCursor = showCursor
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (t *TextView) Focus(delegate func(p Primitive)) {
|
||||
t.Lock()
|
||||
|
@ -818,7 +829,7 @@ func (t *TextView) write(p []byte) (n int, err error) {
|
|||
return len(p), nil
|
||||
}
|
||||
|
||||
// SetWrapWidth set the maximum width of lines when wrapping is enabled.
|
||||
// SetWrapWidth sets the maximum width of lines when wrapping is enabled.
|
||||
// When set to 0 the width of the TextView is used.
|
||||
func (t *TextView) SetWrapWidth(width int) {
|
||||
t.Lock()
|
||||
|
@ -827,7 +838,7 @@ func (t *TextView) SetWrapWidth(width int) {
|
|||
t.wrapWidth = width
|
||||
}
|
||||
|
||||
// SetReindexBuffer set a flag controlling whether the buffer is reindexed when
|
||||
// SetReindexBuffer sets a flag controlling whether the buffer is reindexed when
|
||||
// it is modified. This improves the performance of TextViews whose contents
|
||||
// always have line-breaks in the same location. This must be called after the
|
||||
// buffer has been indexed.
|
||||
|
@ -1022,9 +1033,18 @@ func (t *TextView) reindexBuffer(width int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *TextView) updateCursorPos(screen tcell.Screen, x int, y int) {
|
||||
if !t.showCursor || x == -1 {
|
||||
screen.HideCursor()
|
||||
return
|
||||
}
|
||||
screen.ShowCursor(x, y)
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (t *TextView) Draw(screen tcell.Screen) {
|
||||
if !t.GetVisible() {
|
||||
t.updateCursorPos(screen, -1, -1)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1036,6 +1056,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
// Get the available size.
|
||||
x, y, width, height := t.GetInnerRect()
|
||||
if height == 0 {
|
||||
t.updateCursorPos(screen, -1, -1)
|
||||
return
|
||||
}
|
||||
t.pageSize = height
|
||||
|
@ -1077,6 +1098,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
|
||||
// If we don't have an index, there's nothing to draw.
|
||||
if t.index == nil {
|
||||
t.updateCursorPos(screen, x, y)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1152,6 +1174,8 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
verticalOffset = height - len(t.index)
|
||||
}
|
||||
}
|
||||
var lastLine int
|
||||
var lastPosX int
|
||||
|
||||
// Draw the buffer.
|
||||
defaultStyle := tcell.StyleDefault.Foreground(t.textColor).Background(t.backgroundColor)
|
||||
|
@ -1161,6 +1185,9 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
break
|
||||
}
|
||||
|
||||
lastLine = line
|
||||
lastPosX = -1
|
||||
|
||||
// Get the text for this line.
|
||||
index := t.index[line]
|
||||
text := t.buffer[index.Line][index.Pos:index.NextPos]
|
||||
|
@ -1293,6 +1320,8 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
}
|
||||
}
|
||||
|
||||
lastPosX = posX
|
||||
|
||||
// Advance.
|
||||
posX += screenWidth
|
||||
return false
|
||||
|
@ -1300,6 +1329,16 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
|||
}
|
||||
}
|
||||
|
||||
cursorX, cursorY := x+lastPosX+1, y+lastLine-t.lineOffset
|
||||
if cursorX >= x+width {
|
||||
cursorX = x
|
||||
cursorY++
|
||||
if cursorY > height {
|
||||
cursorX = -1
|
||||
}
|
||||
}
|
||||
t.updateCursorPos(screen, cursorX, cursorY)
|
||||
|
||||
// If this view is not scrollable, we'll purge the buffer of lines that have
|
||||
// scrolled out of view.
|
||||
if !t.scrollable && t.lineOffset > 0 {
|
||||
|
|
Loading…
Reference in New Issue