1 /* 2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <jni.h> 27 #include <stdio.h> 28 #include <jni_util.h> 29 #include <string.h> 30 #include "gtk2_interface.h" 31 #include "sun_awt_X11_GtkFileDialogPeer.h" 32 #include "java_awt_FileDialog.h" 33 #include "debug_assert.h" 34 35 static JavaVM *jvm; 36 37 /* To cache some method IDs */ 38 static jmethodID filenameFilterCallbackMethodID = NULL; 39 static jmethodID setFileInternalMethodID = NULL; 40 static jfieldID widgetFieldID = NULL; 41 42 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_initIDs 43 (JNIEnv *env, jclass cx) 44 { 45 filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, 46 "filenameFilterCallback", "(Ljava/lang/String;)Z"); 47 DASSERT(filenameFilterCallbackMethodID != NULL); 48 CHECK_NULL(filenameFilterCallbackMethodID); 49 50 setFileInternalMethodID = (*env)->GetMethodID(env, cx, 51 "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); 52 DASSERT(setFileInternalMethodID != NULL); 53 CHECK_NULL(setFileInternalMethodID); 54 67 JNU_CHECK_EXCEPTION_RETURN(env, FALSE); 68 69 return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, 70 filename); 71 } 72 73 static void quit(JNIEnv * env, jobject jpeer, gboolean isSignalHandler) 74 { 75 jthrowable pendingException; 76 if (pendingException = (*env)->ExceptionOccurred(env)) { 77 (*env)->ExceptionClear(env); 78 } 79 80 GtkWidget * dialog = (GtkWidget*)jlong_to_ptr( 81 (*env)->GetLongField(env, jpeer, widgetFieldID)); 82 83 if (dialog != NULL) 84 { 85 // Callbacks from GTK signals are made within the GTK lock 86 // So, within a signal handler there is no need to call 87 // gdk_threads_enter() / fp_gdk_threads_leave() 88 if (!isSignalHandler) { 89 fp_gdk_threads_enter(); 90 } 91 92 fp_gtk_widget_hide (dialog); 93 fp_gtk_widget_destroy (dialog); 94 95 fp_gtk_main_quit (); 96 97 (*env)->SetLongField(env, jpeer, widgetFieldID, 0); 98 99 if (!isSignalHandler) { 100 fp_gdk_threads_leave(); 101 } 102 } 103 104 if (pendingException) { 105 (*env)->Throw(env, pendingException); 106 } 107 } 108 109 /* 110 * Class: sun_awt_X11_GtkFileDialogPeer 111 * Method: quit 112 * Signature: ()V 113 */ 114 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit 115 (JNIEnv * env, jobject jpeer) 116 { 117 quit(env, jpeer, FALSE); 118 } 119 120 /* 121 * Class: sun_awt_X11_GtkFileDialogPeer 122 * Method: toFront 123 * Signature: ()V 124 */ 125 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_toFront 126 (JNIEnv * env, jobject jpeer) 127 { 128 GtkWidget * dialog; 129 130 fp_gdk_threads_enter(); 131 132 dialog = (GtkWidget*)jlong_to_ptr( 133 (*env)->GetLongField(env, jpeer, widgetFieldID)); 134 135 if (dialog != NULL) { 136 fp_gtk_window_present((GtkWindow*)dialog); 137 } 138 139 fp_gdk_threads_leave(); 140 } 141 142 /* 143 * Class: sun_awt_X11_GtkFileDialogPeer 144 * Method: setBounds 145 * Signature: (IIIII)V 146 */ 147 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_setBounds 148 (JNIEnv * env, jobject jpeer, jint x, jint y, jint width, jint height, jint op) 149 { 150 GtkWindow* dialog; 151 152 fp_gdk_threads_enter(); 153 154 dialog = (GtkWindow*)jlong_to_ptr( 155 (*env)->GetLongField(env, jpeer, widgetFieldID)); 156 157 if (dialog != NULL) { 158 if (x >= 0 && y >= 0) { 159 fp_gtk_window_move(dialog, (gint)x, (gint)y); 160 } 161 if (width > 0 && height > 0) { 162 fp_gtk_window_resize(dialog, (gint)width, (gint)height); 163 } 164 } 165 166 fp_gdk_threads_leave(); 167 } 168 169 /* 170 * baseDir should be freed by user. 171 */ 172 static gboolean isFromSameDirectory(GSList* list, gchar** baseDir) { 173 174 GSList *it = list; 175 gchar* prevDir = NULL; 176 gboolean isAllDirsSame = TRUE; 177 178 while (it) { 179 gchar* dir = fp_g_path_get_dirname((gchar*) it->data); 180 181 if (prevDir && strcmp(prevDir, dir) != 0) { 182 isAllDirsSame = FALSE; 183 fp_g_free(dir); 184 break; 185 } 186 187 if (!prevDir) { 188 prevDir = strdup(dir); 189 } 190 fp_g_free(dir); 191 192 it = it->next; 193 } 194 195 if (isAllDirsSame) { 196 *baseDir = prevDir; 197 } else { 198 free(prevDir); 199 *baseDir = strdup("/"); 200 } 201 202 return isAllDirsSame; 203 } 204 205 /** 206 * Convert a GSList to an array of filenames 207 */ 208 static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list, jstring* jcurrent_folder) 209 { 210 jstring str; 211 jclass stringCls; 212 GSList *iterator; 213 jobjectArray array; 214 int i; 215 gchar* entry; 216 gchar * baseDir; 217 gboolean isFromSameDir; 218 219 if (list == NULL) { 220 return NULL; 221 } 222 223 stringCls = (*env)->FindClass(env, "java/lang/String"); 224 if (stringCls == NULL) { 225 (*env)->ExceptionClear(env); 226 JNU_ThrowInternalError(env, "Could not get java.lang.String class"); 227 return NULL; 228 } 229 230 array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL); 231 if (array == NULL) { 232 (*env)->ExceptionClear(env); 233 JNU_ThrowInternalError(env, "Could not instantiate array files array"); 234 return NULL; 235 } 236 237 isFromSameDir = isFromSameDirectory(list, &baseDir); 238 239 *jcurrent_folder = (*env)->NewStringUTF(env, baseDir); 240 if (*jcurrent_folder == NULL) { 241 free(baseDir); 242 return NULL; 243 } 244 245 for (iterator = list, i=0; 246 iterator; 247 iterator = iterator->next, i++) { 248 249 entry = (gchar*) iterator->data; 250 264 break; 265 } 266 } 267 } 268 269 free(baseDir); 270 return array; 271 } 272 273 static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) 274 { 275 JNIEnv *env; 276 GSList *filenames; 277 jstring jcurrent_folder = NULL; 278 jobjectArray jfilenames; 279 280 env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); 281 filenames = NULL; 282 283 if (responseId == GTK_RESPONSE_ACCEPT) { 284 filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); 285 } 286 287 jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder); 288 289 if (!(*env)->ExceptionCheck(env)) { 290 (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, 291 jcurrent_folder, jfilenames); 292 } 293 294 quit(env, (jobject)obj, TRUE); 295 } 296 297 /* 298 * Class: sun_awt_X11_GtkFileDialogPeer 299 * Method: run 300 * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;ZII)V 301 */ 302 JNIEXPORT void JNICALL 303 Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, 304 jstring jtitle, jint mode, jstring jdir, jstring jfile, 305 jobject jfilter, jboolean multiple, int x, int y) 306 { 307 GtkWidget *dialog = NULL; 308 GtkFileFilter *filter; 309 310 if (jvm == NULL) { 311 (*env)->GetJavaVM(env, &jvm); 312 JNU_CHECK_EXCEPTION(env); 313 } 314 315 fp_gdk_threads_enter(); 316 317 const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); 318 if (title == NULL) { 319 (*env)->ExceptionClear(env); 320 JNU_ThrowOutOfMemoryError(env, "Could not get title"); 321 return; 322 } 323 324 if (mode == java_awt_FileDialog_SAVE) { 325 /* Save action */ 326 dialog = fp_gtk_file_chooser_dialog_new(title, NULL, 327 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, 328 GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); 329 } 330 else { 331 /* Default action OPEN */ 332 dialog = fp_gtk_file_chooser_dialog_new(title, NULL, 333 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, 334 GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); 335 336 /* Set multiple selection mode, that is allowed only in OPEN action */ 337 if (multiple) { 338 fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), 339 multiple); 340 } 341 } 342 343 if (jtitle != NULL) { 344 (*env)->ReleaseStringUTFChars(env, jtitle, title); 345 } 346 347 /* Set the directory */ 348 if (jdir != NULL) { 349 const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); 350 if (dir == NULL) { 351 (*env)->ExceptionClear(env); 352 JNU_ThrowOutOfMemoryError(env, "Could not get dir"); 353 return; 354 } 355 fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); 356 (*env)->ReleaseStringUTFChars(env, jdir, dir); 357 } 358 359 /* Set the filename */ 360 if (jfile != NULL) { 361 const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); 362 if (filename == NULL) { 363 (*env)->ExceptionClear(env); 364 JNU_ThrowOutOfMemoryError(env, "Could not get filename"); 365 return; 366 } 367 if (mode == java_awt_FileDialog_SAVE) { 368 fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); 369 } else { 370 fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); 371 } 372 (*env)->ReleaseStringUTFChars(env, jfile, filename); 373 } 374 375 /* Set the file filter */ 376 if (jfilter != NULL) { 377 filter = fp_gtk_file_filter_new(); 378 fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, 379 filenameFilterCallback, jpeer, NULL); 380 fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); 381 } 382 383 /* Other Properties */ 384 if (fp_gtk_check_version(2, 8, 0) == NULL) { 385 fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( 386 dialog), TRUE); 387 } 388 389 /* Set the initial location */ 390 if (x >= 0 && y >= 0) { 391 fp_gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); 392 393 // NOTE: it doesn't set the initial size for the file chooser 394 // as it seems like the file chooser overrides the size internally 395 } 396 397 fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( 398 handle_response), jpeer); 399 400 (*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog)); 401 402 fp_gtk_widget_show(dialog); 403 404 fp_gtk_main(); 405 fp_gdk_threads_leave(); 406 } 407 | 1 /* 2 * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <jni.h> 27 #include <stdio.h> 28 #include <jni_util.h> 29 #include <string.h> 30 #include "gtk_interface.h" 31 #include "sun_awt_X11_GtkFileDialogPeer.h" 32 #include "java_awt_FileDialog.h" 33 #include "debug_assert.h" 34 35 typedef void GtkWidget; 36 static JavaVM *jvm; 37 38 /* To cache some method IDs */ 39 static jmethodID filenameFilterCallbackMethodID = NULL; 40 static jmethodID setFileInternalMethodID = NULL; 41 static jfieldID widgetFieldID = NULL; 42 43 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_initIDs 44 (JNIEnv *env, jclass cx) 45 { 46 filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, 47 "filenameFilterCallback", "(Ljava/lang/String;)Z"); 48 DASSERT(filenameFilterCallbackMethodID != NULL); 49 CHECK_NULL(filenameFilterCallbackMethodID); 50 51 setFileInternalMethodID = (*env)->GetMethodID(env, cx, 52 "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); 53 DASSERT(setFileInternalMethodID != NULL); 54 CHECK_NULL(setFileInternalMethodID); 55 68 JNU_CHECK_EXCEPTION_RETURN(env, FALSE); 69 70 return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, 71 filename); 72 } 73 74 static void quit(JNIEnv * env, jobject jpeer, gboolean isSignalHandler) 75 { 76 jthrowable pendingException; 77 if (pendingException = (*env)->ExceptionOccurred(env)) { 78 (*env)->ExceptionClear(env); 79 } 80 81 GtkWidget * dialog = (GtkWidget*)jlong_to_ptr( 82 (*env)->GetLongField(env, jpeer, widgetFieldID)); 83 84 if (dialog != NULL) 85 { 86 // Callbacks from GTK signals are made within the GTK lock 87 // So, within a signal handler there is no need to call 88 // gdk_threads_enter() / gtk->gdk_threads_leave() 89 if (!isSignalHandler) { 90 gtk->gdk_threads_enter(); 91 } 92 93 gtk->gtk_widget_hide (dialog); 94 gtk->gtk_widget_destroy (dialog); 95 96 gtk->gtk_main_quit (); 97 98 (*env)->SetLongField(env, jpeer, widgetFieldID, 0); 99 100 if (!isSignalHandler) { 101 gtk->gdk_threads_leave(); 102 } 103 } 104 105 if (pendingException) { 106 (*env)->Throw(env, pendingException); 107 } 108 } 109 110 /* 111 * Class: sun_awt_X11_GtkFileDialogPeer 112 * Method: quit 113 * Signature: ()V 114 */ 115 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit 116 (JNIEnv * env, jobject jpeer) 117 { 118 quit(env, jpeer, FALSE); 119 } 120 121 /* 122 * Class: sun_awt_X11_GtkFileDialogPeer 123 * Method: toFront 124 * Signature: ()V 125 */ 126 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_toFront 127 (JNIEnv * env, jobject jpeer) 128 { 129 GtkWidget * dialog; 130 131 gtk->gdk_threads_enter(); 132 133 dialog = (GtkWidget*)jlong_to_ptr( 134 (*env)->GetLongField(env, jpeer, widgetFieldID)); 135 136 if (dialog != NULL) { 137 gtk->gtk_window_present((GtkWindow*)dialog); 138 } 139 140 gtk->gdk_threads_leave(); 141 } 142 143 /* 144 * Class: sun_awt_X11_GtkFileDialogPeer 145 * Method: setBounds 146 * Signature: (IIIII)V 147 */ 148 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_setBounds 149 (JNIEnv * env, jobject jpeer, jint x, jint y, jint width, jint height, jint op) 150 { 151 GtkWindow* dialog; 152 153 gtk->gdk_threads_enter(); 154 155 dialog = (GtkWindow*)jlong_to_ptr( 156 (*env)->GetLongField(env, jpeer, widgetFieldID)); 157 158 if (dialog != NULL) { 159 if (x >= 0 && y >= 0) { 160 gtk->gtk_window_move(dialog, (gint)x, (gint)y); 161 } 162 if (width > 0 && height > 0) { 163 gtk->gtk_window_resize(dialog, (gint)width, (gint)height); 164 } 165 } 166 167 gtk->gdk_threads_leave(); 168 } 169 170 /* 171 * baseDir should be freed by user. 172 */ 173 static gboolean isFromSameDirectory(GSList* list, gchar** baseDir) { 174 175 GSList *it = list; 176 gchar* prevDir = NULL; 177 gboolean isAllDirsSame = TRUE; 178 179 while (it) { 180 gchar* dir = gtk->g_path_get_dirname((gchar*) it->data); 181 182 if (prevDir && strcmp(prevDir, dir) != 0) { 183 isAllDirsSame = FALSE; 184 gtk->g_free(dir); 185 break; 186 } 187 188 if (!prevDir) { 189 prevDir = strdup(dir); 190 } 191 gtk->g_free(dir); 192 193 it = it->next; 194 } 195 196 if (isAllDirsSame) { 197 *baseDir = prevDir; 198 } else { 199 free(prevDir); 200 *baseDir = strdup("/"); 201 } 202 203 return isAllDirsSame; 204 } 205 206 /** 207 * Convert a GSList to an array of filenames 208 */ 209 static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list, jstring* jcurrent_folder) 210 { 211 jstring str; 212 jclass stringCls; 213 GSList *iterator; 214 jobjectArray array; 215 int i; 216 gchar* entry; 217 gchar * baseDir; 218 gboolean isFromSameDir; 219 220 if (list == NULL) { 221 return NULL; 222 } 223 224 stringCls = (*env)->FindClass(env, "java/lang/String"); 225 if (stringCls == NULL) { 226 (*env)->ExceptionClear(env); 227 JNU_ThrowInternalError(env, "Could not get java.lang.String class"); 228 return NULL; 229 } 230 231 array = (*env)->NewObjectArray(env, gtk->gtk_g_slist_length(list), stringCls, NULL); 232 if (array == NULL) { 233 (*env)->ExceptionClear(env); 234 JNU_ThrowInternalError(env, "Could not instantiate array files array"); 235 return NULL; 236 } 237 238 isFromSameDir = isFromSameDirectory(list, &baseDir); 239 240 *jcurrent_folder = (*env)->NewStringUTF(env, baseDir); 241 if (*jcurrent_folder == NULL) { 242 free(baseDir); 243 return NULL; 244 } 245 246 for (iterator = list, i=0; 247 iterator; 248 iterator = iterator->next, i++) { 249 250 entry = (gchar*) iterator->data; 251 265 break; 266 } 267 } 268 } 269 270 free(baseDir); 271 return array; 272 } 273 274 static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) 275 { 276 JNIEnv *env; 277 GSList *filenames; 278 jstring jcurrent_folder = NULL; 279 jobjectArray jfilenames; 280 281 env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); 282 filenames = NULL; 283 284 if (responseId == GTK_RESPONSE_ACCEPT) { 285 filenames = gtk->gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); 286 } 287 288 jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder); 289 290 if (!(*env)->ExceptionCheck(env)) { 291 (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, 292 jcurrent_folder, jfilenames); 293 } 294 295 quit(env, (jobject)obj, TRUE); 296 } 297 298 /* 299 * Class: sun_awt_X11_GtkFileDialogPeer 300 * Method: run 301 * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;ZII)V 302 */ 303 JNIEXPORT void JNICALL 304 Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, 305 jstring jtitle, jint mode, jstring jdir, jstring jfile, 306 jobject jfilter, jboolean multiple, int x, int y) 307 { 308 GtkWidget *dialog = NULL; 309 GtkFileFilter *filter; 310 311 if (jvm == NULL) { 312 (*env)->GetJavaVM(env, &jvm); 313 JNU_CHECK_EXCEPTION(env); 314 } 315 316 gtk->gdk_threads_enter(); 317 318 const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); 319 if (title == NULL) { 320 (*env)->ExceptionClear(env); 321 JNU_ThrowOutOfMemoryError(env, "Could not get title"); 322 return; 323 } 324 325 if (mode == java_awt_FileDialog_SAVE) { 326 /* Save action */ 327 dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, 328 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, 329 GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); 330 } 331 else { 332 /* Default action OPEN */ 333 dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, 334 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, 335 GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); 336 337 /* Set multiple selection mode, that is allowed only in OPEN action */ 338 if (multiple) { 339 gtk->gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), 340 multiple); 341 } 342 } 343 344 if (jtitle != NULL) { 345 (*env)->ReleaseStringUTFChars(env, jtitle, title); 346 } 347 348 /* Set the directory */ 349 if (jdir != NULL) { 350 const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); 351 if (dir == NULL) { 352 (*env)->ExceptionClear(env); 353 JNU_ThrowOutOfMemoryError(env, "Could not get dir"); 354 return; 355 } 356 gtk->gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); 357 (*env)->ReleaseStringUTFChars(env, jdir, dir); 358 } 359 360 /* Set the filename */ 361 if (jfile != NULL) { 362 const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); 363 if (filename == NULL) { 364 (*env)->ExceptionClear(env); 365 JNU_ThrowOutOfMemoryError(env, "Could not get filename"); 366 return; 367 } 368 if (mode == java_awt_FileDialog_SAVE) { 369 gtk->gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); 370 } else { 371 gtk->gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); 372 } 373 (*env)->ReleaseStringUTFChars(env, jfile, filename); 374 } 375 376 /* Set the file filter */ 377 if (jfilter != NULL) { 378 filter = gtk->gtk_file_filter_new(); 379 gtk->gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, 380 filenameFilterCallback, jpeer, NULL); 381 gtk->gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); 382 } 383 384 /* Other Properties */ 385 if (gtk->gtk_check_version(2, 8, 0) == NULL || 386 gtk->gtk_check_version(3, 0, 0) == NULL) { 387 gtk->gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( 388 dialog), TRUE); 389 } 390 391 /* Set the initial location */ 392 if (x >= 0 && y >= 0) { 393 gtk->gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); 394 395 // NOTE: it doesn't set the initial size for the file chooser 396 // as it seems like the file chooser overrides the size internally 397 } 398 399 gtk->g_signal_connect_data(dialog, "response", G_CALLBACK( 400 handle_response), jpeer, 0, 0); 401 402 (*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog)); 403 404 gtk->gtk_widget_show(dialog); 405 406 gtk->gtk_main(); 407 gtk->gdk_threads_leave(); 408 } 409 |