1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package ui
import (
"log"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"golang.org/x/exp/slices"
)
type Collection struct {
Width, Height int
hoverDetector hoverDetector
widgets []Widget
}
func (c *Collection) Layout() (int, int) {
return c.Width, c.Height
}
func (c *Collection) Widgets() []Widget {
return c.widgets
}
func (c *Collection) Clear() {
c.widgets = []Widget{}
}
func (c *Collection) ResetHover() {
c.hoverDetector.reset(0, 0)
}
func (c *Collection) AddWidget(w Widget) {
if w == nil {
log.Panicf("Adding nil widget to collection")
}
if slices.Contains(c.widgets, w) {
log.Panicf("Double insertion of %v", w)
}
c.widgets = append(c.widgets, w)
}
func (c *Collection) FindWidget(toFind Widget) int {
for i, w := range c.widgets {
if w != toFind {
continue
}
return i
}
return -1
}
func (c *Collection) RemoveWidget(widget Widget) {
idx := c.FindWidget(widget)
if idx != -1 {
c.RemoveWidgetAt(idx)
}
}
func (c *Collection) RemoveWidgetAt(idx int) {
nwidgets := len(c.widgets)
c.widgets[idx] = c.widgets[nwidgets-1]
c.widgets = c.widgets[:nwidgets-1]
}
func (c *Collection) Draw(screen *ebiten.Image) {
for _, w := range c.widgets {
w.Draw(screen)
}
}
func (c *Collection) Update() error {
x, y := ebiten.CursorPosition()
var activeWidget Widget
// Iterate the widget in reverse order to ensure that upper widgets are
// considered first
for i := len(c.widgets) - 1; i >= 0; i-- {
w := c.widgets[i]
if !w.Contains(x, y) {
continue
}
activeWidget = w
break
}
c.hoverDetector.update(c, x, y, activeWidget)
if activeWidget == nil {
return nil
}
scrollX, scrollY := ebiten.Wheel()
if scrollX != 0 || scrollY != 0 {
if scrollable, ok := activeWidget.(Scrollable); ok {
scrollable.Scroll(int(scrollX), int(scrollY))
}
}
if textInput, ok := activeWidget.(*TextInput); ok {
var input []rune
input = ebiten.AppendInputChars(input)
if len(input) > 0 {
textInput.AddInput(input)
}
textInput.HandleKey()
}
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
if btn, ok := activeWidget.(Clickable); ok {
btn.Click(x, y)
}
}
return nil
}
|