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 }