Add possibility to filter by file type in FileWidget
It would be great if you could ask for a specified file type in a parameter definition:
// @File(label="Open file", style="open", type="*.xls;*.xlsx") inputFile
so that the resulting FileWidget dialog would filter the directory by file type.
Adding more attributes to the @Parameter annotation in Java land is not really tenable for stuff like this. However, it is a great fit for the existing style attribute. The point of style is to provide some "hints" for how you want the input widget to work. So that seems like a good match here.
Maybe we could do something like:
@File(label="Open file", style="open:*.xls;*.xlsx") inputFile
And extend the mechanism as needed (maybe by additional plugins...) to support whatever syntax is useful for specifying file filters. This could include useful stuff like "image formats only" (in all formats ImageJ supports), "text formats only", etc.
The downside of tying this metadata to the style is that it would not enforce those limitations at validation time. Whereas with things like min and max and stepSize those requirements can be enforced beyond the widget level.
Validation in general could certainly use some improvement in the framework; see scijava/scijava-common#47 for details.
In particular, it would be useful if you can provide a java.io.FileFilter or java.io.FileNameFilter. For scripting in particular, we might provide shortcuts for org.apache.commons.io.filefilter.WildcardFilter and org.apache.commons.io.filefilter.RegexFileFilter.
Do we have to change FileWidget to account for this? Or rather parse the style annotation, split it at : and then create a filter?
For example:
style="open:*.xls;*.xlsx" => new WildcardFilter({"*.xls", "*.xlsx"})
style="open:/.*\.(xls|xlsx)/ => new RegexFileFilter(/.*\.(xls|xlsx)/)
Also, we should consider whether this filter restricts the allowed files, or we use it simply to facilitate file choice by offering multiple filter types in the "File of Type" dropdown for JFileChooser.
With https://github.com/scijava/scijava-ui-swing/commit/73281ecafabaef8e4eee2a75bda339e90cf86507 (see also https://github.com/scijava/scijava-ui-swing/pull/27), filtering by file extension is now possible with the following syntax:
#@ File (style = "open, extensions:xls/xlsx") inputFile
So this is implemented at the UI level. If at some point we want to restrict file types at the scijava-common level, we should re-open this issue.
I am not exactly sure what you mean by implemented at the UI level, but following this forum post I reopen the issue.
It seems that trying to use style="extensions:png/jpg" as depicted on the wiki page for script parameters, does not work with single #@File input.
Seeing my comment above, this must have worked at the time of writing. If it doesn't now, it's a regression.
I'll reopen the issue.
I dug in the code a bit, I could find only one place in the SwingFileListWidget class where the chooseFiles method supposed to do the file filtering based on extensions (as far as understood) is called.
However there is no case above this line for a style that would mention specific file extensions, only the file/directory style options, is that where the missing bit is ?
The filter is derived from the widgetStyle parameter here, and then handed over to the chooseFiles() method.
As I wrote above, it was working at the time when we implemented and tested it.
It might be that some changes in the framework broke the functionality in some situations, though. We'll have to test all of these:
-
#@ File (style="extensions:png/jpg") fas a single parameter (supposed to open a file chooser dialog directly) -
#@ File (style="extensions:png/jpg") ftogether with other parameters (supposed to create aFileWidget) -
#@ File[] (style="extensions:png/jpg") filesas a single parameter (supposed to open a (multiple) file chooser dialog directly) -
#@ File[] (style="extensions:png/jpg") filestogether with other parameters (supposed to create aFileListWidget)
While testing for extensions, I also noticed that
#@ File[] (style="directory") dirs
print dirs
As a single parameter does not seem to have the expected behaviour, it still allows the selection of files.
However with other parameters, using the Add Folder content button correctly return only folders entries for the selected folder.
The single-file widget works as expected.
EDIT : My fault, it works, just using directories and not directory
EDIT2: I guess we could make the File array also work with directory as style.
Replacing
} else if (widgetModel.isStyle(FileListWidget.DIRECTORIES_ONLY))
by
} else if (widgetModel.isStyle(FileListWidget.DIRECTORIES_ONLY)) || (widgetModel.isStyle(FileWidget.DIRECTORY_STYLE))
at this line
Thanks @LauLauThom for testing.
Note that the style attribute also has some other flaws currently: https://github.com/scijava/scijava-common/issues/333 I just never got around to tackle these in a robust way (with adding tests etc.), and it seems nobody else had free resources to do this either.
we could make the File array also work with
directoryasstyle
Do we really want to allow this? It feels to me like being tolerant of typos and also allowing fyles, flies, oven, safe etc.
Everything we allow here will have to be supported (and maintained) forever.