...
1 package messeji
2
3 import (
4 "sync"
5
6 "github.com/hajimehoshi/ebiten/v2"
7 "github.com/hajimehoshi/ebiten/v2/inpututil"
8 "golang.org/x/image/font"
9 )
10
11
12
13
14
15
16 type InputField struct {
17 *TextField
18
19
20
21 changedFunc func(r rune) (accept bool)
22
23
24
25 selectedFunc func() (accept bool)
26
27
28 readBuffer []rune
29
30
31 keyBuffer []ebiten.Key
32
33
34 rawRuneBuffer []rune
35
36
37 rawKeyBuffer []ebiten.Key
38
39 sync.Mutex
40 }
41
42
43 func NewInputField(face font.Face, faceMutex *sync.Mutex) *InputField {
44 f := &InputField{
45 TextField: NewTextField(face, faceMutex),
46 }
47 f.TextField.suffix = "_"
48 return f
49 }
50
51
52
53 func (f *InputField) SetHandleKeyboard(handle bool) {
54 f.Lock()
55 defer f.Unlock()
56
57 f.handleKeyboard = handle
58 }
59
60
61
62 func (f *InputField) SetChangedFunc(changedFunc func(r rune) (accept bool)) {
63 f.changedFunc = changedFunc
64 }
65
66
67
68
69 func (f *InputField) SetSelectedFunc(selectedFunc func() (accept bool)) {
70 f.selectedFunc = selectedFunc
71 }
72
73
74 func (f *InputField) HandleKeyboardEvent(key ebiten.Key, r rune) (handled bool, err error) {
75 f.Lock()
76 defer f.Unlock()
77
78 if !f.visible || rectIsZero(f.r) {
79 return
80 }
81
82 if !f.handleKeyboard {
83 return
84 }
85
86
87 if r > 0 {
88 f.handleRunes([]rune{r})
89 return true, nil
90 }
91
92
93 f.handleKeys([]ebiten.Key{key})
94 return true, nil
95 }
96
97 func (f *InputField) handleRunes(runes []rune) bool {
98 var redraw bool
99 for _, r := range runes {
100 if f.changedFunc != nil {
101 f.Unlock()
102 accept := f.changedFunc(r)
103 f.Lock()
104
105 if !accept {
106 continue
107 }
108 }
109
110 f.TextField._write([]byte(string(r)))
111 redraw = true
112 }
113
114 return redraw
115 }
116
117 func (f *InputField) handleKeys(keys []ebiten.Key) bool {
118 var redraw bool
119 for _, key := range keys {
120 switch key {
121 case ebiten.KeyBackspace:
122 l := len(f.buffer)
123 if l > 0 {
124 var rewrap bool
125 if len(f.incoming) != 0 {
126 line := string(f.incoming)
127 f.incoming = append(f.incoming, []byte(line[:len(line)-1])...)
128 } else if len(f.buffer[l-1]) == 0 {
129 f.buffer = f.buffer[:l-1]
130 rewrap = true
131 } else {
132 line := string(f.buffer[l-1])
133 f.buffer[l-1] = []byte(line[:len(line)-1])
134 rewrap = true
135 }
136 if rewrap && (f.needWrap == -1 || f.needWrap > l-1) {
137 f.needWrap = l - 1
138 }
139 redraw = true
140 f.modified = true
141 f.redraw = true
142 }
143 case ebiten.KeyEnter, ebiten.KeyKPEnter:
144 if f.selectedFunc != nil {
145 f.Unlock()
146 accept := f.selectedFunc()
147 f.Lock()
148
149
150 if accept {
151 f.incoming = f.incoming[:0]
152 f.buffer = f.buffer[:0]
153 f.bufferWrapped = f.bufferWrapped[:0]
154 f.lineWidths = f.lineWidths[:0]
155 f.needWrap = 0
156 f.wrapStart = 0
157 f.modified = true
158 f.redraw = true
159 redraw = true
160 }
161 } else if !f.singleLine {
162
163 f.incoming = append(f.incoming, '\n')
164 f.modified = true
165 f.redraw = true
166 redraw = true
167 }
168 }
169 }
170 return redraw
171 }
172
173
174
175 func (f *InputField) Update() error {
176 f.Lock()
177 defer f.Unlock()
178
179 if !f.visible || rectIsZero(f.r) {
180 return nil
181 }
182
183 if !f.handleKeyboard {
184 return f.TextField.Update()
185 }
186
187 var redraw bool
188
189
190 f.readBuffer = ebiten.AppendInputChars(f.readBuffer[:0])
191 if f.handleRunes(f.readBuffer) {
192 redraw = true
193 }
194 if f.handleRunes(f.rawRuneBuffer) {
195 redraw = true
196 }
197 f.rawRuneBuffer = f.rawRuneBuffer[:0]
198
199
200 f.keyBuffer = inpututil.AppendJustPressedKeys(f.keyBuffer[:0])
201 if f.handleKeys(f.keyBuffer) {
202 redraw = true
203 }
204 if f.handleKeys(f.rawKeyBuffer) {
205 redraw = true
206 }
207 f.rawKeyBuffer = f.rawKeyBuffer[:0]
208
209 if redraw {
210 f.bufferModified()
211 }
212
213 return f.TextField.Update()
214 }
215
View as plain text