Render shortcuts on Menus

This commit is contained in:
Luke I. Wilson 2021-03-20 17:35:32 -05:00
parent ce66bc4bc6
commit df106cbbff
3 changed files with 42 additions and 8 deletions

1
go.mod
View File

@ -4,5 +4,6 @@ go 1.12
require ( require (
github.com/gdamore/tcell/v2 v2.2.0 github.com/gdamore/tcell/v2 v2.2.0
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/zyedidia/clipboard v1.0.3 // indirect github.com/zyedidia/clipboard v1.0.3 // indirect
) )

View File

@ -1 +0,0 @@
wtf thisis a test

View File

@ -6,11 +6,13 @@ import (
"unicode" "unicode"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
runewidth "github.com/mattn/go-runewidth"
) )
// Item is an interface implemented by ItemEntry and ItemMenu to be listed in Menus. // Item is an interface implemented by ItemEntry and ItemMenu to be listed in Menus.
type Item interface { type Item interface {
GetName() string GetName() string
GetShortcut() rune
} }
// An ItemSeparator is like a blank Item that cannot actually be selected. It is useful // An ItemSeparator is like a blank Item that cannot actually be selected. It is useful
@ -22,6 +24,10 @@ func (i *ItemSeparator) GetName() string {
return "" return ""
} }
func (i *ItemSeparator) GetShortcut() rune {
return 0
}
// ItemEntry is a listing in a Menu with a name and callback. // ItemEntry is a listing in a Menu with a name and callback.
type ItemEntry struct { type ItemEntry struct {
Name string Name string
@ -34,11 +40,19 @@ func (i *ItemEntry) GetName() string {
return i.Name return i.Name
} }
func (i *ItemEntry) GetShortcut() rune {
return i.Shortcut
}
// GetName returns the name of the Menu. // GetName returns the name of the Menu.
func (m *Menu) GetName() string { func (m *Menu) GetName() string {
return m.Name return m.Name
} }
func (m *Menu) GetShortcut() rune {
return 0
}
// A MenuBar is a horizontal list of menus. // A MenuBar is a horizontal list of menus.
type MenuBar struct { type MenuBar struct {
ItemSelectedCallback func() ItemSelectedCallback func()
@ -358,6 +372,11 @@ func (m *Menu) Draw(s tcell.Screen) {
str := strings.Repeat(" ", m.width-2-len) // Fill space after menu names to border str := strings.Repeat(" ", m.width-2-len) // Fill space after menu names to border
DrawStr(s, m.x+1+len, m.y+1+i, str, sty) DrawStr(s, m.x+1+len, m.y+1+i, str, sty)
if shortcut := item.GetShortcut(); shortcut != 0 { // If the item has a shortcut...
str := " Ctrl+" + string(shortcut) + " "
DrawStr(s, m.x+m.width-1-runewidth.StringWidth(str), m.y+1+i, str, sty)
}
} }
} }
} }
@ -380,18 +399,33 @@ func (m *Menu) SetPos(x, y int) {
m.x, m.y = x, y m.x, m.y = x, y
} }
func (m *Menu) GetMinSize() (int, int) {
return m.GetSize()
}
// GetSize returns the size of the Menu. // GetSize returns the size of the Menu.
func (m *Menu) GetSize() (int, int) { func (m *Menu) GetSize() (int, int) {
// TODO: no, pls don't do this // TODO: no, pls don't do this
maxLen := 0 maxNameLen := 0
for _, item := range m.Items { var widestRune int = 0 // Will contribute to the width
len := len(item.GetName()) for i := range m.Items {
if len > maxLen { nameLen := len(m.Items[i].GetName())
maxLen = len if nameLen > maxNameLen {
maxNameLen = nameLen
}
if s := m.Items[i].GetShortcut(); runewidth.RuneWidth(s) > widestRune {
widestRune = runewidth.RuneWidth(s) // For the sake of good unicode
} }
} }
m.width = maxLen + 2 // Add two for padding
m.height = len(m.Items) + 2 // And another two for the same reason ... shortcutsWidth := 0
if widestRune > 0 {
shortcutsWidth = 2 + 5 + widestRune + 1 // " Ctrl+(rune) " (with one cell padding surrounding)
}
m.width = 1 + maxNameLen + shortcutsWidth + 1 // Add two for padding
m.height = 1 + len(m.Items) + 1 // And another two for the same reason ...
return m.width, m.height return m.width, m.height
} }