From 07fc190b5fbcae9ed892fb16670a7c958960c75e Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 14 Jan 2025 16:29:27 +0100 Subject: [PATCH] Native Libraries: moved code to JNIUtils.cpp and *MessageDialog.cpp --- .../src/main/cpp/GtkFileChooser.cpp | 70 +-------------- .../src/main/cpp/GtkMessageDialog.cpp | 76 +++++++++++++++++ .../src/main/cpp/JNIUtils.cpp | 37 ++++++++ .../src/main/headers/JNIUtils.h | 36 ++++++++ .../src/main/objcpp/MacFileChooser.mm | 58 ------------- .../src/main/objcpp/MacMessageDialog.mm | 85 +++++++++++++++++++ .../src/main/cpp/JNIUtils.cpp | 67 +++++++++++++++ .../src/main/cpp/WinFileChooser.cpp | 74 +++------------- .../src/main/cpp/WinMessageDialog.cpp | 38 +++++++++ .../src/main/headers/JNIUtils.h | 53 ++++++++++++ 10 files changed, 405 insertions(+), 189 deletions(-) create mode 100644 flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkMessageDialog.cpp create mode 100644 flatlaf-natives/flatlaf-natives-linux/src/main/cpp/JNIUtils.cpp create mode 100644 flatlaf-natives/flatlaf-natives-linux/src/main/headers/JNIUtils.h create mode 100644 flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacMessageDialog.mm create mode 100644 flatlaf-natives/flatlaf-natives-windows/src/main/cpp/JNIUtils.cpp create mode 100644 flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinMessageDialog.cpp create mode 100644 flatlaf-natives/flatlaf-natives-windows/src/main/headers/JNIUtils.h 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 7e427a85..1aacde3a 100644 --- a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkFileChooser.cpp @@ -19,6 +19,7 @@ #include #include #include +#include "JNIUtils.h" #include "com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h" /** @@ -32,26 +33,6 @@ extern Window getWindowHandle( JNIEnv* env, JAWT* awt, jobject window, Display** // declare internal methods static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList ); -//---- class AutoReleaseStringUTF8 -------------------------------------------- - -class AutoReleaseStringUTF8 { - JNIEnv* env; - jstring javaString; - const char* chars; - -public: - AutoReleaseStringUTF8( JNIEnv* _env, jstring _javaString ) { - env = _env; - javaString = _javaString; - chars = (javaString != NULL) ? env->GetStringUTFChars( javaString, NULL ) : NULL; - } - ~AutoReleaseStringUTF8() { - if( chars != NULL ) - env->ReleaseStringUTFChars( javaString, chars ); - } - operator const gchar*() { return chars; } -}; - //---- helper ----------------------------------------------------------------- #define isOptionSet( option ) ((optionsSet & com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_ ## option) != 0) @@ -293,52 +274,3 @@ static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList ) { 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; -} diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkMessageDialog.cpp b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkMessageDialog.cpp new file mode 100644 index 00000000..34f26c1b --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/GtkMessageDialog.cpp @@ -0,0 +1,76 @@ +/* + * Copyright 2025 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "JNIUtils.h" +#include "com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h" + +/** + * @author Karl Tauber + * @since 3.6 + */ + +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; +} diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/JNIUtils.cpp b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/JNIUtils.cpp new file mode 100644 index 00000000..bd587070 --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/cpp/JNIUtils.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2024 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// avoid inlining of printf() +#define _NO_CRT_STDIO_INLINE + +#include "JNIUtils.h" + +/** + * @author Karl Tauber + */ + +//---- class AutoReleaseStringUTF8 -------------------------------------------- + +AutoReleaseStringUTF8::AutoReleaseStringUTF8( JNIEnv* _env, jstring _javaString ) { + env = _env; + javaString = _javaString; + chars = (javaString != NULL) ? env->GetStringUTFChars( javaString, NULL ) : NULL; +} + +AutoReleaseStringUTF8::~AutoReleaseStringUTF8() { + if( chars != NULL ) + env->ReleaseStringUTFChars( javaString, chars ); +} diff --git a/flatlaf-natives/flatlaf-natives-linux/src/main/headers/JNIUtils.h b/flatlaf-natives/flatlaf-natives-linux/src/main/headers/JNIUtils.h new file mode 100644 index 00000000..6d7d8c22 --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-linux/src/main/headers/JNIUtils.h @@ -0,0 +1,36 @@ +/* + * Copyright 2025 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +/** + * @author Karl Tauber + */ + +//---- class AutoReleaseStringUTF8 -------------------------------------------- + +class AutoReleaseStringUTF8 { + JNIEnv* env; + jstring javaString; + const char* chars; + +public: + AutoReleaseStringUTF8( JNIEnv* _env, jstring _javaString ); + ~AutoReleaseStringUTF8(); + + operator const gchar*() { return chars; } +}; 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 a782ca74..891d97c2 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacFileChooser.mm @@ -366,61 +366,3 @@ static jobjectArray urlsToStringArray( JNIEnv* env, NSArray* urls ) { } return array; } - -extern "C" -JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showMessageDialog - ( JNIEnv* env, jclass cls, jlong hwndParent, jint alertStyle, jstring messageText, jstring informativeText, - jint defaultButton, jobjectArray buttons ) -{ - JNI_COCOA_ENTER() - - // convert Java strings to NSString (on Java thread) - NSString* nsMessageText = JavaToNSString( env, messageText ); - NSString* nsInformativeText = JavaToNSString( env, informativeText ); - - jint buttonCount = env->GetArrayLength( buttons ); - NSMutableArray* nsButtons = [NSMutableArray array]; - for( int i = 0; i < buttonCount; i++ ) { - NSString* nsButton = JavaToNSString( env, (jstring) env->GetObjectArrayElement( buttons, i ) ); - [nsButtons addObject:nsButton]; - } - - jint result = -1; - jint* presult = &result; - - // show alert on macOS thread - [FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - NSAlert* alert = [[NSAlert alloc] init]; - - // use empty string because if alert.messageText is not set it displays "Alert" - alert.messageText = (nsMessageText != NULL) ? nsMessageText : @""; - if( nsInformativeText != NULL ) - alert.informativeText = nsInformativeText; - - // alert style - switch( alertStyle ) { - case /* JOptionPane.ERROR_MESSAGE */ 0: alert.alertStyle = NSAlertStyleCritical; break; - default: - case /* JOptionPane.INFORMATION_MESSAGE */ 1: alert.alertStyle = NSAlertStyleInformational; break; - case /* JOptionPane.WARNING_MESSAGE */ 2: alert.alertStyle = NSAlertStyleWarning; break; - } - - // add buttons - for( int i = 0; i < nsButtons.count; i++ ) { - NSButton* b = [alert addButtonWithTitle:nsButtons[i]]; - if( i == defaultButton ) - alert.window.defaultButtonCell = b.cell; - } - - // show alert - NSInteger response = [alert runModal]; - - // if no buttons added, which shows a single OK button, the response is 0 when clicking OK - // if buttons added, response is 1000+buttonIndex - *presult = MAX( response - NSAlertFirstButtonReturn, 0 ); - }]; - - return result; - - JNI_COCOA_EXIT() -} diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacMessageDialog.mm b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacMessageDialog.mm new file mode 100644 index 00000000..d186c8e6 --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacMessageDialog.mm @@ -0,0 +1,85 @@ +/* + * Copyright 2024 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import +#import "JNIUtils.h" +#import "JNFRunLoop.h" +#import "com_formdev_flatlaf_ui_FlatNativeMacLibrary.h" + +/** + * @author Karl Tauber + * @since 3.6 + */ + +extern "C" +JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showMessageDialog + ( JNIEnv* env, jclass cls, jlong hwndParent, jint alertStyle, jstring messageText, jstring informativeText, + jint defaultButton, jobjectArray buttons ) +{ + JNI_COCOA_ENTER() + + // convert Java strings to NSString (on Java thread) + NSString* nsMessageText = JavaToNSString( env, messageText ); + NSString* nsInformativeText = JavaToNSString( env, informativeText ); + + jint buttonCount = env->GetArrayLength( buttons ); + NSMutableArray* nsButtons = [NSMutableArray array]; + for( int i = 0; i < buttonCount; i++ ) { + NSString* nsButton = JavaToNSString( env, (jstring) env->GetObjectArrayElement( buttons, i ) ); + [nsButtons addObject:nsButton]; + } + + jint result = -1; + jint* presult = &result; + + // show alert on macOS thread + [FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + NSAlert* alert = [[NSAlert alloc] init]; + + // use empty string because if alert.messageText is not set it displays "Alert" + alert.messageText = (nsMessageText != NULL) ? nsMessageText : @""; + if( nsInformativeText != NULL ) + alert.informativeText = nsInformativeText; + + // alert style + switch( alertStyle ) { + case /* JOptionPane.ERROR_MESSAGE */ 0: alert.alertStyle = NSAlertStyleCritical; break; + default: + case /* JOptionPane.INFORMATION_MESSAGE */ 1: alert.alertStyle = NSAlertStyleInformational; break; + case /* JOptionPane.WARNING_MESSAGE */ 2: alert.alertStyle = NSAlertStyleWarning; break; + } + + // add buttons + for( int i = 0; i < nsButtons.count; i++ ) { + NSButton* b = [alert addButtonWithTitle:nsButtons[i]]; + if( i == defaultButton ) + alert.window.defaultButtonCell = b.cell; + } + + // show alert + NSInteger response = [alert runModal]; + + // if no buttons added, which shows a single OK button, the response is 0 when clicking OK + // if buttons added, response is 1000+buttonIndex + *presult = MAX( response - NSAlertFirstButtonReturn, 0 ); + }]; + + return result; + + JNI_COCOA_EXIT() +} diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/JNIUtils.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/JNIUtils.cpp new file mode 100644 index 00000000..bc24a10e --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/JNIUtils.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2024 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// avoid inlining of printf() +#define _NO_CRT_STDIO_INLINE + +#include "JNIUtils.h" + +/** + * @author Karl Tauber + */ + +//---- class AutoReleaseString ------------------------------------------------ + +AutoReleaseString::AutoReleaseString( JNIEnv* _env, jstring _javaString ) { + env = _env; + javaString = _javaString; + chars = (javaString != NULL) ? env->GetStringChars( javaString, NULL ) : NULL; +} + +AutoReleaseString::~AutoReleaseString() { + if( chars != NULL ) + env->ReleaseStringChars( javaString, chars ); +} + +//---- class AutoReleaseStringArray ------------------------------------------- + +AutoReleaseStringArray::AutoReleaseStringArray( JNIEnv* _env, jobjectArray _javaStringArray ) { + env = _env; + count = (_javaStringArray != NULL) ? env->GetArrayLength( _javaStringArray ) : 0; + if( count <= 0 ) + return; + + javaStringArray = new jstring[count]; + charsArray = new const jchar*[count]; + + for( int i = 0; i < count; i++ ) { + javaStringArray[i] = (jstring) env->GetObjectArrayElement( _javaStringArray, i ); + charsArray[i] = env->GetStringChars( javaStringArray[i] , NULL ); + } +} + +AutoReleaseStringArray::~AutoReleaseStringArray() { + if( count == 0 ) + return; + + for( int i = 0; i < count; i++ ) { + env->ReleaseStringChars( javaStringArray[i], charsArray[i] ); + env->DeleteLocalRef( javaStringArray[i] ); + } + + delete[] javaStringArray; + delete[] charsArray; +} 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 2a643643..1eebe21e 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinFileChooser.cpp @@ -19,6 +19,7 @@ #include #include +#include "JNIUtils.h" #include "com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h" /** @@ -54,26 +55,6 @@ public: operator T*() { return ptr; } }; -//---- class AutoReleaseString ------------------------------------------------ - -class AutoReleaseString { - JNIEnv* env; - jstring javaString; - const jchar* chars; - -public: - AutoReleaseString( JNIEnv* _env, jstring _javaString ) { - env = _env; - javaString = _javaString; - chars = (javaString != NULL) ? env->GetStringChars( javaString, NULL ) : NULL; - } - ~AutoReleaseString() { - if( chars != NULL ) - env->ReleaseStringChars( javaString, chars ); - } - operator LPCWSTR() { return (LPCWSTR) chars; } -}; - //---- class AutoReleaseIShellItem -------------------------------------------- class AutoReleaseIShellItem : public AutoReleasePtr { @@ -87,49 +68,30 @@ public: //---- class FilterSpec ------------------------------------------------------- class FilterSpec { - JNIEnv* env = NULL; - jstring* jnames = NULL; - jstring* jspecs = NULL; + AutoReleaseStringArray fileTypes; public: UINT count = 0; COMDLG_FILTERSPEC* specs = NULL; public: - FilterSpec( JNIEnv* _env, jobjectArray fileTypes ) { - if( fileTypes == NULL ) + FilterSpec( JNIEnv* _env, jobjectArray _fileTypes ) + : fileTypes( _env, _fileTypes ) + { + if( fileTypes.count == 0 ) return; - env = _env; - count = env->GetArrayLength( fileTypes ) / 2; - if( count <= 0 ) - return; - - specs = new COMDLG_FILTERSPEC[count]; - jnames = new jstring[count]; - jspecs = new jstring[count]; + count = fileTypes.count / 2; + specs = new COMDLG_FILTERSPEC[fileTypes.count]; for( int i = 0; i < count; i++ ) { - jnames[i] = (jstring) env->GetObjectArrayElement( fileTypes, i * 2 ); - jspecs[i] = (jstring) env->GetObjectArrayElement( fileTypes, (i * 2) + 1 ); - specs[i].pszName = (LPCWSTR) env->GetStringChars( jnames[i] , NULL ); - specs[i].pszSpec = (LPCWSTR) env->GetStringChars( jspecs[i], NULL ); + specs[i].pszName = fileTypes[i * 2]; + specs[i].pszSpec = fileTypes[(i * 2) + 1]; } } ~FilterSpec() { - if( specs == NULL ) - return; - - for( int i = 0; i < count; i++ ) { - env->ReleaseStringChars( jnames[i], (jchar *) specs[i].pszName ); - env->ReleaseStringChars( jspecs[i], (jchar *) specs[i].pszSpec ); - env->DeleteLocalRef( jnames[i] ); - env->DeleteLocalRef( jspecs[i] ); - } - - delete[] jnames; - delete[] jspecs; - delete[] specs; + if( specs != NULL ) + delete[] specs; } }; @@ -369,15 +331,3 @@ static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog ) 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( hwndParent ), ctext, ccaption, type ); -} diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinMessageDialog.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinMessageDialog.cpp new file mode 100644 index 00000000..38b9dd3a --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinMessageDialog.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2024 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// avoid inlining of printf() +#define _NO_CRT_STDIO_INLINE + +#include +#include "JNIUtils.h" +#include "com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h" + +/** + * @author Karl Tauber + * @since 3.6 + */ + +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( hwndParent ), ctext, ccaption, type ); +} diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/JNIUtils.h b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/JNIUtils.h new file mode 100644 index 00000000..5eaad97c --- /dev/null +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/JNIUtils.h @@ -0,0 +1,53 @@ +/* + * Copyright 2025 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +/** + * @author Karl Tauber + */ + +//---- class AutoReleaseString ------------------------------------------------ + +class AutoReleaseString { + JNIEnv* env; + jstring javaString; + const jchar* chars; + +public: + AutoReleaseString( JNIEnv* _env, jstring _javaString ); + ~AutoReleaseString(); + + operator LPCWSTR() { return (LPCWSTR) chars; } +}; + +//---- class AutoReleaseStringArray ------------------------------------------- + +class AutoReleaseStringArray { + JNIEnv* env; + jstring* javaStringArray; + const jchar** charsArray; + +public: + UINT count; + +public: + AutoReleaseStringArray( JNIEnv* _env, jobjectArray _javaStringArray ); + ~AutoReleaseStringArray(); + + operator LPCWSTR*() { return (LPCWSTR*) charsArray; } +};