Added quick chars to MenuBar and Menus

This commit is contained in:
Luke I. Wilson 2021-03-19 19:58:59 -05:00
parent 83567c1341
commit ffaad36c78
4 changed files with 54 additions and 25 deletions

22
main.go
View File

@ -70,12 +70,12 @@ func main() {
barFocused := false
fileMenu := ui.NewMenu("File", &theme)
fileMenu := ui.NewMenu("_File", &theme)
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New File", Callback: func() {
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_New File", Callback: func() {
textEdit := ui.NewTextEdit(&s, "", "", &theme) // No file path, no contents
tabContainer.AddTab("noname", textEdit)
}}, &ui.ItemEntry{Name: "Open...", Callback: func() {
}}, &ui.ItemEntry{Name: "_Open...", Callback: func() {
callback := func(filePaths []string) {
for _, path := range filePaths {
file, err := os.Open(path)
@ -109,7 +109,7 @@ func main() {
},
)
changeFocus(fileSelector)
}}, &ui.ItemEntry{Name: "Save", Callback: func() {
}}, &ui.ItemEntry{Name: "_Save", Callback: func() {
if tabContainer.GetTabCount() > 0 {
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
te := tab.Child.(*ui.TextEdit)
@ -124,7 +124,7 @@ func main() {
}
}
}
}}, &ui.ItemEntry{Name: "Save As...", Callback: func() {
}}, &ui.ItemEntry{Name: "Save _As...", Callback: func() {
// TODO: implement a "Save as" dialog system, and show that when trying to save noname files
callback := func(filePaths []string) {
fileSelector = nil // Hide the file selector
@ -142,14 +142,14 @@ func main() {
},
)
changeFocus(fileSelector)
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Exit", Callback: func() {
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "E_xit", Callback: func() {
s.Fini()
os.Exit(0)
}}})
editMenu := ui.NewMenu("Edit", &theme)
editMenu := ui.NewMenu("_Edit", &theme)
editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Cut", Callback: func() {
editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_Cut", Callback: func() {
if tabContainer.GetTabCount() > 0 {
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
te := tab.Child.(*ui.TextEdit)
@ -160,7 +160,7 @@ func main() {
_ = ClipWrite(selectedStr) // Add the selectedStr to clipboard
}
}
}}, &ui.ItemEntry{Name: "Copy", Callback: func() {
}}, &ui.ItemEntry{Name: "_Copy", Callback: func() {
if tabContainer.GetTabCount() > 0 {
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
te := tab.Child.(*ui.TextEdit)
@ -169,7 +169,7 @@ func main() {
_ = ClipWrite(selectedStr) // Add selectedStr to clipboard
}
}
}}, &ui.ItemEntry{Name: "Paste", Callback: func() {
}}, &ui.ItemEntry{Name: "_Paste", Callback: func() {
if tabContainer.GetTabCount() > 0 {
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
te := tab.Child.(*ui.TextEdit)
@ -182,7 +182,7 @@ func main() {
}
}}})
searchMenu := ui.NewMenu("Search", &theme)
searchMenu := ui.NewMenu("_Search", &theme)
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
s.Beep()

View File

@ -15,11 +15,33 @@ func DrawRect(s tcell.Screen, x, y, width, height int, char rune, style tcell.St
// DrawStr will render each character of a string at `x` and `y`.
func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) {
runes := []rune(str)
for idx := 0; idx < len(runes); idx++ {
s.SetContent(x+idx, y, runes[idx], nil, style)
for idx, r := range runes {
s.SetContent(x+idx, y, r, nil, style)
}
}
// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
// quick char (any rune after an underscore) with an underline. Returned is the number of
// columns that were drawn to the screen. This is useful to know the length of the string
// drawn, minus the underscore.
func DrawQuickCharStr(s tcell.Screen, x, y int, str string, style tcell.Style) int {
runes := []rune(str)
col := 0
for i := 0; i < len(runes); i++ {
r := runes[i]
if r == '_' && i+1 < len(runes) {
i++
sty := style.Underline(true)
s.SetContent(x+col, y, runes[i], nil, sty)
} else {
s.SetContent(x+col, y, r, nil, style)
}
col++
}
return col
}
// DrawRectOutline draws only the outline of a rectangle, using `ul`, `ur`, `bl`, and `br`
// for the corner runes, and `hor` and `vert` for the horizontal and vertical runes, respectively.
func DrawRectOutline(s tcell.Screen, x, y, _width, _height int, ul, ur, bl, br, hor, vert rune, style tcell.Style) {

View File

@ -90,13 +90,14 @@ func (b *MenuBar) Draw(s tcell.Screen) {
col := b.x + 1
for i, item := range b.Menus {
str := fmt.Sprintf(" %s ", item.Name) // Surround the name in spaces
var sty tcell.Style
if b.selected == i && b.focused { // If we are drawing the selected item ...
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use style for selected items
} else {
sty = normalStyle
sty := normalStyle
if b.focused && b.selected == i {
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use special style for selected item
}
DrawStr(s, col, b.y, str, sty)
DrawQuickCharStr(s, col, b.y, str, sty)
col += len(str)
}
@ -185,14 +186,16 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
case tcell.KeyRune: // Search for the matching quick char in menu names
if !b.menusVisible { // If the selected Menu is not open/visible
for _, m := range b.Menus {
for i, m := range b.Menus {
found, r := QuickCharInString(m.Name)
if found && r == ev.Rune() {
b.menusVisible = true
b.selected = i
menu := &b.Menus[b.selected]
(*menu).SetPos(b.GetMenuXPos(b.selected), b.y+1)
(*menu).SetFocused(true)
break
}
}
} else {
@ -306,9 +309,11 @@ func (m *Menu) Draw(s tcell.Screen) {
} else {
sty = defaultStyle
}
itemName := item.GetName()
str := fmt.Sprintf("%s%s", itemName, strings.Repeat(" ", m.width-2-len(itemName)))
DrawStr(s, m.x+1, m.y+1+i, str, sty)
len := DrawQuickCharStr(s, m.x+1, m.y+1+i, item.GetName(), sty)
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)
}
}
}
@ -368,10 +373,13 @@ func (m *Menu) HandleEvent(event tcell.Event) bool {
case tcell.KeyRune:
// TODO: support quick chars for sub-menus
for i, item := range m.Items {
if m.selected == i {
continue // Skip the item we're on
}
found, r := QuickCharInString(item.GetName())
if found && r == ev.Rune() {
m.selected = i
m.ActivateItemUnderCursor()
break
}
}

View File

@ -36,7 +36,6 @@ var DefaultTheme = Theme{
"MenuBarSelected": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
"Menu": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),
"MenuSelected": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
"QuickChar": tcell.Style{}.Foreground(tcell.ColorYellow).Background(tcell.ColorBlack),
"Tab": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
"TabContainer": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
"TabSelected": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),