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