System File Chooser: (PR #988)
Some checks failed
CI / build (push) Has been cancelled
Error Prone / error-prone (push) Has been cancelled
CI / release (push) Has been cancelled

- fixed missing filter in combobox if only `setFileFilter(myFilter)` is used, but not `addChoosableFileFilter(myFilter)`
- fallback Swing file chooser did ignore `isAcceptAllFileFilterUsed()`
- check for supported filter types in `setFileFilter()`
This commit is contained in:
Karl Tauber
2025-11-30 15:39:41 +01:00
parent 1e724029ae
commit 1c6e8774cf

View File

@@ -24,7 +24,9 @@ import java.awt.Window;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@@ -282,14 +284,14 @@ public class SystemFileChooser
this( (File) null );
}
/** @see JFileChooser#JFileChooser(String) */
/** @see JFileChooser#JFileChooser(String) */
public SystemFileChooser( String currentDirectoryPath ) {
this( (currentDirectoryPath != null)
? FileSystemView.getFileSystemView().createFileObject( currentDirectoryPath )
: null );
}
/** @see JFileChooser#JFileChooser(File) */
/** @see JFileChooser#JFileChooser(File) */
public SystemFileChooser( File currentDirectory ) {
setCurrentDirectory( currentDirectory );
@@ -367,12 +369,23 @@ public class SystemFileChooser
setApproveButtonMnemonic( vk );
}
/** @see JFileChooser#getFileSelectionMode() */
/**
* Returns file-selection mode.
* Possible values are {@link #FILES_ONLY} and {@link #DIRECTORIES_ONLY}.
* Default is {@link #FILES_ONLY}.
*
* @see JFileChooser#getFileSelectionMode()
*/
public int getFileSelectionMode() {
return fileSelectionMode;
}
/** @see JFileChooser#setFileSelectionMode(int) */
/**
* Sets file-selection mode.
* Possible values are {@link #FILES_ONLY} and {@link #DIRECTORIES_ONLY}.
*
* @see JFileChooser#setFileSelectionMode(int)
*/
public void setFileSelectionMode( int fileSelectionMode ) {
if( fileSelectionMode != FILES_ONLY && fileSelectionMode != DIRECTORIES_ONLY )
throw new IllegalArgumentException( "Invalid file selection mode " + fileSelectionMode );
@@ -488,8 +501,7 @@ public class SystemFileChooser
if( filter == null || filters.contains( filter ) )
return;
if( !(filter instanceof FileNameExtensionFilter) && !(filter instanceof AcceptAllFileFilter) )
throw new IllegalArgumentException( "Filter class not supported: " + filter.getClass().getName() );
checkSupportedFileFilter( filter );
// either insert filter before "All Files" filter, or append to the end
int size = filters.size();
@@ -559,15 +571,35 @@ public class SystemFileChooser
/** @see JFileChooser#setFileFilter(javax.swing.filechooser.FileFilter) */
public void setFileFilter( FileFilter filter ) {
checkSupportedFileFilter( filter );
this.fileFilter = filter;
}
private int indexOfCurrentFilter() {
return filters.indexOf( fileFilter );
private void checkSupportedFileFilter( FileFilter filter ) throws IllegalArgumentException {
if( filter == null ||
filter instanceof FileNameExtensionFilter ||
filter instanceof AcceptAllFileFilter )
return;
throw new IllegalArgumentException( "Filter class not supported: " + filter.getClass().getName() );
}
private boolean hasOnlyAcceptAll() {
return filters.size() == 1 && filters.get( 0 ) == getAcceptAllFileFilter();
private List<FileFilter> getFiltersForDialog() {
// has only accept-all filter
if( filters.size() == 1 &&
filters.get( 0 ) == getAcceptAllFileFilter() &&
(fileFilter == getAcceptAllFileFilter() || fileFilter == null) )
return Collections.emptyList();
// check whether current filter is already in list
if( (fileFilter != null && filters.contains( fileFilter )) || fileFilter == null )
return filters;
// add current file filter to list
List<FileFilter> filters2 = new ArrayList<>( filters );
filters2.add( 0, fileFilter );
return filters2;
}
public ApproveCallback getApproveCallback() {
@@ -854,9 +886,10 @@ public class SystemFileChooser
int fileTypeIndex = 0;
ArrayList<String> fileTypes = new ArrayList<>();
if( !fc.isDirectorySelectionEnabled() ) {
if( !fc.hasOnlyAcceptAll() ) {
fileTypeIndex = fc.indexOfCurrentFilter();
for( FileFilter filter : fc.getChoosableFileFilters() ) {
List<FileFilter> filters = fc.getFiltersForDialog();
if( !filters.isEmpty() ) {
fileTypeIndex = filters.indexOf( fc.getFileFilter() );
for( FileFilter filter : filters ) {
if( filter instanceof FileNameExtensionFilter ) {
fileTypes.add( filter.getDescription() );
fileTypes.add( "*." + String.join( ";*.", ((FileNameExtensionFilter)filter).getExtensions() ) );
@@ -975,18 +1008,21 @@ public class SystemFileChooser
// filter
int fileTypeIndex = 0;
ArrayList<String> fileTypes = new ArrayList<>();
if( !fc.isDirectorySelectionEnabled() && !fc.hasOnlyAcceptAll() ) {
fileTypeIndex = fc.indexOfCurrentFilter();
for( FileFilter filter : fc.getChoosableFileFilters() ) {
if( filter instanceof FileNameExtensionFilter ) {
fileTypes.add( filter.getDescription() );
for( String ext : ((FileNameExtensionFilter)filter).getExtensions() )
fileTypes.add( ext );
fileTypes.add( null );
} else if( filter instanceof AcceptAllFileFilter ) {
fileTypes.add( filter.getDescription() );
fileTypes.add( "*" );
fileTypes.add( null );
if( !fc.isDirectorySelectionEnabled() ) {
List<FileFilter> filters = fc.getFiltersForDialog();
if( !filters.isEmpty() ) {
fileTypeIndex = filters.indexOf( fc.getFileFilter() );
for( FileFilter filter : filters ) {
if( filter instanceof FileNameExtensionFilter ) {
fileTypes.add( filter.getDescription() );
for( String ext : ((FileNameExtensionFilter)filter).getExtensions() )
fileTypes.add( ext );
fileTypes.add( null );
} else if( filter instanceof AcceptAllFileFilter ) {
fileTypes.add( filter.getDescription() );
fileTypes.add( "*" );
fileTypes.add( null );
}
}
}
}
@@ -1090,18 +1126,21 @@ public class SystemFileChooser
// filter
int fileTypeIndex = 0;
ArrayList<String> fileTypes = new ArrayList<>();
if( !fc.isDirectorySelectionEnabled() && !fc.hasOnlyAcceptAll() ) {
fileTypeIndex = fc.indexOfCurrentFilter();
for( FileFilter filter : fc.getChoosableFileFilters() ) {
if( filter instanceof FileNameExtensionFilter ) {
fileTypes.add( filter.getDescription() );
for( String ext : ((FileNameExtensionFilter)filter).getExtensions() )
fileTypes.add( caseInsensitiveGlobPattern( ext ) );
fileTypes.add( null );
} else if( filter instanceof AcceptAllFileFilter ) {
fileTypes.add( filter.getDescription() );
fileTypes.add( "*" );
fileTypes.add( null );
if( !fc.isDirectorySelectionEnabled() ) {
List<FileFilter> filters = fc.getFiltersForDialog();
if( !filters.isEmpty() ) {
fileTypeIndex = filters.indexOf( fc.getFileFilter() );
for( FileFilter filter : filters ) {
if( filter instanceof FileNameExtensionFilter ) {
fileTypes.add( filter.getDescription() );
for( String ext : ((FileNameExtensionFilter)filter).getExtensions() )
fileTypes.add( caseInsensitiveGlobPattern( ext ) );
fileTypes.add( null );
} else if( filter instanceof AcceptAllFileFilter ) {
fileTypes.add( filter.getDescription() );
fileTypes.add( "*" );
fileTypes.add( null );
}
}
}
}
@@ -1202,6 +1241,7 @@ public class SystemFileChooser
chooser.setFileSelectionMode( fc.getFileSelectionMode() );
chooser.setMultiSelectionEnabled( fc.isMultiSelectionEnabled() );
chooser.setFileHidingEnabled( fc.isFileHidingEnabled() );
chooser.setAcceptAllFileFilterUsed( fc.isAcceptAllFileFilterUsed() );
// system file dialogs do not support multi-selection for Save File dialogs
if( chooser.isMultiSelectionEnabled() &&
@@ -1210,24 +1250,21 @@ public class SystemFileChooser
chooser.setMultiSelectionEnabled( false );
// filter
if( !fc.isDirectorySelectionEnabled() && !fc.hasOnlyAcceptAll() ) {
FileFilter currentFilter = fc.getFileFilter();
for( FileFilter filter : fc.getChoosableFileFilters() ) {
javax.swing.filechooser.FileFilter jfilter = convertFilter( filter, chooser );
if( jfilter == null )
continue;
if( !fc.isDirectorySelectionEnabled() ) {
List<FileFilter> filters = fc.getFiltersForDialog();
if( !filters.isEmpty() ) {
FileFilter currentFilter = fc.getFileFilter();
chooser.removeChoosableFileFilter( chooser.getAcceptAllFileFilter() );
for( FileFilter filter : filters ) {
javax.swing.filechooser.FileFilter jfilter = convertFilter( filter, chooser );
if( jfilter == null )
continue;
chooser.addChoosableFileFilter( jfilter );
if( filter == currentFilter ) {
chooser.setFileFilter( jfilter );
currentFilter = null;
chooser.addChoosableFileFilter( jfilter );
if( filter == currentFilter )
chooser.setFileFilter( jfilter );
}
}
if( currentFilter != null ) {
javax.swing.filechooser.FileFilter jfilter = convertFilter( currentFilter, chooser );
if( jfilter != null )
chooser.setFileFilter( jfilter );
}
}
// paths