mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget{,/material}: rebuild label and editor with textView
This commit rebuilds the editor and label types on the common foundation provided by textView. This enables labels to have optional state that makes them selectable, and allows the two widgets to share the code for managing cursor positions, displaying selections, and soforth. Labels now have an additional Layout function which can be invoked if they have a Selectable. It accepts a layout.Widget used to paint their contents. Stateless labels should still use the old Layout method. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package widget
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"testing"
|
||||
|
||||
"gioui.org/font/gofont"
|
||||
"gioui.org/io/key"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op"
|
||||
"gioui.org/text"
|
||||
"gioui.org/unit"
|
||||
)
|
||||
|
||||
func TestSelectableZeroValue(t *testing.T) {
|
||||
var s Selectable
|
||||
if s.Text() != "" {
|
||||
t.Errorf("expected zero value to have no text, got %q", s.Text())
|
||||
}
|
||||
if start, end := s.Selection(); start != 0 || end != 0 {
|
||||
t.Errorf("expected start=0, end=0, got start=%d, end=%d", start, end)
|
||||
}
|
||||
if selected := s.SelectedText(); selected != "" {
|
||||
t.Errorf("expected selected text to be \"\", got %q", selected)
|
||||
}
|
||||
s.SetCaret(5, 5)
|
||||
if start, end := s.Selection(); start != 0 || end != 0 {
|
||||
t.Errorf("expected start=0, end=0, got start=%d, end=%d", start, end)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that an existing selection is dismissed when you press arrow keys.
|
||||
func TestSelectableMove(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Locale: english,
|
||||
}
|
||||
cache := text.NewShaper(gofont.Collection())
|
||||
font := text.Font{}
|
||||
fontSize := unit.Sp(10)
|
||||
|
||||
str := `0123456789`
|
||||
|
||||
// Layout once to populate e.lines and get focus.
|
||||
gtx.Queue = newQueue(key.FocusEvent{Focus: true})
|
||||
s := new(Selectable)
|
||||
|
||||
w := func(layout.Context) layout.Dimensions { return layout.Dimensions{} }
|
||||
Label{
|
||||
Selectable: s,
|
||||
}.LayoutSelectable(gtx, cache, text.Font{}, fontSize, str, w)
|
||||
|
||||
testKey := func(keyName string) {
|
||||
// Select 345
|
||||
s.SetCaret(3, 6)
|
||||
if start, end := s.Selection(); start != 3 || end != 6 {
|
||||
t.Errorf("expected start=%d, end=%d, got start=%d, end=%d", 3, 6, start, end)
|
||||
}
|
||||
if expected, got := "345", s.SelectedText(); expected != got {
|
||||
t.Errorf("KeyName %s, expected %q, got %q", keyName, expected, got)
|
||||
}
|
||||
|
||||
// Press the key
|
||||
gtx.Queue = newQueue(key.Event{State: key.Press, Name: keyName})
|
||||
Label{
|
||||
Selectable: s,
|
||||
}.LayoutSelectable(gtx, cache, font, fontSize, str, w)
|
||||
|
||||
if expected, got := "", s.SelectedText(); expected != got {
|
||||
t.Errorf("KeyName %s, expected %q, got %q", keyName, expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
testKey(key.NameLeftArrow)
|
||||
testKey(key.NameRightArrow)
|
||||
testKey(key.NameUpArrow)
|
||||
testKey(key.NameDownArrow)
|
||||
}
|
||||
|
||||
func TestSelectableConfigurations(t *testing.T) {
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Exact(image.Pt(300, 300)),
|
||||
Locale: english,
|
||||
}
|
||||
cache := text.NewShaper(gofont.Collection())
|
||||
fontSize := unit.Sp(10)
|
||||
font := text.Font{}
|
||||
sentence := "\n\n\n\n\n\n\n\n\n\n\n\nthe quick brown fox jumps over the lazy dog"
|
||||
w := func(layout.Context) layout.Dimensions { return layout.Dimensions{} }
|
||||
|
||||
for _, alignment := range []text.Alignment{text.Start, text.Middle, text.End} {
|
||||
for _, zeroMin := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("Alignment: %v ZeroMinConstraint: %v", alignment, zeroMin), func(t *testing.T) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
if zeroMin {
|
||||
gtx.Constraints.Min = image.Point{}
|
||||
} else {
|
||||
gtx.Constraints.Min = gtx.Constraints.Max
|
||||
}
|
||||
s := new(Selectable)
|
||||
label := Label{
|
||||
Alignment: alignment,
|
||||
Selectable: s,
|
||||
}
|
||||
interactiveDims := label.LayoutSelectable(gtx, cache, font, fontSize, sentence, w)
|
||||
staticDims := label.Layout(gtx, cache, font, fontSize, sentence)
|
||||
|
||||
if interactiveDims != staticDims {
|
||||
t.Errorf("expected consistent dimensions, static returned %#+v, interactive returned %#+v", staticDims, interactiveDims)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user