mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
System File Chooser: support "approve" callback and system message dialog on Windows and Linux (not yet used in SystemFileChooser
This commit is contained in:
@@ -24,6 +24,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
@@ -131,7 +132,7 @@ public class FlatNativeLinuxLibrary
|
||||
FC_create_folders = 1 << 5; // default for Save
|
||||
|
||||
/**
|
||||
* Shows the Linux system file dialog
|
||||
* Shows the Linux/GTK system file dialog
|
||||
* <a href="https://docs.gtk.org/gtk3/class.FileChooserDialog.html">GtkFileChooserDialog</a>.
|
||||
* <p>
|
||||
* Uses {@code GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER} if {@link #FC_select_folder} is set in parameter {@code optionsSet}.
|
||||
@@ -151,6 +152,7 @@ public class FlatNativeLinuxLibrary
|
||||
* @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 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.
|
||||
* Two or more strings and {@code null} are required for each filter.
|
||||
@@ -164,5 +166,34 @@ public class FlatNativeLinuxLibrary
|
||||
*/
|
||||
public native static String[] showFileChooser( Window owner, boolean open,
|
||||
String title, String okButtonLabel, String currentName, String currentFolder,
|
||||
int optionsSet, int optionsClear, int fileTypeIndex, String... fileTypes );
|
||||
int optionsSet, int optionsClear, FileChooserCallback callback,
|
||||
int fileTypeIndex, String... fileTypes );
|
||||
|
||||
/** @since 3.6 */
|
||||
public interface FileChooserCallback {
|
||||
boolean approve( String[] files, long hwndFileDialog );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a GTK message box
|
||||
* <a href="https://docs.gtk.org/gtk3/class.MessageDialog.html">GtkMessageDialog</a>.
|
||||
* <p>
|
||||
* For use in {@link FileChooserCallback} only.
|
||||
*
|
||||
* @param hwndParent the parent of the message box
|
||||
* @param messageType type of message being displayed:
|
||||
* {@link JOptionPane#ERROR_MESSAGE}, {@link JOptionPane#INFORMATION_MESSAGE},
|
||||
* {@link JOptionPane#WARNING_MESSAGE}, {@link JOptionPane#QUESTION_MESSAGE} or
|
||||
* {@link JOptionPane#PLAIN_MESSAGE}
|
||||
* @param primaryText primary text; if the dialog has a secondary text,
|
||||
* this will appear as title in a larger bold font
|
||||
* @param secondaryText secondary text; shown below of primary text; or {@code null}
|
||||
* @param defaultButton index of the default button, which can be pressed using ENTER key
|
||||
* @param buttons texts of the buttons; if no buttons given the a default "OK" button is shown
|
||||
* @return index of pressed button; or -1 for ESC key
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public native static int showMessageDialog( long hwndParent, int messageType,
|
||||
String primaryText, String secondaryText, int defaultButton, String... buttons );
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ public class FlatNativeWindowsLibrary
|
||||
* @param defaultExtension default extension to be added to file name in save dialog; or {@code null}
|
||||
* @param optionsSet options to set; see {@code FOS_*} constants
|
||||
* @param optionsClear options to clear; see {@code FOS_*} 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.
|
||||
* Pairs of strings are required for each filter.
|
||||
@@ -231,5 +232,29 @@ public class FlatNativeWindowsLibrary
|
||||
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, int fileTypeIndex, String... fileTypes );
|
||||
int optionsSet, int optionsClear, FileChooserCallback callback,
|
||||
int fileTypeIndex, String... fileTypes );
|
||||
|
||||
/** @since 3.6 */
|
||||
public interface FileChooserCallback {
|
||||
boolean approve( String[] files, long hwndFileDialog );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a Windows message box
|
||||
* <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox">MessageBox</a>.
|
||||
* <p>
|
||||
* For use in {@link FileChooserCallback} only.
|
||||
*
|
||||
* @param hwndParent the parent of the message box
|
||||
* @param text message to be displayed
|
||||
* @param caption dialog box title
|
||||
* @param type see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#parameters">MessageBox parameter uType</a>
|
||||
* @return see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#return-value">MessageBox Return value</a>
|
||||
* @return index of pressed button; or -1 for ESC key
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public native static int showMessageDialog( long hwndParent,
|
||||
String text, String caption, int type );
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ public class SystemFileChooser
|
||||
new Thread( () -> {
|
||||
filenamesRef.set( showSystemDialog( owner, fc ) );
|
||||
secondaryLoop.exit();
|
||||
} ).start();
|
||||
}, "FlatLaf SystemFileChooser" ).start();
|
||||
secondaryLoop.enter();
|
||||
|
||||
String[] filenames = filenamesRef.get();
|
||||
@@ -552,7 +552,7 @@ public class SystemFileChooser
|
||||
// show system file dialog
|
||||
return FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||
fc.getDialogTitle(), approveButtonText, null, fileName,
|
||||
folder, saveAsItem, null, null, optionsSet, optionsClear,
|
||||
folder, saveAsItem, null, null, optionsSet, optionsClear, null,
|
||||
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||
}
|
||||
}
|
||||
@@ -693,7 +693,7 @@ public class SystemFileChooser
|
||||
// show system file dialog
|
||||
return FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||
fc.getDialogTitle(), approveButtonText, currentName, currentFolder,
|
||||
optionsSet, optionsClear, fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||
optionsSet, optionsClear, null, fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||
}
|
||||
|
||||
private String caseInsensitiveGlobPattern( String ext ) {
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
// declare external methods
|
||||
extern Window getWindowHandle( JNIEnv* env, JAWT* awt, jobject window, Display** display_return );
|
||||
|
||||
// declare internal methods
|
||||
static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList );
|
||||
|
||||
//---- class AutoReleaseStringUTF8 --------------------------------------------
|
||||
|
||||
class AutoReleaseStringUTF8 {
|
||||
@@ -142,10 +145,37 @@ static void handle_realize( GtkWidget* dialog, gpointer data ) {
|
||||
g_object_unref( gdkOwner );
|
||||
}
|
||||
|
||||
struct ResponseData {
|
||||
JNIEnv* env;
|
||||
jobject callback;
|
||||
GSList* fileList;
|
||||
|
||||
ResponseData( JNIEnv* _env, jobject _callback ) {
|
||||
env = _env;
|
||||
callback = _callback;
|
||||
fileList = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static void handle_response( GtkWidget* dialog, gint responseId, gpointer data ) {
|
||||
// get filenames if user pressed OK
|
||||
if( responseId == GTK_RESPONSE_ACCEPT )
|
||||
*((GSList**)data) = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
|
||||
if( responseId == GTK_RESPONSE_ACCEPT ) {
|
||||
ResponseData *response = static_cast<ResponseData*>( data );
|
||||
if( response->callback != NULL ) {
|
||||
GSList* fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
|
||||
jobjectArray files = fileListToStringArray( response->env, fileList );
|
||||
|
||||
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 ) )
|
||||
return; // keep dialog open
|
||||
}
|
||||
|
||||
response->fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
|
||||
}
|
||||
|
||||
// hide/destroy file dialog and quit loop
|
||||
gtk_widget_hide( dialog );
|
||||
@@ -159,7 +189,7 @@ extern "C"
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser
|
||||
( JNIEnv* env, jclass cls, jobject owner, jboolean open,
|
||||
jstring title, jstring okButtonLabel, jstring currentName, jstring currentFolder,
|
||||
jint optionsSet, jint optionsClear, jint fileTypeIndex, jobjectArray fileTypes )
|
||||
jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes )
|
||||
{
|
||||
// initialize GTK
|
||||
if( !gtk_init_check( NULL, NULL ) )
|
||||
@@ -222,8 +252,8 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrar
|
||||
|
||||
// show dialog
|
||||
// (similar to what's done in sun_awt_X11_GtkFileDialogPeer.c)
|
||||
GSList* fileList = NULL;
|
||||
g_signal_connect( dialog, "response", G_CALLBACK( handle_response ), &fileList );
|
||||
ResponseData responseData( env, callback );
|
||||
g_signal_connect( dialog, "response", G_CALLBACK( handle_response ), &responseData );
|
||||
gtk_widget_show( dialog );
|
||||
|
||||
// necessary to bring file dialog to the front (and make it active)
|
||||
@@ -241,10 +271,14 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrar
|
||||
gtk_main();
|
||||
|
||||
// canceled?
|
||||
if( fileList == NULL )
|
||||
if( responseData.fileList == NULL )
|
||||
return newJavaStringArray( env, 0 );
|
||||
|
||||
// convert GSList to Java string array
|
||||
return fileListToStringArray( env, responseData.fileList );
|
||||
}
|
||||
|
||||
static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList ) {
|
||||
guint count = g_slist_length( fileList );
|
||||
jobjectArray array = newJavaStringArray( env, count );
|
||||
GSList* it = fileList;
|
||||
@@ -259,3 +293,52 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrar
|
||||
g_slist_free( fileList );
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showMessageDialog
|
||||
( JNIEnv* env, jclass cls, jlong hwndParent, jint messageType, jstring primaryText, jstring secondaryText,
|
||||
jint defaultButton, jobjectArray buttons )
|
||||
{
|
||||
GtkWindow* window = (GtkWindow*) hwndParent;
|
||||
|
||||
// convert message type
|
||||
GtkMessageType gmessageType;
|
||||
switch( messageType ) {
|
||||
case /* JOptionPane.ERROR_MESSAGE */ 0: gmessageType = GTK_MESSAGE_ERROR; break;
|
||||
case /* JOptionPane.INFORMATION_MESSAGE */ 1: gmessageType = GTK_MESSAGE_INFO; break;
|
||||
case /* JOptionPane.WARNING_MESSAGE */ 2: gmessageType = GTK_MESSAGE_WARNING; break;
|
||||
case /* JOptionPane.QUESTION_MESSAGE */ 3: gmessageType = GTK_MESSAGE_QUESTION; break;
|
||||
default:
|
||||
case /* JOptionPane.PLAIN_MESSAGE */ -1: gmessageType = GTK_MESSAGE_OTHER; break;
|
||||
}
|
||||
|
||||
// convert Java strings to C strings
|
||||
AutoReleaseStringUTF8 cprimaryText( env, primaryText );
|
||||
AutoReleaseStringUTF8 csecondaryText( env, secondaryText );
|
||||
|
||||
// create GTK file chooser dialog
|
||||
// https://docs.gtk.org/gtk3/class.MessageDialog.html
|
||||
jint buttonCount = env->GetArrayLength( buttons );
|
||||
GtkWidget* dialog = gtk_message_dialog_new( window, GTK_DIALOG_MODAL, gmessageType,
|
||||
(buttonCount > 0) ? GTK_BUTTONS_NONE : GTK_BUTTONS_OK,
|
||||
"%s", (const gchar*) cprimaryText );
|
||||
if( csecondaryText != NULL )
|
||||
gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( dialog ), "%s", (const gchar*) csecondaryText );
|
||||
|
||||
// add buttons
|
||||
for( int i = 0; i < buttonCount; i++ ) {
|
||||
AutoReleaseStringUTF8 str( env, (jstring) env->GetObjectArrayElement( buttons, i ) );
|
||||
gtk_dialog_add_button( GTK_DIALOG( dialog ), str, i );
|
||||
}
|
||||
|
||||
// set default button
|
||||
gtk_dialog_set_default_response( GTK_DIALOG( dialog ), MIN( MAX( defaultButton, 0 ), buttonCount - 1 ) );
|
||||
|
||||
// show message dialog
|
||||
gint responseID = gtk_dialog_run( GTK_DIALOG( dialog ) );
|
||||
gtk_widget_destroy( dialog );
|
||||
|
||||
// return -1 if closed with ESC key
|
||||
return (responseID >= 0) ? responseID : -1;
|
||||
}
|
||||
|
||||
@@ -40,10 +40,18 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xS
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||
* Method: showFileChooser
|
||||
* Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;III[Ljava/lang/String;)[Ljava/lang/String;
|
||||
* Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeLinuxLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser
|
||||
(JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jint, jint, jint, jobjectArray);
|
||||
(JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||
* Method: showMessageDialog
|
||||
* Signature: (JILjava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showMessageDialog
|
||||
(JNIEnv *, jclass, jlong, jint, jstring, jstring, jint, jobjectArray);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ tasks {
|
||||
compilerArgs.addAll( toolChain.map {
|
||||
when( it ) {
|
||||
is Gcc, is Clang -> listOf( "-O2", "-DUNICODE" )
|
||||
is VisualCpp -> listOf( "/O2", "/Zl", "/GS-", "/DUNICODE" )
|
||||
is VisualCpp -> listOf( "/O2", "/GS-", "/DUNICODE" )
|
||||
else -> emptyList()
|
||||
}
|
||||
} )
|
||||
@@ -81,7 +81,7 @@ tasks {
|
||||
linkerArgs.addAll( toolChain.map {
|
||||
when( it ) {
|
||||
is Gcc, is Clang -> listOf( "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32", "-lDwmapi", "-lOle32", "-luuid" )
|
||||
is VisualCpp -> listOf( "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "Ole32.lib", "uuid.lib", "/NODEFAULTLIB" )
|
||||
is VisualCpp -> listOf( "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "Ole32.lib", "uuid.lib" )
|
||||
else -> emptyList()
|
||||
}
|
||||
} )
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
// declare external methods
|
||||
extern HWND getWindowHandle( JNIEnv* env, jobject window );
|
||||
|
||||
// declare internal methods
|
||||
static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog );
|
||||
|
||||
//---- class AutoReleasePtr ---------------------------------------------------
|
||||
|
||||
template<class T> class AutoReleasePtr {
|
||||
@@ -38,6 +41,10 @@ public:
|
||||
AutoReleasePtr() {
|
||||
ptr = NULL;
|
||||
}
|
||||
AutoReleasePtr( T* p ) {
|
||||
ptr = p;
|
||||
ptr->AddRef();
|
||||
}
|
||||
~AutoReleasePtr() {
|
||||
if( ptr != NULL )
|
||||
ptr->Release();
|
||||
@@ -126,6 +133,86 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//---- class DialogEventHandler -----------------------------------------------
|
||||
|
||||
// see https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appplatform/commonfiledialog/CommonFileDialogApp.cpp
|
||||
|
||||
class DialogEventHandler : public IFileDialogEvents {
|
||||
JNIEnv* env;
|
||||
jboolean open;
|
||||
jobject callback;
|
||||
LONG refCount = 1;
|
||||
|
||||
public:
|
||||
DialogEventHandler( JNIEnv* _env, jboolean _open, jobject _callback ) {
|
||||
env = _env;
|
||||
open = _open;
|
||||
callback = _callback;
|
||||
}
|
||||
|
||||
//---- IFileDialogEvents methods ----
|
||||
|
||||
IFACEMETHODIMP OnFileOk( IFileDialog* dialog ) {
|
||||
if( callback == NULL )
|
||||
return S_OK;
|
||||
|
||||
// get files
|
||||
jobjectArray files;
|
||||
if( open ) {
|
||||
AutoReleasePtr<IFileOpenDialog> openDialog;
|
||||
HRESULT hr = dialog->QueryInterface( &openDialog );
|
||||
files = SUCCEEDED( hr ) ? getFiles( env, true, openDialog ) : getFiles( env, false, dialog );
|
||||
} else
|
||||
files = getFiles( env, false, dialog );
|
||||
|
||||
// get hwnd of file dialog
|
||||
HWND hwndFileDialog = 0;
|
||||
AutoReleasePtr<IOleWindow> window;
|
||||
if( SUCCEEDED( dialog->QueryInterface( &window ) ) )
|
||||
window->GetWindow( &hwndFileDialog );
|
||||
|
||||
// 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 )
|
||||
return S_OK;
|
||||
return env->CallBooleanMethod( callback, approveID, files, hwndFileDialog ) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OnFolderChange( IFileDialog* ) { return S_OK; }
|
||||
IFACEMETHODIMP OnFolderChanging( IFileDialog*, IShellItem* ) { return S_OK; }
|
||||
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 OnOverwrite( IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE* ) { return S_OK; }
|
||||
|
||||
//---- IUnknown methods ----
|
||||
|
||||
IFACEMETHODIMP QueryInterface( REFIID riid, void** ppv ) {
|
||||
if( riid != IID_IFileDialogEvents && riid != IID_IUnknown )
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppv = static_cast<IFileDialogEvents*>( this );
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) AddRef() {
|
||||
return InterlockedIncrement( &refCount );
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) Release() {
|
||||
LONG newRefCount = InterlockedDecrement( &refCount );
|
||||
if( newRefCount == 0 )
|
||||
delete this;
|
||||
return newRefCount;
|
||||
}
|
||||
|
||||
private:
|
||||
~DialogEventHandler() {}
|
||||
};
|
||||
|
||||
//---- class CoInitializer ----------------------------------------------------
|
||||
|
||||
class CoInitializer {
|
||||
@@ -163,7 +250,7 @@ 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, jint fileTypeIndex, jobjectArray fileTypes )
|
||||
jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes )
|
||||
{
|
||||
// initialize COM library
|
||||
CoInitializer coInitializer;
|
||||
@@ -226,20 +313,31 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibr
|
||||
CHECK_HRESULT( dialog->SetFileTypeIndex( min( fileTypeIndex + 1, specs.count ) ) );
|
||||
}
|
||||
|
||||
// add event handler
|
||||
AutoReleasePtr<DialogEventHandler> handler( new DialogEventHandler( env, open, callback ) );
|
||||
DWORD dwCookie = 0;
|
||||
CHECK_HRESULT( dialog->Advise( handler, &dwCookie ) );
|
||||
|
||||
// show dialog
|
||||
HWND hwndOwner = (owner != NULL) ? getWindowHandle( env, owner ) : NULL;
|
||||
HRESULT hr = dialog->Show( hwndOwner );
|
||||
dialog->Unadvise( dwCookie );
|
||||
if( hr == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
||||
return newJavaStringArray( env, 0 );
|
||||
CHECK_HRESULT( hr );
|
||||
|
||||
// convert shell items to Java string array
|
||||
// get selected files as Java string array
|
||||
return getFiles( env, open, dialog );
|
||||
}
|
||||
|
||||
static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog ) {
|
||||
if( open ) {
|
||||
AutoReleasePtr<IShellItemArray> shellItems;
|
||||
DWORD count;
|
||||
CHECK_HRESULT( ((IFileOpenDialog*)(IFileDialog*)dialog)->GetResults( &shellItems ) );
|
||||
CHECK_HRESULT( shellItems->GetCount( &count ) );
|
||||
|
||||
// convert shell items to Java string array
|
||||
jobjectArray array = newJavaStringArray( env, count );
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
AutoReleasePtr<IShellItem> shellItem;
|
||||
@@ -260,6 +358,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibr
|
||||
CHECK_HRESULT( dialog->GetResult( &shellItem ) );
|
||||
CHECK_HRESULT( shellItem->GetDisplayName( SIGDN_FILESYSPATH, &path ) );
|
||||
|
||||
// convert shell item to Java string array
|
||||
jstring jpath = newJavaString( env, path );
|
||||
CoTaskMemFree( path );
|
||||
|
||||
@@ -270,3 +369,15 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibr
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageDialog
|
||||
( JNIEnv* env, jclass cls, jlong hwndParent, jstring text, jstring caption, jint type )
|
||||
{
|
||||
// convert Java strings to C strings
|
||||
AutoReleaseString ctext( env, text );
|
||||
AutoReleaseString ccaption( env, caption );
|
||||
|
||||
return ::MessageBox( reinterpret_cast<HWND>( hwndParent ), ctext, ccaption, type );
|
||||
}
|
||||
|
||||
@@ -116,10 +116,18 @@ 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;III[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;)[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, jint, jobjectArray);
|
||||
(JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
||||
* Method: showMessageDialog
|
||||
* Signature: (JLjava/lang/String;Ljava/lang/String;I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageDialog
|
||||
(JNIEnv *, jclass, jlong, jstring, jstring, jint);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -124,10 +124,20 @@ public class FlatSystemFileChooserLinuxTest
|
||||
}
|
||||
int fileTypeIndex = fileTypeIndexSlider.getValue();
|
||||
|
||||
FlatNativeLinuxLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> {
|
||||
System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) );
|
||||
if( showMessageDialogOnOKCheckBox.isSelected() ) {
|
||||
System.out.println( FlatNativeLinuxLibrary.showMessageDialog( hwndFileDialog,
|
||||
JOptionPane.INFORMATION_MESSAGE,
|
||||
"primary text", "secondary text", 1, "Yes", "No" ) );
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if( direct ) {
|
||||
String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||
title, okButtonLabel, currentName, currentFolder,
|
||||
optionsSet.get(), optionsClear.get(), fileTypeIndex, fileTypes );
|
||||
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes );
|
||||
|
||||
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||
} else {
|
||||
@@ -137,7 +147,7 @@ public class FlatSystemFileChooserLinuxTest
|
||||
new Thread( () -> {
|
||||
String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||
title, okButtonLabel, currentName, currentFolder,
|
||||
optionsSet.get(), optionsClear.get(), fileTypeIndex, fileTypes2 );
|
||||
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 );
|
||||
|
||||
System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() );
|
||||
|
||||
@@ -248,6 +258,7 @@ public class FlatSystemFileChooserLinuxTest
|
||||
saveButton = new JButton();
|
||||
openDirectButton = new JButton();
|
||||
saveDirectButton = new JButton();
|
||||
showMessageDialogOnOKCheckBox = new JCheckBox();
|
||||
filesScrollPane = new JScrollPane();
|
||||
filesField = new JTextArea();
|
||||
|
||||
@@ -397,6 +408,10 @@ public class FlatSystemFileChooserLinuxTest
|
||||
saveDirectButton.addActionListener(e -> saveDirect());
|
||||
add(saveDirectButton, "cell 0 7 3 1");
|
||||
|
||||
//---- showMessageDialogOnOKCheckBox ----
|
||||
showMessageDialogOnOKCheckBox.setText("show message dialog on OK");
|
||||
add(showMessageDialogOnOKCheckBox, "cell 0 7 3 1");
|
||||
|
||||
//======== filesScrollPane ========
|
||||
{
|
||||
|
||||
@@ -443,6 +458,7 @@ public class FlatSystemFileChooserLinuxTest
|
||||
private JButton saveButton;
|
||||
private JButton openDirectButton;
|
||||
private JButton saveDirectButton;
|
||||
private JCheckBox showMessageDialogOnOKCheckBox;
|
||||
private JScrollPane filesScrollPane;
|
||||
private JTextArea filesField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "8.2.2.0.9999" Java: "21.0.1" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -198,6 +198,12 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showMessageDialogOnOKCheckBox"
|
||||
"text": "show message dialog on OK"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7 3 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "filesScrollPane"
|
||||
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||
|
||||
@@ -139,11 +139,21 @@ public class FlatSystemFileChooserWindowsTest
|
||||
fileTypes = fileTypesStr.trim().split( "[,]+" );
|
||||
int fileTypeIndex = fileTypeIndexSlider.getValue();
|
||||
|
||||
FlatNativeWindowsLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> {
|
||||
System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) );
|
||||
if( showMessageDialogOnOKCheckBox.isSelected() ) {
|
||||
System.out.println( FlatNativeWindowsLibrary.showMessageDialog( hwndFileDialog,
|
||||
"some text", "title",
|
||||
/* MB_ICONINFORMATION */ 0x00000040 | /* MB_YESNO */ 0x00000004 ) );
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if( direct ) {
|
||||
String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||
title, okButtonLabel, fileNameLabel, fileName,
|
||||
folder, saveAsItem, defaultFolder, defaultExtension,
|
||||
optionsSet.get(), optionsClear.get(), fileTypeIndex, fileTypes );
|
||||
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes );
|
||||
|
||||
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||
} else {
|
||||
@@ -154,7 +164,7 @@ public class FlatSystemFileChooserWindowsTest
|
||||
String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||
title, okButtonLabel, fileNameLabel, fileName,
|
||||
folder, saveAsItem, defaultFolder, defaultExtension,
|
||||
optionsSet.get(), optionsClear.get(), fileTypeIndex, fileTypes2 );
|
||||
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 );
|
||||
|
||||
System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() );
|
||||
|
||||
@@ -290,6 +300,7 @@ public class FlatSystemFileChooserWindowsTest
|
||||
saveButton = new JButton();
|
||||
openDirectButton = new JButton();
|
||||
saveDirectButton = new JButton();
|
||||
showMessageDialogOnOKCheckBox = new JCheckBox();
|
||||
filesScrollPane = new JScrollPane();
|
||||
filesField = new JTextArea();
|
||||
|
||||
@@ -534,6 +545,10 @@ public class FlatSystemFileChooserWindowsTest
|
||||
saveDirectButton.addActionListener(e -> saveDirect());
|
||||
add(saveDirectButton, "cell 0 11 3 1");
|
||||
|
||||
//---- showMessageDialogOnOKCheckBox ----
|
||||
showMessageDialogOnOKCheckBox.setText("show message dialog on OK");
|
||||
add(showMessageDialogOnOKCheckBox, "cell 0 11 3 1");
|
||||
|
||||
//======== filesScrollPane ========
|
||||
{
|
||||
|
||||
@@ -605,6 +620,7 @@ public class FlatSystemFileChooserWindowsTest
|
||||
private JButton saveButton;
|
||||
private JButton openDirectButton;
|
||||
private JButton saveDirectButton;
|
||||
private JCheckBox showMessageDialogOnOKCheckBox;
|
||||
private JScrollPane filesScrollPane;
|
||||
private JTextArea filesField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
@@ -343,6 +343,12 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 11 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showMessageDialogsOnOKCheckBox"
|
||||
"text": "show message dialog on OK"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 11 3 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "filesScrollPane"
|
||||
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||
|
||||
Reference in New Issue
Block a user