...
1 package messeji
2
3 import (
4 "sync"
5
6 "github.com/hajimehoshi/ebiten/v2"
7 "github.com/hajimehoshi/ebiten/v2/inpututil"
8 "github.com/hajimehoshi/ebiten/v2/text/v2"
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(fontSource *text.GoTextFaceSource, fontSize int, fontMutex *sync.Mutex) *InputField {
44 f := &InputField{
45 TextField: NewTextField(fontSource, fontSize, fontMutex),
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 ok := f.handleRunes([]rune{r})
89 if ok {
90 f.resizeFont()
91 }
92 return true, nil
93 }
94
95
96 ok := f.handleKeys([]ebiten.Key{key})
97 if ok {
98 f.resizeFont()
99 }
100 return true, nil
101 }
102
103 func (f *InputField) handleRunes(runes []rune) bool {
104 var redraw bool
105 for _, r := range runes {
106 if f.changedFunc != nil {
107 f.Unlock()
108 accept := f.changedFunc(r)
109 f.Lock()
110
111 if !accept {
112 continue
113 }
114 }
115
116 f.TextField._write([]byte(string(r)))
117 redraw = true
118 }
119
120 return redraw
121 }
122
123 func (f *InputField) handleKeys(keys []ebiten.Key) bool {
124 var redraw bool
125 for _, key := range keys {
126 switch key {
127 case ebiten.KeyBackspace:
128 l := len(f.buffer)
129 if l > 0 {
130 var rewrap bool
131 if len(f.incoming) != 0 {
132 line := string(f.incoming)
133 f.incoming = append(f.incoming, []byte(line[:len(line)-1])...)
134 } else if len(f.buffer[l-1]) == 0 {
135 f.buffer = f.buffer[:l-1]
136 rewrap = true
137 } else {
138 line := string(f.buffer[l-1])
139 f.buffer[l-1] = []byte(line[:len(line)-1])
140 rewrap = true
141 }
142 if rewrap && (f.needWrap == -1 || f.needWrap > l-1) {
143 f.needWrap = l - 1
144 }
145 redraw = true
146 f.modified = true
147 f.redraw = true
148 }
149 case ebiten.KeyEnter, ebiten.KeyKPEnter:
150 if f.selectedFunc != nil {
151 f.Unlock()
152 accept := f.selectedFunc()
153 f.Lock()
154
155
156 if accept {
157 f.incoming = f.incoming[:0]
158 f.buffer = f.buffer[:0]
159 f.bufferWrapped = f.bufferWrapped[:0]
160 f.lineWidths = f.lineWidths[:0]
161 f.needWrap = 0
162 f.wrapStart = 0
163 f.modified = true
164 f.redraw = true
165 redraw = true
166 }
167 } else if !f.singleLine {
168
169 f.incoming = append(f.incoming, '\n')
170 f.modified = true
171 f.redraw = true
172 redraw = true
173 }
174 }
175 }
176 return redraw
177 }
178
179
180
181 func (f *InputField) Update() error {
182 f.Lock()
183 defer f.Unlock()
184
185 if !f.visible || rectIsZero(f.r) {
186 return nil
187 }
188
189 if !f.handleKeyboard {
190 return f.TextField.Update()
191 }
192
193 var redraw bool
194
195
196 f.readBuffer = ebiten.AppendInputChars(f.readBuffer[:0])
197 if f.handleRunes(f.readBuffer) {
198 redraw = true
199 }
200 if f.handleRunes(f.rawRuneBuffer) {
201 redraw = true
202 }
203 f.rawRuneBuffer = f.rawRuneBuffer[:0]
204
205
206 f.keyBuffer = inpututil.AppendJustPressedKeys(f.keyBuffer[:0])
207 if f.handleKeys(f.keyBuffer) {
208 redraw = true
209 }
210 if f.handleKeys(f.rawKeyBuffer) {
211 redraw = true
212 }
213 f.rawKeyBuffer = f.rawKeyBuffer[:0]
214
215 if redraw {
216 f.resizeFont()
217 f.bufferModified()
218 }
219
220 return f.TextField.Update()
221 }
222
View as plain text