forked from joejulian/gio
widget: add Editor.Filter for filtering unwanted characters
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+17
-5
@@ -49,6 +49,9 @@ type Editor struct {
|
|||||||
InputHint key.InputHint
|
InputHint key.InputHint
|
||||||
// MaxLen limits the editor content to a maximum length. Zero means no limit.
|
// MaxLen limits the editor content to a maximum length. Zero means no limit.
|
||||||
MaxLen int
|
MaxLen int
|
||||||
|
// Filter is the list of characters allowed in the Editor. If Filter is empty,
|
||||||
|
// all characters are allowed.
|
||||||
|
Filter string
|
||||||
|
|
||||||
eventKey int
|
eventKey int
|
||||||
font text.Font
|
font text.Font
|
||||||
@@ -1235,12 +1238,21 @@ func (e *Editor) replace(start, end int, s string, addHistory bool) int {
|
|||||||
startPos := e.closestPosition(combinedPos{runes: start})
|
startPos := e.closestPosition(combinedPos{runes: start})
|
||||||
endPos := e.closestPosition(combinedPos{runes: end})
|
endPos := e.closestPosition(combinedPos{runes: end})
|
||||||
startOff := e.runeOffset(startPos.runes)
|
startOff := e.runeOffset(startPos.runes)
|
||||||
sc := utf8.RuneCountInString(s)
|
|
||||||
el := e.Len()
|
el := e.Len()
|
||||||
for e.MaxLen > 0 && el+sc > e.MaxLen {
|
var sc int
|
||||||
_, n := utf8.DecodeLastRuneInString(s)
|
idx := 0
|
||||||
s = s[:len(s)-n]
|
for idx < len(s) {
|
||||||
sc--
|
if e.MaxLen > 0 && el+sc >= e.MaxLen {
|
||||||
|
s = s[:idx]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, n := utf8.DecodeRuneInString(s[idx:])
|
||||||
|
if e.Filter != "" && !strings.Contains(e.Filter, s[idx:idx+n]) {
|
||||||
|
s = s[:idx] + s[idx+n:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
idx += n
|
||||||
|
sc++
|
||||||
}
|
}
|
||||||
newEnd := startPos.runes + sc
|
newEnd := startPos.runes + sc
|
||||||
replaceSize := endPos.runes - startPos.runes
|
replaceSize := endPos.runes - startPos.runes
|
||||||
|
|||||||
@@ -1036,6 +1036,37 @@ func TestEditor_MaxLen(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEditor_Filter(t *testing.T) {
|
||||||
|
e := new(Editor)
|
||||||
|
|
||||||
|
e.Filter = "123456789"
|
||||||
|
e.SetText("abcde1234")
|
||||||
|
if got, want := e.Text(), "1234"; got != want {
|
||||||
|
t.Errorf("editor failed to filter SetText")
|
||||||
|
}
|
||||||
|
|
||||||
|
e.SetText("2345678")
|
||||||
|
gtx := layout.Context{
|
||||||
|
Ops: new(op.Ops),
|
||||||
|
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||||
|
Queue: newQueue(
|
||||||
|
key.EditEvent{Range: key.Range{Start: 0, End: 0}, Text: "ab1"},
|
||||||
|
key.SelectionEvent{Start: 4, End: 4},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
cache := text.NewCache(gofont.Collection())
|
||||||
|
fontSize := unit.Sp(10)
|
||||||
|
font := text.Font{}
|
||||||
|
e.Layout(gtx, cache, font, fontSize, nil)
|
||||||
|
|
||||||
|
if got, want := e.Text(), "12345678"; got != want {
|
||||||
|
t.Errorf("editor failed to filter EditEvent")
|
||||||
|
}
|
||||||
|
if start, end := e.Selection(); start != 2 || end != 2 {
|
||||||
|
t.Errorf("editor failed to adjust SelectionEvent")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func textWidth(e *Editor, lineNum, colStart, colEnd int) float32 {
|
func textWidth(e *Editor, lineNum, colStart, colEnd int) float32 {
|
||||||
var w fixed.Int26_6
|
var w fixed.Int26_6
|
||||||
glyphs := e.lines[lineNum].Layout.Glyphs
|
glyphs := e.lines[lineNum].Layout.Glyphs
|
||||||
|
|||||||
Reference in New Issue
Block a user