all: use a single tag per widget for event handling

With the introduction of filters, it is now possible to have one tag per
widget by convention. Note that gestures still have their own tags, for
disambiguation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-11-25 14:36:00 -06:00
parent c515b7804e
commit 75314fcee2
4 changed files with 23 additions and 25 deletions
+4 -5
View File
@@ -21,7 +21,6 @@ type Clickable struct {
click gesture.Click click gesture.Click
history []Press history []Press
keyTag struct{}
requestClicks int requestClicks int
focused bool focused bool
pressedKey key.Name pressedKey key.Name
@@ -69,7 +68,7 @@ func (b *Clickable) Pressed() bool {
// Focus requests the input focus for the element. // Focus requests the input focus for the element.
func (b *Clickable) Focus(gtx layout.Context) { func (b *Clickable) Focus(gtx layout.Context) {
gtx.Execute(key.FocusCmd{Tag: &b.keyTag}) gtx.Execute(key.FocusCmd{Tag: b})
} }
// Focused reports whether b has focus. // Focused reports whether b has focus.
@@ -97,7 +96,7 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension
defer clip.Rect(image.Rectangle{Max: dims.Size}).Push(gtx.Ops).Pop() defer clip.Rect(image.Rectangle{Max: dims.Size}).Push(gtx.Ops).Pop()
semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops) semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops)
b.click.Add(gtx.Ops) b.click.Add(gtx.Ops)
event.InputOp(gtx.Ops, &b.keyTag) event.InputOp(gtx.Ops, b)
c.Add(gtx.Ops) c.Add(gtx.Ops)
return dims return dims
} }
@@ -141,7 +140,7 @@ func (b *Clickable) Update(gtx layout.Context) (Click, bool) {
} }
case gesture.KindPress: case gesture.KindPress:
if e.Source == pointer.Mouse { if e.Source == pointer.Mouse {
gtx.Execute(key.FocusCmd{Tag: &b.keyTag}) gtx.Execute(key.FocusCmd{Tag: b})
} }
b.history = append(b.history, Press{ b.history = append(b.history, Press{
Position: e.Position, Position: e.Position,
@@ -156,7 +155,7 @@ func (b *Clickable) Update(gtx layout.Context) (Click, bool) {
filters = append(filters, key.Filter{Name: key.NameReturn}, key.Filter{Name: key.NameSpace}) filters = append(filters, key.Filter{Name: key.NameReturn}, key.Filter{Name: key.NameSpace})
} }
for { for {
e, ok := gtx.Event(&b.keyTag, filters...) e, ok := gtx.Event(b, filters...)
if !ok { if !ok {
break break
} }
+6 -7
View File
@@ -18,10 +18,9 @@ type Draggable struct {
// Type contains the MIME type and matches transfer.SourceOp. // Type contains the MIME type and matches transfer.SourceOp.
Type string Type string
handle struct{} drag gesture.Drag
drag gesture.Drag click f32.Point
click f32.Point pos f32.Point
pos f32.Point
} }
func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions { func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions {
@@ -32,7 +31,7 @@ func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dim
stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops) stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
d.drag.Add(gtx.Ops) d.drag.Add(gtx.Ops)
event.InputOp(gtx.Ops, &d.handle) event.InputOp(gtx.Ops, d)
stack.Pop() stack.Pop()
if drag != nil && d.drag.Pressed() { if drag != nil && d.drag.Pressed() {
@@ -66,7 +65,7 @@ func (d *Draggable) Update(gtx layout.Context) (mime string, requested bool) {
d.pos = pos d.pos = pos
for { for {
e, ok := gtx.Event(&d.handle, transfer.SourceFilter{Type: d.Type}) e, ok := gtx.Event(d, transfer.SourceFilter{Type: d.Type})
if !ok { if !ok {
break break
} }
@@ -80,7 +79,7 @@ func (d *Draggable) Update(gtx layout.Context) (mime string, requested bool) {
// Offer the data ready for a drop. Must be called after being Requested. // Offer the data ready for a drop. Must be called after being Requested.
// The mime must be one in the requested list. // The mime must be one in the requested list.
func (d *Draggable) Offer(gtx layout.Context, mime string, data io.ReadCloser) { func (d *Draggable) Offer(gtx layout.Context, mime string, data io.ReadCloser) {
gtx.Execute(transfer.OfferCmd{Tag: &d.handle, Type: mime, Data: data}) gtx.Execute(transfer.OfferCmd{Tag: d, Type: mime, Data: data})
} }
// Pos returns the drag position relative to its initial click position. // Pos returns the drag position relative to its initial click position.
+6 -5
View File
@@ -25,16 +25,17 @@ func TestDraggable(t *testing.T) {
drag := &Draggable{ drag := &Draggable{
Type: "file", Type: "file",
} }
tgt := new(int)
defer pointer.PassOp{}.Push(gtx.Ops).Pop() defer pointer.PassOp{}.Push(gtx.Ops).Pop()
dims := drag.Layout(gtx, func(gtx layout.Context) layout.Dimensions { dims := drag.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Dimensions{Size: gtx.Constraints.Min} return layout.Dimensions{Size: gtx.Constraints.Min}
}, nil) }, nil)
stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops) stack := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
event.InputOp(gtx.Ops, drag) event.InputOp(gtx.Ops, tgt)
stack.Pop() stack.Pop()
drag.Update(gtx) drag.Update(gtx)
r.Event(drag, transfer.TargetFilter{Type: drag.Type}) r.Event(tgt, transfer.TargetFilter{Type: drag.Type})
r.Frame(gtx.Ops) r.Frame(gtx.Ops)
r.Queue( r.Queue(
pointer.Event{ pointer.Event{
@@ -52,10 +53,10 @@ func TestDraggable(t *testing.T) {
) )
ofr := &offer{data: "hello"} ofr := &offer{data: "hello"}
drag.Update(gtx) drag.Update(gtx)
r.Event(drag, transfer.TargetFilter{Type: drag.Type}) r.Event(tgt, transfer.TargetFilter{Type: drag.Type})
drag.Offer(gtx, "file", ofr) drag.Offer(gtx, "file", ofr)
e, ok := r.Event(drag, transfer.TargetFilter{Type: drag.Type}) e, ok := r.Event(tgt, transfer.TargetFilter{Type: drag.Type})
if !ok { if !ok {
t.Fatalf("expected event") t.Fatalf("expected event")
} }
@@ -66,7 +67,7 @@ func TestDraggable(t *testing.T) {
if ofr.closed { if ofr.closed {
t.Error("offer closed prematurely") t.Error("offer closed prematurely")
} }
e, ok = r.Event(drag, transfer.TargetFilter{Type: drag.Type}) e, ok = r.Event(tgt, transfer.TargetFilter{Type: drag.Type})
if !ok { if !ok {
t.Fatalf("expected event") t.Fatalf("expected event")
} }
+7 -8
View File
@@ -71,7 +71,6 @@ type Editor struct {
// scratch is a byte buffer that is reused to efficiently read portions of text // scratch is a byte buffer that is reused to efficiently read portions of text
// from the textView. // from the textView.
scratch []byte scratch []byte
eventKey int
blinkStart time.Time blinkStart time.Time
focused bool focused bool
@@ -381,7 +380,7 @@ func (e *Editor) processKey(gtx layout.Context) {
// adjust keeps track of runes dropped because of MaxLen. // adjust keeps track of runes dropped because of MaxLen.
var adjust int var adjust int
for { for {
ke, ok := gtx.Event(&e.eventKey, filters...) ke, ok := gtx.Event(e, filters...)
if !ok { if !ok {
break break
} }
@@ -479,7 +478,7 @@ func (e *Editor) command(gtx layout.Context, k key.Event) {
// half is in Editor.processKey() under clipboard.Event. // half is in Editor.processKey() under clipboard.Event.
case "V": case "V":
if !e.ReadOnly { if !e.ReadOnly {
gtx.Execute(clipboard.ReadCmd{Tag: &e.eventKey}) gtx.Execute(clipboard.ReadCmd{Tag: e})
} }
// Copy or Cut selection -- ignored if nothing selected. // Copy or Cut selection -- ignored if nothing selected.
case "C", "X": case "C", "X":
@@ -560,7 +559,7 @@ func (e *Editor) command(gtx layout.Context, k key.Event) {
// Focus requests the input focus for the Editor. // Focus requests the input focus for the Editor.
func (e *Editor) Focus(gtx layout.Context) { func (e *Editor) Focus(gtx layout.Context) {
gtx.Execute(key.FocusCmd{Tag: &e.eventKey}) gtx.Execute(key.FocusCmd{Tag: e})
gtx.Execute(key.SoftKeyboardCmd{Show: true}) gtx.Execute(key.SoftKeyboardCmd{Show: true})
} }
@@ -605,7 +604,7 @@ func (e *Editor) Update(gtx layout.Context) {
} }
if newSel != e.ime.selection { if newSel != e.ime.selection {
e.ime.selection = newSel e.ime.selection = newSel
gtx.Execute(key.SelectionCmd{Tag: &e.eventKey, Range: newSel.rng, Caret: newSel.caret}) gtx.Execute(key.SelectionCmd{Tag: e, Range: newSel.rng, Caret: newSel.caret})
} }
e.updateSnippet(gtx, e.ime.start, e.ime.end) e.updateSnippet(gtx, e.ime.start, e.ime.end)
@@ -662,7 +661,7 @@ func (e *Editor) updateSnippet(gtx layout.Context, start, end int) {
return return
} }
e.ime.snippet = newSnip e.ime.snippet = newSnip
gtx.Execute(key.SnippetCmd{Tag: &e.eventKey, Snippet: newSnip}) gtx.Execute(key.SnippetCmd{Tag: e, Snippet: newSnip})
} }
func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.CallOp) layout.Dimensions { func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.CallOp) layout.Dimensions {
@@ -677,8 +676,8 @@ func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.Call
defer clip.Rect(image.Rectangle{Max: visibleDims.Size}).Push(gtx.Ops).Pop() defer clip.Rect(image.Rectangle{Max: visibleDims.Size}).Push(gtx.Ops).Pop()
pointer.CursorText.Add(gtx.Ops) pointer.CursorText.Add(gtx.Ops)
event.InputOp(gtx.Ops, &e.eventKey) event.InputOp(gtx.Ops, e)
key.InputHintOp{Tag: &e.eventKey, Hint: e.InputHint}.Add(gtx.Ops) key.InputHintOp{Tag: e, Hint: e.InputHint}.Add(gtx.Ops)
e.scroller.Add(gtx.Ops) e.scroller.Add(gtx.Ops)