File and directory view elements wip
This commit is contained in:
parent
60aac053fb
commit
d9bddce20b
73
elements/file/directory.go
Normal file
73
elements/file/directory.go
Normal 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
67
elements/file/file.go
Normal 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
18
elements/file/fs.go
Normal 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)
|
||||||
|
}
|
62
examples/fileBrowser/main.go
Normal file
62
examples/fileBrowser/main.go
Normal 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()
|
||||||
|
}
|
Reference in New Issue
Block a user