Textmanip now operates on a dot instead of a cursor

This commit is contained in:
Sasha Koshka 2023-02-13 01:52:31 -05:00
parent 8ac5108211
commit 4bc8566820
2 changed files with 125 additions and 61 deletions

View File

@ -15,7 +15,7 @@ type TextBox struct {
core core.CoreControl
focusableControl core.FocusableCoreControl
cursor int
dot textmanip.Dot
scroll int
placeholder string
text []rune
@ -74,42 +74,44 @@ func (element *TextBox) HandleKeyDown(key input.Key, modifiers input.Modifiers)
return
}
// TODO: text selection with shift
scrollMemory := element.scroll
altered := true
textChanged := false
switch {
case key == input.KeyBackspace:
if len(element.text) < 1 { break }
element.text, element.cursor = textmanip.Backspace (
element.text, element.dot = textmanip.Backspace (
element.text,
element.cursor,
element.dot,
modifiers.Control)
textChanged = true
case key == input.KeyDelete:
if len(element.text) < 1 { break }
element.text, element.cursor = textmanip.Delete (
element.text, element.dot = textmanip.Delete (
element.text,
element.cursor,
element.dot,
modifiers.Control)
textChanged = true
case key == input.KeyLeft:
element.cursor = textmanip.MoveLeft (
element.dot = textmanip.MoveLeft (
element.text,
element.cursor,
element.dot,
modifiers.Control)
case key == input.KeyRight:
element.cursor = textmanip.MoveRight (
element.dot = textmanip.MoveRight (
element.text,
element.cursor,
element.dot,
modifiers.Control)
case key.Printable():
element.text, element.cursor = textmanip.Type (
element.text, element.dot = textmanip.Type (
element.text,
element.cursor,
element.dot,
rune(key))
textChanged = true
@ -154,8 +156,8 @@ func (element *TextBox) SetValue (text string) {
element.text = []rune(text)
element.runOnChange()
element.valueDrawer.SetText(element.text)
if element.cursor > element.valueDrawer.Length() {
element.cursor = element.valueDrawer.Length()
if element.dot.End > element.valueDrawer.Length() {
element.dot = textmanip.EmptyDot(element.valueDrawer.Length())
}
element.scrollToCursor()
element.redo()
@ -238,7 +240,7 @@ func (element *TextBox) scrollToCursor () {
bounds := element.Bounds().Inset(element.config.Padding())
bounds = bounds.Sub(bounds.Min)
bounds.Max.X -= element.valueDrawer.Em().Round()
cursorPosition := element.valueDrawer.PositionOf(element.cursor)
cursorPosition := element.valueDrawer.PositionOf(element.dot.End)
cursorPosition.X -= element.scroll
maxX := bounds.Max.X
minX := maxX
@ -328,8 +330,9 @@ func (element *TextBox) draw () {
if element.Focused() {
// cursor
// TODO: draw selection if exists
cursorPosition := element.valueDrawer.PositionOf (
element.cursor)
element.dot.End)
artist.Line (
element.core,
foreground, 1,

View File

@ -2,7 +2,40 @@ package textmanip
import "unicode"
func WordToLeft (text []rune, cursor int) (length int) {
type Dot struct { Start, End int }
func EmptyDot (position int) Dot {
return Dot { position, position }
}
func (dot Dot) Canon () Dot {
if dot.Start > dot.End {
return Dot { dot.End, dot.Start }
} else {
return dot
}
}
func (dot Dot) Empty () bool {
return dot.Start == dot.End
}
func (dot Dot) Add (delta int) Dot {
return Dot {
dot.Start + delta,
dot.End + delta,
}
}
func (dot Dot) Sub (delta int) Dot {
return Dot {
dot.Start - delta,
dot.End - delta,
}
}
func WordToLeft (text []rune, dot Dot) (length int) {
cursor := dot.End
if cursor < 1 { return }
if cursor > len(text) { cursor = len(text) }
@ -18,7 +51,8 @@ func WordToLeft (text []rune, cursor int) (length int) {
return
}
func WordToRight (text []rune, cursor int) (length int) {
func WordToRight (text []rune, dot Dot) (length int) {
cursor := dot.End
if cursor < 0 { return }
if cursor > len(text) { cursor = len(text) }
@ -34,66 +68,93 @@ func WordToRight (text []rune, cursor int) (length int) {
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) }
func Backspace (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
if dot.Empty() {
cursor := dot.End
if cursor < 1 { return text, dot }
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) {
distance := 1
if word {
distance = WordToLeft(text, dot)
}
result = append(result, text[:cursor - distance]...)
result = append(result, text[cursor:]...)
moved = EmptyDot(cursor - distance)
} else {
return Delete(text, dot, word)
}
moved = cursor + 1
return
}
func MoveLeft (text []rune, cursor int, word bool) (moved int) {
if cursor < 1 { return cursor }
func Delete (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
if dot.Empty() {
cursor := dot.End
if cursor < 0 { return text, dot }
if cursor > len(text) { cursor = len(text) }
distance := 1
if word {
distance = WordToRight(text, dot)
}
result = append(result, text[:cursor]...)
result = append(result, text[cursor + distance:]...)
moved = dot
return
} else {
result = append(result, text[:dot.Start]...)
result = append(result, text[dot.End:]...)
moved = EmptyDot(dot.Start)
return
}
}
func Type (text []rune, dot Dot, character rune) (result []rune, moved Dot) {
if dot.Empty() {
cursor := dot.End
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 = EmptyDot(cursor + 1)
return
} else {
result = append(result, text[:dot.Start]...)
result = append(result, character)
result = append(result, text[dot.End:]...)
moved = EmptyDot(dot.Start)
return
}
}
func MoveLeft (text []rune, dot Dot, word bool) (moved Dot) {
cursor := dot.Start
if cursor < 1 { return EmptyDot(cursor) }
if cursor > len(text) { cursor = len(text) }
moved = 1
distance := 1
if word {
moved = WordToLeft(text, cursor)
distance = WordToLeft(text, dot)
}
moved = cursor - moved
moved = EmptyDot(cursor - distance)
return
}
func MoveRight (text []rune, cursor int, word bool) (moved int) {
if cursor < 0 { return cursor }
func MoveRight (text []rune, dot Dot, word bool) (moved Dot) {
cursor := dot.End
if cursor < 0 { return EmptyDot(cursor) }
if cursor > len(text) { cursor = len(text) }
moved = 1
distance := 1
if word {
moved = WordToRight(text, cursor)
distance = WordToRight(text, dot)
}
moved = cursor + moved
moved = EmptyDot(cursor + distance)
return
}