...
1 package etk
2
3 import (
4 "image"
5 "image/color"
6
7 "github.com/hajimehoshi/ebiten/v2"
8 "golang.org/x/image/font/sfnt"
9 )
10
11
12 type Window struct {
13 *Box
14 font *sfnt.Font
15 fontSize int
16 frameSize int
17 titleSize int
18 titles []*Text
19 floating []bool
20 fullscreen []Widget
21 modified bool
22 }
23
24
25 func NewWindow() *Window {
26 return &Window{
27 Box: NewBox(),
28 font: Style.TextFont,
29 fontSize: Scale(Style.TextSize),
30 frameSize: Scale(4),
31 titleSize: Scale(40),
32 }
33 }
34
35
36 func (w *Window) SetRect(r image.Rectangle) {
37 w.Lock()
38 defer w.Unlock()
39
40 w.rect = r
41 w.modified = true
42 }
43
44
45 func (w *Window) SetFont(fnt *sfnt.Font, size int) {
46 w.Lock()
47 defer w.Unlock()
48
49 w.font = fnt
50 w.fontSize = size
51
52 for _, title := range w.titles {
53 title.SetFont(w.font, w.fontSize)
54 }
55 }
56
57
58 func (w *Window) SetFrameSize(size int) {
59 w.Lock()
60 defer w.Unlock()
61
62 w.frameSize = size
63 w.modified = true
64 }
65
66
67 func (w *Window) SetTitleSize(size int) {
68 w.Lock()
69 defer w.Unlock()
70
71 w.titleSize = size
72 w.modified = true
73 }
74
75
76
77
78 func (w *Window) SetFullscreen(index int) {
79 w.Lock()
80 defer w.Unlock()
81
82 if index == -1 {
83 w.fullscreen = w.fullscreen[:0]
84 } else if index >= 0 && index < len(w.children) {
85 w.fullscreen = append(w.fullscreen[:0], w.children[index])
86 }
87 w.modified = true
88 }
89
90
91 func (w *Window) Children() []Widget {
92 w.Lock()
93 defer w.Unlock()
94
95 if len(w.fullscreen) != 0 {
96 return w.fullscreen
97 }
98 return w.children
99 }
100
101
102 func (w *Window) Clear() {
103 w.Lock()
104 defer w.Unlock()
105
106 w.children = w.children[:0]
107 w.titles = w.titles[:0]
108 w.floating = w.floating[:0]
109 w.fullscreen = w.fullscreen[:0]
110 }
111
112
113 func (w *Window) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
114 return true, nil
115 }
116
117
118 func (w *Window) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
119 return true, nil
120 }
121
122
123 func (w *Window) Draw(screen *ebiten.Image) error {
124 if w.modified {
125 if len(w.fullscreen) != 0 {
126 w.fullscreen[0].SetRect(w.rect)
127 } else {
128 for i, wgt := range w.children {
129 r := wgt.Rect()
130 if r.Empty() || (!w.floating[i] && !r.Eq(w.rect)) {
131 r = w.rect
132 }
133 if r.Max.X >= w.rect.Max.X {
134 r = r.Sub(image.Point{r.Max.X - w.rect.Max.X, 0})
135 }
136 if r.Max.Y >= w.rect.Max.Y {
137 r = r.Sub(image.Point{0, r.Max.Y - w.rect.Max.Y})
138 }
139 if r.Min.X < w.rect.Min.X {
140 r.Min.X = w.rect.Min.X
141 }
142 if r.Min.Y < w.rect.Min.Y {
143 r.Min.Y = w.rect.Min.Y
144 }
145 wgt.SetRect(r)
146 }
147 }
148 w.modified = false
149 }
150 return nil
151 }
152
153
154 func (w *Window) AddChild(wgt ...Widget) {
155 w.Lock()
156 defer w.Unlock()
157
158 for _, widget := range wgt {
159 t := NewText("")
160 t.SetFont(w.font, w.fontSize)
161
162 w.children = append(w.children, &windowWidget{NewBox(), t, widget, w})
163 w.titles = append(w.titles, t)
164 w.floating = append(w.floating, false)
165 }
166 w.modified = true
167 }
168
169
170 func (w *Window) AddChildWithTitle(wgt Widget, title string) int {
171 w.Lock()
172 defer w.Unlock()
173
174 t := NewText(title)
175 t.SetFont(w.font, w.fontSize)
176
177 w.children = append(w.children, &windowWidget{NewBox(), t, wgt, w})
178 w.titles = append(w.titles, t)
179 w.floating = append(w.floating, false)
180
181 w.modified = true
182 return len(w.children) - 1
183 }
184
185 type windowWidget struct {
186 *Box
187 title *Text
188 wgt Widget
189 w *Window
190 }
191
192 func (w *windowWidget) SetRect(r image.Rectangle) {
193 w.Lock()
194 defer w.Unlock()
195
196 w.rect = r
197 w.title.SetRect(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+w.w.titleSize))
198 w.wgt.SetRect(image.Rect(r.Min.X, r.Min.Y+w.w.titleSize, r.Max.X, r.Max.Y))
199 }
200
201 func (w *windowWidget) Background() color.RGBA {
202 return color.RGBA{0, 0, 0, 255}
203 }
204
205 func (w *windowWidget) Draw(screen *ebiten.Image) error {
206 w.title.Draw(screen)
207
208 background := w.wgt.Background()
209 if background.A != 0 {
210 screen.SubImage(w.wgt.Rect()).(*ebiten.Image).Fill(background)
211 }
212 return w.wgt.Draw(screen)
213 }
214
View as plain text