keyboard navigation fixed

This commit is contained in:
piotr 2021-05-28 03:10:13 +02:00
parent e9899d2753
commit 002fd076fc
4 changed files with 96 additions and 88 deletions

Binary file not shown.

View File

@ -1,5 +1,5 @@
window { window {
background-color: rgba (36, 47, 79, 0.92); background-color: rgba (36, 47, 79, 0.9);
color: #eeeeee color: #eeeeee
} }
@ -19,4 +19,9 @@ button {
button:hover { button:hover {
background-color: rgba (255, 255, 255, 0.1) background-color: rgba (255, 255, 255, 0.1)
} }
#pinned-box {
padding-bottom: 5px;
border-bottom: 1px dotted gray
}

13
main.go
View File

@ -88,7 +88,8 @@ var (
fileSearchResults []string fileSearchResults []string
searchEntry *gtk.SearchEntry searchEntry *gtk.SearchEntry
phrase string phrase string
fileSearchResultListBox *gtk.ListBox fileSearchResultListBox *gtk.ListBox // tbd
fileSearchResultFlowBox *gtk.FlowBox
buttonsWrapper *gtk.Box buttonsWrapper *gtk.Box
buttonBox *gtk.EventBox buttonBox *gtk.EventBox
confirmationBox *gtk.Box confirmationBox *gtk.Box
@ -115,6 +116,7 @@ var itemPadding = flag.Uint("padding", 2, "vertical item padding")
var lang = flag.String("lang", "", "force lang, e.g. \"en\", \"pl\"") var lang = flag.String("lang", "", "force lang, e.g. \"en\", \"pl\"")
var fileManager = flag.String("fm", "thunar", "File Manager") var fileManager = flag.String("fm", "thunar", "File Manager")
var term = flag.String("term", "alacritty", "Terminal emulator") var term = flag.String("term", "alacritty", "Terminal emulator")
var nameLimit = flag.Int("l", 90, "file name length Limit")
func main() { func main() {
timeStart := time.Now() timeStart := time.Now()
@ -238,7 +240,7 @@ func main() {
gtk.MainQuit() gtk.MainQuit()
}) })
win.Connect("key-release-event", func(window *gtk.Window, event *gdk.Event) { win.Connect("key-release-event", func(window *gtk.Window, event *gdk.Event) bool {
key := &gdk.EventKey{Event: event} key := &gdk.EventKey{Event: event}
if key.KeyVal() == gdk.KEY_Escape { if key.KeyVal() == gdk.KEY_Escape {
s, _ := searchEntry.GetText() s, _ := searchEntry.GetText()
@ -248,7 +250,10 @@ func main() {
} else { } else {
gtk.MainQuit() gtk.MainQuit()
} }
} else {
return false
} }
return false
}) })
// Close the window on leave, but not immediately, to avoid accidental closes // Close the window on leave, but not immediately, to avoid accidental closes
@ -277,7 +282,7 @@ func main() {
categoriesWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) categoriesWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
categoriesButtonBox := setUpCategoriesButtonBox() categoriesButtonBox := setUpCategoriesButtonBox()
categoriesWrapper.PackStart(categoriesButtonBox, true, false, 0) categoriesWrapper.PackStart(categoriesButtonBox, true, false, 0)
outerVBox.PackStart(categoriesWrapper, false, false, 10) outerVBox.PackStart(categoriesWrapper, false, false, 0)
pinnedWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) pinnedWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
outerVBox.PackStart(pinnedWrapper, false, false, 0) outerVBox.PackStart(pinnedWrapper, false, false, 0)
@ -287,7 +292,7 @@ func main() {
pinnedFlowBox = setUpPinnedFlowBox() pinnedFlowBox = setUpPinnedFlowBox()
resultWindow, _ = gtk.ScrolledWindowNew(nil, nil) resultWindow, _ = gtk.ScrolledWindowNew(nil, nil)
resultWindow.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) resultWindow.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
resultWindow.Connect("enter-notify-event", func() { resultWindow.Connect("enter-notify-event", func() {
cancelClose() cancelClose()
}) })

View File

