130 lines
3.3 KiB
Go
130 lines
3.3 KiB
Go
|
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
|
||
|
}
|