build text-entry component
This commit is contained in:
parent
bb01987b3b
commit
e9b6c95019
81
ui/ui.go
81
ui/ui.go
@ -515,3 +515,84 @@ func (p *KeyValue) SetVisible(b bool) {
|
|||||||
func (p *KeyValue) GetValue() string {
|
func (p *KeyValue) GetValue() string {
|
||||||
return p.value
|
return p.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EditableTextLine struct {
|
||||||
|
x, y int
|
||||||
|
h, w int
|
||||||
|
text string
|
||||||
|
style tcell.Style
|
||||||
|
visible bool
|
||||||
|
cursorPos int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEditableTextLine(initialText string) *EditableTextLine {
|
||||||
|
return &EditableTextLine{
|
||||||
|
text: initialText,
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) SetSize(x, y, _, _ int) {
|
||||||
|
p.x, p.y, p.h, p.w = x, y, 1, len(p.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) SetStyle(s tcell.Style) {
|
||||||
|
p.style = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) Draw(s tcell.Screen) {
|
||||||
|
if !p.visible {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for j, r := range p.text {
|
||||||
|
s.SetContent(p.x+j, p.y, r, nil, p.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) SetText(t string) {
|
||||||
|
p.text = t
|
||||||
|
if len(p.text) == 0 {
|
||||||
|
p.ResetCursor(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.ResetCursor(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) ResetCursor(beginning bool) {
|
||||||
|
if beginning {
|
||||||
|
p.cursorPos = 0
|
||||||
|
} else {
|
||||||
|
p.cursorPos = len(p.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) InsertAtCursor(r rune) {
|
||||||
|
if len(p.text) == 0 {
|
||||||
|
p.text = string(r)
|
||||||
|
p.cursorPos = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.text = p.text[0:p.cursorPos] + string(r) + p.text[p.cursorPos:len(p.text)]
|
||||||
|
p.cursorPos = p.cursorPos + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) MoveCursor(i int) {
|
||||||
|
if p.cursorPos+i < 0 {
|
||||||
|
p.cursorPos = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.cursorPos+i > len(p.text) {
|
||||||
|
p.cursorPos = len(p.text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.cursorPos = p.cursorPos + i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EditableTextLine) DeleteAtCursor() {
|
||||||
|
if len(p.text) == 0 {
|
||||||
|
p.cursorPos = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.text = p.text[0:p.cursorPos-1] + p.text[p.cursorPos:len(p.text)]
|
||||||
|
p.cursorPos = p.cursorPos - 1
|
||||||
|
}
|
||||||
|
@ -174,3 +174,66 @@ func TestContainerTwoBoxesPercentageVStack(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewEditableTextLine(t *testing.T) {
|
||||||
|
e := NewEditableTextLine("")
|
||||||
|
e.InsertAtCursor('a')
|
||||||
|
e.InsertAtCursor('b')
|
||||||
|
e.InsertAtCursor('c')
|
||||||
|
if e.text != "abc" {
|
||||||
|
fmt.Printf("expected: 'abc', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.MoveCursor(-1)
|
||||||
|
e.InsertAtCursor('d')
|
||||||
|
if e.text != "abdc" {
|
||||||
|
fmt.Printf("expected: 'abdc', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.MoveCursor(-20)
|
||||||
|
e.InsertAtCursor('e')
|
||||||
|
if e.text != "eabdc" {
|
||||||
|
fmt.Printf("expected: 'eabdc', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.MoveCursor(20)
|
||||||
|
e.InsertAtCursor('f')
|
||||||
|
if e.text != "eabdcf" {
|
||||||
|
fmt.Printf("expected: 'eabdcf', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.MoveCursor(1)
|
||||||
|
e.InsertAtCursor('g')
|
||||||
|
if e.text != "eabdcfg" {
|
||||||
|
fmt.Printf("expected: 'eabdcfg', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.DeleteAtCursor()
|
||||||
|
e.DeleteAtCursor()
|
||||||
|
e.MoveCursor(-1)
|
||||||
|
e.DeleteAtCursor()
|
||||||
|
if e.text != "eabc" {
|
||||||
|
fmt.Printf("expected: 'eabc', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.ResetCursor(false)
|
||||||
|
e.InsertAtCursor('h')
|
||||||
|
e.ResetCursor(true)
|
||||||
|
e.InsertAtCursor('g')
|
||||||
|
if e.text != "geabch" {
|
||||||
|
fmt.Printf("expected: 'geabch', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.SetText("the rain in spain")
|
||||||
|
e.InsertAtCursor('s')
|
||||||
|
if e.text != "the rain in spains" {
|
||||||
|
fmt.Printf("expected: 'the rain in spains', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
e.SetText("")
|
||||||
|
e.InsertAtCursor('s')
|
||||||
|
if e.text != "s" {
|
||||||
|
fmt.Printf("expected: 's', actual: '%+v'", e.text)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user