@ -21,10 +21,11 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
flowBox.SetMaxChildrenPerLine(uint(len(pinned))) flowBox.SetMaxChildrenPerLine(uint(len(pinned)))
} }
//flowBox.SetMinChildrenPerLine(9)
flowBox.SetColumnSpacing(20) flowBox.SetColumnSpacing(20)
flowBox.SetHomogeneous(true) flowBox.SetHomogeneous(true)
flowBox.SetRowSpacing(20) flowBox.SetRowSpacing(20)
flowBox.SetProperty("name", "pinned-box")
flowBox.SetSelectionMode(gtk.SELECTION_NONE)
if len(pinned) > 0 { if len(pinned) > 0 {
for _, desktopID := range pinned { for _, desktopID := range pinned {
@ -63,6 +64,9 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
} }
return false return false
}) })
btn.Connect("activate", func() {
launch(entry.Exec, entry.Terminal)
})
flowBox.Add(btn) flowBox.Add(btn)
} }
@ -73,7 +77,10 @@ func setUpPinnedFlowBox() *gtk.FlowBox {
}) })
pinnedFlowBoxWrapper.PackStart(flowBox, true, false, 0) pinnedFlowBoxWrapper.PackStart(flowBox, true, false, 0)
flowBox.ShowAll() //While moving focus with arrow keys we want buttons to get focus directly
flowBox.GetChildren().Foreach(func(item interface{}) {
item.(*gtk.Widget).SetCanFocus(false)
})
return flowBox return flowBox
} }
@ -99,7 +106,6 @@ func setUpCategoriesButtonBox() *gtk.EventBox {
eventBox.Add(hBox) eventBox.Add(hBox)
button, _ := gtk.ButtonNewWithLabel("All") button, _ := gtk.ButtonNewWithLabel("All")
button.Connect("clicked", func(item *gtk.Button) { button.Connect("clicked", func(item *gtk.Button) {
searchEntry.GrabFocus()
searchEntry.SetText("") searchEntry.SetText("")
appFlowBox = setUpAppsFlowBox(nil, "") appFlowBox = setUpAppsFlowBox(nil, "")
for _, btn := range catButtons { for _, btn := range catButtons {
@ -118,7 +124,6 @@ func setUpCategoriesButtonBox() *gtk.EventBox {
name := cat.Name name := cat.Name
b := *button b := *button
button.Connect("clicked", func(item *gtk.Button) { button.Connect("clicked", func(item *gtk.Button) {
searchEntry.GrabFocus()
searchEntry.SetText("") searchEntry.SetText("")
// !!! since gotk3 FlowBox type does not implement set_filter_func, we need to rebuild appFlowBox // !!! since gotk3 FlowBox type does not implement set_filter_func, we need to rebuild appFlowBox
appFlowBox = setUpAppsFlowBox(lists[name], "") appFlowBox = setUpAppsFlowBox(lists[name], "")
@ -171,6 +176,8 @@ func setUpAppsFlowBox(categoryList []string, searchPhrase string) *gtk.FlowBox {
flowBox.SetColumnSpacing(20) flowBox.SetColumnSpacing(20)
flowBox.SetRowSpacing(20) flowBox.SetRowSpacing(20)
flowBox.SetHomogeneous(true) flowBox.SetHomogeneous(true)
flowBox.SetSelectionMode(gtk.SELECTION_NONE)
for _, entry := range desktopEntries { for _, entry := range desktopEntries {
if searchPhrase == "" { if searchPhrase == "" {
if !entry.NoDisplay { if !entry.NoDisplay {
@ -197,6 +204,10 @@ func setUpAppsFlowBox(categoryList []string, searchPhrase string) *gtk.FlowBox {
hWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) hWrapper, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
appSearchResultWrapper.PackStart(hWrapper, false, false, 0) appSearchResultWrapper.PackStart(hWrapper, false, false, 0)
hWrapper.PackStart(flowBox, true, false, 0) hWrapper.PackStart(flowBox, true, false, 0)
// While moving focus with arrow keys we want buttons to get focus directly
flowBox.GetChildren().Foreach(func(item interface{}) {
item.(*gtk.Widget).SetCanFocus(false)
})
resultWindow.ShowAll() resultWindow.ShowAll()
return flowBox return flowBox
@ -231,6 +242,9 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
} }
return false return false
}) })
button.Connect("activate", func() {
launch(exec, terminal)
})
button.Connect("enter-notify-event", func() { button.Connect("enter-notify-event", func() {
statusLabel.SetText(desc) statusLabel.SetText(desc)
}) })
@ -240,18 +254,19 @@ func flowBoxButton(entry desktopEntry) *gtk.Button {
return button return button
} }
func setUpFileSearchResult() *gtk.ListBox { func setUpFileSearchResult() *gtk.FlowBox {
if fileSearchResultListBox != nil { if fileSearchResultFlowBox != nil {
fileSearchResultListBox.Destroy() fileSearchResultFlowBox.Destroy()
} }
listBox, _ := gtk.ListBoxNew() flowBox, _ := gtk.FlowBoxNew()
listBox.Connect("enter-notify-event", func() { flowBox.SetProperty("orientation", gtk.ORIENTATION_VERTICAL)
flowBox.Connect("enter-notify-event", func() {
cancelClose() cancelClose()
}) })
fileSearchResultWrapper.PackStart(listBox, false, false, 10) fileSearchResultWrapper.PackStart(flowBox, false, false, 10)
listBox.ShowAll() flowBox.ShowAll() // TODO: check if necessary here
return listBox return flowBox
} }
func walk(path string, d fs.DirEntry, e error) error { func walk(path string, d fs.DirEntry, e error) error {
@ -270,6 +285,7 @@ func walk(path string, d fs.DirEntry, e error) error {
func setUpSearchEntry() *gtk.SearchEntry { func setUpSearchEntry() *gtk.SearchEntry {
searchEntry, _ := gtk.SearchEntryNew() searchEntry, _ := gtk.SearchEntryNew()
searchEntry.SetPlaceholderText("Type to search")
searchEntry.Connect("enter-notify-event", func() { searchEntry.Connect("enter-notify-event", func() {
cancelClose() cancelClose()
}) })
@ -285,31 +301,30 @@ func setUpSearchEntry() *gtk.SearchEntry {
appFlowBox = setUpAppsFlowBox(nil, phrase) appFlowBox = setUpAppsFlowBox(nil, phrase)
if len(phrase) > 2 { if len(phrase) > 2 {
if fileSearchResultListBox != nil { if fileSearchResultFlowBox != nil {
fileSearchResultListBox.Destroy() fileSearchResultFlowBox.Destroy()
} }
fileSearchResultListBox = setUpFileSearchResult() fileSearchResultFlowBox = setUpFileSearchResult()
for key := range userDirsMap { for key := range userDirsMap {
if key != "home" { if key != "home" {
fileSearchResults = nil fileSearchResults = nil
if len(fileSearchResults) == 0 { if len(fileSearchResults) == 0 {
fileSearchResultListBox.Show() fileSearchResultFlowBox.Show()
} }
filepath.WalkDir(userDirsMap[key], walk)
searchUserDir(key) searchUserDir(key)
} }
} }
if fileSearchResultListBox.GetChildren().Length() == 0 { if fileSearchResultFlowBox.GetChildren().Length() == 0 {
fileSearchResultListBox.Hide() fileSearchResultFlowBox.Hide()
} }
} else { } else {
if fileSearchResultListBox != nil { if fileSearchResultFlowBox != nil {
fileSearchResultListBox.Destroy() fileSearchResultFlowBox.Destroy()
} }
} }
} else { } else {
if fileSearchResultListBox != nil { if fileSearchResultFlowBox != nil {
fileSearchResultListBox.Destroy() fileSearchResultFlowBox.Destroy()
} }
appFlowBox = setUpAppsFlowBox(nil, "") appFlowBox = setUpAppsFlowBox(nil, "")
} }
@ -324,90 +339,73 @@ func setUpSearchEntry() *gtk.SearchEntry {
func searchUserDir(dir string) { func searchUserDir(dir string) {
fileSearchResults = nil fileSearchResults = nil
filepath.WalkDir(userDirsMap[dir], walk) filepath.WalkDir(userDirsMap[dir], walk)
if fileSearchResults != nil && len(fileSearchResults) > 0 {
row := setUpUserDirsListRow(fmt.Sprintf("folder-%s", dir), "", dir, userDirsMap) if fileSearchResults != nil && len(fileSearchResults) > 2 {
fileSearchResultListBox.Add(row) btn := setUpUserDirButton(fmt.Sprintf("folder-%s", dir), "", dir, userDirsMap)
fileSearchResultListBox.ShowAll() fileSearchResultFlowBox.Add(btn)
for _, path := range fileSearchResults { for _, path := range fileSearchResults {
partOfPathToShow := strings.Split(path, userDirsMap[dir])[1] partOfPathToShow := strings.Split(path, userDirsMap[dir])[1]
if partOfPathToShow != "" { if partOfPathToShow != "" {
row := setUpUserFileSearchResultRow(partOfPathToShow, path) btn := setUpUserFileSearchResultButton(partOfPathToShow, path)
fileSearchResultListBox.Add(row) fileSearchResultFlowBox.Add(btn)
} }
} }
fileSearchResultListBox.ShowAll() fileSearchResultFlowBox.Hide()
statusLabel.SetText(fmt.Sprintf("%v results", fileSearchResultListBox.GetChildren().Length()))
statusLabel.SetText(fmt.Sprintf("%v results", fileSearchResultFlowBox.GetChildren().Length()))
num := uint(fileSearchResultFlowBox.GetChildren().Length() / 3)
fileSearchResultFlowBox.SetMinChildrenPerLine(num + 1)
fileSearchResultFlowBox.SetMaxChildrenPerLine(num + 1)
//While moving focus with arrow keys we want buttons to get focus directly
fileSearchResultFlowBox.GetChildren().Foreach(func(item interface{}) {
item.(*gtk.Widget).SetCanFocus(false)
})
fileSearchResultFlowBox.ShowAll()
} }
} }
func setUpUserDirsListRow(iconName, displayName, entryName string, userDirsMap map[string]string) *gtk.ListBoxRow { func setUpUserDirButton(iconName, displayName, entryName string, userDirsMap map[string]string) *gtk.Box {
if displayName == "" { if displayName == "" {
parts := strings.Split(userDirsMap[entryName], "/") parts := strings.Split(userDirsMap[entryName], "/")
displayName = parts[(len(parts) - 1)] displayName = parts[(len(parts) - 1)]
} }
row, _ := gtk.ListBoxRowNew() box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
//row.SetCanFocus(false) button, _ := gtk.ButtonNew()
row.SetSelectable(false) img, _ := gtk.ImageNewFromIconName(iconName, gtk.ICON_SIZE_MENU)
vBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) button.SetImage(img)
eventBox, _ := gtk.EventBoxNew()
hBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 6)
eventBox.Add(hBox)
vBox.PackStart(eventBox, false, false, *itemPadding*3)
img, _ := gtk.ImageNewFromIconName(iconName, gtk.ICON_SIZE_DND) if len(displayName) > *nameLimit {
hBox.PackStart(img, false, false, 0) displayName = fmt.Sprintf("%s...", displayName[:*nameLimit-3])
if len(displayName) > 45 {
displayName = fmt.Sprintf("%s...", displayName[:42])
} }
lbl, _ := gtk.LabelNew(displayName) button.SetLabel(displayName)
hBox.PackStart(lbl, false, false, 0)
row.Add(vBox)
row.Connect("activate", func() { button.Connect("clicked", func() {
launch(fmt.Sprintf("%s %s", *fileManager, userDirsMap[entryName]), false) launch(fmt.Sprintf("%s %s", *fileManager, userDirsMap[entryName]), false)
}) })
eventBox.Connect("button-release-event", func(row *gtk.ListBoxRow, e *gdk.Event) bool { box.PackStart(button, false, true, 0)
btnEvent := gdk.EventButtonNewFromEvent(e) return box
if btnEvent.Button() == 1 {
launch(fmt.Sprintf("%s %s", *fileManager, userDirsMap[entryName]), false)
return true
}
return false
})
return row
} }
func setUpUserFileSearchResultRow(fileName, filePath string) *gtk.ListBoxRow { func setUpUserFileSearchResultButton(fileName, filePath string) *gtk.Box {
row, _ := gtk.ListBoxRowNew() box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
row.SetSelectable(false) button, _ := gtk.ButtonNew()
vBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
eventBox, _ := gtk.EventBoxNew()
hBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
eventBox.Add(hBox)
vBox.PackStart(eventBox, false, false, *itemPadding)
if len(fileName) > 150 { tooltipText := ""
fileName = fmt.Sprintf("%s...", fileName[:147]) if len(fileName) > *nameLimit {
tooltipText = fileName
fileName = fmt.Sprintf("%s...", fileName[:*nameLimit-3])
}
button.SetLabel(fileName)
if tooltipText != "" {
button.SetTooltipText(tooltipText)
} }
lbl, _ := gtk.LabelNew(fileName)
hBox.PackStart(lbl, false, false, 0)
row.Add(vBox)
row.Connect("activate", func() { button.Connect("clicked", func() {
open(filePath) open(filePath)
}) })
eventBox.Connect("button-release-event", func(row *gtk.ListBoxRow, e *gdk.Event) bool { box.PackStart(button, false, true, 0)
btnEvent := gdk.EventButtonNewFromEvent(e) return box
if btnEvent.Button() == 1 {
open(filePath)
return true
}
return false
})
return row
} }