More intelligent text editing with new textmanip system

This commit is contained in:
Sasha Koshka 2023-01-18 01:19:10 -05:00
parent b03cba57e1
commit 2bf2baf69e
2 changed files with 146 additions and 9 deletions

View File

@ -4,6 +4,7 @@ import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/textmanip"
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
type TextBox struct {
@ -15,7 +16,7 @@ type TextBox struct {
cursor int
placeholder string
text string
text []rune
placeholderDrawer artist.TextDrawer
valueDrawer artist.TextDrawer
}
@ -50,14 +51,51 @@ func (element *TextBox) HandleKeyDown (
modifiers tomo.Modifiers,
repeated bool,
) {
altered := true
switch {
case key == tomo.KeyBackspace:
if len(element.text) < 1 { break }
element.cursor --
element.SetText(element.text[:len(element.text) - 1])
element.text, element.cursor = textmanip.Backspace (
element.text,
element.cursor,
modifiers.Control)
case key == tomo.KeyDelete:
if len(element.text) < 1 { break }
element.text, element.cursor = textmanip.Delete (
element.text,
element.cursor,
modifiers.Control)
case key == tomo.KeyLeft:
element.cursor = textmanip.MoveLeft (
element.text,
element.cursor,
modifiers.Control)
case key == tomo.KeyRight:
element.cursor = textmanip.MoveRight (
element.text,
element.cursor,
modifiers.Control)
case key.Printable():
element.cursor ++
element.SetText(element.text + string(rune(key)))
element.text, element.cursor = textmanip.Type (
element.text,
element.cursor,
rune(key))
default:
altered = false
}
if altered {
element.valueDrawer.SetText(element.text)
}
if altered && element.core.HasImage () {
element.draw()
element.core.PushAll()
}
}
@ -130,10 +168,10 @@ func (element *TextBox) updateMinimumSize () {
}
func (element *TextBox) SetText (text string) {
if element.text == text { return }
// if element.text == text { return }
element.text = text
element.valueDrawer.SetText([]rune(text))
element.text = []rune(text)
element.valueDrawer.SetText(element.text)
if element.cursor > element.valueDrawer.Length() {
element.cursor = element.valueDrawer.Length()
}
@ -160,7 +198,7 @@ func (element *TextBox) draw () {
innerBounds.Max.X -= theme.Padding()
innerBounds.Max.Y -= theme.Padding()
if element.text == "" && !element.selected {
if element.text == nil && !element.selected {
// draw placeholder
textBounds := element.placeholderDrawer.LayoutBounds()
offset := image.Point {

99
textmanip/textmanip.go Normal file
View File

@ -0,0 +1,99 @@
package textmanip
import "unicode"
func WordToLeft (text []rune, cursor int) (length int) {
if cursor < 1 { return }
if cursor > len(text) { cursor = len(text) }
index := cursor - 1
for index >= 0 && unicode.IsSpace(text[index]) {
length ++
index --
}
for index >= 0 && !unicode.IsSpace(text[index]) {
length ++
index --
}
return
}
func WordToRight (text []rune, cursor int) (length int) {
if cursor < 0 { return }
if cursor > len(text) { cursor = len(text) }
index := cursor
for index < len(text) && unicode.IsSpace(text[index]) {
length ++
index ++
}
for index < len(text) && !unicode.IsSpace(text[index]) {
length ++
index ++
}
return
}
func Backspace (text []rune, cursor int, word bool) (result []rune, moved int) {
if cursor < 1 { return text, cursor }
if cursor > len(text) { cursor = len(text) }
moved = 1
if word {
moved = WordToLeft(text, cursor)
}
result = append(result, text[:cursor - moved]...)
result = append(result, text[cursor:]...)
moved = cursor - moved
return
}
func Delete (text []rune, cursor int, word bool) (result []rune, moved int) {
if cursor < 0 { return text, cursor }
if cursor > len(text) { cursor = len(text) }
moved = 1
if word {
moved = WordToRight(text, cursor)
}
result = append(result, text[:cursor]...)
result = append(result, text[cursor + moved:]...)
moved = cursor
return
}
func Type (text []rune, cursor int, character rune) (result []rune, moved int) {
if cursor < 0 { cursor = 0 }
if cursor > len(text) { cursor = len(text) }
result = append(result, text[:cursor]...)
result = append(result, character)
if cursor < len(text) {
result = append(result, text[cursor:]...)
}
moved = cursor + 1
return
}
func MoveLeft (text []rune, cursor int, word bool) (moved int) {
if cursor < 1 { return cursor }
if cursor > len(text) { cursor = len(text) }
moved = 1
if word {
moved = WordToLeft(text, cursor)
}
moved = cursor - moved
return
}
func MoveRight (text []rune, cursor int, word bool) (moved int) {
if cursor < 0 { return cursor }
if cursor > len(text) { cursor = len(text) }
moved = 1
if word {
moved = WordToRight(text, cursor)
}
moved = cursor + moved
return
}