Added shortcut keys possibility to Menus
This commit is contained in:
parent
fefa34c2b6
commit
ce66bc4bc6
9
main.go
9
main.go
@ -128,7 +128,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
changeFocus(fileSelector)
|
changeFocus(fileSelector)
|
||||||
}}, &ui.ItemEntry{Name: "_Save", Callback: func() {
|
}}, &ui.ItemEntry{Name: "_Save", Shortcut: 's', Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -287,6 +287,13 @@ main_loop:
|
|||||||
if ev.Key() == tcell.KeyCtrlQ { // TODO: replace with shortcut keys in menus
|
if ev.Key() == tcell.KeyCtrlQ { // TODO: replace with shortcut keys in menus
|
||||||
break main_loop
|
break main_loop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ev.Modifiers() & tcell.ModCtrl != 0 {
|
||||||
|
handled := bar.HandleEvent(ev)
|
||||||
|
if handled {
|
||||||
|
continue // Avoid passing the event to the focusedComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
focusedComponent.HandleEvent(ev)
|
focusedComponent.HandleEvent(ev)
|
||||||
|
1
testfile.txt
Executable file
1
testfile.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
wtf thisis a test
|
59
ui/menu.go
59
ui/menu.go
@ -3,6 +3,7 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
)
|
)
|
||||||
@ -10,11 +11,6 @@ import (
|
|||||||
// 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 returns the shortcut character to activate the Item without opening
|
|
||||||
// the Menu. For example, if the shortcut were 'a', then the user would have to press
|
|
||||||
// `Ctrl + a`. If the shortcut were 'A', then the user would press `Ctrl + Shift + a`.
|
|
||||||
// The zero value means "no shortcut".
|
|
||||||
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
|
||||||
@ -26,15 +22,11 @@ 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
|
||||||
Callback func()
|
|
||||||
Shortcut rune
|
Shortcut rune
|
||||||
|
Callback func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetName returns the name of the ItemEntry.
|
// GetName returns the name of the ItemEntry.
|
||||||
@ -42,19 +34,11 @@ 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 // Menus don't have shortcuts
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()
|
||||||
@ -211,6 +195,24 @@ func (b *MenuBar) SetSize(width, height int) {
|
|||||||
func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
||||||
switch ev := event.(type) {
|
switch ev := event.(type) {
|
||||||
case *tcell.EventKey:
|
case *tcell.EventKey:
|
||||||
|
// Shortcuts (Ctrl + s or Ctrl + (Shift) A, for example)
|
||||||
|
if ev.Modifiers() & tcell.ModCtrl != 0 {
|
||||||
|
// tcell calls Ctrl + rune keys "Ctrl-(RUNE)" so we want to remove the "Ctrl-"
|
||||||
|
// prefix, and turn the remaining part of the string into a rune.
|
||||||
|
keyRune := []rune(tcell.KeyNames[ev.Key()][5:])[0]
|
||||||
|
|
||||||
|
keyRune = unicode.ToLower(keyRune) // Make the rune lowercase.
|
||||||
|
|
||||||
|
// Find who the shortcut key belongs to
|
||||||
|
for i := range b.menus {
|
||||||
|
handled := b.menus[i].handleShortcut(keyRune)
|
||||||
|
if handled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false // The shortcut key was not handled by any menus
|
||||||
|
}
|
||||||
|
|
||||||
switch ev.Key() {
|
switch ev.Key() {
|
||||||
case tcell.KeyEnter:
|
case tcell.KeyEnter:
|
||||||
if !b.menusVisible { // If menus are not visible...
|
if !b.menusVisible { // If menus are not visible...
|
||||||
@ -229,6 +231,7 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
|||||||
b.CursorRight()
|
b.CursorRight()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quick char
|
||||||
case tcell.KeyRune: // Search for the matching quick char in menu names
|
case tcell.KeyRune: // Search for the matching quick char in menu names
|
||||||
if !b.menusVisible { // If the selected Menu is not open/visible
|
if !b.menusVisible { // If the selected Menu is not open/visible
|
||||||
for i, m := range b.menus {
|
for i, m := range b.menus {
|
||||||
@ -241,7 +244,7 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return b.menus[b.selected].HandleEvent(event) // Have menu handle quick char event
|
return b.menus[b.selected].HandleEvent(event) // Have menu handle quick char event
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if b.menusVisible {
|
if b.menusVisible {
|
||||||
@ -397,6 +400,24 @@ func (m *Menu) SetSize(width, height int) {
|
|||||||
// Cannot set the size of a Menu
|
// Cannot set the size of a Menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Menu) handleShortcut(r rune) bool {
|
||||||
|
for i := range m.Items {
|
||||||
|
switch typ := m.Items[i].(type) {
|
||||||
|
case *ItemSeparator:
|
||||||
|
continue
|
||||||
|
case *Menu:
|
||||||
|
return typ.handleShortcut(r) // Have the sub-menu handle the shortcut
|
||||||
|
case *ItemEntry:
|
||||||
|
if typ.Shortcut == r { // If this item matches the shortcut we're finding...
|
||||||
|
m.selected = i
|
||||||
|
m.ActivateItemUnderCursor() // Activate it
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// HandleEvent will handle events for a Menu and may propogate them
|
// HandleEvent will handle events for a Menu and may propogate them
|
||||||
// to sub-menus. Returns true if the event was handled.
|
// to sub-menus. Returns true if the event was handled.
|
||||||
func (m *Menu) HandleEvent(event tcell.Event) bool {
|
func (m *Menu) HandleEvent(event tcell.Event) bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user