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