From edda52048c9f87d0a4b8f453062af739d82bf867 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 5 Jan 2026 16:54:57 +0100 Subject: [PATCH] System File Chooser: update current filter before invoking approve callback and after closing dialog (issue #1065) --- .github/workflows/natives.yml | 6 +- CHANGELOG.md | 2 + .../flatlaf/ui/FlatNativeLinuxLibrary.java | 15 ++--- .../flatlaf/ui/FlatNativeMacLibrary.java | 11 ++-- .../flatlaf/ui/FlatNativeWindowsLibrary.java | 11 ++-- .../flatlaf/util/SystemFileChooser.java | 61 ++++++++++++++++--- .../src/main/cpp/ApiVersion.cpp | 2 +- .../src/main/cpp/GtkFileChooser.cpp | 32 +++++++--- ...ormdev_flatlaf_ui_FlatNativeLinuxLibrary.h | 4 +- ..._formdev_flatlaf_ui_FlatNativeMacLibrary.h | 4 +- .../src/main/objcpp/ApiVersion.mm | 2 +- .../src/main/objcpp/MacFileChooser.mm | 32 +++++++++- .../src/main/cpp/ApiVersion.cpp | 2 +- .../src/main/cpp/WinFileChooser.cpp | 22 +++++-- ...mdev_flatlaf_ui_FlatNativeWindowsLibrary.h | 4 +- .../FlatSystemFileChooserLinuxTest.java | 21 +++++-- .../testing/FlatSystemFileChooserMacTest.java | 21 +++++-- .../testing/FlatSystemFileChooserTest.java | 6 +- .../FlatSystemFileChooserWindowsTest.java | 21 +++++-- 19 files changed, 207 insertions(+), 72 deletions(-) diff --git a/.github/workflows/natives.yml b/.github/workflows/natives.yml index 3c434036..ca231dbc 100644 --- a/.github/workflows/natives.yml +++ b/.github/workflows/natives.yml @@ -73,7 +73,8 @@ jobs: run: ./gradlew build-natives --no-daemon - name: Sign Windows DLLs - if: matrix.os == 'windows-latest' + if: false +# if: matrix.os == 'windows-latest' uses: skymatic/code-sign-action@v3 with: certificate: '${{ secrets.CODE_SIGN_CERT_BASE64 }}' @@ -82,7 +83,8 @@ jobs: folder: 'flatlaf-core/src/main/resources/com/formdev/flatlaf/natives' - name: Sign macOS natives - if: matrix.os == 'DISABLED--macos-latest' + if: false +# if: matrix.os == 'DISABLED--macos-latest' env: CERT_BASE64: ${{ secrets.CODE_SIGN_CERT_BASE64 }} CERT_PASSWORD: ${{ secrets.CODE_SIGN_CERT_PASSWORD }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c460d8..f8210246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ FlatLaf Change Log ## 3.7.1-SNAPSHOT +- System File Chooser: Update current filter before invoking approve callback + and after closing dialog. (issue #1065) - ComboBox: Added UI property `ComboBox.buttonFocusedEditableBackground`. (issue #1068) - Popup: Fixed scrolling popup painting issue on Windows 10 when a glass pane is diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeLinuxLibrary.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeLinuxLibrary.java index 14e58039..63fc9264 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeLinuxLibrary.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeLinuxLibrary.java @@ -37,7 +37,7 @@ import com.formdev.flatlaf.util.SystemInfo; */ public class FlatNativeLinuxLibrary { - private static int API_VERSION_LINUX = 3003; + private static int API_VERSION_LINUX = 3004; /** * Checks whether native library is loaded/available. @@ -186,8 +186,8 @@ public class FlatNativeLinuxLibrary * Use '__' for '_' character (e.g. "Choose__and__Quit"). * @param currentName user-editable filename currently shown in the filename field in save dialog; or {@code null} * @param currentFolder current directory shown in the dialog; or {@code null} - * @param optionsSet options to set; see {@code FOS_*} constants - * @param optionsClear options to clear; see {@code FOS_*} constants + * @param optionsSet options to set; see {@code FC_*} constants + * @param optionsClear options to clear; see {@code FC_*} constants * @param callback approve callback; or {@code null} * @param fileTypeIndex the file type that appears as selected (zero-based) * @param fileTypes file types that the dialog can open or save. @@ -195,19 +195,20 @@ public class FlatNativeLinuxLibrary * First string is the display name of the filter shown in the combobox (e.g. "Text Files"). * Subsequent strings are the filter patterns (e.g. "*.txt" or "*"). * {@code null} is required to mark end of filter. + * @param retFileTypeIndex returns selected file type (zero-based); array must be have one element * @return file path(s) that the user selected; an empty array if canceled; * or {@code null} on failures (no dialog shown) * - * @since 3.7 + * @since 3.7.1 */ public native static String[] showFileChooser( Window owner, int dark, boolean open, String title, String okButtonLabel, String currentName, String currentFolder, int optionsSet, int optionsClear, FileChooserCallback callback, - int fileTypeIndex, String... fileTypes ); + int fileTypeIndex, String[] fileTypes, int[] retFileTypeIndex ); - /** @since 3.7 */ + /** @since 3.7.1 */ public interface FileChooserCallback { - boolean approve( String[] files, long hwndFileDialog ); + boolean approve( String[] files, int fileTypeIndex, long hwndFileDialog ); } /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java index 460ab899..8799ebc6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java @@ -45,7 +45,7 @@ import com.formdev.flatlaf.util.SystemInfo; */ public class FlatNativeMacLibrary { - private static int API_VERSION_MACOS = 2002; + private static int API_VERSION_MACOS = 2003; /** * Checks whether native library is loaded/available. @@ -117,20 +117,21 @@ public class FlatNativeMacLibrary * First string is the display name of the filter shown in the combobox (e.g. "Text Files"). * Subsequent strings are the filter patterns (e.g. "txt" or "*"). * {@code null} is required to mark end of filter. + * @param retFileTypeIndex returns selected file type (zero-based); array must be have one element * @return file path(s) that the user selected; an empty array if canceled; * or {@code null} on failures (no dialog shown) * - * @since 3.7 + * @since 3.7.1 */ public native static String[] showFileChooser( Window owner, int dark, boolean open, String title, String prompt, String message, String filterFieldLabel, String nameFieldLabel, String nameFieldStringValue, String directoryURL, int optionsSet, int optionsClear, FileChooserCallback callback, - int fileTypeIndex, String... fileTypes ); + int fileTypeIndex, String[] fileTypes, int[] retFileTypeIndex ); - /** @since 3.7 */ + /** @since 3.7.1 */ public interface FileChooserCallback { - boolean approve( String[] files, long hwndFileDialog ); + boolean approve( String[] files, int fileTypeIndex, long hwndFileDialog ); } /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java index a5caaef7..83690fee 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java @@ -31,7 +31,7 @@ import com.formdev.flatlaf.util.SystemInfo; */ public class FlatNativeWindowsLibrary { - private static int API_VERSION_WINDOWS = 1002; + private static int API_VERSION_WINDOWS = 1003; private static long osBuildNumber = Long.MIN_VALUE; @@ -226,20 +226,21 @@ public class FlatNativeWindowsLibrary * Pairs of strings are required for each filter. * First string is the display name of the filter shown in the combobox (e.g. "Text Files"). * Second string is the filter pattern (e.g. "*.txt", "*.exe;*.dll" or "*.*"). + * @param retFileTypeIndex returns selected file type (zero-based); array must be have one element * @return file path(s) that the user selected; an empty array if canceled; * or {@code null} on failures (no dialog shown) * - * @since 3.7 + * @since 3.7.1 */ public native static String[] showFileChooser( Window owner, boolean open, String title, String okButtonLabel, String fileNameLabel, String fileName, String folder, String saveAsItem, String defaultFolder, String defaultExtension, int optionsSet, int optionsClear, FileChooserCallback callback, - int fileTypeIndex, String... fileTypes ); + int fileTypeIndex, String[] fileTypes, int[] retFileTypeIndex ); - /** @since 3.7 */ + /** @since 3.7.1 */ public interface FileChooserCallback { - boolean approve( String[] files, long hwndFileDialog ); + boolean approve( String[] files, int fileTypeIndex, long hwndFileDialog ); } /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemFileChooser.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemFileChooser.java index 86057afe..3c63d232 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemFileChooser.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemFileChooser.java @@ -28,6 +28,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -607,6 +608,11 @@ public class SystemFileChooser return filters2; } + private void updateFileFilter( List filters, int index ) { + if( index >= 0 && index < filters.size() ) + setFileFilter( filters.get( index ) ); + } + public ApproveCallback getApproveCallback() { return approveCallback; } @@ -890,6 +896,7 @@ public class SystemFileChooser // filter int fileTypeIndex = 0; ArrayList fileTypes = new ArrayList<>(); + ArrayList fileTypeFilters = new ArrayList<>(); if( !fc.isDirectorySelectionEnabled() ) { List filters = fc.getFiltersForDialog(); if( !filters.isEmpty() ) { @@ -898,9 +905,11 @@ public class SystemFileChooser if( filter instanceof FileNameExtensionFilter ) { fileTypes.add( filter.getDescription() ); fileTypes.add( "*." + String.join( ";*.", ((FileNameExtensionFilter)filter).getExtensions() ) ); + fileTypeFilters.add( filter ); } else if( filter instanceof AcceptAllFileFilter ) { fileTypes.add( filter.getDescription() ); fileTypes.add( "*.*" ); + fileTypeFilters.add( filter ); } } } @@ -916,19 +925,24 @@ public class SystemFileChooser // callback FlatNativeWindowsLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null) - ? (files, hwndFileDialog) -> { + ? (files, fileTypeIndex2, hwndFileDialog) -> { + fc.updateFileFilter( fileTypeFilters, fileTypeIndex2 ); return invokeApproveCallback( fc, files, new WindowsApproveContext( hwndFileDialog ) ); } : null; // show system file dialog - return FlatNativeWindowsLibrary.showFileChooser( owner, open, + int[] retFileTypeIndex = { -1 }; + String[] result = FlatNativeWindowsLibrary.showFileChooser( owner, open, fc.getDialogTitle(), approveButtonText, fc.getPlatformProperty( WINDOWS_FILE_NAME_LABEL ), fileName, folder, saveAsItem, fc.getPlatformProperty( WINDOWS_DEFAULT_FOLDER ), fc.getPlatformProperty( WINDOWS_DEFAULT_EXTENSION ), optionsSet, optionsClear, callback, - fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) ); + fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ), retFileTypeIndex ); + if( result != null ) + fc.updateFileFilter( fileTypeFilters, retFileTypeIndex[0] ); + return result; } //---- class WindowsApproveContext ---- @@ -1013,6 +1027,7 @@ public class SystemFileChooser // filter int fileTypeIndex = 0; ArrayList fileTypes = new ArrayList<>(); + ArrayList fileTypeFilters = new ArrayList<>(); if( !fc.isDirectorySelectionEnabled() ) { List filters = fc.getFiltersForDialog(); if( !filters.isEmpty() ) { @@ -1023,10 +1038,12 @@ public class SystemFileChooser for( String ext : ((FileNameExtensionFilter)filter).getExtensions() ) fileTypes.add( ext ); fileTypes.add( null ); + fileTypeFilters.add( filter ); } else if( filter instanceof AcceptAllFileFilter ) { fileTypes.add( filter.getDescription() ); fileTypes.add( "*" ); fileTypes.add( null ); + fileTypeFilters.add( filter ); } } } @@ -1034,18 +1051,23 @@ public class SystemFileChooser // callback FlatNativeMacLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null) - ? (files, hwndFileDialog) -> { + ? (files, fileTypeIndex2, hwndFileDialog) -> { + fc.updateFileFilter( fileTypeFilters, fileTypeIndex2 ); return invokeApproveCallback( fc, files, new MacApproveContext( hwndFileDialog ) ); } : null; // show system file dialog - return FlatNativeMacLibrary.showFileChooser( owner, dark, open, + int[] retFileTypeIndex = { -1 }; + String[] result = FlatNativeMacLibrary.showFileChooser( owner, dark, open, fc.getDialogTitle(), fc.getApproveButtonText(), fc.getPlatformProperty( MAC_MESSAGE ), fc.getPlatformProperty( MAC_FILTER_FIELD_LABEL ), fc.getPlatformProperty( MAC_NAME_FIELD_LABEL ), nameFieldStringValue, directoryURL, optionsSet, optionsClear, callback, - fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) ); + fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ), retFileTypeIndex ); + if( result != null ) + fc.updateFileFilter( fileTypeFilters, retFileTypeIndex[0] ); + return result; } //---- class MacApproveContext ---- @@ -1141,6 +1163,7 @@ public class SystemFileChooser // filter int fileTypeIndex = 0; ArrayList fileTypes = new ArrayList<>(); + ArrayList fileTypeFilters = new ArrayList<>(); if( !fc.isDirectorySelectionEnabled() ) { List filters = fc.getFiltersForDialog(); if( !filters.isEmpty() ) { @@ -1151,10 +1174,12 @@ public class SystemFileChooser for( String ext : ((FileNameExtensionFilter)filter).getExtensions() ) fileTypes.add( caseInsensitiveGlobPattern( ext ) ); fileTypes.add( null ); + fileTypeFilters.add( filter ); } else if( filter instanceof AcceptAllFileFilter ) { fileTypes.add( filter.getDescription() ); fileTypes.add( "*" ); fileTypes.add( null ); + fileTypeFilters.add( filter ); } } } @@ -1162,15 +1187,20 @@ public class SystemFileChooser // callback FlatNativeLinuxLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null) - ? (files, hwndFileDialog) -> { + ? (files, fileTypeIndex2, hwndFileDialog) -> { + fc.updateFileFilter( fileTypeFilters, fileTypeIndex2 ); return invokeApproveCallback( fc, files, new LinuxApproveContext( hwndFileDialog ) ); } : null; // show system file dialog - return FlatNativeLinuxLibrary.showFileChooser( owner, dark, open, + int[] retFileTypeIndex = { -1 }; + String[] result = FlatNativeLinuxLibrary.showFileChooser( owner, dark, open, fc.getDialogTitle(), approveButtonText, currentName, currentFolder, optionsSet, optionsClear, callback, - fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) ); + fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ), retFileTypeIndex ); + if( result != null ) + fc.updateFileFilter( fileTypeFilters, retFileTypeIndex[0] ); + return result; } private String caseInsensitiveGlobPattern( String ext ) { @@ -1253,6 +1283,8 @@ public class SystemFileChooser { @Override public File[] showDialog( Window owner, SystemFileChooser fc ) { + IdentityHashMap filterMap = new IdentityHashMap<>(); + JFileChooser chooser = new JFileChooser() { @Override public void approveSelection() { @@ -1273,6 +1305,7 @@ public class SystemFileChooser // callback ApproveCallback approveCallback = fc.getApproveCallback(); if( approveCallback != null ) { + updateFileFilter( fc, this, filterMap ); int result = approveCallback.approve( files, new SwingApproveContext( this ) ); if( result == CANCEL_OPTION ) return; @@ -1313,6 +1346,7 @@ public class SystemFileChooser chooser.addChoosableFileFilter( jfilter ); if( filter == currentFilter ) chooser.setFileFilter( jfilter ); + filterMap.put( jfilter, filter ); } } } @@ -1340,6 +1374,7 @@ public class SystemFileChooser // show dialog int result = chooser.showDialog( owner, null ); + updateFileFilter( fc, chooser, filterMap ); // save window size Dimension windowSize = chooser.getSize(); @@ -1367,6 +1402,14 @@ public class SystemFileChooser return null; } + private void updateFileFilter( SystemFileChooser fc, JFileChooser chooser, + IdentityHashMap filterMap ) + { + FileFilter fileFilter = filterMap.get( chooser.getFileFilter() ); + if( fileFilter != null ) + fc.setFileFilter( fileFilter ); + } + private static boolean checkMustExist( JFileChooser chooser, File[] files ) { for( File file : files ) { if( !file.exists() ) { diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/ApiVersion.cpp b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/ApiVersion.cpp index ae0a7d73..6957df8d 100644 --- a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/ApiVersion.cpp +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/ApiVersion.cpp @@ -24,7 +24,7 @@ // increase this version if changing API or functionality of native library // also update version in Java class com.formdev.flatlaf.ui.FlatNativeLinuxLibrary -#define API_VERSION_LINUX 3003 +#define API_VERSION_LINUX 3004 //---- JNI methods ------------------------------------------------------------ diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp index 828ba66e..065c4c01 100644 --- a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp @@ -58,6 +58,7 @@ static void initFilters( GtkFileChooser* chooser, JNIEnv* env, jint fileTypeInde gtk_file_chooser_add_filter( chooser, filter ); if( fileTypeIndex == filterIndex ) gtk_file_chooser_set_filter( chooser, filter ); + g_object_set_data( G_OBJECT( filter ), "flatlaf-filter-index", GINT_TO_POINTER( filterIndex + 1 ) ); filter = NULL; filterIndex++; } @@ -130,32 +131,42 @@ struct ResponseData { JNIEnv* env; jobject callback; GSList* fileList; + int filterIndex; ResponseData( JNIEnv* _env, jobject _callback ) { env = _env; callback = _callback; fileList = NULL; + filterIndex = -1; } }; static void handle_response( GtkWidget* dialog, gint responseId, gpointer data ) { + GtkFileChooser* chooser = GTK_FILE_CHOOSER( dialog ); + ResponseData *response = static_cast( data ); + + // get selected filter (even if user cancels dialog) + GtkFileFilter* filter = gtk_file_chooser_get_filter( chooser ); + response->filterIndex = (filter != NULL) + ? GPOINTER_TO_INT( g_object_get_data( G_OBJECT( filter ), "flatlaf-filter-index" ) ) - 1 + : -1; + // get filenames if user pressed OK if( responseId == GTK_RESPONSE_ACCEPT ) { - ResponseData *response = static_cast( data ); if( response->callback != NULL ) { - GSList* fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) ); + GSList* fileList = gtk_file_chooser_get_filenames( chooser ); jobjectArray files = fileListToStringArray( response->env, fileList ); - + jint filterIndex = response->filterIndex; GtkWindow* window = GTK_WINDOW( dialog ); // invoke callback: boolean approve( String[] files, long hwnd ); jclass cls = response->env->GetObjectClass( response->callback ); - jmethodID approveID = response->env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" ); - if( approveID != NULL && !response->env->CallBooleanMethod( response->callback, approveID, files, window ) ) + jmethodID approveID = response->env->GetMethodID( cls, "approve", "([Ljava/lang/String;IJ)Z" ); + if( approveID != NULL && !response->env->CallBooleanMethod( response->callback, approveID, files, filterIndex, window ) ) return; // keep dialog open } - response->fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) ); + response->fileList = gtk_file_chooser_get_filenames( chooser ); } // hide/destroy file dialog and quit loop @@ -170,7 +181,8 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser ( JNIEnv* env, jclass cls, jobject owner, jint dark, jboolean open, jstring title, jstring okButtonLabel, jstring currentName, jstring currentFolder, - jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes ) + jint optionsSet, jint optionsClear, jobject callback, + jint fileTypeIndex, jobjectArray fileTypes, jintArray retFileTypeIndex ) { // initialize GTK if( !gtk_init_check( NULL, NULL ) ) @@ -282,7 +294,11 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrar // start event loop (will be quit in respone handler) gtk_main(); - // canceled? + // return selected filter + jint selectedFilterIndex = responseData.filterIndex; + env->SetIntArrayRegion( retFileTypeIndex, 0, 1, &selectedFilterIndex ); + + // return empty array if canceled if( responseData.fileList == NULL ) return newJavaStringArray( env, 0 ); diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/headers/com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h b/flatlaf-natives/flatlaf-natives-linux/src/main/headers/com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h index 2d855b67..1194917a 100644 --- a/flatlaf-natives/flatlaf-natives-linux/src/main/headers/com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/headers/com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h @@ -64,10 +64,10 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_is /* * Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary * Method: showFileChooser - * Signature: (Ljava/awt/Window;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeLinuxLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String; + * Signature: (Ljava/awt/Window;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeLinuxLibrary/FileChooserCallback;I[Ljava/lang/String;[I)[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser - (JNIEnv *, jclass, jobject, jint, jboolean, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray); + (JNIEnv *, jclass, jobject, jint, jboolean, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray, jintArray); /* * Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h b/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h index 301039b2..9138a85d 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h @@ -82,10 +82,10 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_togg /* * Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary * Method: showFileChooser - * Signature: (Ljava/awt/Window;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeMacLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String; + * Signature: (Ljava/awt/Window;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeMacLibrary/FileChooserCallback;I[Ljava/lang/String;[I)[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showFileChooser - (JNIEnv *, jclass, jobject, jint, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray); + (JNIEnv *, jclass, jobject, jint, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray, jintArray); /* * Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/ApiVersion.mm b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/ApiVersion.mm index b9b9a9b4..3f44bf0b 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/ApiVersion.mm +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/ApiVersion.mm @@ -24,7 +24,7 @@ // increase this version if changing API or functionality of native library // also update version in Java class com.formdev.flatlaf.ui.FlatNativeMacLibrary -#define API_VERSION_MACOS 2002 +#define API_VERSION_MACOS 2003 //---- JNI methods ------------------------------------------------------------ diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm index 52c2b28a..729df865 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm @@ -35,6 +35,7 @@ static NSArray* getDialogURLs( NSSavePanel* dialog ); @interface FileChooserDelegate : NSObject { NSArray* _filters; + int _selectedFormatIndex; JavaVM* _jvm; jobject _callback; @@ -43,18 +44,26 @@ static NSArray* getDialogURLs( NSSavePanel* dialog ); @property (nonatomic, assign) NSSavePanel* dialog; + - (id) init; - (void) initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex :(NSString*)filterFieldLabel :(bool)showSingleFilterField; - (void) selectFormat: (id)sender; - (void) selectFormatAtIndex: (int)index; + - (int) selectedFormatIndex; @end @implementation FileChooserDelegate + - (id) init { + _selectedFormatIndex = -1; + return self; + } + - (void) initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex :(NSString*)filterFieldLabel :(bool)showSingleFilterField { _filters = filters; + _selectedFormatIndex = filterIndex; // get filter names NSArray* filterNames = filters.lastObject; @@ -125,6 +134,12 @@ static NSArray* getDialogURLs( NSSavePanel* dialog ); // to support older macOS versions 10.14+ and because of some problems with allowedContentTypes: // https://github.com/chromium/chromium/blob/d8e0032963b7ca4728ff4117933c0feb3e479b7a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm#L209-232 _dialog.allowedFileTypes = [fileTypes containsObject:@"*"] ? nil : fileTypes; + + _selectedFormatIndex = index; + } + + - (int) selectedFormatIndex { + return _selectedFormatIndex; } //---- NSOpenSavePanelDelegate ---- @@ -161,12 +176,13 @@ static NSArray* getDialogURLs( NSSavePanel* dialog ); JNI_THREAD_ENTER( _jvm, true ) jobjectArray files = urlsToStringArray( env, urls ); + jint selectedFormatIndex = ((FileChooserDelegate*)((NSSavePanel*)sender).delegate).selectedFormatIndex; jlong window = (jlong) sender; // invoke callback: boolean approve( String[] files, long hwnd ); jclass cls = env->GetObjectClass( _callback ); - jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" ); - if( approveID != NULL && !env->CallBooleanMethod( _callback, approveID, files, window ) ) { + jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;IJ)Z" ); + if( approveID != NULL && !env->CallBooleanMethod( _callback, approveID, files, selectedFormatIndex, window ) ) { _urlsSet = NULL; return false; // keep dialog open } @@ -265,7 +281,8 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_ ( JNIEnv* env, jclass cls, jobject owner, jint dark, jboolean open, jstring title, jstring prompt, jstring message, jstring filterFieldLabel, jstring nameFieldLabel, jstring nameFieldStringValue, jstring directoryURL, - jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes ) + jint optionsSet, jint optionsClear, jobject callback, + jint fileTypeIndex, jobjectArray fileTypes, jintArray retFileTypeIndex ) { JNI_COCOA_ENTER() @@ -365,17 +382,26 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_ // show dialog NSModalResponse response = [dialog runModal]; + + // return selected filter + jint selectedFormatIndex = delegate.selectedFormatIndex; + env->SetIntArrayRegion( retFileTypeIndex, 0, 1, &selectedFormatIndex ); + [delegate release]; + + // return empty array if canceled if( response != NSModalResponseOK ) { *purls = @[]; return; } + // get selected file(s) *purls = getDialogURLs( dialog ); JNI_COCOA_CATCH() }]; + // return null on failures if( urls == NULL ) return NULL; diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/ApiVersion.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/ApiVersion.cpp index 0f2e7a97..c8c204b8 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/ApiVersion.cpp +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/ApiVersion.cpp @@ -24,7 +24,7 @@ // increase this version if changing API or functionality of native library // also update version in Java class com.formdev.flatlaf.ui.FlatNativeWindowsLibrary -#define API_VERSION_WINDOWS 1002 +#define API_VERSION_WINDOWS 1003 //---- JNI methods ------------------------------------------------------------ diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp index 85a7b719..0a9a97d5 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp @@ -128,6 +128,11 @@ public: } else files = getFiles( env, false, dialog ); + // get selected filter + UINT selectedFileTypeIndex = 0; + dialog->GetFileTypeIndex( &selectedFileTypeIndex ); + jint jselectedFileTypeIndex = selectedFileTypeIndex - 1; + // get hwnd of file dialog HWND hwndFileDialog = 0; AutoReleasePtr window; @@ -136,10 +141,10 @@ public: // invoke callback: boolean approve( String[] files, long hwnd ); jclass cls = env->GetObjectClass( callback ); - jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" ); + jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;IJ)Z" ); if( approveID == NULL ) return S_OK; - return env->CallBooleanMethod( callback, approveID, files, hwndFileDialog ) ? S_OK : S_FALSE; + return env->CallBooleanMethod( callback, approveID, files, jselectedFileTypeIndex, hwndFileDialog ) ? S_OK : S_FALSE; } IFACEMETHODIMP OnFolderChange( IFileDialog* ) { return S_OK; } @@ -147,7 +152,7 @@ public: IFACEMETHODIMP OnHelp( IFileDialog* ) { return S_OK; } IFACEMETHODIMP OnSelectionChange( IFileDialog* ) { return S_OK; } IFACEMETHODIMP OnShareViolation( IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE* ) { return S_OK; } - IFACEMETHODIMP OnTypeChange( IFileDialog*pfd ) { return S_OK; } + IFACEMETHODIMP OnTypeChange( IFileDialog* ) { return S_OK; } IFACEMETHODIMP OnOverwrite( IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE* ) { return S_OK; } //---- IUnknown methods ---- @@ -213,7 +218,8 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibr ( JNIEnv* env, jclass cls, jobject owner, jboolean open, jstring title, jstring okButtonLabel, jstring fileNameLabel, jstring fileName, jstring folder, jstring saveAsItem, jstring defaultFolder, jstring defaultExtension, - jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes ) + jint optionsSet, jint optionsClear, jobject callback, + jint fileTypeIndex, jobjectArray fileTypes, jintArray retFileTypeIndex ) { // initialize COM library CoInitializer coInitializer; @@ -285,6 +291,14 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibr HWND hwndOwner = (owner != NULL) ? getWindowHandle( env, owner ) : NULL; HRESULT hr = dialog->Show( hwndOwner ); dialog->Unadvise( dwCookie ); + + // return selected filter + UINT selectedFileTypeIndex = 0; + CHECK_HRESULT( dialog->GetFileTypeIndex( &selectedFileTypeIndex ) ); + jint jselectedFileTypeIndex = selectedFileTypeIndex - 1; + env->SetIntArrayRegion( retFileTypeIndex, 0, 1, &jselectedFileTypeIndex ); + + // return empty array if canceled if( hr == HRESULT_FROM_WIN32(ERROR_CANCELLED) ) return newJavaStringArray( env, 0 ); CHECK_HRESULT( hr ); diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h index b5b33245..05acfbae 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h @@ -116,10 +116,10 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_ /* * Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary * Method: showFileChooser - * Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeWindowsLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String; + * Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeWindowsLibrary/FileChooserCallback;I[Ljava/lang/String;[I)[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showFileChooser - (JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray); + (JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray, jintArray); /* * Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserLinuxTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserLinuxTest.java index 52af4b9a..95b35125 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserLinuxTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserLinuxTest.java @@ -110,8 +110,8 @@ public class FlatSystemFileChooserLinuxTest } int fileTypeIndex = fileTypeIndexSlider.getValue(); - FlatNativeLinuxLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> { - System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) ); + FlatNativeLinuxLibrary.FileChooserCallback callback = (files, fileTypeIndex2, hwndFileDialog) -> { + System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) + " " + fileTypeIndex2 ); if( showMessageDialogOnOKCheckBox.isSelected() ) { System.out.println( FlatNativeLinuxLibrary.showMessageDialog( hwndFileDialog, JOptionPane.INFORMATION_MESSAGE, @@ -124,24 +124,28 @@ public class FlatSystemFileChooserLinuxTest int dark = FlatLaf.isLafDark() ? 1 : 0; if( direct ) { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, dark, open, title, okButtonLabel, currentName, currentFolder, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes, retFileTypeIndex ); - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } else { SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop(); String[] fileTypes2 = fileTypes; new Thread( () -> { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, dark, open, title, okButtonLabel, currentName, currentFolder, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes2, retFileTypeIndex ); System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() ); EventQueue.invokeLater( () -> { - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } ); } ).start(); @@ -150,6 +154,11 @@ public class FlatSystemFileChooserLinuxTest } } + private void outputResult( String[] files, int retFileTypeIndex ) { + filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + filesField.append( "\n\nretFileTypeIndex " + retFileTypeIndex ); + } + private static String n( String s ) { return s != null && !s.isEmpty() ? s : null; } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserMacTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserMacTest.java index 5c6c2a99..1af07ef9 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserMacTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserMacTest.java @@ -145,8 +145,8 @@ public class FlatSystemFileChooserMacTest } int fileTypeIndex = fileTypeIndexSlider.getValue(); - FlatNativeMacLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> { - System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) ); + FlatNativeMacLibrary.FileChooserCallback callback = (files, fileTypeIndex2, hwndFileDialog) -> { + System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) + " " + fileTypeIndex2 ); if( showMessageDialogOnOKCheckBox.isSelected() ) { int result = FlatNativeMacLibrary.showMessageDialog( hwndFileDialog, JOptionPane.INFORMATION_MESSAGE, @@ -160,26 +160,30 @@ public class FlatSystemFileChooserMacTest int dark = FlatLaf.isLafDark() ? 1 : 0; if( direct ) { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeMacLibrary.showFileChooser( owner, dark, open, title, prompt, message, filterFieldLabel, nameFieldLabel, nameFieldStringValue, directoryURL, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes, retFileTypeIndex ); - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } else { SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop(); String[] fileTypes2 = fileTypes; new Thread( () -> { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeMacLibrary.showFileChooser( owner, dark, open, title, prompt, message, filterFieldLabel, nameFieldLabel, nameFieldStringValue, directoryURL, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes2, retFileTypeIndex ); System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() ); SwingUtilities.invokeLater( () -> { - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } ); } ).start(); @@ -188,6 +192,11 @@ public class FlatSystemFileChooserMacTest } } + private void outputResult( String[] files, int retFileTypeIndex ) { + filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + filesField.append( "\n\nretFileTypeIndex " + retFileTypeIndex ); + } + private static String n( String s ) { return s != null && !s.isEmpty() ? s : null; } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserTest.java index 2fc682a3..c063e307 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserTest.java @@ -310,7 +310,8 @@ public class FlatSystemFileChooserTest "result", result, "currentDirectory", fc.getCurrentDirectory(), "selectedFile", fc.getSelectedFile(), - "selectedFiles", fc.getSelectedFiles() ); + "selectedFiles", fc.getSelectedFiles(), + "fileFilter", fc.getFileFilter() ); } private void outputSwingFileChooser( String type, JFileChooser fc, int result ) { @@ -319,7 +320,8 @@ public class FlatSystemFileChooserTest "result", result, "currentDirectory", fc.getCurrentDirectory(), "selectedFile", fc.getSelectedFile(), - "selectedFiles", fc.getSelectedFiles() ); + "selectedFiles", fc.getSelectedFiles(), + "fileFilter", fc.getFileFilter() ); } private void outputAWTFileChooser( FileDialog fc ) { diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserWindowsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserWindowsTest.java index b6ddbc4e..d00ada85 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserWindowsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSystemFileChooserWindowsTest.java @@ -131,8 +131,8 @@ public class FlatSystemFileChooserWindowsTest fileTypes = fileTypesStr.trim().split( "[,]+" ); int fileTypeIndex = fileTypeIndexSlider.getValue(); - FlatNativeWindowsLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> { - System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) ); + FlatNativeWindowsLibrary.FileChooserCallback callback = (files, fileTypeIndex2, hwndFileDialog) -> { + System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) + " " + fileTypeIndex2 ); if( showMessageDialogOnOKCheckBox.isSelected() ) { System.out.println( FlatNativeWindowsLibrary.showMessageDialog( hwndFileDialog, JOptionPane.INFORMATION_MESSAGE, @@ -142,26 +142,30 @@ public class FlatSystemFileChooserWindowsTest }; if( direct ) { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open, title, okButtonLabel, fileNameLabel, fileName, folder, saveAsItem, defaultFolder, defaultExtension, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes, retFileTypeIndex ); - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } else { SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop(); String[] fileTypes2 = fileTypes; new Thread( () -> { + int[] retFileTypeIndex = { -1 }; String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open, title, okButtonLabel, fileNameLabel, fileName, folder, saveAsItem, defaultFolder, defaultExtension, - optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 ); + optionsSet.get(), optionsClear.get(), callback, + fileTypeIndex, fileTypes2, retFileTypeIndex ); System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() ); EventQueue.invokeLater( () -> { - filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + outputResult( files, retFileTypeIndex[0] ); } ); } ).start(); @@ -170,6 +174,11 @@ public class FlatSystemFileChooserWindowsTest } } + private void outputResult( String[] files, int retFileTypeIndex ) { + filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" ); + filesField.append( "\n\nretFileTypeIndex " + retFileTypeIndex ); + } + private static String n( String s ) { return s != null && !s.isEmpty() ? s : null; }