objects/file.go

130 lines
3.3 KiB
Go
Raw Permalink Normal View History

2024-08-27 11:38:35 -06:00
package objects
import "time"
import "unicode"
import "git.tebibyte.media/tomo/tomo"
import "git.tebibyte.media/tomo/tomo/data"
import "git.tebibyte.media/tomo/tomo/input"
import "git.tebibyte.media/tomo/tomo/event"
import "git.tebibyte.media/tomo/objects/layouts"
var _ tomo.Object = new(File)
// File is a representation of a file or directory.
type File struct {
box tomo.ContainerBox
label *Label
icon *MimeIcon
mime data.Mime
lastClick time.Time
on struct {
doubleClick event.FuncBroadcaster
}
}
// NewFile creates a new file icon with the given name and MIME type.
func NewFile (name string, mime data.Mime) *File {
file := &File {
box: tomo.NewContainerBox(),
label: NewLabel(""),
icon: NewMimeIcon(mime, tomo.IconSizeLarge),
}
file.box.SetRole(tomo.R("objects", "File"))
file.box.SetAttr(tomo.ALayout(layouts.ContractVertical))
file.box.Add(file.icon)
file.box.Add(file.label)
file.box.SetAttr(tomo.AAlign(tomo.AlignMiddle, tomo.AlignStart))
file.label.SetAlign(tomo.AlignMiddle, tomo.AlignStart)
// file.label.SetOverflow(false, true)
// file.label.SetWrap(true)
file.SetType(mime)
file.SetName(name)
file.box.SetInputMask(true)
file.box.SetFocusable(true)
file.box.OnButtonDown(file.handleButtonDown)
file.box.OnButtonUp(file.handleButtonUp)
file.box.OnKeyDown(file.handleKeyDown)
file.box.OnKeyUp(file.handleKeyUp)
return file
}
// GetBox returns the underlying box.
func (this *File) GetBox () tomo.Box {
return this.box
}
// SetFocused sets whether or not this file has keyboard focus. If set to
// true, this method will steal focus away from whichever object currently has
// focus.
func (this *File) SetFocused (focused bool) {
this.box.SetFocused(focused)
}
// SetName sets the text of the file's label.
func (this *File) SetName (text string) {
this.label.SetText(truncateText(text, 16))
}
// SetType sets the MIME type of the file.
func (this *File) SetType (mime data.Mime) {
this.mime = mime
this.icon.SetIcon(mime, tomo.IconSizeLarge)
}
// OnDoubleClick specifies a function to be called when the file is
// double-clicked.
func (this *File) OnDoubleClick (callback func ()) event.Cookie {
return this.on.doubleClick.Connect(callback)
}
func (this *File) handleKeyDown (key input.Key, numberPad bool) bool {
if key != input.KeyEnter && key != input.Key(' ') { return false }
return true
}
func (this *File) handleKeyUp (key input.Key, numberPad bool) bool {
if key != input.KeyEnter && key != input.Key(' ') { return false }
this.on.doubleClick.Broadcast()
return true
}
func (this *File) handleButtonDown (button input.Button) bool {
if button != input.ButtonLeft { return false }
return true
}
func (this *File) handleButtonUp (button input.Button) bool {
if button != input.ButtonLeft { return false }
if this.box.Window().MousePosition().In(this.box.Bounds()) {
// TODO double click delay should be configurable
if time.Since(this.lastClick) < time.Second {
this.on.doubleClick.Broadcast()
}
this.lastClick = time.Now()
}
return true
}
func truncateText (text string, max int) string {
lastChar := -1
len := 0
for index, char := range text {
if !unicode.IsSpace(char) {
lastChar = index
}
len ++
if len >= max {
if lastChar != -1 {
return text[:lastChar] + "..."
}
break
}
}
return text
}