~pierrec/giox

ref: c164e218831e giox/widgetx/input.go -rw-r--r-- 2.6 KiB
c164e218Pierre Curto cm/iconx: update the set of icons 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package widgetx

import (
	"gioui.org/io/key"
	"gioui.org/layout"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/x/eventx"
)

type Input struct {
	Padding   unit.Value
	Leading   layout.Widget
	Trailing  layout.Widget
	Editor    *widget.Editor
	NoUnfocus bool // disables ESC to unfocus

	changed   bool
	submitted bool
	text      string // cached text from the Editor, only updated upon Editor changes
}

func (in *Input) update() {
	// Look for changes in the search text.
	// If changed, cache the new text string.
	for _, ev := range in.Editor.Events() {
		switch ev.(type) {
		case widget.SubmitEvent:
			in.submitted = true
		case widget.ChangeEvent:
		default:
			continue
		}
		in.changed = true
		in.text = in.Editor.Text()
		break
	}
}

func (in *Input) Layout(gtx layout.Context, ed layout.Widget) layout.Dimensions {
	in.update()
	gtx.Constraints.Max.X = gtx.Constraints.Min.X
	inPadding := layout.UniformInset(in.Padding)
	return inPadding.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
		return layout.Flex{
			Axis:      layout.Horizontal,
			Alignment: layout.Middle,
		}.Layout(gtx,
			layout.Rigid(func(gtx layout.Context) layout.Dimensions {
				if w := in.Leading; w != nil {
					return layout.Inset{Right: in.Padding}.Layout(gtx, w)
				}
				return layout.Dimensions{}
			}),
			layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
				if in.NoUnfocus {
					return ed(gtx)
				}
				spy, gtx := eventx.Enspy(gtx)
				dims := ed(gtx)
				// Catch the ESC key being pressed to release the widget's focus.
				for _, g := range spy.AllEvents() {
					for _, ev := range g.Items {
						if ev, ok := ev.(key.Event); ok && ev.Name == key.NameEscape {
							key.FocusOp{}.Add(gtx.Ops)
							break
						}
					}
				}
				return dims
			}),
			layout.Rigid(func(gtx layout.Context) layout.Dimensions {
				if w := in.Trailing; w != nil {
					return layout.Inset{Left: in.Padding}.Layout(gtx, w)
				}
				return layout.Dimensions{}
			}),
		)
	})
}

func (in *Input) Focused() bool {
	return in.Editor.Focused()
}

func (in *Input) Focus() {
	in.Editor.Focus()
}

// Clear clears the input text. It does not change the active state.
func (in *Input) Clear() {
	in.changed = true
	in.text = ""
	in.Editor.SetText("")
}

// Text returns the current input text.
func (in *Input) Text() string {
	return in.text
}

// Changed returns whether or not the text input has changed since last call.
func (in *Input) Changed() bool {
	changed := in.changed
	in.changed = false
	return changed
}

func (in *Input) Submitted() bool {
	submitted := in.submitted
	in.submitted = false
	in.changed = false
	return submitted
}