File and directory view elements wip

This commit is contained in:
Sasha Koshka 2023-03-21 12:26:48 -04:00
parent 60aac053fb
commit d9bddce20b
4 changed files with 220 additions and 0 deletions

View File

@ -0,0 +1,73 @@
package fileElements
import "io/fs"
import "path/filepath"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
type ReadDirStatFS interface {
fs.ReadDirFS
fs.StatFS
}
type DirectoryView struct {
*basicElements.List
filesystem ReadDirStatFS
location string
onChoose func (file string)
}
func NewDirectoryView (
location string,
within ReadDirStatFS,
) (
element *DirectoryView,
err error,
) {
element = &DirectoryView {
List: basicElements.NewList(),
}
err = element.SetLocation(location, within)
return
}
func (element *DirectoryView) Location () (string, fs.ReadDirFS) {
return element.location, element.filesystem
}
func (element *DirectoryView) SetLocation (
location string,
within ReadDirStatFS,
) error {
if within == nil {
within = defaultFS { }
}
element.location = location
element.filesystem = within
return element.Update()
}
func (element *DirectoryView) Update () error {
entries, err := element.filesystem.ReadDir(element.location)
listEntries := make([]basicElements.ListEntry, len(entries))
for index, entry := range entries {
filePath := filepath.Join(element.location, entry.Name())
listEntries[index] = basicElements.NewListEntry (
entry.Name(),
func () {
filePath := filePath
if element.onChoose != nil {
element.onChoose(filePath)
}
})
}
element.Clear()
element.Append(listEntries...)
return err
}
func (element *DirectoryView) OnChoose (callback func (file string)) {
element.onChoose = callback
}

67
elements/file/file.go Normal file
View File

@ -0,0 +1,67 @@
package fileElements
import "io/fs"
import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
// File is a
type File struct {
*basicElements.Icon
// we inherit from Icon directly because it is not our responsibility
// to draw text. this will be the responsibility of the directory that
// contains the file. we don't handle mouse events on the file label
// text either because when the user clicks on that we want to rename
// the file.
filesystem fs.StatFS
location string
onChoose func ()
}
func NewFile (
location string,
within fs.StatFS,
) (
element *File,
err error,
) {
element = &File {
Icon: basicElements.NewIcon(theme.IconFile, theme.IconSizeLarge),
}
err = element.SetLocation(location, within)
return
}
func (element *File) Location () (string, fs.StatFS) {
return element.location, element.filesystem
}
func (element *File) SetLocation (
location string,
within fs.StatFS,
) error {
if within == nil {
within = defaultFS { }
}
element.location = location
element.filesystem = within
return element.Update()
}
func (element *File) Update () error {
info, err := element.filesystem.Stat(element.location)
if err != nil { return err }
if info.IsDir() {
element.SetIcon(theme.IconDirectory, theme.IconSizeLarge)
} else {
element.SetIcon(theme.IconFile, theme.IconSizeLarge)
}
return err
}
func (element *File) OnChoose (callback func ()) {
element.onChoose = callback
}

18
elements/file/fs.go Normal file
View File

@ -0,0 +1,18 @@
package fileElements
import "os"
import "io/fs"
type defaultFS struct { }
func (defaultFS) Open (name string) (fs.File, error) {
return os.Open(name)
}
func (defaultFS) ReadDir (name string) ([]DirEntry, error) {
return os.ReadDir(name)
}
func (defaultFS) Stat (name string) (FileInfo, error) {
return os.Stat(name)
}

View File

@ -0,0 +1,62 @@
package main
import "os"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/file"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
func main () {
tomo.Run(run)
}
func run () {
window, _ := tomo.NewWindow(384, 384)
window.SetTitle("File browser")
container := containers.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container)
controlBar := containers.NewContainer(basicLayouts.Horizontal { })
backButton := basicElements.NewButton("Back")
backButton.SetIcon(theme.IconBackward)
backButton.ShowText(false)
forwardButton := basicElements.NewButton("Forward")
forwardButton.SetIcon(theme.IconForward)
forwardButton.ShowText(false)
refreshButton := basicElements.NewButton("Refresh")
refreshButton.SetIcon(theme.IconRefresh)
refreshButton.ShowText(false)
upwardButton := basicElements.NewButton("Go Up")
upwardButton.SetIcon(theme.IconUpward)
upwardButton.ShowText(false)
locationInput := basicElements.NewTextBox("Location", "")
scrollContainer := containers.NewScrollContainer(false, true)
homeDir,_ := os.UserHomeDir()
directoryView, _ := fileElements.NewDirectoryView(homeDir)
directoryView.Collapse(0, 8)
choose := func (filePath string) {
directoryView.SetLocation(filePath)
locationInput.SetValue(directoryView.Location())
}
directoryView.OnChoose(choose)
locationInput.OnEnter (func () {
choose(locationInput.Value())
})
choose(homeDir)
scrollContainer.Adopt(directoryView)
controlBar.Adopt(backButton, false)
controlBar.Adopt(forwardButton, false)
controlBar.Adopt(refreshButton, false)
controlBar.Adopt(upwardButton, false)
controlBar.Adopt(locationInput, true)
container.Adopt(controlBar, false)
container.Adopt(scrollContainer, true)
window.OnClose(tomo.Stop)
window.Show()
}