1 #include <jni.h> 2 #include <stdio.h> 3 #include <jni_util.h> 4 #include <string.h> 5 #include "gtk2_interface.h" 6 #include "sun_awt_X11_GtkFileDialogPeer.h" 7 8 static JavaVM *jvm; 9 static GtkWidget *dialog = NULL; 10 11 /* To cache some method IDs */ 12 static jmethodID filenameFilterCallbackMethodID = NULL; 13 static jmethodID setFileInternalMethodID = NULL; 14 15 static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gpointer obj) 16 { 17 JNIEnv *env; 18 jclass cx; 19 jstring filename; 20 21 env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); 22 23 if (filenameFilterCallbackMethodID == NULL) { 24 cx = (*env)->GetObjectClass(env, (jobject) obj); 25 if (cx == NULL) { 26 JNU_ThrowInternalError(env, "Could not get file filter class"); 27 return 0; 28 } 29 30 filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, 31 "filenameFilterCallback", "(Ljava/lang/String;)Z"); 32 if (filenameFilterCallbackMethodID == NULL) { 33 JNU_ThrowInternalError(env, 34 "Could not get filenameFilterCallback method id"); 35 return 0; 36 } 37 } 38 39 filename = (*env)->NewStringUTF(env, filter_info->filename); 40 41 return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, 42 filename); 43 } 44 45 /* 46 * Class: sun_awt_X11_GtkFileDialogPeer 47 * Method: quit 48 * Signature: ()V 49 */ 50 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit 51 (JNIEnv * env, jobject jpeer) 52 { 53 if (dialog != NULL) 54 { 55 fp_gtk_widget_hide (dialog); 56 fp_gtk_widget_destroy (dialog); 57 58 fp_gtk_main_quit (); 59 dialog = NULL; 60 } 61 } 62 63 /** 64 * Convert a GSList to an array of filenames (without the parent folder) 65 */ 66 static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list) 67 { 68 jstring str; 69 jclass stringCls; 70 GSList *iterator; 71 jobjectArray array; 72 int i; 73 char* entry; 74 75 if (NULL == list) { 76 return NULL; 77 } 78 79 stringCls = (*env)->FindClass(env, "java/lang/String"); 80 if (stringCls == NULL) { 81 JNU_ThrowInternalError(env, "Could not get java.lang.String class"); 82 return NULL; 83 } 84 85 array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, 86 NULL); 87 if (array == NULL) { 88 JNU_ThrowInternalError(env, "Could not instantiate array files array"); 89 return NULL; 90 } 91 92 i = 0; 93 for (iterator = list; iterator; iterator = iterator->next) { 94 entry = (char*) iterator->data; 95 entry = strrchr(entry, '/') + 1; 96 str = (*env)->NewStringUTF(env, entry); 97 (*env)->SetObjectArrayElement(env, array, i, str); 98 i++; 99 } 100 101 return array; 102 } 103 104 static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) 105 { 106 JNIEnv *env; 107 char *current_folder; 108 GSList *filenames; 109 jclass cx; 110 jstring jcurrent_folder; 111 jobjectArray jfilenames; 112 113 env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); 114 current_folder = NULL; 115 filenames = NULL; 116 117 if (responseId == GTK_RESPONSE_ACCEPT) { 118 current_folder = fp_gtk_file_chooser_get_current_folder( 119 GTK_FILE_CHOOSER(dialog)); 120 filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); 121 } 122 123 if (setFileInternalMethodID == NULL) { 124 cx = (*env)->GetObjectClass(env, (jobject) obj); 125 if (cx == NULL) { 126 JNU_ThrowInternalError(env, "Could not get GTK peer class"); 127 return; 128 } 129 130 setFileInternalMethodID = (*env)->GetMethodID(env, cx, 131 "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); 132 if (setFileInternalMethodID == NULL) { 133 JNU_ThrowInternalError(env, 134 "Could not get setFileInternalMethodID method id"); 135 return; 136 } 137 } 138 139 jcurrent_folder = (*env)->NewStringUTF(env, current_folder); 140 jfilenames = toFilenamesArray(env, filenames); 141 142 (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, jcurrent_folder, 143 jfilenames); 144 fp_g_free(current_folder); 145 146 Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL); 147 } 148 149 /* 150 * Class: sun_awt_X11_GtkFileDialogPeer 151 * Method: run 152 * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;Z;)V 153 */ 154 JNIEXPORT void JNICALL 155 Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, 156 jstring jtitle, jint mode, jstring jdir, jstring jfile, 157 jobject jfilter, jboolean multiple) 158 { 159 GtkFileFilter *filter; 160 161 if (jvm == NULL) { 162 (*env)->GetJavaVM(env, &jvm); 163 } 164 165 fp_gdk_threads_init(); 166 fp_gdk_threads_enter(); 167 168 const char *title = (*env)->GetStringUTFChars(env, jtitle, 0); 169 170 if (mode == 1) { 171 /* Save action */ 172 dialog = fp_gtk_file_chooser_dialog_new(title, NULL, 173 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, 174 GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); 175 } 176 else { 177 /* Default action OPEN */ 178 dialog = fp_gtk_file_chooser_dialog_new(title, NULL, 179 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, 180 GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); 181 182 /* Set multiple selection mode, that is allowed only in OPEN action */ 183 if (multiple) { 184 fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), 185 multiple); 186 } 187 } 188 189 (*env)->ReleaseStringUTFChars(env, jtitle, title); 190 191 /* Set the directory */ 192 if (jdir != NULL) { 193 const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); 194 fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); 195 (*env)->ReleaseStringUTFChars(env, jdir, dir); 196 } 197 198 /* Set the filename */ 199 if (jfile != NULL) { 200 const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); 201 fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); 202 (*env)->ReleaseStringUTFChars(env, jfile, filename); 203 } 204 205 /* Set the file filter */ 206 if (jfilter != NULL) { 207 filter = fp_gtk_file_filter_new(); 208 fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, 209 filenameFilterCallback, jpeer, NULL); 210 fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); 211 } 212 213 /* Other Properties */ 214 if (fp_gtk_check_version(2, 8, 0) == NULL) { 215 fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( 216 dialog), TRUE); 217 } 218 219 fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( 220 handle_response), jpeer); 221 fp_gtk_widget_show(dialog); 222 223 fp_gtk_main(); 224 fp_gdk_threads_leave(); 225 }