Bug fix with focusing wrong component after using menu item
This commit is contained in:
parent
119aac195e
commit
8db551ceae
111
main.go
111
main.go
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user