1 package etk
2
3 import (
4 "image"
5 "image/color"
6
7 "codeberg.org/tslocum/etk/messeji"
8 "github.com/hajimehoshi/ebiten/v2"
9 "github.com/hajimehoshi/ebiten/v2/text/v2"
10 )
11
12
13
14 type Input struct {
15 *Box
16 field *messeji.InputField
17 onChange func(text string, r rune) (accept bool)
18 onConfirm func(text string) (handled bool)
19 cursor string
20 borderSize int
21 borderFocused color.RGBA
22 borderUnfocused color.RGBA
23 focus bool
24 }
25
26
27 func NewInput(text string, onChange func(text string, r rune) (accept bool), onConfirm func(text string) (handled bool)) *Input {
28 f := messeji.NewInputField(Style.TextFont, Scale(Style.TextSize), fontMutex)
29 f.SetForegroundColor(Style.TextColorLight)
30 f.SetBackgroundColor(transparent)
31 f.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
32 f.SetScrollBorderSize(Scale(Style.ScrollBorderSize))
33 f.SetScrollBorderColors(Style.ScrollBorderTop, Style.ScrollBorderRight, Style.ScrollBorderBottom, Style.ScrollBorderLeft)
34 f.SetPrefix("")
35 f.SetSuffix("")
36 f.SetText(text)
37 f.SetHandleKeyboard(true)
38
39 i := &Input{
40 Box: NewBox(),
41 field: f,
42 onChange: onChange,
43 onConfirm: onConfirm,
44 cursor: "_",
45 borderSize: Scale(Style.InputBorderSize),
46 borderFocused: Style.InputBorderFocused,
47 borderUnfocused: Style.InputBorderUnfocused,
48 }
49 i.SetBackground(Style.InputBgColor)
50 f.SetChangedFunc(func(r rune) (accept bool) {
51 if i.onChange != nil {
52 text := f.Text()
53 if r == 0 && len(text) > 0 {
54 return i.onChange(text[:len(text)-1], 0)
55 }
56 return i.onChange(text+string(r), r)
57 }
58 return true
59 })
60 f.SetSelectedFunc(func() (accept bool) {
61 if i.onConfirm != nil {
62 return i.onConfirm(f.Text())
63 }
64 return true
65 })
66 return i
67 }
68
69
70 func (i *Input) SetRect(r image.Rectangle) {
71 i.Box.rect = r
72
73 i.field.SetRect(r)
74
75 for _, w := range i.children {
76 w.SetRect(r)
77 }
78 }
79
80
81 func (i *Input) SetBorderSize(size int) {
82 i.Lock()
83 defer i.Unlock()
84
85 i.borderSize = size
86 }
87
88
89 func (i *Input) SetBorderColors(focused color.RGBA, unfocused color.RGBA) {
90 i.Lock()
91 defer i.Unlock()
92
93 i.borderFocused = focused
94 i.borderUnfocused = unfocused
95 }
96
97
98 func (i *Input) Foreground() color.RGBA {
99 i.Lock()
100 defer i.Unlock()
101
102 return i.field.ForegroundColor()
103 }
104
105
106 func (i *Input) SetForeground(c color.RGBA) {
107 i.Lock()
108 defer i.Unlock()
109
110 i.field.SetForegroundColor(c)
111 }
112
113
114 func (i *Input) SetPrefix(prefix string) {
115 i.Lock()
116 defer i.Unlock()
117
118 i.field.SetPrefix(prefix)
119 }
120
121
122 func (i *Input) SetSuffix(suffix string) {
123 i.Lock()
124 defer i.Unlock()
125
126 i.field.SetSuffix(suffix)
127 }
128
129
130 func (i *Input) SetCursor(cursor string) {
131 i.Lock()
132 defer i.Unlock()
133
134 i.cursor = cursor
135 if i.focus {
136 i.field.SetSuffix(cursor)
137 }
138 }
139
140
141 func (i *Input) Focus() bool {
142 return i.focus
143 }
144
145
146 func (i *Input) SetFocus(focus bool) bool {
147 i.focus = focus
148
149 var cursor string
150 if focus {
151 cursor = i.cursor
152 }
153 i.field.SetSuffix(cursor)
154 return true
155 }
156
157
158 func (i *Input) Text() string {
159 i.Lock()
160 defer i.Unlock()
161
162 return i.field.Text()
163 }
164
165
166 func (i *Input) SetText(text string) {
167 i.Lock()
168 defer i.Unlock()
169
170 i.field.SetText(text)
171 }
172
173
174 func (i *Input) SetScrollBarWidth(width int) {
175 i.Lock()
176 defer i.Unlock()
177
178 i.field.SetScrollBarWidth(width)
179 }
180
181
182 func (i *Input) SetScrollBarColors(area color.RGBA, handle color.RGBA) {
183 i.Lock()
184 defer i.Unlock()
185
186 i.field.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
187 }
188
189
190 func (i *Input) SetScrollBarVisible(scrollVisible bool) {
191 i.Lock()
192 defer i.Unlock()
193
194 i.field.SetScrollBarVisible(scrollVisible)
195 }
196
197
198
199 func (i *Input) SetAutoHideScrollBar(autoHide bool) {
200 i.Lock()
201 defer i.Unlock()
202
203 i.field.SetAutoHideScrollBar(autoHide)
204 }
205
206
207 func (t *Input) SetFont(fnt *text.GoTextFaceSource, size int) {
208 t.Lock()
209 defer t.Unlock()
210
211 t.field.SetFont(fnt, size, fontMutex)
212 }
213
214
215
216 func (t *Input) SetAutoResize(resize bool) {
217 t.Lock()
218 defer t.Unlock()
219
220 t.field.SetAutoResize(resize)
221 }
222
223
224 func (i *Input) Padding() int {
225 i.Lock()
226 defer i.Unlock()
227
228 return i.field.Padding()
229 }
230
231
232 func (i *Input) SetPadding(padding int) {
233 i.Lock()
234 defer i.Unlock()
235
236 i.field.SetPadding(padding)
237 }
238
239
240 func (i *Input) SetWordWrap(wrap bool) {
241 i.Lock()
242 defer i.Unlock()
243
244 i.field.SetWordWrap(wrap)
245 }
246
247
248 func (i *Input) SetHorizontal(h Alignment) {
249 i.Lock()
250 defer i.Unlock()
251
252 i.field.SetHorizontal(messeji.Alignment(h))
253 }
254
255
256 func (i *Input) SetVertical(v Alignment) {
257 i.Lock()
258 defer i.Unlock()
259
260 i.field.SetVertical(messeji.Alignment(v))
261 }
262
263
264 func (i *Input) SetMask(r rune) {
265 i.Lock()
266 defer i.Unlock()
267
268 i.field.SetMask(r)
269 }
270
271
272
273 func (i *Input) SetChangeFunc(onChange func(text string, r rune) (accept bool)) {
274 i.Lock()
275 defer i.Unlock()
276
277 i.onChange = onChange
278 }
279
280
281 func (i *Input) SetConfirmFunc(onConfirm func(text string) (handled bool)) {
282 i.Lock()
283 defer i.Unlock()
284
285 i.onConfirm = onConfirm
286 }
287
288
289
290 func (i *Input) Cursor() ebiten.CursorShapeType {
291 return ebiten.CursorShapeText
292 }
293
294
295 func (i *Input) Write(p []byte) (n int, err error) {
296 return i.field.Write(p)
297 }
298
299
300 func (i *Input) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
301 if !i.focus {
302 return false, nil
303 }
304
305 return i.field.HandleKeyboardEvent(key, r)
306 }
307
308
309 func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
310 return i.field.HandleMouseEvent(cursor, pressed, clicked)
311 }
312
313
314 func (i *Input) Draw(screen *ebiten.Image) error {
315 i.field.Draw(screen)
316
317
318 if i.borderSize == 0 {
319 return nil
320 }
321 r := i.rect
322 c := i.borderUnfocused
323 if i.focus {
324 c = i.borderFocused
325 }
326 screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Min.X+i.borderSize, r.Max.Y)).(*ebiten.Image).Fill(c)
327 screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+i.borderSize)).(*ebiten.Image).Fill(c)
328 screen.SubImage(image.Rect(r.Max.X-i.borderSize, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(c)
329 screen.SubImage(image.Rect(r.Min.X, r.Max.Y-i.borderSize, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(c)
330 return nil
331 }
332
View as plain text