DirectoryView uses File to display files
This commit is contained in:
parent
dcc672e2bc
commit
68341517f7
@ -219,7 +219,6 @@ func (element *DocumentContainer) NotifyFlexibleHeightChange (child elements.Fle
|
|||||||
element.core.DamageAll()
|
element.core.DamageAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *DocumentContainer) SetTheme (new theme.Theme) {
|
func (element *DocumentContainer) SetTheme (new theme.Theme) {
|
||||||
if new == element.theme.Theme { return }
|
if new == element.theme.Theme { return }
|
||||||
|
@ -1,22 +1,44 @@
|
|||||||
package fileElements
|
package fileElements
|
||||||
|
|
||||||
import "io/fs"
|
import "io/fs"
|
||||||
|
import "image"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/config"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/elements"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
|
|
||||||
type ReadDirStatFS interface {
|
type fileLayoutEntry struct {
|
||||||
fs.ReadDirFS
|
*File
|
||||||
fs.StatFS
|
fs.DirEntry
|
||||||
|
Bounds image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirectoryView displays a list of files within a particular directory and
|
||||||
|
// file system.
|
||||||
type DirectoryView struct {
|
type DirectoryView struct {
|
||||||
*basicElements.List
|
*core.Core
|
||||||
|
*core.Propagator
|
||||||
|
core core.CoreControl
|
||||||
|
|
||||||
|
children []fileLayoutEntry
|
||||||
|
scroll image.Point
|
||||||
|
contentBounds image.Rectangle
|
||||||
|
|
||||||
|
config config.Wrapped
|
||||||
|
theme theme.Wrapped
|
||||||
|
|
||||||
|
onScrollBoundsChange func ()
|
||||||
|
|
||||||
filesystem ReadDirStatFS
|
filesystem ReadDirStatFS
|
||||||
location string
|
location string
|
||||||
onChoose func (file string)
|
onChoose func (file string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDirectoryView creates a new directory view. If within is nil, it will use
|
||||||
|
// the OS file system.
|
||||||
func NewDirectoryView (
|
func NewDirectoryView (
|
||||||
location string,
|
location string,
|
||||||
within ReadDirStatFS,
|
within ReadDirStatFS,
|
||||||
@ -24,17 +46,21 @@ func NewDirectoryView (
|
|||||||
element *DirectoryView,
|
element *DirectoryView,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
element = &DirectoryView {
|
element = &DirectoryView { }
|
||||||
List: basicElements.NewList(),
|
element.theme.Case = theme.C("files", "directoryView")
|
||||||
}
|
element.Core, element.core = core.NewCore(element, element.redoAll)
|
||||||
|
element.Propagator = core.NewPropagator(element, element.core)
|
||||||
err = element.SetLocation(location, within)
|
err = element.SetLocation(location, within)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Location returns the directory's location and filesystem.
|
||||||
func (element *DirectoryView) Location () (string, fs.ReadDirFS) {
|
func (element *DirectoryView) Location () (string, fs.ReadDirFS) {
|
||||||
return element.location, element.filesystem
|
return element.location, element.filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the directory's location and filesystem. If within is nil,
|
||||||
|
// it will use the OS file system.
|
||||||
func (element *DirectoryView) SetLocation (
|
func (element *DirectoryView) SetLocation (
|
||||||
location string,
|
location string,
|
||||||
within ReadDirStatFS,
|
within ReadDirStatFS,
|
||||||
@ -42,32 +68,231 @@ func (element *DirectoryView) SetLocation (
|
|||||||
if within == nil {
|
if within == nil {
|
||||||
within = defaultFS { }
|
within = defaultFS { }
|
||||||
}
|
}
|
||||||
|
element.scroll = image.Point { }
|
||||||
element.location = location
|
element.location = location
|
||||||
element.filesystem = within
|
element.filesystem = within
|
||||||
return element.Update()
|
return element.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update refreshes the directory's contents.
|
||||||
func (element *DirectoryView) Update () error {
|
func (element *DirectoryView) Update () error {
|
||||||
|
defer element.redoAll()
|
||||||
entries, err := element.filesystem.ReadDir(element.location)
|
entries, err := element.filesystem.ReadDir(element.location)
|
||||||
|
|
||||||
listEntries := make([]basicElements.ListEntry, len(entries))
|
// disown all entries
|
||||||
|
for _, file := range element.children {
|
||||||
|
file.DrawTo(nil, image.Rectangle { }, nil)
|
||||||
|
file.SetParent(nil)
|
||||||
|
|
||||||
|
if file.Focused() {
|
||||||
|
file.HandleUnfocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
element.children = make([]fileLayoutEntry, len(entries))
|
||||||
for index, entry := range entries {
|
for index, entry := range entries {
|
||||||
filePath := filepath.Join(element.location, entry.Name())
|
filePath := filepath.Join(element.location, entry.Name())
|
||||||
listEntries[index] = basicElements.NewListEntry (
|
file, err := NewFile (
|
||||||
entry.Name(),
|
filePath,
|
||||||
func () {
|
element.filesystem)
|
||||||
filePath := filePath
|
if err != nil { return err }
|
||||||
|
file.SetParent(element)
|
||||||
|
element.children[index].File = file
|
||||||
|
element.children[index].DirEntry = entry
|
||||||
|
element.OnChoose (func (filepath string) {
|
||||||
if element.onChoose != nil {
|
if element.onChoose != nil {
|
||||||
element.onChoose(filePath)
|
element.onChoose(filePath)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
element.Clear()
|
|
||||||
element.Append(listEntries...)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnChoose sets a function to be called when the user double-clicks a file or
|
||||||
|
// sub-directory within the directory view.
|
||||||
func (element *DirectoryView) OnChoose (callback func (file string)) {
|
func (element *DirectoryView) OnChoose (callback func (file string)) {
|
||||||
element.onChoose = callback
|
element.onChoose = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountChildren returns the amount of children contained within this element.
|
||||||
|
func (element *DirectoryView) CountChildren () (count int) {
|
||||||
|
return len(element.children)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Child returns the child at the specified index. If the index is out of
|
||||||
|
// bounds, this method will return nil.
|
||||||
|
func (element *DirectoryView) Child (index int) (child elements.Element) {
|
||||||
|
if index < 0 || index > len(element.children) { return }
|
||||||
|
return element.children[index].File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *DirectoryView) redoAll () {
|
||||||
|
if !element.core.HasImage() { return }
|
||||||
|
|
||||||
|
// do a layout
|
||||||
|
element.doLayout()
|
||||||
|
|
||||||
|
maxScrollHeight := element.maxScrollHeight()
|
||||||
|
if element.scroll.Y > maxScrollHeight {
|
||||||
|
element.scroll.Y = maxScrollHeight
|
||||||
|
element.doLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a background
|
||||||
|
rocks := make([]image.Rectangle, len(element.children))
|
||||||
|
for index, entry := range element.children {
|
||||||
|
rocks[index] = entry.Bounds
|
||||||
|
}
|
||||||
|
pattern := element.theme.Pattern (
|
||||||
|
theme.PatternPinboard,
|
||||||
|
theme.State { })
|
||||||
|
artist.DrawShatter(element.core, pattern, element.Bounds(), rocks...)
|
||||||
|
|
||||||
|
element.partition()
|
||||||
|
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok {
|
||||||
|
parent.NotifyScrollBoundsChange(element)
|
||||||
|
}
|
||||||
|
if element.onScrollBoundsChange != nil {
|
||||||
|
element.onScrollBoundsChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *DirectoryView) partition () {
|
||||||
|
for _, entry := range element.children {
|
||||||
|
entry.DrawTo(nil, entry.Bounds, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cut our canvas up and give peices to child elements
|
||||||
|
for _, entry := range element.children {
|
||||||
|
if entry.Bounds.Overlaps(element.Bounds()) {
|
||||||
|
entry.DrawTo (
|
||||||
|
canvas.Cut(element.core, entry.Bounds),
|
||||||
|
entry.Bounds, func (region image.Rectangle) {
|
||||||
|
element.core.DamageRegion(region)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyMinimumSizeChange notifies the container that the minimum size of a
|
||||||
|
// child element has changed.
|
||||||
|
func (element *DirectoryView) NotifyMinimumSizeChange (child elements.Element) {
|
||||||
|
element.redoAll()
|
||||||
|
element.core.DamageAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTheme sets the element's theme.
|
||||||
|
func (element *DirectoryView) SetTheme (new theme.Theme) {
|
||||||
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
|
element.Propagator.SetTheme(new)
|
||||||
|
element.redoAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig sets the element's configuration.
|
||||||
|
func (element *DirectoryView) SetConfig (new config.Config) {
|
||||||
|
if new == element.config.Config { return }
|
||||||
|
element.Propagator.SetConfig(new)
|
||||||
|
element.redoAll()
|
||||||
|
}
|
||||||
|
// ScrollContentBounds returns the full content size of the element.
|
||||||
|
func (element *DirectoryView) ScrollContentBounds () image.Rectangle {
|
||||||
|
return element.contentBounds
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScrollViewportBounds returns the size and position of the element's
|
||||||
|
// viewport relative to ScrollBounds.
|
||||||
|
func (element *DirectoryView) ScrollViewportBounds () image.Rectangle {
|
||||||
|
padding := element.theme.Padding(theme.PatternPinboard)
|
||||||
|
bounds := padding.Apply(element.Bounds())
|
||||||
|
bounds = bounds.Sub(bounds.Min).Add(element.scroll)
|
||||||
|
return bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScrollTo scrolls the viewport to the specified point relative to
|
||||||
|
// ScrollBounds.
|
||||||
|
func (element *DirectoryView) ScrollTo (position image.Point) {
|
||||||
|
if position.Y < 0 {
|
||||||
|
position.Y = 0
|
||||||
|
}
|
||||||
|
maxScrollHeight := element.maxScrollHeight()
|
||||||
|
if position.Y > maxScrollHeight {
|
||||||
|
position.Y = maxScrollHeight
|
||||||
|
}
|
||||||
|
element.scroll = position
|
||||||
|
if element.core.HasImage() {
|
||||||
|
element.redoAll()
|
||||||
|
element.core.DamageAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnScrollBoundsChange sets a function to be called when the element's viewport
|
||||||
|
// bounds, content bounds, or scroll axes change.
|
||||||
|
func (element *DirectoryView) OnScrollBoundsChange (callback func ()) {
|
||||||
|
element.onScrollBoundsChange = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScrollAxes returns the supported axes for scrolling.
|
||||||
|
func (element *DirectoryView) ScrollAxes () (horizontal, vertical bool) {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *DirectoryView) maxScrollHeight () (height int) {
|
||||||
|
padding := element.theme.Padding(theme.PatternSunken)
|
||||||
|
viewportHeight := element.Bounds().Dy() - padding.Vertical()
|
||||||
|
height = element.contentBounds.Dy() - viewportHeight
|
||||||
|
if height < 0 { height = 0 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *DirectoryView) doLayout () {
|
||||||
|
margin := element.theme.Margin(theme.PatternPinboard)
|
||||||
|
padding := element.theme.Padding(theme.PatternPinboard)
|
||||||
|
bounds := padding.Apply(element.Bounds())
|
||||||
|
element.contentBounds = image.Rectangle { }
|
||||||
|
|
||||||
|
beginningOfRow := true
|
||||||
|
dot := bounds.Min.Sub(element.scroll)
|
||||||
|
for index, entry := range element.children {
|
||||||
|
width, height := entry.MinimumSize()
|
||||||
|
|
||||||
|
if dot.X + width > bounds.Max.X {
|
||||||
|
dot.X = bounds.Min.Sub(element.scroll).X
|
||||||
|
dot.Y += height
|
||||||
|
if index > 1 {
|
||||||
|
dot.Y += margin.Y
|
||||||
|
}
|
||||||
|
beginningOfRow = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if beginningOfRow {
|
||||||
|
beginningOfRow = false
|
||||||
|
} else {
|
||||||
|
dot.X += margin.X
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Bounds.Min = dot
|
||||||
|
entry.Bounds.Max = image.Pt(dot.X + width, dot.Y + height)
|
||||||
|
element.children[index] = entry
|
||||||
|
element.contentBounds = element.contentBounds.Union(entry.Bounds)
|
||||||
|
dot.X += width
|
||||||
|
}
|
||||||
|
|
||||||
|
element.contentBounds =
|
||||||
|
element.contentBounds.Sub(element.contentBounds.Min)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *DirectoryView) updateMinimumSize () {
|
||||||
|
padding := element.theme.Padding(theme.PatternPinboard)
|
||||||
|
minimumWidth := 0
|
||||||
|
for _, entry := range element.children {
|
||||||
|
width, _ := entry.MinimumSize()
|
||||||
|
if width > minimumWidth {
|
||||||
|
minimumWidth = width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element.core.SetMinimumSize (
|
||||||
|
minimumWidth + padding.Horizontal(),
|
||||||
|
padding.Vertical())
|
||||||
|
}
|
||||||
|
@ -1,24 +1,31 @@
|
|||||||
package fileElements
|
package fileElements
|
||||||
|
|
||||||
import "io/fs"
|
import "io/fs"
|
||||||
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/config"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
|
|
||||||
// File is a
|
// File displays an interactive visual representation of a file within any
|
||||||
|
// file system.
|
||||||
type File struct {
|
type File struct {
|
||||||
*basicElements.Icon
|
*core.Core
|
||||||
|
*core.FocusableCore
|
||||||
|
core core.CoreControl
|
||||||
|
focusableControl core.FocusableCoreControl
|
||||||
|
|
||||||
// we inherit from Icon directly because it is not our responsibility
|
config config.Wrapped
|
||||||
// to draw text. this will be the responsibility of the directory that
|
theme theme.Wrapped
|
||||||
// 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.
|
|
||||||
|
|
||||||
|
iconID theme.Icon
|
||||||
filesystem fs.StatFS
|
filesystem fs.StatFS
|
||||||
location string
|
location string
|
||||||
onChoose func ()
|
onChoose func ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFile creates a new file element. If within is nil, it will use the OS file
|
||||||
|
// system
|
||||||
func NewFile (
|
func NewFile (
|
||||||
location string,
|
location string,
|
||||||
within fs.StatFS,
|
within fs.StatFS,
|
||||||
@ -26,17 +33,22 @@ func NewFile (
|
|||||||
element *File,
|
element *File,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
element = &File {
|
element = &File { }
|
||||||
Icon: basicElements.NewIcon(theme.IconFile, theme.IconSizeLarge),
|
element.theme.Case = theme.C("files", "file")
|
||||||
}
|
element.Core, element.core = core.NewCore(element, element.drawAll)
|
||||||
|
element.FocusableCore,
|
||||||
|
element.focusableControl = core.NewFocusableCore(element.core, element.drawAndPush)
|
||||||
err = element.SetLocation(location, within)
|
err = element.SetLocation(location, within)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Location returns the file's location and filesystem.
|
||||||
func (element *File) Location () (string, fs.StatFS) {
|
func (element *File) Location () (string, fs.StatFS) {
|
||||||
return element.location, element.filesystem
|
return element.location, element.filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the file's location and filesystem. If within is nil, it
|
||||||
|
// will use the OS file system.
|
||||||
func (element *File) SetLocation (
|
func (element *File) SetLocation (
|
||||||
location string,
|
location string,
|
||||||
within fs.StatFS,
|
within fs.StatFS,
|
||||||
@ -49,19 +61,79 @@ func (element *File) SetLocation (
|
|||||||
return element.Update()
|
return element.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update refreshes the element to match the file it represents.
|
||||||
func (element *File) Update () error {
|
func (element *File) Update () error {
|
||||||
|
element.iconID = theme.IconError
|
||||||
info, err := element.filesystem.Stat(element.location)
|
info, err := element.filesystem.Stat(element.location)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
|
|
||||||
|
// TODO: choose icon based on file mime type
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
element.SetIcon(theme.IconDirectory, theme.IconSizeLarge)
|
element.iconID = theme.IconDirectory
|
||||||
} else {
|
} else {
|
||||||
element.SetIcon(theme.IconFile, theme.IconSizeLarge)
|
element.iconID = theme.IconFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.drawAndPush()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *File) OnChoose (callback func ()) {
|
func (element *File) OnChoose (callback func ()) {
|
||||||
element.onChoose = callback
|
element.onChoose = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (element *File) state () theme.State {
|
||||||
|
return theme.State {
|
||||||
|
Disabled: !element.Enabled(),
|
||||||
|
Focused: element.Focused(),
|
||||||
|
// Pressed: element.pressed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *File) icon () artist.Icon {
|
||||||
|
return element.theme.Icon(element.iconID, theme.IconSizeLarge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *File) updateMinimumSize () {
|
||||||
|
padding := element.theme.Padding(theme.PatternButton)
|
||||||
|
icon := element.icon()
|
||||||
|
if icon == nil {
|
||||||
|
element.core.SetMinimumSize (
|
||||||
|
padding.Horizontal(),
|
||||||
|
padding.Vertical())
|
||||||
|
} else {
|
||||||
|
bounds := padding.Inverse().Apply(icon.Bounds())
|
||||||
|
element.core.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *File) drawAndPush () {
|
||||||
|
if element.core.HasImage() {
|
||||||
|
element.drawAll()
|
||||||
|
element.core.DamageAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *File) drawAll () {
|
||||||
|
// background
|
||||||
|
state := element.state()
|
||||||
|
bounds := element.Bounds()
|
||||||
|
element.theme.
|
||||||
|
Pattern(theme.PatternButton, state).
|
||||||
|
Draw(element.core, bounds)
|
||||||
|
|
||||||
|
// icon
|
||||||
|
icon := element.icon()
|
||||||
|
if icon != nil {
|
||||||
|
iconBounds := icon.Bounds()
|
||||||
|
offset := image.Pt (
|
||||||
|
(bounds.Dx() - iconBounds.Dx()) / 2,
|
||||||
|
(bounds.Dy() - iconBounds.Dy()) / 2)
|
||||||
|
icon.Draw (
|
||||||
|
element.core,
|
||||||
|
element.theme.Color (
|
||||||
|
theme.ColorForeground, state),
|
||||||
|
bounds.Min.Add(offset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,16 +3,23 @@ package fileElements
|
|||||||
import "os"
|
import "os"
|
||||||
import "io/fs"
|
import "io/fs"
|
||||||
|
|
||||||
|
// ReadDirStatFS is a combination of fs.ReadDirFS and fs.StatFS. It is the
|
||||||
|
// minimum filesystem needed to satisfy a directory view.
|
||||||
|
type ReadDirStatFS interface {
|
||||||
|
fs.ReadDirFS
|
||||||
|
fs.StatFS
|
||||||
|
}
|
||||||
|
|
||||||
type defaultFS struct { }
|
type defaultFS struct { }
|
||||||
|
|
||||||
func (defaultFS) Open (name string) (fs.File, error) {
|
func (defaultFS) Open (name string) (fs.File, error) {
|
||||||
return os.Open(name)
|
return os.Open(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (defaultFS) ReadDir (name string) ([]DirEntry, error) {
|
func (defaultFS) ReadDir (name string) ([]fs.DirEntry, error) {
|
||||||
return os.ReadDir(name)
|
return os.ReadDir(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (defaultFS) Stat (name string) (FileInfo, error) {
|
func (defaultFS) Stat (name string) (fs.FileInfo, error) {
|
||||||
return os.Stat(name)
|
return os.Stat(name)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
import "path/filepath"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
|
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
|
||||||
@ -18,6 +19,7 @@ func run () {
|
|||||||
window.SetTitle("File browser")
|
window.SetTitle("File browser")
|
||||||
container := containers.NewContainer(basicLayouts.Vertical { true, true })
|
container := containers.NewContainer(basicLayouts.Vertical { true, true })
|
||||||
window.Adopt(container)
|
window.Adopt(container)
|
||||||
|
homeDir, _ := os.UserHomeDir()
|
||||||
|
|
||||||
controlBar := containers.NewContainer(basicLayouts.Horizontal { })
|
controlBar := containers.NewContainer(basicLayouts.Horizontal { })
|
||||||
backButton := basicElements.NewButton("Back")
|
backButton := basicElements.NewButton("Back")
|
||||||
@ -34,13 +36,17 @@ func run () {
|
|||||||
upwardButton.ShowText(false)
|
upwardButton.ShowText(false)
|
||||||
locationInput := basicElements.NewTextBox("Location", "")
|
locationInput := basicElements.NewTextBox("Location", "")
|
||||||
|
|
||||||
|
statusBar := containers.NewContainer(basicLayouts.Horizontal { true, false })
|
||||||
|
directory, _ := fileElements.NewFile(homeDir, nil)
|
||||||
|
baseName := basicElements.NewLabel(filepath.Base(homeDir), false)
|
||||||
|
|
||||||
scrollContainer := containers.NewScrollContainer(false, true)
|
scrollContainer := containers.NewScrollContainer(false, true)
|
||||||
homeDir,_ := os.UserHomeDir()
|
directoryView, _ := fileElements.NewDirectoryView(homeDir, nil)
|
||||||
directoryView, _ := fileElements.NewDirectoryView(homeDir)
|
|
||||||
directoryView.Collapse(0, 8)
|
|
||||||
choose := func (filePath string) {
|
choose := func (filePath string) {
|
||||||
directoryView.SetLocation(filePath)
|
directoryView.SetLocation(filePath, nil)
|
||||||
locationInput.SetValue(directoryView.Location())
|
directory.SetLocation(filePath, nil)
|
||||||
|
locationInput.SetValue(filePath)
|
||||||
|
baseName.SetText(filepath.Base(filePath))
|
||||||
}
|
}
|
||||||
directoryView.OnChoose(choose)
|
directoryView.OnChoose(choose)
|
||||||
locationInput.OnEnter (func () {
|
locationInput.OnEnter (func () {
|
||||||
@ -48,14 +54,18 @@ func run () {
|
|||||||
})
|
})
|
||||||
choose(homeDir)
|
choose(homeDir)
|
||||||
|
|
||||||
scrollContainer.Adopt(directoryView)
|
|
||||||
controlBar.Adopt(backButton, false)
|
controlBar.Adopt(backButton, false)
|
||||||
controlBar.Adopt(forwardButton, false)
|
controlBar.Adopt(forwardButton, false)
|
||||||
controlBar.Adopt(refreshButton, false)
|
controlBar.Adopt(refreshButton, false)
|
||||||
controlBar.Adopt(upwardButton, false)
|
controlBar.Adopt(upwardButton, false)
|
||||||
controlBar.Adopt(locationInput, true)
|
controlBar.Adopt(locationInput, true)
|
||||||
|
scrollContainer.Adopt(directoryView)
|
||||||
|
statusBar.Adopt(directory, false)
|
||||||
|
statusBar.Adopt(baseName, false)
|
||||||
|
|
||||||
container.Adopt(controlBar, false)
|
container.Adopt(controlBar, false)
|
||||||
container.Adopt(scrollContainer, true)
|
container.Adopt(scrollContainer, true)
|
||||||
|
container.Adopt(statusBar, false)
|
||||||
|
|
||||||
window.OnClose(tomo.Stop)
|
window.OnClose(tomo.Stop)
|
||||||
window.Show()
|
window.Show()
|
||||||
|
Reference in New Issue
Block a user