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