Files

210 lines
3.7 KiB
Go

package uiterm
import (
"strings"
// "unicode/utf8"
"github.com/nsf/termbox-go"
)
type Textbox struct {
Text string
Fg, Bg Attribute
Input func(ui *Ui, textbox *Textbox, text string)
ui *Ui
active bool
x0, y0, x1, y1 int
pos int
history []string
historyIndex int
historyDraft string
}
func (t *Textbox) uiInitialize(ui *Ui) {
t.ui = ui
t.pos = 0
}
func (t *Textbox) uiSetActive(active bool) {
t.active = active
t.uiDraw()
}
func (t *Textbox) uiSetBounds(x0, y0, x1, y1 int) {
t.x0 = x0
t.y0 = y0
t.x1 = x1
t.y1 = y1
t.uiDraw()
}
func (t *Textbox) uiDraw() {
t.ui.beginDraw()
defer t.ui.endDraw()
reader := strings.NewReader(t.Text)
if t.pos < 0 {
t.pos = 0
}
if t.pos > len(t.Text) {
t.pos = len(t.Text)
}
for y := t.y0; y < t.y1; y++ {
for x := t.x0; x < t.x1; x++ {
var chr rune
if ch, _, err := reader.ReadRune(); err != nil {
chr = ' '
} else {
chr = ch
}
termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
}
}
if t.active {
var x = 0
var y = 0
var idx = -1
var flag = false
for y = t.y0; y < t.y1; y++ {
for x = t.x0; x < t.x1; x++ {
idx += 1
if idx == t.pos {
flag = true
}
if flag == true {
break
}
}
if flag == true {
break
}
}
termbox.SetCursor(x, y)
}
}
func (t *Textbox) uiKeyEvent(key Key) {
redraw := false
switch key {
case KeyHome:
t.pos = 0
redraw = true
case KeyEnd:
t.pos = len(t.Text)
redraw = true
case KeyArrowLeft:
t.pos -= 1
redraw = true
case KeyArrowRight:
t.pos += 1
redraw = true
case KeyCtrlC:
t.Text = ""
t.pos = 0
t.resetHistoryNavigation()
redraw = true
case KeyEnter:
text := t.Text
if t.Input != nil {
t.Input(t.ui, t, text)
}
t.addHistory(text)
t.Text = ""
t.pos = 0
t.resetHistoryNavigation()
redraw = true
case KeyArrowUp, KeyAltArrowUp, KeyArrowDown, KeyAltArrowDown:
redraw = t.handleHistoryKey(key)
case KeySpace:
t.uiCharacterEvent(' ')
case KeyBackspace:
case KeyBackspace2:
if len(t.Text) > 0 {
if t.pos > 0 {
t.Text = t.Text[:t.pos-1] + t.Text[t.pos:]
t.pos -= 1
}
}
// if r, size := utf8.DecodeLastRuneInString(t.Text); r != utf8.RuneError {
// t.Text = t.Text[:len(t.Text)-size]
//t.pos-=size
redraw = true
// }
// }
}
if redraw {
t.uiDraw()
}
}
func (t *Textbox) uiCharacterEvent(chr rune) {
var s = string(chr)
t.Text = t.Text[:t.pos] + s + t.Text[t.pos:]
t.pos += len(s)
t.uiDraw()
}
func (t *Textbox) setText(text string) {
t.Text = text
t.pos = len(text)
}
func (t *Textbox) addHistory(text string) {
if strings.TrimSpace(text) == "" {
return
}
if len(t.history) > 0 && t.history[len(t.history)-1] == text {
t.historyIndex = len(t.history)
return
}
t.history = append(t.history, text)
t.historyIndex = len(t.history)
}
func (t *Textbox) handleHistoryKey(key Key) bool {
switch key {
case KeyArrowUp, KeyAltArrowUp:
return t.previousHistory()
case KeyArrowDown, KeyAltArrowDown:
return t.nextHistory()
default:
return false
}
}
func (t *Textbox) previousHistory() bool {
if len(t.history) == 0 {
return false
}
if t.historyIndex == len(t.history) {
t.historyDraft = t.Text
}
if t.historyIndex > 0 {
t.historyIndex--
}
t.setText(t.history[t.historyIndex])
return true
}
func (t *Textbox) nextHistory() bool {
if len(t.history) == 0 || t.historyIndex == len(t.history) {
return false
}
if t.historyIndex < len(t.history)-1 {
t.historyIndex++
t.setText(t.history[t.historyIndex])
return true
}
t.historyIndex = len(t.history)
t.setText(t.historyDraft)
t.historyDraft = ""
return true
}
func (t *Textbox) resetHistoryNavigation() {
t.historyIndex = len(t.history)
t.historyDraft = ""
}