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 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 }