| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- package widget
- import (
- "fyne.io/fyne/v2"
- "fyne.io/fyne/v2/canvas"
- "fyne.io/fyne/v2/internal/repository/mime"
- "fyne.io/fyne/v2/internal/widget"
- "fyne.io/fyne/v2/storage"
- "fyne.io/fyne/v2/theme"
- )
- const (
- ratioDown = 0.45
- ratioTextSize = 0.22
- )
- // FileIcon is an adaption of widget.Icon for showing files and folders
- //
- // Since: 1.4
- type FileIcon struct {
- BaseWidget
- // Deprecated: Selection is now handled externally.
- Selected bool
- URI fyne.URI
- resource fyne.Resource
- extension string
- }
- // NewFileIcon takes a filepath and creates an icon with an overlaid label using the detected mimetype and extension
- //
- // Since: 1.4
- func NewFileIcon(uri fyne.URI) *FileIcon {
- i := &FileIcon{URI: uri}
- i.ExtendBaseWidget(i)
- return i
- }
- // SetURI changes the URI and makes the icon reflect a different file
- func (i *FileIcon) SetURI(uri fyne.URI) {
- i.URI = uri
- i.Refresh()
- }
- func (i *FileIcon) setURI(uri fyne.URI) {
- if uri == nil {
- i.resource = theme.FileIcon()
- return
- }
- i.URI = uri
- i.resource = i.lookupIcon(i.URI)
- i.extension = trimmedExtension(uri)
- }
- // MinSize returns the size that this widget should not shrink below
- func (i *FileIcon) MinSize() fyne.Size {
- i.ExtendBaseWidget(i)
- return i.BaseWidget.MinSize()
- }
- // CreateRenderer is a private method to Fyne which links this widget to its renderer
- func (i *FileIcon) CreateRenderer() fyne.WidgetRenderer {
- i.ExtendBaseWidget(i)
- i.propertyLock.Lock()
- i.setURI(i.URI)
- i.propertyLock.Unlock()
- i.propertyLock.RLock()
- defer i.propertyLock.RUnlock()
- // TODO remove background when `SetSelected` is gone.
- background := canvas.NewRectangle(theme.SelectionColor())
- background.Hide()
- s := &fileIconRenderer{file: i, background: background}
- s.img = canvas.NewImageFromResource(s.file.resource)
- s.img.FillMode = canvas.ImageFillContain
- s.ext = canvas.NewText(s.file.extension, theme.BackgroundColor())
- s.ext.Alignment = fyne.TextAlignCenter
- s.SetObjects([]fyne.CanvasObject{s.background, s.img, s.ext})
- return s
- }
- // SetSelected makes the file look like it is selected.
- //
- // Deprecated: Selection is now handled externally.
- func (i *FileIcon) SetSelected(selected bool) {
- i.Selected = selected
- i.Refresh()
- }
- func (i *FileIcon) lookupIcon(uri fyne.URI) fyne.Resource {
- if i.isDir(uri) {
- return theme.FolderIcon()
- }
- mainMimeType, _ := mime.Split(uri.MimeType())
- switch mainMimeType {
- case "application":
- return theme.FileApplicationIcon()
- case "audio":
- return theme.FileAudioIcon()
- case "image":
- return theme.FileImageIcon()
- case "text":
- return theme.FileTextIcon()
- case "video":
- return theme.FileVideoIcon()
- default:
- return theme.FileIcon()
- }
- }
- func (i *FileIcon) isDir(uri fyne.URI) bool {
- if _, ok := uri.(fyne.ListableURI); ok {
- return true
- }
- listable, err := storage.ListerForURI(uri)
- if err != nil {
- return false
- }
- i.URI = listable // Avoid having to call storage.ListerForURI(uri) the next time.
- return true
- }
- type fileIconRenderer struct {
- widget.BaseRenderer
- file *FileIcon
- background *canvas.Rectangle
- ext *canvas.Text
- img *canvas.Image
- }
- func (s *fileIconRenderer) MinSize() fyne.Size {
- return fyne.NewSquareSize(theme.IconInlineSize())
- }
- func (s *fileIconRenderer) Layout(size fyne.Size) {
- isize := fyne.Min(size.Width, size.Height)
- xoff := float32(0)
- yoff := (size.Height - isize) / 2
- if size.Width > size.Height {
- xoff = (size.Width - isize) / 2
- }
- yoff += isize * ratioDown
- oldSize := s.ext.TextSize
- s.ext.TextSize = float32(int(isize * ratioTextSize))
- s.ext.Resize(fyne.NewSize(isize, s.ext.MinSize().Height))
- s.ext.Move(fyne.NewPos(xoff, yoff))
- if oldSize != s.ext.TextSize {
- s.ext.Refresh()
- }
- s.Objects()[0].Resize(size)
- s.Objects()[1].Resize(size)
- }
- func (s *fileIconRenderer) Refresh() {
- s.file.propertyLock.Lock()
- s.file.setURI(s.file.URI)
- s.file.propertyLock.Unlock()
- s.file.propertyLock.RLock()
- s.img.Resource = s.file.resource
- s.ext.Text = s.file.extension
- s.file.propertyLock.RUnlock()
- if s.file.Selected {
- s.background.Show()
- s.ext.Color = theme.SelectionColor()
- if _, ok := s.img.Resource.(*theme.InvertedThemedResource); !ok {
- s.img.Resource = theme.NewInvertedThemedResource(s.img.Resource)
- }
- } else {
- s.background.Hide()
- s.ext.Color = theme.BackgroundColor()
- if res, ok := s.img.Resource.(*theme.InvertedThemedResource); ok {
- s.img.Resource = res.Original()
- }
- }
- canvas.Refresh(s.file.super())
- canvas.Refresh(s.ext)
- }
- func trimmedExtension(uri fyne.URI) string {
- ext := uri.Extension()
- if len(ext) > 5 {
- ext = ext[:5]
- }
- return ext
- }
|