...
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 func (t *Text) resizeFont() {
165 if !t.textResize {
166 if t.textAutoSize == t.textSize {
167 return
168 }
169 t.textAutoSize = t.textSize
170 ff := FontFace(t.textFont, t.textSize)
171 t.field.SetFont(ff, fontMutex)
172 return
173 }
174
175 w, h := t.rect.Dx()-t.field.Padding()*2, t.rect.Dy()-t.field.Padding()*2
176 if w == 0 || h == 0 {
177 if t.textAutoSize == t.textSize {
178 return
179 }
180 t.textAutoSize = t.textSize
181 ff := FontFace(t.textFont, t.textSize)
182 t.field.SetFont(ff, fontMutex)
183 return
184 }
185
186 var autoSize int
187 var ff font.Face
188 for autoSize = t.textSize; autoSize > 0; autoSize-- {
189 ff = FontFace(t.textFont, autoSize)
190 bounds := BoundString(ff, t.field.Text())
191 if bounds.Dx() <= w && bounds.Dy() <= h {
192 break
193 }
194 }
195 if t.textAutoSize == autoSize {
196 return
197 }
198
199 t.field.SetFont(ff, fontMutex)
200 t.textAutoSize = autoSize
201 }
202
203 func (t *Text) scrollBarVisible() bool {
204 if t.textResize {
205 return false
206 }
207 return t.scrollVisible
208 }
209
210
211 func (t *Text) SetScrollBarVisible(scrollVisible bool) {
212 t.Lock()
213 defer t.Unlock()
214
215 t.scrollVisible = scrollVisible
216 t.field.SetScrollBarVisible(t.scrollBarVisible())
217 }
218
219
220
221 func (t *Text) SetAutoHideScrollBar(autoHide bool) {
222 t.Lock()
223 defer t.Unlock()
224
225 t.field.SetAutoHideScrollBar(autoHide)
226 }
227
228
229 func (t *Text) SetFont(fnt *sfnt.Font, size int) {
230 t.Lock()
231 defer t.Unlock()
232
233 t.textFont, t.textSize = fnt, size
234 t.resizeFont()
235 }
236
237
238
239 func (t *Text) SetAutoResize(resize bool) {
240 t.Lock()
241 defer t.Unlock()
242
243 t.textResize = resize
244 t.resizeFont()
245 t.field.SetScrollBarVisible(t.scrollBarVisible())
246 }
247
248
249 func (t *Text) Padding() int {
250 t.Lock()
251 defer t.Unlock()
252
253 return t.field.Padding()
254 }
255
256
257 func (t *Text) SetPadding(padding int) {
258 t.Lock()
259 defer t.Unlock()
260
261 t.field.SetPadding(padding)
262 }
263
264
265
266 func (t *Text) SetFollow(follow bool) {
267 t.Lock()
268 defer t.Unlock()
269
270 t.field.SetFollow(follow)
271 }
272
273
274
275 func (t *Text) SetSingleLine(single bool) {
276 t.Lock()
277 defer t.Unlock()
278
279 t.field.SetSingleLine(single)
280 }
281
282
283 func (t *Text) SetMask(r rune) {
284 t.Lock()
285 defer t.Unlock()
286
287 t.field.SetMask(r)
288 }
289
290
291 func (t *Text) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
292 return t.field.HandleKeyboardEvent(key, r)
293 }
294
295
296 func (t *Text) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
297 return t.field.HandleMouseEvent(cursor, pressed, clicked)
298 }
299
300
301 func (t *Text) Draw(screen *ebiten.Image) error {
302 t.field.Draw(screen)
303 return nil
304 }
305
306
307 func (t *Text) Children() []Widget {
308 t.Lock()
309 defer t.Unlock()
310
311 return t.children
312 }
313
314
315 func (t *Text) AddChild(w ...Widget) {
316 t.Lock()
317 defer t.Unlock()
318
319 t.children = append(t.children, w...)
320 }
321
322 var _ Widget = &Text{}
323
View as plain text