~whereswaldon/rosebud

3d729ef9df4ddbeb975a2c4f00d2b37f22bf5dba — Chris Waldon 1 year, 2 months ago 37d92b5
appwidget: fix many small editing bugs

This commit fixes the following:

- the form type used to keep a slice of appwidget.TxEditor and append to it.
  When the underlying slice grew, it would be forced to copy the first few
  editors into a new slice. This made their addresses change, thus invalidating
  the input tags that they were using and making the active editor lose focus.
- when tabbing to move between editors, the TxEditor accidentally passed events
  into the underlying editor that the editor wasn't looking for. This made the
  editor behave very strangely, inserting characters in the wrong order.
- when typing in the editor, we now only show suggestions when you modify the
  text and it does not match the most recently applied suggestion.
- we now dismiss the suggestor when the editor loses focus.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
1 files changed, 14 insertions(+), 9 deletions(-)

M appwidget/tx-editor.go
M appwidget/tx-editor.go => appwidget/tx-editor.go +14 -9
@@ 1,7 1,6 @@
package appwidget

import (
	"log"
	"strings"

	"gioui.org/io/event"


@@ 121,11 120,12 @@ type TxChangedEvent struct{}
func (TxChangedEvent) ImplementsEvent() {}

type TxEditor struct {
	Editor           widget.Editor
	Suggestor        Suggestor[string]
	suggesting       bool
	suggestionEvents []suggestionEvent
	externalEvents   []interface{}
	Editor            widget.Editor
	appliedSuggestion string
	Suggestor         Suggestor[string]
	suggesting        bool
	suggestionEvents  []suggestionEvent
	externalEvents    []interface{}
}

func (e *TxEditor) suggestEvents() []suggestionEvent {


@@ 146,7 146,6 @@ func (e *TxEditor) Suggesting() bool {

func (e *TxEditor) SetSuggestions(suggestions []string) {
	e.Suggestor.Entities = suggestions
	log.Printf("set suggestions: %v", suggestions)
}

// ApplySuggestion replaces what the user has typed with a properly-formed


@@ 154,6 153,7 @@ func (e *TxEditor) SetSuggestions(suggestions []string) {
func (e *TxEditor) applySuggestion(event SuggestionAcceptedEvent[string]) {
	e.suggesting = false
	e.Editor.SetText(event.Suggestion)
	e.appliedSuggestion = event.Suggestion
	e.externalEvents = append(e.externalEvents, TxChangedEvent{})
}



@@ 174,6 174,10 @@ func (e *TxEditor) processBodyEvents(keyEvents []event.Event) []event.Event {
		event := keyEvents[i]
		var dropEvent bool
		switch event := event.(type) {
		case key.FocusEvent:
			if !event.Focus {
				e.suggesting = false
			}
		case key.Event:
			switch event.Name {
			case key.NameEscape:


@@ 221,7 225,7 @@ func (e *TxEditor) Layout(gtx C, editor layout.Widget) D {
	for _, event := range e.Editor.Events() {
		switch event.(type) {
		case widget.ChangeEvent:
			if e.Editor.Text() != "" {
			if txt := e.Editor.Text(); txt != e.appliedSuggestion && txt != "" {
				e.suggesting = true
				op.InvalidateOp{}.Add(gtx.Ops)
			}


@@ 236,8 240,9 @@ func (e *TxEditor) Layout(gtx C, editor layout.Widget) D {
	// Intercept and filter events on their way to the editor.
	tag := e.Editor.KeyTag()
	editorKeys := gtx.Events(tag)
	editorKeys = append(editorKeys, gtx.Events(e)...)
	ourKeys := gtx.Events(e)
	editorKeys = e.processBodyEvents(editorKeys)
	e.processBodyEvents(ourKeys)

	key.InputOp{
		Tag:  e,