diff --git a/main.go b/main.go index 6670997..2f00fc4 100644 --- a/main.go +++ b/main.go @@ -26,8 +26,11 @@ var icon []byte // this is the app icon //go:generate go run ./filetypes/cmd/gen.go var validFileTypes = filetypes.Valid + var fileList *tk.ToplevelWidget var lb *tk.ListboxWidget +var img = tk.Label() +var fileListBindVar = tk.Variable("FileList") var directoryState struct { currentDirectory string @@ -62,19 +65,17 @@ func isImage(entry os.DirEntry) bool { return false } -func newFileInDirectory(img *tk.LabelWidget) func() { - return func() { - files := tk.GetOpenFile(tk.Filetypes(filetypes.GetTkTypes(validFileTypes)), tk.Multiple(false)) - if len(files) < 1 || files[0] == "" { - log.Println("no file chosen") - return - } - file := strings.Join(files, " ") // GetOpenFile returns an array split on spaces! - openFileAndDirectory(img, file) +func newFileInDirectory() { + files := tk.GetOpenFile(tk.Filetypes(filetypes.GetTkTypes(validFileTypes)), tk.Multiple(false)) + if len(files) < 1 || files[0] == "" { + log.Println("no file chosen") + return } + file := strings.Join(files, " ") // GetOpenFile returns an array split on spaces! + openFileAndDirectory(file) } -func openFileAndDirectory(img *tk.LabelWidget, file string) { +func openFileAndDirectory(file string) { directoryState.currentFile = filepath.Base(file) directoryState.currentDirectory = filepath.Dir(file) dirfiles, err := os.ReadDir(directoryState.currentDirectory) @@ -88,33 +89,31 @@ func openFileAndDirectory(img *tk.LabelWidget, file string) { directoryState.images = append(directoryState.images, v.Name()) } } - updateImage(file, img) + updateImage(file) } -func newDirectory(img *tk.LabelWidget) func() { - return func() { - dir := tk.ChooseDirectory() - if dir == "" { - log.Println("no directory chosen") - return - } - directoryState.currentDirectory = dir - dirfiles, err := os.ReadDir(directoryState.currentDirectory) - if err != nil { - log.Println(err) - return - } - directoryState.images = []string{} - for _, v := range dirfiles { - if isImage(v) { - directoryState.images = append(directoryState.images, v.Name()) - } - } - updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[0]), img) +func newDirectory() { + dir := tk.ChooseDirectory() + if dir == "" { + log.Println("no directory chosen") + return } + directoryState.currentDirectory = dir + dirfiles, err := os.ReadDir(directoryState.currentDirectory) + if err != nil { + log.Println(err) + return + } + directoryState.images = []string{} + for _, v := range dirfiles { + if isImage(v) { + directoryState.images = append(directoryState.images, v.Name()) + } + } + updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[0])) } -func updateImage(file string, img *tk.LabelWidget) { +func updateImage(file string) { var i image.Image f, err := os.Open(file) @@ -142,11 +141,11 @@ func updateImage(file string, img *tk.LabelWidget) { must(strconv.Atoi(tk.WinfoScreenHeight(tk.App)))-50, imaging.CatmullRom, ) - repaint(img, filepath.Base(file), tk.Data(i)) + repaint(filepath.Base(file), tk.Data(i)) directoryState.currentFile = filepath.Base(file) } -func repaint(img *tk.LabelWidget, name string, data tk.Opt) { +func repaint(name string, data tk.Opt) { // TODO: sometimes, when going from a big image to a smaller one, // the window remains the same height as the big image, // even as the width shrinks to fit the smaller image. @@ -160,103 +159,102 @@ func repaint(img *tk.LabelWidget, name string, data tk.Opt) { tk.App.Center() } -func main() { - tk.App.IconPhoto(tk.NewPhoto(tk.Data(icon)), tk.DefaultIcon()) - img := tk.Label() - repaint(img, "", tk.Data(noise)) +func destroyFileList(destroy bool) { + if destroy { + tk.Destroy(fileList) + } + fileList = nil + lb = nil + fileListBindVar.Set("0") +} - tk.MacOpenDocument(func(e string) { - openFileAndDirectory(img, e) - }) +func constructFileList() { + fileList = tk.Toplevel() + fileList.WmTitle("Files") + lb = fileList.Listbox(tk.Height(0)) + for i := range directoryState.images { + lb.Insert("end", directoryState.images[i]) + if i == slices.Index(directoryState.images, directoryState.currentFile) { + lb.SelectionSet(i) + } + } + tk.Pack(lb) + tk.Bind(lb, "<>", tk.Command(func() { + selection := lb.Curselection() + updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[selection[0]])) + })) + tk.Bind(fileList, "", tk.Command(func(e *tk.Event) { + // list closed by user click on + destroyFileList(false) + })) + fileListBindVar.Set("1") +} + +func menuSelect() { + if fileListBindVar.Get() == "1" && fileList == nil { + constructFileList() + } else if fileListBindVar.Get() == "0" && fileList != nil { + destroyFileList(true) + } +} + +func moveSelectInFileList(target int) { + if lb != nil { + lb.SelectionClear("0", "end") + lb.SelectionSet(target) + lb.See(target) + } +} + +func keyPress(e *tk.Event) { + curr := slices.Index(directoryState.images, directoryState.currentFile) + switch e.Keysym { + case ".": + log.Printf("state: %+v", directoryState) + case "o": + newFileInDirectory() + case "a": + if fileList == nil { + constructFileList() + } else { + destroyFileList(true) + } + case "Up", "Right": + if curr > 0 { + updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[curr-1])) + moveSelectInFileList(curr - 1) + } + case "Down", "Left": + if curr < len(directoryState.images)-1 && curr != -1 { + updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[curr+1])) + moveSelectInFileList(curr + 1) + } + } +} + +func main() { + tk.App.IconPhoto(tk.NewPhoto(tk.Data(icon))) + tk.MacOpenDocument(openFileAndDirectory) menubar := tk.Menu() fileMenu := menubar.Menu() - fileMenu.AddCommand(tk.Lbl("Open File"), tk.Accelerator("O"), tk.Command(newFileInDirectory(img))) - fileMenu.AddCommand(tk.Lbl("Open Directory"), tk.Command(newDirectory(img))) + fileMenu.AddCommand(tk.Lbl("Open File"), tk.Accelerator("O"), tk.Command(newFileInDirectory)) + fileMenu.AddCommand(tk.Lbl("Open Directory"), tk.Command(newDirectory)) fileMenu.AddSeparator() checkbox := fileMenu.AddCheckbutton(tk.Lbl("Show Filelist")) - bindVar := tk.Variable("FileList") - fileMenu.EntryConfigure(checkbox, bindVar) + + fileMenu.EntryConfigure(checkbox, fileListBindVar) menubar.AddCascade(tk.Lbl("File"), tk.Underline(0), tk.Mnu(fileMenu)) tk.App.Configure(tk.Mnu(menubar)) - destroyFileList := func(destroy bool) { - if destroy { - tk.Destroy(fileList) - } - fileList = nil - lb = nil - bindVar.Set("0") - } - constructFileList := func() { - fileList = tk.Toplevel() - fileList.WmTitle("Files") - lb = fileList.Listbox(tk.Height(0)) - for i := range directoryState.images { - lb.Insert("end", directoryState.images[i]) - if i == slices.Index(directoryState.images, directoryState.currentFile) { - lb.SelectionSet(i) - } - } - tk.Pack(lb) - tk.Bind(lb, "<>", tk.Command(func() { - selection := lb.Curselection() - updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[selection[0]]), img) - })) - tk.Bind(fileList, "", tk.Command(func(e *tk.Event) { - // list closed by user click on - destroyFileList(false) - })) - bindVar.Set("1") - } - - tk.Bind(fileMenu, "<>", tk.Command(func() { - if bindVar.Get() == "1" && fileList == nil { - constructFileList() - } else if bindVar.Get() == "0" && fileList != nil { - destroyFileList(true) - } - })) - - tk.Bind(tk.App, "", tk.Command(func(e *tk.Event) { - curr := slices.Index(directoryState.images, directoryState.currentFile) - switch e.Keysym { - case ".": - log.Printf("state: %+v", directoryState) - case "o": - newFileInDirectory(img)() - case "a": - if fileList == nil { - constructFileList() - } else { - // list closed by 'a' - destroyFileList(true) - } - case "Up", "Right": - if curr > 0 { - updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[curr-1]), img) - if lb != nil { - lb.SelectionClear("0", "end") - lb.SelectionSet(curr - 1) - lb.See(curr - 1) - } - } - case "Down", "Left": - if curr < len(directoryState.images)-1 && curr != -1 { - updateImage(filepath.Join(directoryState.currentDirectory, directoryState.images[curr+1]), img) - if lb != nil { - lb.SelectionClear("0", "end") - lb.SelectionSet(curr + 1) - lb.See(curr + 1) - } - } - } - })) + tk.Bind(fileMenu, "<>", tk.Command(menuSelect)) + tk.Bind(tk.App, "", tk.Command(keyPress)) // todo: resize image based on scroll events // tk.Bind(tk.App, "", tk.Command(func(e *tk.Event) { // log.Printf("%v, %v", int16(e.Delta>>16), int16(e.Delta&0xFFFF)) // })) + repaint("", tk.Data(noise)) tk.Pack(img) tk.App.Center() tk.App.Wait()