mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 02:15:34 +00:00
widget: remove assumption that Context.Queue is an interface
We're about to make Context.Queue a concrete type, and this change replaces code that relies on Queue being an interface. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+86
-71
@@ -20,9 +20,9 @@ import (
|
|||||||
"gioui.org/font"
|
"gioui.org/font"
|
||||||
"gioui.org/font/gofont"
|
"gioui.org/font/gofont"
|
||||||
"gioui.org/font/opentype"
|
"gioui.org/font/opentype"
|
||||||
"gioui.org/io/event"
|
|
||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
|
"gioui.org/io/router"
|
||||||
"gioui.org/io/system"
|
"gioui.org/io/system"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
@@ -96,17 +96,14 @@ func assertContents(t *testing.T, e *Editor, contents string, selectionStart, se
|
|||||||
// TestEditorReadOnly ensures that mouse and keyboard interactions with readonly
|
// TestEditorReadOnly ensures that mouse and keyboard interactions with readonly
|
||||||
// editors do nothing but manipulate the text selection.
|
// editors do nothing but manipulate the text selection.
|
||||||
func TestEditorReadOnly(t *testing.T) {
|
func TestEditorReadOnly(t *testing.T) {
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Constraints{
|
Constraints: layout.Constraints{
|
||||||
Max: image.Pt(100, 100),
|
Max: image.Pt(100, 100),
|
||||||
},
|
},
|
||||||
Locale: english,
|
Locale: english,
|
||||||
}
|
Queue: r,
|
||||||
gtx.Queue = &testQueue{
|
|
||||||
events: []event.Event{
|
|
||||||
key.FocusEvent{Focus: true},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
@@ -118,12 +115,20 @@ func TestEditorReadOnly(t *testing.T) {
|
|||||||
if cStart != cEnd {
|
if cStart != cEnd {
|
||||||
t.Errorf("unexpected initial caret positions")
|
t.Errorf("unexpected initial caret positions")
|
||||||
}
|
}
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Focus()
|
||||||
|
layoutEditor := func() layout.Dimensions {
|
||||||
|
return e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
}
|
||||||
|
layoutEditor()
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
gtx.Ops.Reset()
|
||||||
|
layoutEditor()
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
|
||||||
// Select everything.
|
// Select everything.
|
||||||
gtx.Ops.Reset()
|
gtx.Ops.Reset()
|
||||||
gtx.Queue = &testQueue{events: []event.Event{key.Event{Name: "A", Modifiers: key.ModShortcut}}}
|
r.Queue(key.Event{Name: "A", Modifiers: key.ModShortcut})
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
layoutEditor()
|
||||||
textContent := e.Text()
|
textContent := e.Text()
|
||||||
cStart2, cEnd2 := e.Selection()
|
cStart2, cEnd2 := e.Selection()
|
||||||
if cStart2 > cEnd2 {
|
if cStart2 > cEnd2 {
|
||||||
@@ -138,7 +143,7 @@ func TestEditorReadOnly(t *testing.T) {
|
|||||||
|
|
||||||
// Type some new characters.
|
// Type some new characters.
|
||||||
gtx.Ops.Reset()
|
gtx.Ops.Reset()
|
||||||
gtx.Queue = &testQueue{events: []event.Event{key.EditEvent{Range: key.Range{Start: cStart2, End: cEnd2}, Text: "something else"}}}
|
r.Queue(key.EditEvent{Range: key.Range{Start: cStart2, End: cEnd2}, Text: "something else"})
|
||||||
e.Update(gtx)
|
e.Update(gtx)
|
||||||
textContent2 := e.Text()
|
textContent2 := e.Text()
|
||||||
if textContent2 != textContent {
|
if textContent2 != textContent {
|
||||||
@@ -147,8 +152,8 @@ func TestEditorReadOnly(t *testing.T) {
|
|||||||
|
|
||||||
// Try to delete selection.
|
// Try to delete selection.
|
||||||
gtx.Ops.Reset()
|
gtx.Ops.Reset()
|
||||||
gtx.Queue = &testQueue{events: []event.Event{key.Event{Name: key.NameDeleteBackward}}}
|
r.Queue(key.Event{Name: key.NameDeleteBackward})
|
||||||
dims := e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
dims := layoutEditor()
|
||||||
textContent2 = e.Text()
|
textContent2 = e.Text()
|
||||||
if textContent2 != textContent {
|
if textContent2 != textContent {
|
||||||
t.Errorf("readonly editor modified by delete key.Event")
|
t.Errorf("readonly editor modified by delete key.Event")
|
||||||
@@ -157,14 +162,14 @@ func TestEditorReadOnly(t *testing.T) {
|
|||||||
// Click and drag from the middle of the first line
|
// Click and drag from the middle of the first line
|
||||||
// to the center.
|
// to the center.
|
||||||
gtx.Ops.Reset()
|
gtx.Ops.Reset()
|
||||||
gtx.Queue = &testQueue{events: []event.Event{
|
r.Queue(
|
||||||
pointer.Event{
|
pointer.Event{
|
||||||
Kind: pointer.Press,
|
Kind: pointer.Press,
|
||||||
Buttons: pointer.ButtonPrimary,
|
Buttons: pointer.ButtonPrimary,
|
||||||
Position: f32.Pt(float32(dims.Size.X)*.5, 5),
|
Position: f32.Pt(float32(dims.Size.X)*.5, 5),
|
||||||
},
|
},
|
||||||
pointer.Event{
|
pointer.Event{
|
||||||
Kind: pointer.Drag,
|
Kind: pointer.Move,
|
||||||
Buttons: pointer.ButtonPrimary,
|
Buttons: pointer.ButtonPrimary,
|
||||||
Position: layout.FPt(dims.Size).Mul(.5),
|
Position: layout.FPt(dims.Size).Mul(.5),
|
||||||
},
|
},
|
||||||
@@ -173,7 +178,7 @@ func TestEditorReadOnly(t *testing.T) {
|
|||||||
Buttons: pointer.ButtonPrimary,
|
Buttons: pointer.ButtonPrimary,
|
||||||
Position: layout.FPt(dims.Size).Mul(.5),
|
Position: layout.FPt(dims.Size).Mul(.5),
|
||||||
},
|
},
|
||||||
}}
|
)
|
||||||
e.Update(gtx)
|
e.Update(gtx)
|
||||||
cStart3, cEnd3 := e.Selection()
|
cStart3, cEnd3 := e.Selection()
|
||||||
if cStart3 == cStart2 || cEnd3 == cEnd2 {
|
if cStart3 == cStart2 || cEnd3 == cEnd2 {
|
||||||
@@ -496,22 +501,22 @@ func TestEditorLigature(t *testing.T) {
|
|||||||
|
|
||||||
func TestEditorDimensions(t *testing.T) {
|
func TestEditorDimensions(t *testing.T) {
|
||||||
e := new(Editor)
|
e := new(Editor)
|
||||||
tq := &testQueue{
|
r := new(router.Router)
|
||||||
events: []event.Event{
|
|
||||||
key.EditEvent{Text: "A"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Constraints{Max: image.Pt(100, 100)},
|
Constraints: layout.Constraints{Max: image.Pt(100, 100)},
|
||||||
Queue: tq,
|
Queue: r,
|
||||||
Locale: english,
|
Locale: english,
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
|
e.Focus()
|
||||||
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
r.Queue(key.EditEvent{Text: "A"})
|
||||||
dims := e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
dims := e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
if dims.Size.X == 0 {
|
if dims.Size.X < 5 {
|
||||||
t.Errorf("EditEvent was not reflected in Editor width")
|
t.Errorf("EditEvent was not reflected in Editor width")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -882,9 +887,11 @@ f 2 4 6 8 f
|
|||||||
g 2 4 6 8 g
|
g 2 4 6 8 g
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Locale: english,
|
Locale: english,
|
||||||
|
Queue: r,
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
@@ -895,30 +902,30 @@ g 2 4 6 8 g
|
|||||||
// Layout once with no events; populate e.lines.
|
// Layout once with no events; populate e.lines.
|
||||||
gtx.Queue = nil
|
gtx.Queue = nil
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
_ = e.Events() // throw away any events from this layout
|
e.Events() // throw away any events from this layout
|
||||||
|
|
||||||
|
e.Focus()
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
gtx.Queue = r
|
||||||
// Build the selection events
|
// Build the selection events
|
||||||
startPos := e.text.closestToRune(start)
|
startPos := e.text.closestToRune(start)
|
||||||
endPos := e.text.closestToRune(end)
|
endPos := e.text.closestToRune(end)
|
||||||
tq := &testQueue{
|
r.Queue(
|
||||||
events: []event.Event{
|
pointer.Event{
|
||||||
pointer.Event{
|
Buttons: pointer.ButtonPrimary,
|
||||||
Buttons: pointer.ButtonPrimary,
|
Kind: pointer.Press,
|
||||||
Kind: pointer.Press,
|
Source: pointer.Mouse,
|
||||||
Source: pointer.Mouse,
|
Time: tim,
|
||||||
Time: tim,
|
Position: f32.Pt(textWidth(e, startPos.lineCol.line, 0, startPos.lineCol.col), textBaseline(e, startPos.lineCol.line)),
|
||||||
Position: f32.Pt(textWidth(e, startPos.lineCol.line, 0, startPos.lineCol.col), textBaseline(e, startPos.lineCol.line)),
|
|
||||||
},
|
|
||||||
pointer.Event{
|
|
||||||
Kind: pointer.Release,
|
|
||||||
Source: pointer.Mouse,
|
|
||||||
Time: tim,
|
|
||||||
Position: f32.Pt(textWidth(e, endPos.lineCol.line, 0, endPos.lineCol.col), textBaseline(e, endPos.lineCol.line)),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
pointer.Event{
|
||||||
|
Kind: pointer.Release,
|
||||||
|
Source: pointer.Mouse,
|
||||||
|
Time: tim,
|
||||||
|
Position: f32.Pt(textWidth(e, endPos.lineCol.line, 0, endPos.lineCol.col), textBaseline(e, endPos.lineCol.line)),
|
||||||
|
},
|
||||||
|
)
|
||||||
tim += time.Second // Avoid multi-clicks.
|
tim += time.Second // Avoid multi-clicks.
|
||||||
gtx.Queue = tq
|
|
||||||
|
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
for _, evt := range e.Events() {
|
for _, evt := range e.Events() {
|
||||||
@@ -980,19 +987,27 @@ func TestSelectMove(t *testing.T) {
|
|||||||
e := new(Editor)
|
e := new(Editor)
|
||||||
e.SetText(`0123456789`)
|
e.SetText(`0123456789`)
|
||||||
|
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Locale: english,
|
Locale: english,
|
||||||
|
Queue: r,
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
|
|
||||||
// Layout once to populate e.lines and get focus.
|
// Layout once to populate e.lines and get focus.
|
||||||
gtx.Queue = newQueue(key.FocusEvent{Focus: true})
|
e.Focus()
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
// Set up selecton so the Editor key handler filters for all 4 directional keys.
|
||||||
|
e.SetCaret(3, 6)
|
||||||
|
gtx.Ops.Reset()
|
||||||
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
|
||||||
testKey := func(keyName string) {
|
for _, keyName := range []string{key.NameLeftArrow, key.NameRightArrow, key.NameUpArrow, key.NameDownArrow} {
|
||||||
// Select 345
|
// Select 345
|
||||||
e.SetCaret(3, 6)
|
e.SetCaret(3, 6)
|
||||||
if expected, got := "345", e.SelectedText(); expected != got {
|
if expected, got := "345", e.SelectedText(); expected != got {
|
||||||
@@ -1000,18 +1015,15 @@ func TestSelectMove(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Press the key
|
// Press the key
|
||||||
gtx.Queue = newQueue(key.Event{State: key.Press, Name: keyName})
|
r.Queue(key.Event{State: key.Press, Name: keyName})
|
||||||
|
gtx.Ops.Reset()
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
|
||||||
if expected, got := "", e.SelectedText(); expected != got {
|
if expected, got := "", e.SelectedText(); expected != got {
|
||||||
t.Errorf("KeyName %s, expected %q, got %q", keyName, 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 TestEditor_Read(t *testing.T) {
|
func TestEditor_Read(t *testing.T) {
|
||||||
@@ -1064,17 +1076,22 @@ func TestEditor_MaxLen(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e.SetText("2345678")
|
e.SetText("2345678")
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||||
Queue: newQueue(
|
Queue: r,
|
||||||
key.EditEvent{Range: key.Range{Start: 0, End: 2}, Text: "1234"},
|
|
||||||
key.SelectionEvent{Start: 4, End: 4},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
|
e.Focus()
|
||||||
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
r.Queue(
|
||||||
|
key.EditEvent{Range: key.Range{Start: 0, End: 2}, Text: "1234"},
|
||||||
|
key.SelectionEvent{Start: 4, End: 4},
|
||||||
|
)
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
|
||||||
if got, want := e.Text(), "12345678"; got != want {
|
if got, want := e.Text(), "12345678"; got != want {
|
||||||
@@ -1095,17 +1112,22 @@ func TestEditor_Filter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e.SetText("2345678")
|
e.SetText("2345678")
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||||
Queue: newQueue(
|
Queue: r,
|
||||||
key.EditEvent{Range: key.Range{Start: 0, End: 0}, Text: "ab1"},
|
|
||||||
key.SelectionEvent{Start: 4, End: 4},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
|
e.Focus()
|
||||||
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
r.Queue(
|
||||||
|
key.EditEvent{Range: key.Range{Start: 0, End: 0}, Text: "ab1"},
|
||||||
|
key.SelectionEvent{Start: 4, End: 4},
|
||||||
|
)
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
|
||||||
if got, want := e.Text(), "12345678"; got != want {
|
if got, want := e.Text(), "12345678"; got != want {
|
||||||
@@ -1120,16 +1142,21 @@ func TestEditor_Submit(t *testing.T) {
|
|||||||
e := new(Editor)
|
e := new(Editor)
|
||||||
e.Submit = true
|
e.Submit = true
|
||||||
|
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Constraints: layout.Exact(image.Pt(100, 100)),
|
Constraints: layout.Exact(image.Pt(100, 100)),
|
||||||
Queue: newQueue(
|
Queue: r,
|
||||||
key.EditEvent{Range: key.Range{Start: 0, End: 0}, Text: "ab1\n"},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fontSize := unit.Sp(10)
|
fontSize := unit.Sp(10)
|
||||||
font := font.Font{}
|
font := font.Font{}
|
||||||
|
e.Focus()
|
||||||
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
r.Queue(
|
||||||
|
key.EditEvent{Range: key.Range{Start: 0, End: 0}, Text: "ab1\n"},
|
||||||
|
)
|
||||||
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
|
||||||
if got, want := e.Text(), "ab1"; got != want {
|
if got, want := e.Text(), "ab1"; got != want {
|
||||||
@@ -1164,15 +1191,3 @@ func textBaseline(e *Editor, lineNum int) float32 {
|
|||||||
start := e.text.closestToLineCol(lineNum, 0)
|
start := e.text.closestToLineCol(lineNum, 0)
|
||||||
return float32(start.y)
|
return float32(start.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
type testQueue struct {
|
|
||||||
events []event.Event
|
|
||||||
}
|
|
||||||
|
|
||||||
func newQueue(e ...event.Event) *testQueue {
|
|
||||||
return &testQueue{events: e}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *testQueue) Events(_ event.Tag) []event.Event {
|
|
||||||
return q.events
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"gioui.org/font"
|
"gioui.org/font"
|
||||||
"gioui.org/font/gofont"
|
"gioui.org/font/gofont"
|
||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
|
"gioui.org/io/router"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
@@ -33,9 +34,11 @@ func TestSelectableZeroValue(t *testing.T) {
|
|||||||
|
|
||||||
// Verify that an existing selection is dismissed when you press arrow keys.
|
// Verify that an existing selection is dismissed when you press arrow keys.
|
||||||
func TestSelectableMove(t *testing.T) {
|
func TestSelectableMove(t *testing.T) {
|
||||||
|
r := new(router.Router)
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: new(op.Ops),
|
Ops: new(op.Ops),
|
||||||
Locale: english,
|
Locale: english,
|
||||||
|
Queue: r,
|
||||||
}
|
}
|
||||||
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection()))
|
||||||
fnt := font.Font{}
|
fnt := font.Font{}
|
||||||
@@ -44,13 +47,18 @@ func TestSelectableMove(t *testing.T) {
|
|||||||
str := `0123456789`
|
str := `0123456789`
|
||||||
|
|
||||||
// Layout once to populate e.lines and get focus.
|
// Layout once to populate e.lines and get focus.
|
||||||
gtx.Queue = newQueue(key.FocusEvent{Focus: true})
|
|
||||||
s := new(Selectable)
|
s := new(Selectable)
|
||||||
|
|
||||||
|
s.Focus()
|
||||||
s.SetText(str)
|
s.SetText(str)
|
||||||
|
// Set up selection so the Selectable filters for all 4 directional keys.
|
||||||
s.Layout(gtx, cache, font.Font{}, fontSize, op.CallOp{}, op.CallOp{})
|
s.Layout(gtx, cache, font.Font{}, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
s.SetCaret(3, 6)
|
||||||
|
s.Layout(gtx, cache, font.Font{}, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
|
||||||
testKey := func(keyName string) {
|
for _, keyName := range []string{key.NameLeftArrow, key.NameRightArrow, key.NameUpArrow, key.NameDownArrow} {
|
||||||
// Select 345
|
// Select 345
|
||||||
s.SetCaret(3, 6)
|
s.SetCaret(3, 6)
|
||||||
if start, end := s.Selection(); start != 3 || end != 6 {
|
if start, end := s.Selection(); start != 3 || end != 6 {
|
||||||
@@ -61,19 +69,15 @@ func TestSelectableMove(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Press the key
|
// Press the key
|
||||||
gtx.Queue = newQueue(key.Event{State: key.Press, Name: keyName})
|
r.Queue(key.Event{State: key.Press, Name: keyName})
|
||||||
s.SetText(str)
|
s.SetText(str)
|
||||||
s.Layout(gtx, cache, fnt, fontSize, op.CallOp{}, op.CallOp{})
|
s.Layout(gtx, cache, fnt, fontSize, op.CallOp{}, op.CallOp{})
|
||||||
|
r.Frame(gtx.Ops)
|
||||||
|
|
||||||
if expected, got := "", s.SelectedText(); expected != got {
|
if expected, got := "", s.SelectedText(); expected != got {
|
||||||
t.Errorf("KeyName %s, expected %q, got %q", keyName, 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) {
|
func TestSelectableConfigurations(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user