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