Added quick chars to MenuBar and Menus
This commit is contained in:
parent
83567c1341
commit
ffaad36c78
22
main.go
22
main.go
@ -70,12 +70,12 @@ func main() {
|
|||||||
|
|
||||||
barFocused := false
|
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
|
textEdit := ui.NewTextEdit(&s, "", "", &theme) // No file path, no contents
|
||||||
tabContainer.AddTab("noname", textEdit)
|
tabContainer.AddTab("noname", textEdit)
|
||||||
}}, &ui.ItemEntry{Name: "Open...", Callback: func() {
|
}}, &ui.ItemEntry{Name: "_Open...", Callback: func() {
|
||||||
callback := func(filePaths []string) {
|
callback := func(filePaths []string) {
|
||||||
for _, path := range filePaths {
|
for _, path := range filePaths {
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
@ -109,7 +109,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
changeFocus(fileSelector)
|
changeFocus(fileSelector)
|
||||||
}}, &ui.ItemEntry{Name: "Save", Callback: func() {
|
}}, &ui.ItemEntry{Name: "_Save", 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)
|
||||||
@ -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
|
// TODO: implement a "Save as" dialog system, and show that when trying to save noname files
|
||||||
callback := func(filePaths []string) {
|
callback := func(filePaths []string) {
|
||||||
fileSelector = nil // Hide the file selector
|
fileSelector = nil // Hide the file selector
|
||||||
@ -142,14 +142,14 @@ func main() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
changeFocus(fileSelector)
|
changeFocus(fileSelector)
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Exit", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "E_xit", Callback: func() {
|
||||||
s.Fini()
|
s.Fini()
|
||||||
os.Exit(0)
|
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 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -160,7 +160,7 @@ func main() {
|
|||||||
_ = ClipWrite(selectedStr) // Add the selectedStr to clipboard
|
_ = ClipWrite(selectedStr) // Add the selectedStr to clipboard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}, &ui.ItemEntry{Name: "Copy", Callback: func() {
|
}}, &ui.ItemEntry{Name: "_Copy", 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)
|
||||||
@ -169,7 +169,7 @@ func main() {
|
|||||||
_ = ClipWrite(selectedStr) // Add selectedStr to clipboard
|
_ = ClipWrite(selectedStr) // Add selectedStr to clipboard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}, &ui.ItemEntry{Name: "Paste", Callback: func() {
|
}}, &ui.ItemEntry{Name: "_Paste", 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)
|
||||||
@ -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() {
|
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||||
s.Beep()
|
s.Beep()
|
||||||
|
@ -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`.
|
// 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) {
|
func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) {
|
||||||
runes := []rune(str)
|
runes := []rune(str)
|
||||||
for idx := 0; idx < len(runes); idx++ {
|
for idx, r := range runes {
|
||||||
s.SetContent(x+idx, y, runes[idx], nil, style)
|
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`
|
// 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.
|
// 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) {
|
func DrawRectOutline(s tcell.Screen, x, y, _width, _height int, ul, ur, bl, br, hor, vert rune, style tcell.Style) {
|
||||||
|
30
ui/menu.go
30
ui/menu.go
@ -90,13 +90,14 @@ func (b *MenuBar) Draw(s tcell.Screen) {
|
|||||||
col := b.x + 1
|
col := b.x + 1
|
||||||
for i, item := range b.Menus {
|
for i, item := range b.Menus {
|
||||||
str := fmt.Sprintf(" %s ", item.Name) // Surround the name in spaces
|
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 := normalStyle
|
||||||
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use style for selected items
|
if b.focused && b.selected == i {
|
||||||
} else {
|
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use special style for selected item
|
||||||
sty = normalStyle
|
|
||||||
}
|
}
|
||||||
DrawStr(s, col, b.y, str, sty)
|
|
||||||
|
DrawQuickCharStr(s, col, b.y, str, sty)
|
||||||
|
|
||||||
col += len(str)
|
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
|
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 _, m := range b.Menus {
|
for i, m := range b.Menus {
|
||||||
found, r := QuickCharInString(m.Name)
|
found, r := QuickCharInString(m.Name)
|
||||||
if found && r == ev.Rune() {
|
if found && r == ev.Rune() {
|
||||||
b.menusVisible = true
|
b.menusVisible = true
|
||||||
|
|
||||||
|
b.selected = i
|
||||||
menu := &b.Menus[b.selected]
|
menu := &b.Menus[b.selected]
|
||||||
(*menu).SetPos(b.GetMenuXPos(b.selected), b.y+1)
|
(*menu).SetPos(b.GetMenuXPos(b.selected), b.y+1)
|
||||||
(*menu).SetFocused(true)
|
(*menu).SetFocused(true)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -306,9 +309,11 @@ func (m *Menu) Draw(s tcell.Screen) {
|
|||||||
} else {
|
} else {
|
||||||
sty = defaultStyle
|
sty = defaultStyle
|
||||||
}
|
}
|
||||||
itemName := item.GetName()
|
|
||||||
str := fmt.Sprintf("%s%s", itemName, strings.Repeat(" ", m.width-2-len(itemName)))
|
len := DrawQuickCharStr(s, m.x+1, m.y+1+i, item.GetName(), sty)
|
||||||
DrawStr(s, m.x+1, m.y+1+i, str, 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:
|
case tcell.KeyRune:
|
||||||
// TODO: support quick chars for sub-menus
|
// TODO: support quick chars for sub-menus
|
||||||
for i, item := range m.Items {
|
for i, item := range m.Items {
|
||||||
|
if m.selected == i {
|
||||||
|
continue // Skip the item we're on
|
||||||
|
}
|
||||||
found, r := QuickCharInString(item.GetName())
|
found, r := QuickCharInString(item.GetName())
|
||||||
if found && r == ev.Rune() {
|
if found && r == ev.Rune() {
|
||||||
m.selected = i
|
m.selected = i
|
||||||
m.ActivateItemUnderCursor()
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ var DefaultTheme = Theme{
|
|||||||
"MenuBarSelected": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
|
"MenuBarSelected": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
|
||||||
"Menu": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),
|
"Menu": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),
|
||||||
"MenuSelected": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
|
"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),
|
"Tab": tcell.Style{}.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
|
||||||
"TabContainer": 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),
|
"TabSelected": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user