package alui import ( "opslag.de/schobers/allg5" "opslag.de/schobers/geom" ) type Menu struct { Proxy panel *StackPanel active int buttons []*Button } func NewMenu() *Menu { m := &Menu{} m.Init() return m } func (m *Menu) Init() { m.panel = &StackPanel{Orientation: OrientationVertical} m.Proxy.Target = m.panel } func (m *Menu) Activate(i int) { if len(m.buttons) == 0 || i < 0 { return } m.active = i % len(m.buttons) } func (m *Menu) Add(text string, onClick func()) { idx := len(m.buttons) button := &Button{Text: text, TextAlign: allg5.AlignCenter} button.OnClick = onClick button.OnEnter = func() { m.updateActiveButton(idx) } if idx == 0 { button.Over = true } m.buttons = append(m.buttons, button) m.panel.Children = append(m.panel.Children, button) } func (m *Menu) Handle(e allg5.Event) { m.Proxy.Handle(e) if len(m.buttons) == 0 { return } switch e := e.(type) { case *allg5.KeyCharEvent: switch e.KeyCode { case allg5.KeyDown: m.updateActiveButton((m.active + 1) % len(m.buttons)) case allg5.KeyUp: m.updateActiveButton((m.active + len(m.buttons) - 1) % len(m.buttons)) case allg5.KeyEnter: if onClick := m.buttons[m.active].OnClick; onClick != nil { onClick() } } case *allg5.MouseMoveEvent: for i, btn := range m.buttons { if btn.Over { m.updateActiveButton(i) break } } m.updateActiveButton(m.active) } } func (m *Menu) Layout(ctx *Context, bounds geom.RectangleF32) {} func (m *Menu) Render(ctx *Context, bounds geom.RectangleF32) { menuHeight := m.Proxy.DesiredSize(ctx).Y width, center := bounds.Dx(), bounds.Center() menuBounds := geom.RectF32(.25*width, center.Y-.5*menuHeight, .75*width, center.Y+.5*menuHeight) m.Proxy.Layout(ctx, menuBounds) m.Proxy.Render(ctx, menuBounds) } func (m *Menu) updateActiveButton(active int) { m.active = active for i, btn := range m.buttons { btn.Over = i == m.active } }