Bug fix with focusing wrong component after using menu item

This commit is contained in:
Luke I. Wilson 2021-03-20 21:51:34 -05:00
parent 119aac195e
commit 8db551ceae
2 changed files with 75 additions and 42 deletions

111
main.go
View File

@ -15,7 +15,13 @@ var theme = ui.Theme{
"StatusBar": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver), "StatusBar": tcell.Style{}.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver),
} }
var focusedComponent ui.Component = nil var (
menuBar *ui.MenuBar
tabContainer *ui.TabContainer
dialog ui.Component // nil if not present (has exclusive focus)
focusedComponent ui.Component = nil
)
func changeFocus(to ui.Component) { func changeFocus(to ui.Component) {
if focusedComponent != nil { if focusedComponent != nil {
@ -39,7 +45,7 @@ func main() {
sizex, sizey := s.Size() sizex, sizey := s.Size()
tabContainer := ui.NewTabContainer(&theme) tabContainer = ui.NewTabContainer(&theme)
tabContainer.SetPos(0, 1) tabContainer.SetPos(0, 1)
tabContainer.SetSize(sizex, sizey-2) tabContainer.SetSize(sizex, sizey-2)
@ -77,17 +83,9 @@ func main() {
} }
} }
var fileSelector *ui.FileSelectorDialog // if nil, we don't draw it
barFocused := false barFocused := false
bar := ui.NewMenuBar(&theme) menuBar = ui.NewMenuBar(&theme)
bar.ItemSelectedCallback = func() {
// When something is selected in the MenuBar,
// we change focus back to the tab container.
changeFocus(tabContainer)
barFocused = false
}
fileMenu := ui.NewMenu("_File", &theme) fileMenu := ui.NewMenu("_File", &theme)
@ -111,23 +109,25 @@ func main() {
textEdit := ui.NewTextEdit(&s, path, string(bytes), &theme) textEdit := ui.NewTextEdit(&s, path, string(bytes), &theme)
tabContainer.AddTab(path, textEdit) tabContainer.AddTab(path, textEdit)
} }
fileSelector = nil // Hide the file selector // TODO: free the dialog instead?
dialog = nil // Hide the file selector
changeFocus(tabContainer) changeFocus(tabContainer)
barFocused = false barFocused = false
} }
fileSelector = ui.NewFileSelectorDialog( dialog = ui.NewFileSelectorDialog(
&s, &s,
"Comma-separated files or a directory", "Comma-separated files or a directory",
true, true,
&theme, &theme,
callback, callback,
func() { // Dialog is canceled func() { // Dialog is canceled
fileSelector = nil dialog = nil
changeFocus(bar) changeFocus(tabContainer)
barFocused = true barFocused = false
}, },
) )
changeFocus(fileSelector) changeFocus(dialog)
}}, &ui.ItemEntry{Name: "_Save", Shortcut: 's', 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())
@ -144,25 +144,30 @@ func main() {
te.Dirty = false te.Dirty = false
} }
changeFocus(tabContainer)
barFocused = false
} }
}}, &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 dialog = nil // Hide the file selector
changeFocus(tabContainer)
barFocused = false
} }
fileSelector = ui.NewFileSelectorDialog( dialog = ui.NewFileSelectorDialog(
&s, &s,
"Select a file to overwrite", "Select a file to overwrite",
false, false,
&theme, &theme,
callback, callback,
func() { // Dialog canceled func() { // Dialog canceled
fileSelector = nil dialog = nil
changeFocus(bar) changeFocus(tabContainer)
barFocused = false
}, },
) )
changeFocus(fileSelector) changeFocus(dialog)
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "_Close", Shortcut: 'q', Callback: func() { }}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "_Close", Shortcut: 'q', Callback: func() {
if tabContainer.GetTabCount() > 0 { if tabContainer.GetTabCount() > 0 {
tabContainer.RemoveTab(tabContainer.GetSelectedTabIdx()) tabContainer.RemoveTab(tabContainer.GetSelectedTabIdx())
@ -172,6 +177,28 @@ func main() {
} }
}}}) }}})
panelMenu := ui.NewMenu("_Panel", &theme)
panelMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_Up", Callback: func() {
}}, &ui.ItemEntry{Name: "_Down", Callback: func() {
}}, &ui.ItemEntry{Name: "_Left", Callback: func() {
}}, &ui.ItemEntry{Name: "_Right", Callback: func() {
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Split _Left", Callback: func() {
}}, &ui.ItemEntry{Name: "Split _Right", Callback: func() {
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "_Move", Shortcut: 'm', Callback: func() {
}}, &ui.ItemEntry{Name: "_Resize", Shortcut: 'r', Callback: func() {
}}, &ui.ItemEntry{Name: "_Float", Callback: func() {
}}})
editMenu := ui.NewMenu("_Edit", &theme) editMenu := ui.NewMenu("_Edit", &theme)
editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_Cut", Shortcut: 'x', Callback: func() { editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_Cut", Shortcut: 'x', Callback: func() {
@ -184,6 +211,8 @@ func main() {
// TODO: better error handling within editor // TODO: better error handling within editor
_ = ClipWrite(selectedStr) // Add the selectedStr to clipboard _ = ClipWrite(selectedStr) // Add the selectedStr to clipboard
} }
changeFocus(tabContainer)
barFocused = false
} }
}}, &ui.ItemEntry{Name: "_Copy", Shortcut: 'c', Callback: func() { }}, &ui.ItemEntry{Name: "_Copy", Shortcut: 'c', Callback: func() {
if tabContainer.GetTabCount() > 0 { if tabContainer.GetTabCount() > 0 {
@ -193,8 +222,10 @@ func main() {
if selectedStr != "" { // If there is something selected... if selectedStr != "" { // If there is something selected...
_ = ClipWrite(selectedStr) // Add selectedStr to clipboard _ = ClipWrite(selectedStr) // Add selectedStr to clipboard
} }
changeFocus(tabContainer)
barFocused = false
} }
}}, &ui.ItemEntry{Name: "_Paste", Shortcut: 'p', Callback: func() { }}, &ui.ItemEntry{Name: "_Paste", Shortcut: 'v', 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)
@ -204,7 +235,14 @@ func main() {
panic(err) panic(err)
} }
te.Insert(contents) te.Insert(contents)
changeFocus(tabContainer)
barFocused = false
} }
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Select _All", Shortcut: 'a', Callback: func() {
}}, &ui.ItemEntry{Name: "Select _Line", Callback: func() {
}}}) }}})
searchMenu := ui.NewMenu("_Search", &theme) searchMenu := ui.NewMenu("_Search", &theme)
@ -213,9 +251,10 @@ func main() {
s.Beep() s.Beep()
}}}) }}})
bar.AddMenu(fileMenu) menuBar.AddMenu(fileMenu)
bar.AddMenu(editMenu) menuBar.AddMenu(panelMenu)
bar.AddMenu(searchMenu) menuBar.AddMenu(editMenu)
menuBar.AddMenu(searchMenu)
changeFocus(tabContainer) // TabContainer is focused by default changeFocus(tabContainer) // TabContainer is focused by default
@ -228,15 +267,15 @@ func main() {
if tabContainer.GetTabCount() > 0 { // Draw the tab container only if a tab is open if tabContainer.GetTabCount() > 0 { // Draw the tab container only if a tab is open
tabContainer.Draw(s) tabContainer.Draw(s)
} }
bar.Draw(s) // Always draw the menu bar menuBar.Draw(s) // Always draw the menu bar
if fileSelector != nil { if dialog != nil {
// Update fileSelector dialog pos and size // Update fileSelector dialog pos and size
diagMinX, diagMinY := fileSelector.GetMinSize() diagMinX, diagMinY := dialog.GetMinSize()
fileSelector.SetSize(diagMinX, diagMinY) dialog.SetSize(diagMinX, diagMinY)
fileSelector.SetPos(sizex/2-diagMinX/2, sizey/2-diagMinY/2) // Center dialog.SetPos(sizex/2-diagMinX/2, sizey/2-diagMinY/2) // Center
fileSelector.Draw(s) dialog.Draw(s)
} }
// Draw statusbar // Draw statusbar
@ -271,24 +310,24 @@ func main() {
case *tcell.EventResize: case *tcell.EventResize:
sizex, sizey = s.Size() sizex, sizey = s.Size()
bar.SetSize(sizex, 1) menuBar.SetSize(sizex, 1)
tabContainer.SetSize(sizex, sizey-2) tabContainer.SetSize(sizex, sizey-2)
s.Sync() // Redraw everything s.Sync() // Redraw everything
case *tcell.EventKey: case *tcell.EventKey:
// On Escape, we change focus between editor and the MenuBar. // On Escape, we change focus between editor and the MenuBar.
if fileSelector == nil { // While no dialog is present... if dialog == nil { // While no dialog is present...
if ev.Key() == tcell.KeyEscape { if ev.Key() == tcell.KeyEscape {
barFocused = !barFocused barFocused = !barFocused
if barFocused { if barFocused {
changeFocus(bar) changeFocus(menuBar)
} else { } else {
changeFocus(tabContainer) changeFocus(tabContainer)
} }
} }
if ev.Modifiers() & tcell.ModCtrl != 0 { if ev.Modifiers() & tcell.ModCtrl != 0 {
handled := bar.HandleEvent(ev) handled := menuBar.HandleEvent(ev)
if handled { if handled {
continue // Avoid passing the event to the focusedComponent continue // Avoid passing the event to the focusedComponent
} }

View File

@ -55,8 +55,6 @@ func (m *Menu) GetShortcut() rune {
// A MenuBar is a horizontal list of menus. // A MenuBar is a horizontal list of menus.
type MenuBar struct { type MenuBar struct {
ItemSelectedCallback func()
menus []*Menu menus []*Menu
x, y int x, y int
width, height int width, height int
@ -78,10 +76,6 @@ func (b *MenuBar) AddMenu(menu *Menu) {
menu.itemSelectedCallback = func() { menu.itemSelectedCallback = func() {
b.menusVisible = false b.menusVisible = false
menu.SetFocused(false) menu.SetFocused(false)
if b.ItemSelectedCallback != nil {
b.ItemSelectedCallback()
}
} }
b.menus = append(b.menus, menu) b.menus = append(b.menus, menu)
} }