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 {
background-color: rgba (36, 47, 79, 0.92);
background-color: rgba (36, 47, 79, 0.9);
color: #eeeeee
}
@ -19,4 +19,9 @@ button {
button:hover {
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
searchEntry *gtk.SearchEntry
phrase string
fileSearchResultListBox *gtk.ListBox
fileSearchResultListBox *gtk.ListBox // tbd
fileSearchResultFlowBox *gtk.FlowBox
buttonsWrapper *gtk.Box
buttonBox *gtk.EventBox
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 fileManager = flag.String("fm", "thunar", "File Manager")
var term = flag.String("term", "alacritty", "Terminal emulator")
var nameLimit = flag.Int("l", 90, "file name length Limit")
func main() {
timeStart := time.Now()
@ -238,7 +240,7 @@ func main() {
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}
if key.KeyVal() == gdk.KEY_Escape {
s, _ := searchEntry.GetText()
@ -248,7 +250,10 @@ func main() {
} else {
gtk.MainQuit()
}
} else {
return false
}
return false
})
// 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)
categoriesButtonBox := setUpCategoriesButtonBox()
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)
outerVBox.PackStart(pinnedWrapper, false, false, 0)
@ -287,7 +292,7 @@ func main() {
pinnedFlowBox = setUpPinnedFlowBox()
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() {
cancelClose()
})

View File

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