1 package etk
2
3 import (
4 "fmt"
5 "image"
6
7 "github.com/hajimehoshi/ebiten/v2"
8 "github.com/hajimehoshi/ebiten/v2/text/v2"
9 )
10
11
12
13 type Window struct {
14 *Box
15 font *text.GoTextFaceSource
16 fontSize int
17 frameSize int
18 list *List
19 listH Alignment
20 listV Alignment
21 listSize int
22 listWidget *WithoutFocus
23 defaultFocus []Widget
24 labels []string
25 active int
26 modified bool
27 listModified bool
28 firstDraw bool
29 }
30
31
32 func NewWindow() *Window {
33 w := &Window{
34 Box: NewBox(),
35 font: Style.TextFont,
36 fontSize: Scale(Style.TextSize),
37 frameSize: Scale(4),
38 listSize: Scale(172),
39 listH: AlignEnd,
40 listV: AlignCenter,
41 active: -1,
42 firstDraw: true,
43 }
44 w.list = NewList(int(float64(Scale(Style.TextSize))*1.5), w.selectItem)
45 w.listWidget = &WithoutFocus{w.list}
46 return w
47 }
48
49
50 func (w *Window) SetRect(r image.Rectangle) {
51 w.Lock()
52 defer w.Unlock()
53
54 w.rect = r
55 w.modified = true
56 }
57
58
59
60
61 func (w *Window) Clip() bool {
62 return false
63 }
64
65
66 func (w *Window) SetFont(fnt *text.GoTextFaceSource, size int) {
67 w.Lock()
68 defer w.Unlock()
69
70 w.font = fnt
71 w.fontSize = size
72 w.list.SetItemHeight(size)
73 }
74
75
76 func (w *Window) SetFrameSize(size int) {
77 w.Lock()
78 defer w.Unlock()
79
80 w.frameSize = size
81 w.modified = true
82 }
83
84
85 func (w *Window) SetListSize(size int) {
86 w.Lock()
87 defer w.Unlock()
88
89 w.listSize = size
90 w.modified = true
91 }
92
93
94 func (w *Window) SetListHorizontal(h Alignment) {
95 w.Lock()
96 defer w.Unlock()
97
98 w.listH = h
99 w.modified = true
100 }
101
102
103 func (w *Window) SetListVertical(v Alignment) {
104 w.Lock()
105 defer w.Unlock()
106
107 w.listV = v
108 w.modified = true
109 }
110
111
112 func (w *Window) Show(index int) {
113 w.Lock()
114 defer w.Unlock()
115
116 if index >= 0 && index < len(w.children) {
117 w.active = index
118 SetFocus(w.defaultFocus[index])
119 } else {
120 w.active = -1
121 }
122 w.modified = true
123 }
124
125
126 func (w *Window) Hide() {
127 w.Lock()
128 defer w.Unlock()
129
130 w.active = -1
131 w.modified = true
132 }
133
134
135 func (w *Window) Children() []Widget {
136 w.Lock()
137 defer w.Unlock()
138
139 if w.active >= 0 && w.active < len(w.children) {
140 if w.listSize > 0 {
141 return []Widget{w.children[w.active], w.listWidget}
142 }
143 return []Widget{w.children[w.active]}
144 } else if w.listSize > 0 {
145 return []Widget{w.listWidget}
146 }
147 return nil
148 }
149
150
151 func (w *Window) Clear() {
152 w.Lock()
153 defer w.Unlock()
154
155 w.children = w.children[:0]
156 w.labels = w.labels[:0]
157 w.active = -1
158 w.listModified = true
159 w.firstDraw = true
160 }
161
162 func (w *Window) selectItem(index int) (accept bool) {
163 if index >= 0 && index < len(w.children) {
164 w.active = index
165 w.modified = true
166 SetFocus(w.defaultFocus[index])
167 }
168 return true
169 }
170
171
172 func (w *Window) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
173 return true, nil
174 }
175
176
177 func (w *Window) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
178 return true, nil
179 }
180
181
182 func (w *Window) Draw(screen *ebiten.Image) error {
183 if w.listModified {
184 w.list.SetItemHeight(int(float64(Scale(w.fontSize)) * 1.5))
185 w.list.Clear()
186 for i := range w.labels {
187 label := w.labels[i]
188 if label == "" {
189 label = fmt.Sprintf("#%d", i)
190 }
191 t := NewText(label)
192 t.SetFont(w.font, Scale(w.fontSize))
193 t.SetAutoResize(true)
194 t.SetVertical(AlignCenter)
195 w.list.AddChildAt(t, 0, i)
196 w.list.SetSelectedItem(0, w.active)
197 }
198 w.listModified = false
199 }
200 if w.modified {
201 if w.active >= 0 {
202 wr := w.rect
203 if w.listSize > 0 {
204 var lr image.Rectangle
205 switch w.listH {
206 case AlignStart:
207 lr = image.Rect(wr.Min.X, wr.Min.Y, wr.Min.X+w.listSize, wr.Max.Y)
208 case AlignEnd:
209 lr = image.Rect(wr.Max.X-w.listSize, wr.Min.Y, wr.Max.X, wr.Max.Y)
210 }
211 switch w.listV {
212 case AlignStart:
213 lr = image.Rect(wr.Min.X, wr.Min.Y, wr.Max.X, wr.Min.Y+w.listSize)
214 case AlignEnd:
215 lr = image.Rect(wr.Min.X, wr.Max.Y-w.listSize, wr.Max.X, wr.Max.Y)
216 }
217 dx, dy := lr.Dx(), lr.Dy()
218 if dx > 0 && dy > 0 && dx <= wr.Dx() && dy <= wr.Dy() {
219 switch w.listH {
220 case AlignStart:
221 wr.Min.X += w.listSize
222 case AlignEnd:
223 wr.Max.X -= w.listSize
224 }
225 switch w.listV {
226 case AlignStart:
227 wr.Min.Y += w.listSize
228 case AlignEnd:
229 wr.Max.Y -= w.listSize
230 }
231 w.list.SetRect(lr)
232 }
233 }
234 w.children[w.active].SetRect(wr)
235 if w.firstDraw {
236 SetFocus(w.children[w.active])
237 w.firstDraw = false
238 }
239 }
240 w.modified = false
241 }
242 return nil
243 }
244
245
246 func (w *Window) AddChild(wgt ...Widget) {
247 w.Lock()
248 defer w.Unlock()
249
250 for _, widget := range wgt {
251 w.children = append(w.children, widget)
252 w.defaultFocus = append(w.defaultFocus, widget)
253 w.labels = append(w.labels, "")
254 }
255 w.modified = true
256 w.listModified = true
257 }
258
259
260 func (w *Window) AddChildWithLabel(wgt Widget, defaultFocus Widget, label string) int {
261 w.Lock()
262 defer w.Unlock()
263
264 w.children = append(w.children, wgt)
265 w.defaultFocus = append(w.defaultFocus, defaultFocus)
266 w.labels = append(w.labels, label)
267
268 w.modified = true
269 w.listModified = true
270 return len(w.children) - 1
271 }
272
View as plain text