package ui import ( "github.com/hajimehoshi/ebiten/v2" ) type Widget interface { Draw(*ebiten.Image) FindObjectAt(int, int) any Contains(int, int) bool Layout() (int, int) IsClickable() bool Click(int, int) IsHoverable() bool Hover(bool, int, int) IsScrollable() bool Scroll(int, int) IsUpdatable() bool Update() error IsFocusable() bool Focus(bool) } type WidgetBase struct { X, Y int Width, Height int img *ebiten.Image Op *ebiten.DrawImageOptions renderImpl func() *ebiten.Image EventHandlersMap } func NewWidgetBase(x, y, width, height int) WidgetBase { return WidgetBase{X: x, Y: y, Width: width, Height: height, Op: &ebiten.DrawImageOptions{}, EventHandlersMap: NewEventHandlersMap()} } func (w *WidgetBase) Draw(screen *ebiten.Image) { if w.img == nil { w.img = w.renderImpl() } op := &ebiten.DrawImageOptions{} op.GeoM.Concat(w.Op.GeoM) op.GeoM.Translate(float64(w.X), float64(w.Y)) screen.DrawImage(w.img, op) } func (w *WidgetBase) DrawImageOptions() *ebiten.DrawImageOptions { return w.Op } func (w *WidgetBase) ForceRedraw() { w.img = nil } func (w *WidgetBase) Contains(x, y int) bool { return x >= 0 && y >= 0 && x >= w.X && x <= w.X+w.Width && y >= w.Y && y <= w.Y+w.Height } func (w *WidgetBase) FindObjectAt(int, int) any { return nil } func (w *WidgetBase) Layout() (int, int) { return w.Width, w.Height }