diff --git a/uri.go b/uri.go index 3bab3532ff..4cde1a1e04 100644 --- a/uri.go +++ b/uri.go @@ -91,3 +91,12 @@ type ListableURI interface { // List returns a list of child URIs of this URI. List() ([]URI, error) } + +// URIWithIcon describes a URI that should be rendered with a certain icon in file browsers. +// +// Since: 2.5 +type URIWithIcon interface { + URI + + Icon() Resource +} diff --git a/widget/fileicon.go b/widget/fileicon.go index 0ea2ea1833..a2f0b86b51 100644 --- a/widget/fileicon.go +++ b/widget/fileicon.go @@ -94,6 +94,9 @@ func (i *FileIcon) SetSelected(selected bool) { } func (i *FileIcon) lookupIcon(uri fyne.URI) fyne.Resource { + if icon, ok := uri.(fyne.URIWithIcon); ok { + return icon.Icon() + } if i.isDir(uri) { return theme.FolderIcon() } @@ -190,6 +193,7 @@ func (s *fileIconRenderer) Refresh() { } } + s.img.Refresh() canvas.Refresh(s.file.super()) canvas.Refresh(s.ext) } diff --git a/widget/fileicon_internal_test.go b/widget/fileicon_internal_test.go index ae522265a9..cc5c46b4fa 100644 --- a/widget/fileicon_internal_test.go +++ b/widget/fileicon_internal_test.go @@ -11,7 +11,6 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" - "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" ) @@ -79,54 +78,6 @@ func TestFileIcon_NewURI_WithFolder(t *testing.T) { assert.Equal(t, theme.FolderIcon(), item.resource) } -func TestFileIcon_NewFileIcon_Rendered(t *testing.T) { - test.NewApp() - defer test.NewApp() - - workingDir, err := os.Getwd() - if err != nil { - fyne.LogError("Could not get current working directory", err) - t.FailNow() - } - - icon := NewFileIcon(nil) - - w := test.NewWindow(icon) - w.Resize(fyne.NewSize(150, 150)) - - test.AssertImageMatches(t, "fileicon/fileicon_nil.png", w.Canvas().Capture()) - - text := filepath.Join(workingDir, "testdata/text") - icon2 := NewFileIcon(storage.NewFileURI(text)) - - w.SetContent(icon2) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_text.png", w.Canvas().Capture()) - - text += ".txt" - icon3 := NewFileIcon(storage.NewFileURI(text)) - - w.SetContent(icon3) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_text_txt.png", w.Canvas().Capture()) - - bin := filepath.Join(workingDir, "testdata/bin") - icon4 := NewFileIcon(storage.NewFileURI(bin)) - - w.SetContent(icon4) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_bin.png", w.Canvas().Capture()) - - dir := filepath.Join(workingDir, "testdata") - icon5 := NewFileIcon(storage.NewFileURI(dir)) - - w.SetContent(icon5) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_folder.png", w.Canvas().Capture()) - - w.Close() -} - func TestFileIcon_SetURI(t *testing.T) { item := newRenderedFileIcon(storage.NewFileURI("/path/to/filename.zip")) assert.Equal(t, ".zip", item.extension) diff --git a/widget/fileicon_test.go b/widget/fileicon_test.go new file mode 100644 index 0000000000..a655e39e41 --- /dev/null +++ b/widget/fileicon_test.go @@ -0,0 +1,97 @@ +package widget_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/driver/software" + "fyne.io/fyne/v2/storage" + "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" +) + +func TestFileIcon_NewFileIcon_Rendered(t *testing.T) { + test.NewApp() + defer test.NewApp() + + workingDir, err := os.Getwd() + if err != nil { + fyne.LogError("Could not get current working directory", err) + t.FailNow() + } + + icon := widget.NewFileIcon(nil) + + w := test.NewWindow(icon) + w.Resize(fyne.NewSize(150, 150)) + + test.AssertImageMatches(t, "fileicon/fileicon_nil.png", w.Canvas().Capture()) + + text := filepath.Join(workingDir, "testdata/text") + icon2 := widget.NewFileIcon(storage.NewFileURI(text)) + + w.SetContent(icon2) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_text.png", w.Canvas().Capture()) + + text += ".txt" + icon3 := widget.NewFileIcon(storage.NewFileURI(text)) + + w.SetContent(icon3) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_text_txt.png", w.Canvas().Capture()) + + bin := filepath.Join(workingDir, "testdata/bin") + icon4 := widget.NewFileIcon(storage.NewFileURI(bin)) + + w.SetContent(icon4) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_bin.png", w.Canvas().Capture()) + + dir := filepath.Join(workingDir, "testdata") + icon5 := widget.NewFileIcon(storage.NewFileURI(dir)) + + w.SetContent(icon5) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_folder.png", w.Canvas().Capture()) + + w.Close() +} + +func TestFileIcon_Icon(t *testing.T) { + data, _ := filepath.Abs("testdata") + dir := storage.NewFileURI(data) + + icon1 := widget.NewFileIcon(dir) + trash := &customURI{URI: dir, icon: theme.DeleteIcon()} + icon2 := widget.NewFileIcon(trash) + + // test icon change + icon1Img := software.Render(icon1, test.Theme()) + icon2Img := software.Render(icon2, test.Theme()) + assert.NotEqual(t, icon1Img, icon2Img) +} + +type customURI struct { + fyne.URI + + name string + icon fyne.Resource +} + +func (c *customURI) Icon() fyne.Resource { + return c.icon +} + +func (c *customURI) Name() string { + if c.name != "" { + return c.name + } + + return c.URI.Name() +}