mirror of
https://github.com/br0xen/termbox-util.git
synced 2024-11-22 13:33:15 +00:00
Input Field still isn't where I want it.
Also added convenience functions to test if termbox events are alpha/numeric/symbol
This commit is contained in:
parent
e93feb0dde
commit
e843ea92b9
@ -1,7 +1,6 @@
|
|||||||
package termboxUtil
|
package termboxUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nsf/termbox-go"
|
"github.com/nsf/termbox-go"
|
||||||
@ -15,6 +14,7 @@ type InputField struct {
|
|||||||
fg, bg termbox.Attribute
|
fg, bg termbox.Attribute
|
||||||
bordered bool
|
bordered bool
|
||||||
wrap bool
|
wrap bool
|
||||||
|
multiline bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateInputField creates an input field at x, y that is w by h
|
// CreateInputField creates an input field at x, y that is w by h
|
||||||
@ -81,12 +81,20 @@ func (i *InputField) SetBordered(b bool) *InputField {
|
|||||||
func (i *InputField) DoesWrap() bool { return i.wrap }
|
func (i *InputField) DoesWrap() bool { return i.wrap }
|
||||||
|
|
||||||
// SetWrap sets whether we wrap the text at width.
|
// SetWrap sets whether we wrap the text at width.
|
||||||
// If 'wrap' is set, we automatically increase the height when we need to.
|
|
||||||
func (i *InputField) SetWrap(b bool) *InputField {
|
func (i *InputField) SetWrap(b bool) *InputField {
|
||||||
i.wrap = b
|
i.wrap = b
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMultiline returns true or false if this field can have multiple lines
|
||||||
|
func (i *InputField) IsMultiline() bool { return i.multiline }
|
||||||
|
|
||||||
|
// SetMultiline sets whether the field can have multiple lines
|
||||||
|
func (i *InputField) SetMultiline(b bool) *InputField {
|
||||||
|
i.multiline = b
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
// HandleKeyPress accepts the termbox event and returns whether it was consumed
|
// HandleKeyPress accepts the termbox event and returns whether it was consumed
|
||||||
func (i *InputField) HandleKeyPress(event termbox.Event) bool {
|
func (i *InputField) HandleKeyPress(event termbox.Event) bool {
|
||||||
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
|
if event.Key == termbox.KeyBackspace || event.Key == termbox.KeyBackspace2 {
|
||||||
@ -114,19 +122,23 @@ func (i *InputField) HandleKeyPress(event termbox.Event) bool {
|
|||||||
case termbox.KeyTab:
|
case termbox.KeyTab:
|
||||||
ch = "\t"
|
ch = "\t"
|
||||||
case termbox.KeyEnter:
|
case termbox.KeyEnter:
|
||||||
ch = "\n"
|
if i.multiline {
|
||||||
|
ch = "\n"
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ch = string(event.Ch)
|
if KeyIsAlphaNumeric(event) || KeyIsSymbol(event) {
|
||||||
|
ch = string(event.Ch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.cursor+len(i.value) == 0 {
|
if i.cursor+len(i.value) == 0 {
|
||||||
i.value = fmt.Sprintf("%s%s", ch, i.value)
|
i.value = string(ch) + i.value
|
||||||
} else if i.cursor == 0 {
|
} else if i.cursor == 0 {
|
||||||
i.value = fmt.Sprintf("%s%s", i.value, ch)
|
i.value = i.value + string(ch)
|
||||||
} else {
|
} else {
|
||||||
strPt1 := i.value[:(len(i.value) + i.cursor)]
|
strPt1 := i.value[:(len(i.value) + i.cursor)]
|
||||||
strPt2 := i.value[(len(i.value) + i.cursor):]
|
strPt2 := i.value[(len(i.value) + i.cursor):]
|
||||||
i.value = fmt.Sprintf("%s%s%s", strPt1, ch, strPt2)
|
i.value = strPt1 + string(ch) + strPt2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -135,76 +147,142 @@ func (i *InputField) HandleKeyPress(event termbox.Event) bool {
|
|||||||
// Draw outputs the input field on the screen
|
// Draw outputs the input field on the screen
|
||||||
func (i *InputField) Draw() {
|
func (i *InputField) Draw() {
|
||||||
maxWidth := i.width
|
maxWidth := i.width
|
||||||
|
maxHeight := i.height
|
||||||
x, y := i.x, i.y
|
x, y := i.x, i.y
|
||||||
startX := i.x
|
startX := i.x
|
||||||
|
startY := i.y
|
||||||
if i.bordered {
|
if i.bordered {
|
||||||
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
DrawBorder(i.x, i.y, i.x+i.width, i.y+i.height, i.fg, i.bg)
|
||||||
maxWidth--
|
maxWidth--
|
||||||
|
maxHeight--
|
||||||
x++
|
x++
|
||||||
y++
|
y++
|
||||||
startX++
|
startX++
|
||||||
|
startY++
|
||||||
}
|
}
|
||||||
|
|
||||||
var strPt1, strPt2 string
|
var valSplit []string //, cursorLine []string
|
||||||
var cursorRune rune
|
if i.multiline {
|
||||||
if len(i.value) > 0 {
|
valSplit = strings.Split(i.value, "\n")
|
||||||
if i.cursor+len(i.value) == 0 {
|
|
||||||
strPt1 = ""
|
|
||||||
strPt2 = i.value[1:]
|
|
||||||
cursorRune = rune(i.value[0])
|
|
||||||
} else if i.cursor == 0 {
|
|
||||||
strPt1 = i.value
|
|
||||||
strPt2 = ""
|
|
||||||
cursorRune = ' '
|
|
||||||
} else {
|
|
||||||
strPt1 = i.value[:(len(i.value) + i.cursor)]
|
|
||||||
strPt2 = i.value[(len(i.value)+i.cursor)+1:]
|
|
||||||
cursorRune = rune(i.value[len(i.value)+i.cursor])
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
strPt1, strPt2, cursorRune = "", "", ' '
|
if i.wrap {
|
||||||
|
var j int
|
||||||
|
for j < len(i.value) {
|
||||||
|
l, h := j, j+i.width
|
||||||
|
//if l >= i.cursor && h <= i.cursor {
|
||||||
|
// cursorLine = append(cursorLine, i.value[l:i.cursor])
|
||||||
|
// cursorLine = append(cursorLine, i.value[i.cursor]...)
|
||||||
|
// cursorLine = append(cursorLine, i.value[i.cursor:h])
|
||||||
|
//} else {
|
||||||
|
valSplit = append(valSplit, i.value[l:h])
|
||||||
|
//}
|
||||||
|
j = h
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// strPt1, strPt2 = all of the text before, after the cursor
|
for j := range valSplit {
|
||||||
// cursorRune is the rune on the cursor
|
DrawStringAtPoint(valSplit[j], x, y+j, i.fg, i.bg)
|
||||||
if i.wrap {
|
}
|
||||||
// Split the text into maxWidth chunks
|
//var valSplit []string
|
||||||
for len(strPt1) > maxWidth { //|| nlCount > 0 {
|
// if it's not multiline, new lines aren't allowed in the input
|
||||||
breakAt := maxWidth
|
/*
|
||||||
DrawStringAtPoint(strPt1[:breakAt], x, y, i.fg, i.bg)
|
multiSplit := strings.Split(i.value, "\n")
|
||||||
x = startX
|
var cursCount int
|
||||||
y++
|
for j := range multiSplit {
|
||||||
strPt1 = strPt1[breakAt:]
|
for k := range multiSplit[j] {
|
||||||
}
|
if cursCount == i.cursor {
|
||||||
x, y = DrawStringAtPoint(strPt1, x, y, i.fg, i.bg)
|
termbox.SetCell(x+k, y+j, rune(multiSplit[j][k]), i.fg, i.bg)
|
||||||
if maxWidth-len(strPt1) <= 0 {
|
} else {
|
||||||
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
|
termbox.SetCell(x+k, y+j, rune(multiSplit[j][k]), i.bg, i.fg)
|
||||||
}
|
|
||||||
if len(strPt2) > 0 {
|
|
||||||
if maxWidth-len(strPt1)-1 > 0 {
|
|
||||||
DrawStringAtPoint(strPt2[:(maxWidth-len(strPt1)-1)], x+1, y, i.fg, i.bg)
|
|
||||||
strPt2 = strPt2[(maxWidth - len(strPt1)):]
|
|
||||||
}
|
|
||||||
nlCount := strings.Count(strPt2, "\n")
|
|
||||||
for len(strPt2) > maxWidth || nlCount > 0 {
|
|
||||||
x, y = DrawStringAtPoint(strPt2[:maxWidth], x, y, i.fg, i.bg)
|
|
||||||
strPt2 = strPt2[maxWidth:]
|
|
||||||
}
|
|
||||||
x, y = DrawStringAtPoint(strPt2, x, y, i.fg, i.bg)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Not wrapping, just adjust the viewport
|
|
||||||
for len(strPt1)+len(strPt2)+1 > maxWidth {
|
|
||||||
if len(strPt1) >= len(strPt2) {
|
|
||||||
if len(strPt1) == 0 {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
strPt1 = strPt1[1:]
|
cursCount++
|
||||||
} else {
|
|
||||||
strPt2 = strPt2[:len(strPt2)-1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x, y := DrawStringAtPoint(strPt1, i.x+1, i.y+1, i.fg, i.bg)
|
*/
|
||||||
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
|
/*
|
||||||
DrawStringAtPoint(strPt2, x+1, y, i.fg, i.bg)
|
if i.wrap {
|
||||||
}
|
// Automatically wrap the text
|
||||||
|
for j := range multiSplit {
|
||||||
|
for len(multiSplit[j]) > maxWidth {
|
||||||
|
valSplit = append(valSplit, multiSplit[j][:maxWidth])
|
||||||
|
multiSplit[j] = multiSplit[j][maxWidth:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
valSplit = multiSplit
|
||||||
|
}
|
||||||
|
for j := range valSplit {
|
||||||
|
DrawStringAtPoint(valSplit[j], x, y+j, i.fg, i.bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
var strPt1, strPt2 string
|
||||||
|
var cursorRune rune
|
||||||
|
if len(i.value) > 0 {
|
||||||
|
if i.cursor+len(i.value) == 0 {
|
||||||
|
strPt1 = ""
|
||||||
|
strPt2 = i.value[1:]
|
||||||
|
cursorRune = rune(i.value[0])
|
||||||
|
} else if i.cursor == 0 {
|
||||||
|
strPt1 = i.value
|
||||||
|
strPt2 = ""
|
||||||
|
cursorRune = ' '
|
||||||
|
} else {
|
||||||
|
strPt1 = i.value[:(len(i.value) + i.cursor)]
|
||||||
|
strPt2 = i.value[(len(i.value)+i.cursor)+1:]
|
||||||
|
cursorRune = rune(i.value[len(i.value)+i.cursor])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strPt1, strPt2, cursorRune = "", "", ' '
|
||||||
|
}
|
||||||
|
// strPt1, strPt2 = all of the text before, after the cursor
|
||||||
|
// cursorRune is the rune on the cursor
|
||||||
|
if i.wrap {
|
||||||
|
// Split the text into maxWidth chunks
|
||||||
|
for len(strPt1) > maxWidth {
|
||||||
|
breakAt := maxWidth
|
||||||
|
DrawStringAtPoint(strPt1[:breakAt], x, y, i.fg, i.bg)
|
||||||
|
x = startX
|
||||||
|
y++
|
||||||
|
strPt1 = strPt1[breakAt:]
|
||||||
|
}
|
||||||
|
x, y = DrawStringAtPoint(strPt1, x, y, i.fg, i.bg)
|
||||||
|
if x >= maxWidth {
|
||||||
|
y++
|
||||||
|
x = startX
|
||||||
|
}
|
||||||
|
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
|
||||||
|
x++
|
||||||
|
if len(strPt2) > 0 {
|
||||||
|
lenLeft := maxWidth - len(strPt1) - 1
|
||||||
|
if lenLeft > 0 && len(strPt2) > lenLeft {
|
||||||
|
DrawStringAtPoint(strPt2[:lenLeft], x+1, y, i.fg, i.bg)
|
||||||
|
strPt2 = strPt2[lenLeft:]
|
||||||
|
}
|
||||||
|
for len(strPt2) > maxWidth {
|
||||||
|
breakAt := maxWidth
|
||||||
|
DrawStringAtPoint(strPt2[:breakAt], x, y, i.fg, i.bg)
|
||||||
|
x = startX
|
||||||
|
y++
|
||||||
|
strPt2 = strPt2[breakAt:]
|
||||||
|
}
|
||||||
|
x, y = DrawStringAtPoint(strPt2, x, y, i.fg, i.bg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not wrapping, just adjust the viewport
|
||||||
|
for len(strPt1)+len(strPt2)+1 > maxWidth {
|
||||||
|
if len(strPt1) >= len(strPt2) {
|
||||||
|
if len(strPt1) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
strPt1 = strPt1[1:]
|
||||||
|
} else {
|
||||||
|
strPt2 = strPt2[:len(strPt2)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x, y := DrawStringAtPoint(strPt1, i.x+1, i.y+1, i.fg, i.bg)
|
||||||
|
termbox.SetCell(x, y, cursorRune, i.bg, i.fg)
|
||||||
|
DrawStringAtPoint(strPt2, x+1, y, i.fg, i.bg)
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,44 @@ const (
|
|||||||
// KeyIsAlphaNumeric Returns whether the termbox event is an
|
// KeyIsAlphaNumeric Returns whether the termbox event is an
|
||||||
// Alpha-Numeric Key Press
|
// Alpha-Numeric Key Press
|
||||||
func KeyIsAlphaNumeric(event termbox.Event) bool {
|
func KeyIsAlphaNumeric(event termbox.Event) bool {
|
||||||
|
return KeyIsAlpha(event) || KeyIsNumeric(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyIsAlpha Returns whether the termbox event is a
|
||||||
|
// alphabetic Key press
|
||||||
|
func KeyIsAlpha(event termbox.Event) bool {
|
||||||
k := event.Ch
|
k := event.Ch
|
||||||
if (k >= 'a' && k <= 'z') || (k >= 'A' && k <= 'Z') || (k >= '0' && k <= '9') {
|
if (k >= 'a' && k <= 'z') || (k >= 'A' && k <= 'Z') {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyIsNumeric Returns whether the termbox event is a
|
||||||
|
// numeric Key press
|
||||||
|
func KeyIsNumeric(event termbox.Event) bool {
|
||||||
|
k := event.Ch
|
||||||
|
if k >= '0' && k <= '9' {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyIsSymbol Returns whether the termbox event is a
|
||||||
|
// symbol Key press
|
||||||
|
func KeyIsSymbol(event termbox.Event) bool {
|
||||||
|
symbols := []rune{'!', '@', '#', '$', '%', '^', '&', '*',
|
||||||
|
'(', ')', '-', '_', '=', '+', '[', ']', '{', '}', '|',
|
||||||
|
';', ':', '"', '\'', ',', '<', '.', '>', '/', '?', '`', '~'}
|
||||||
|
k := event.Ch
|
||||||
|
for i := range symbols {
|
||||||
|
if k == symbols[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/* Basic Output Helpers */
|
/* Basic Output Helpers */
|
||||||
|
|
||||||
// DrawStringAtPoint Draw a string of text at x, y with foreground color fg, background color bg
|
// DrawStringAtPoint Draw a string of text at x, y with foreground color fg, background color bg
|
||||||
|
Loading…
Reference in New Issue
Block a user