package screens import ( "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" blt "lab.zaar.be/thefish/bearlibterminal" "strings" ) const runeIndex = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" type MenuScreen struct { types.Rect mw *mainwindow.MainWindow scm *types.ScreenManager renderParent bool items []interface{} offset int drawFunc func() inputFunc func(string) title string header string footer string redraw bool bgColor string fgColor string } func NewMenuScreen(mw *mainwindow.MainWindow, scm *types.ScreenManager, title, header, footer string, rect types.Rect, renderParent bool) *MenuScreen { return &MenuScreen{ title: title, header: header, footer: footer, Rect: rect, mw: mw, scm: scm, renderParent: renderParent, } } func (ms *MenuScreen) MakeList() *MenuScreen { ms.drawFunc = ms.ListRender ms.inputFunc = ms.ListHandleInput return ms } func (ms *MenuScreen) SetBgColor(color string) *MenuScreen { ms.bgColor = color return ms } func (ms *MenuScreen) SetFgColor(color string) *MenuScreen { ms.fgColor = color return ms } //fixme!! func (ms *MenuScreen) SetItems(items []interface{}) *MenuScreen { ms.items = items return ms } func (ms *MenuScreen) UseEcs() bool { return false } func (ms *MenuScreen) Enter() { ms.redraw = true ms.offset = 0 } func (ms *MenuScreen) HandleInput(input string) { ms.inputFunc(input) } func (ms *MenuScreen) Exit() { menuLayer := ms.mw.GetLayer("menu") menuLayer.ClearRect(ms.Rect) bgLayer := ms.mw.GetLayer("menubg") bgLayer.ClearRect(ms.Rect) } func (ms *MenuScreen) Render() { if ms.renderParent { ms.scm.PreviousScreen.Render() } if ms.redraw || ms.renderParent { ms.redraw = false ms.drawFunc() } } func (ms *MenuScreen) ListHandleInput(input string) { switch input { case "Up", "k": ms.offset = ms.offset - 1 if ms.offset < 0 { ms.offset = 0 } break case "Down", "j": ms.offset = ms.offset + 1 if ms.offset > len(ms.items)-1 { ms.offset = len(ms.items) - 1 } break case "Escape": fallthrough case "Space": ms.scm.SetScreen(ms.scm.PreviousScreen) break } } func (ms *MenuScreen) ListRender() { menuLayer := ms.mw.GetLayer("menu") menuLayer.ClearRect(ms.Rect) bgLayer := ms.mw.GetLayer("menubg") bgLayer.ClearRect(ms.Rect) bgLayer.WithColor(ms.bgColor).NewWindow(ms.Rect).Splash() menuLayer.WithColor(ms.fgColor).NewWindow(ms.Rect).DoubleBordered(ms.title) menuLayer.Print(ms.X+(ms.W/2)-7, ms.Y+ms.H-1, "╡"+"[color=green]Space[/color] to close"+"╞") footerHeight := 0 if ms.footer != "" { _, footerHeight = menuLayer.PrintInside(ms.Rect, ms.footer, 9) footerHeight = footerHeight + 2 } _, headerHeight := menuLayer.PrintInside(ms.Rect, ms.header, blt.TK_ALIGN_LEFT) itemField := types.Rect{ms.X, ms.Y + headerHeight + 1, ms.W, ms.H - headerHeight - footerHeight} _ = itemField var ilw, ilh int if len(ms.items) > 0 { //fixme itemfield object, scroller, inputhandler, current selected item menuItems := make([]string, 0) for i := ms.offset; i < len(ms.items); i++ { if string(ms.items[i].(string)) != "" { menuItems = append(menuItems, ms.items[i].(string)) } } ilw, ilh = menuLayer.PrintInside(itemField, strings.Join(menuItems, "\n"), blt.TK_ALIGN_LEFT) } if ilh < len(ms.items) { ms.drawScrollBar(menuLayer, itemField) } if ilw > itemField.W-4 { fmt.Printf("Excess width of item names found! Need h-scroll of certain names") } } func (ms *MenuScreen) drawScrollBar(menuLayer *mainwindow.Layer, itemField types.Rect) { scrollbarBg := types.NewRect(itemField.X+itemField.W-2, itemField.Y+1, 1, itemField.H-4) menuLayer.WithColor("#77000000").NewWindow(scrollbarBg).Splash() //tick menuLayer.WithColor(ms.fgColor).Put( scrollbarBg.X, scrollbarBg.Y+int(float64(ms.offset)/float64(len(ms.items))*float64(scrollbarBg.H)), "⏹", ) menuLayer.WithColor(ms.fgColor).Put(itemField.X+itemField.W-2, itemField.Y+scrollbarBg.H+1, "↓") menuLayer.WithColor(ms.fgColor).Put(itemField.X+itemField.W-2, itemField.Y, "↑") }