--- /dev/null 2010-02-27 20:37:15.841007123 +0300 +++ new/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c 2010-04-16 18:28:14.000000000 +0400 @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include "gtk2_interface.h" +#include "sun_awt_X11_GtkFileDialogPeer.h" + +static JavaVM *jvm; +static GtkWidget *dialog = NULL; + +/* To cache some method IDs */ +static jmethodID filenameFilterCallbackMethodID = NULL; +static jmethodID setFileInternalMethodID = NULL; + +static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gpointer obj) +{ + JNIEnv *env; + jclass cx; + jstring filename; + + env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + + if (filenameFilterCallbackMethodID == NULL) { + cx = (*env)->GetObjectClass(env, (jobject) obj); + if (cx == NULL) { + JNU_ThrowInternalError(env, "Could not get file filter class"); + return 0; + } + + filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, + "filenameFilterCallback", "(Ljava/lang/String;)Z"); + if (filenameFilterCallbackMethodID == NULL) { + JNU_ThrowInternalError(env, + "Could not get filenameFilterCallback method id"); + return 0; + } + } + + filename = (*env)->NewStringUTF(env, filter_info->filename); + + return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, + filename); +} + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: quit + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit +(JNIEnv * env, jobject jpeer) +{ + if (dialog != NULL) + { + fp_gtk_widget_hide (dialog); + fp_gtk_widget_destroy (dialog); + + fp_gtk_main_quit (); + dialog = NULL; + } +} + +/** + * Convert a GSList to an array of filenames (without the parent folder) + */ +static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list) +{ + jstring str; + jclass stringCls; + GSList *iterator; + jobjectArray array; + int i; + char* entry; + + if (NULL == list) { + return NULL; + } + + stringCls = (*env)->FindClass(env, "java/lang/String"); + if (stringCls == NULL) { + JNU_ThrowInternalError(env, "Could not get java.lang.String class"); + return NULL; + } + + array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, + NULL); + if (array == NULL) { + JNU_ThrowInternalError(env, "Could not instantiate array files array"); + return NULL; + } + + i = 0; + for (iterator = list; iterator; iterator = iterator->next) { + entry = (char*) iterator->data; + entry = strrchr(entry, '/') + 1; + str = (*env)->NewStringUTF(env, entry); + (*env)->SetObjectArrayElement(env, array, i, str); + i++; + } + + return array; +} + +static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) +{ + JNIEnv *env; + char *current_folder; + GSList *filenames; + jclass cx; + jstring jcurrent_folder; + jobjectArray jfilenames; + + env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + current_folder = NULL; + filenames = NULL; + + if (responseId == GTK_RESPONSE_ACCEPT) { + current_folder = fp_gtk_file_chooser_get_current_folder( + GTK_FILE_CHOOSER(dialog)); + filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + } + + if (setFileInternalMethodID == NULL) { + cx = (*env)->GetObjectClass(env, (jobject) obj); + if (cx == NULL) { + JNU_ThrowInternalError(env, "Could not get GTK peer class"); + return; + } + + setFileInternalMethodID = (*env)->GetMethodID(env, cx, + "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); + if (setFileInternalMethodID == NULL) { + JNU_ThrowInternalError(env, + "Could not get setFileInternalMethodID method id"); + return; + } + } + + jcurrent_folder = (*env)->NewStringUTF(env, current_folder); + jfilenames = toFilenamesArray(env, filenames); + + (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, jcurrent_folder, + jfilenames); + fp_g_free(current_folder); + + Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL); +} + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: run + * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;Z;)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, + jstring jtitle, jint mode, jstring jdir, jstring jfile, + jobject jfilter, jboolean multiple) +{ + GtkFileFilter *filter; + + if (jvm == NULL) { + (*env)->GetJavaVM(env, &jvm); + } + + fp_gdk_threads_init(); + fp_gdk_threads_enter(); + + const char *title = (*env)->GetStringUTFChars(env, jtitle, 0); + + if (mode == 1) { + /* Save action */ + dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + } + else { + /* Default action OPEN */ + dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + + /* Set multiple selection mode, that is allowed only in OPEN action */ + if (multiple) { + fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), + multiple); + } + } + + (*env)->ReleaseStringUTFChars(env, jtitle, title); + + /* Set the directory */ + if (jdir != NULL) { + const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); + fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); + (*env)->ReleaseStringUTFChars(env, jdir, dir); + } + + /* Set the filename */ + if (jfile != NULL) { + const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); + fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); + (*env)->ReleaseStringUTFChars(env, jfile, filename); + } + + /* Set the file filter */ + if (jfilter != NULL) { + filter = fp_gtk_file_filter_new(); + fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + filenameFilterCallback, jpeer, NULL); + fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + } + + /* Other Properties */ + if (fp_gtk_check_version(2, 8, 0) == NULL) { + fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( + dialog), TRUE); + } + + fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( + handle_response), jpeer); + fp_gtk_widget_show(dialog); + + fp_gtk_main(); + fp_gdk_threads_leave(); +}