Textmanip now operates on a dot instead of a cursor
This commit is contained in:
parent
8ac5108211
commit
4bc8566820
@ -15,7 +15,7 @@ type TextBox struct {
|
|||||||
core core.CoreControl
|
core core.CoreControl
|
||||||
focusableControl core.FocusableCoreControl
|
focusableControl core.FocusableCoreControl
|
||||||
|
|
||||||
cursor int
|
dot textmanip.Dot
|
||||||
scroll int
|
scroll int
|
||||||
placeholder string
|
placeholder string
|
||||||
text []rune
|
text []rune
|
||||||
@ -74,42 +74,44 @@ func (element *TextBox) HandleKeyDown(key input.Key, modifiers input.Modifiers)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: text selection with shift
|
||||||
|
|
||||||
scrollMemory := element.scroll
|
scrollMemory := element.scroll
|
||||||
altered := true
|
altered := true
|
||||||
textChanged := false
|
textChanged := false
|
||||||
switch {
|
switch {
|
||||||
case key == input.KeyBackspace:
|
case key == input.KeyBackspace:
|
||||||
if len(element.text) < 1 { break }
|
if len(element.text) < 1 { break }
|
||||||
element.text, element.cursor = textmanip.Backspace (
|
element.text, element.dot = textmanip.Backspace (
|
||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.dot,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
textChanged = true
|
textChanged = true
|
||||||
|
|
||||||
case key == input.KeyDelete:
|
case key == input.KeyDelete:
|
||||||
if len(element.text) < 1 { break }
|
if len(element.text) < 1 { break }
|
||||||
element.text, element.cursor = textmanip.Delete (
|
element.text, element.dot = textmanip.Delete (
|
||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.dot,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
textChanged = true
|
textChanged = true
|
||||||
|
|
||||||
case key == input.KeyLeft:
|
case key == input.KeyLeft:
|
||||||
element.cursor = textmanip.MoveLeft (
|
element.dot = textmanip.MoveLeft (
|
||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.dot,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
|
|
||||||
case key == input.KeyRight:
|
case key == input.KeyRight:
|
||||||
element.cursor = textmanip.MoveRight (
|
element.dot = textmanip.MoveRight (
|
||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.dot,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
|
|
||||||
case key.Printable():
|
case key.Printable():
|
||||||
element.text, element.cursor = textmanip.Type (
|
element.text, element.dot = textmanip.Type (
|
||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.dot,
|
||||||
rune(key))
|
rune(key))
|
||||||
textChanged = true
|
textChanged = true
|
||||||
|
|
||||||
@ -154,8 +156,8 @@ func (element *TextBox) SetValue (text string) {
|
|||||||
element.text = []rune(text)
|
element.text = []rune(text)
|
||||||
element.runOnChange()
|
element.runOnChange()
|
||||||
element.valueDrawer.SetText(element.text)
|
element.valueDrawer.SetText(element.text)
|
||||||
if element.cursor > element.valueDrawer.Length() {
|
if element.dot.End > element.valueDrawer.Length() {
|
||||||
element.cursor = element.valueDrawer.Length()
|
element.dot = textmanip.EmptyDot(element.valueDrawer.Length())
|
||||||
}
|
}
|
||||||
element.scrollToCursor()
|
element.scrollToCursor()
|
||||||
element.redo()
|
element.redo()
|
||||||
@ -238,7 +240,7 @@ func (element *TextBox) scrollToCursor () {
|
|||||||
bounds := element.Bounds().Inset(element.config.Padding())
|
bounds := element.Bounds().Inset(element.config.Padding())
|
||||||
bounds = bounds.Sub(bounds.Min)
|
bounds = bounds.Sub(bounds.Min)
|
||||||
bounds.Max.X -= element.valueDrawer.Em().Round()
|
bounds.Max.X -= element.valueDrawer.Em().Round()
|
||||||
cursorPosition := element.valueDrawer.PositionOf(element.cursor)
|
cursorPosition := element.valueDrawer.PositionOf(element.dot.End)
|
||||||
cursorPosition.X -= element.scroll
|
cursorPosition.X -= element.scroll
|
||||||
maxX := bounds.Max.X
|
maxX := bounds.Max.X
|
||||||
minX := maxX
|
minX := maxX
|
||||||
@ -328,8 +330,9 @@ func (element *TextBox) draw () {
|
|||||||
|
|
||||||
if element.Focused() {
|
if element.Focused() {
|
||||||
// cursor
|
// cursor
|
||||||
|
// TODO: draw selection if exists
|
||||||
cursorPosition := element.valueDrawer.PositionOf (
|
cursorPosition := element.valueDrawer.PositionOf (
|
||||||
element.cursor)
|
element.dot.End)
|
||||||
artist.Line (
|
artist.Line (
|
||||||
element.core,
|
element.core,
|
||||||
foreground, 1,
|
foreground, 1,
|
||||||
|
@ -2,7 +2,40 @@ package textmanip
|
|||||||
|
|
||||||
import "unicode"
|
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 < 1 { return }
|
||||||
if cursor > len(text) { cursor = len(text) }
|
if cursor > len(text) { cursor = len(text) }
|
||||||
|
|
||||||
@ -18,7 +51,8 @@ func WordToLeft (text []rune, cursor int) (length int) {
|
|||||||
return
|
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 < 0 { return }
|
||||||
if cursor > len(text) { cursor = len(text) }
|
if cursor > len(text) { cursor = len(text) }
|
||||||
|
|
||||||
@ -34,66 +68,93 @@ func WordToRight (text []rune, cursor int) (length int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Backspace (text []rune, cursor int, word bool) (result []rune, moved int) {
|
func Backspace (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
|
||||||
if cursor < 1 { return text, cursor }
|
if dot.Empty() {
|
||||||
if cursor > len(text) { cursor = len(text) }
|
cursor := dot.End
|
||||||
|
if cursor < 1 { return text, dot }
|
||||||
|
if cursor > len(text) { cursor = len(text) }
|
||||||
|
|
||||||
moved = 1
|
distance := 1
|
||||||
if word {
|
if word {
|
||||||
moved = WordToLeft(text, cursor)
|
distance = WordToLeft(text, dot)
|
||||||
}
|
}
|
||||||
result = append(result, text[:cursor - moved]...)
|
result = append(result, text[:cursor - distance]...)
|
||||||
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:]...)
|
result = append(result, text[cursor:]...)
|
||||||
|
moved = EmptyDot(cursor - distance)
|
||||||
|
} else {
|
||||||
|
return Delete(text, dot, word)
|
||||||
}
|
}
|
||||||
moved = cursor + 1
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func MoveLeft (text []rune, cursor int, word bool) (moved int) {
|
func Delete (text []rune, dot Dot, word bool) (result []rune, moved Dot) {
|
||||||
if cursor < 1 { return cursor }
|
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) }
|
if cursor > len(text) { cursor = len(text) }
|
||||||
|
|
||||||
moved = 1
|
distance := 1
|
||||||
if word {
|
if word {
|
||||||
moved = WordToLeft(text, cursor)
|
distance = WordToLeft(text, dot)
|
||||||
}
|
}
|
||||||
moved = cursor - moved
|
moved = EmptyDot(cursor - distance)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func MoveRight (text []rune, cursor int, word bool) (moved int) {
|
func MoveRight (text []rune, dot Dot, word bool) (moved Dot) {
|
||||||
if cursor < 0 { return cursor }
|
cursor := dot.End
|
||||||
|
|
||||||
|
if cursor < 0 { return EmptyDot(cursor) }
|
||||||
if cursor > len(text) { cursor = len(text) }
|
if cursor > len(text) { cursor = len(text) }
|
||||||
|
|
||||||
moved = 1
|
distance := 1
|
||||||
if word {
|
if word {
|
||||||
moved = WordToRight(text, cursor)
|
distance = WordToRight(text, dot)
|
||||||
}
|
}
|
||||||
moved = cursor + moved
|
moved = EmptyDot(cursor + distance)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user