OSDN Git Service

* gnu/java/awt/peer/gtk/GtkFileDialogPeer.java (nativeSetFile):
authorfnasser <fnasser@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Jan 2004 21:12:25 +0000 (21:12 +0000)
committerfnasser <fnasser@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Jan 2004 21:12:25 +0000 (21:12 +0000)
        New name for the former setFile native method.
        (setFile): New method.
        (setDirectory): Implemented.
        (connectSignals): New native method.
        (setFilenameFilter): Improve comment.
        (getGraphics): Comment.
        (gtkHideFileDialog): New method.
        (gtkDisposeFileDialog): New method.
        (gtkSetFilename): New method.
        * java/awt/Dialog.java (show): Block on modal dialogs, but only
        for FileDialog for now.
        (hide): New method.
        (dispose): New method.
        * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
        (Java_gnu_java_awt_peer_gtk_GtkFileDialog_create): Replace
        deprecated creation functions.  Make dialog modal.  Add it to the
        window group.
        (Java_gnu_java_awt_peer_gtk_GtkFileDialog_connectSignals): New
        function.
        (Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_gtkFileSelectionSetFilename):
        Rename to...
        (Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile): New
        name.
        (window_closed): New function.
        (ok_clicked): New function.
        (cancel_clicked): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75557 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
libjava/java/awt/Dialog.java
libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c

index 17c82cd..9434734 100644 (file)
@@ -1,3 +1,33 @@
+2004-01-08  Fernando Nasser  <fnasser@redhat.com>
+
+       * gnu/java/awt/peer/gtk/GtkFileDialogPeer.java (nativeSetFile):
+       New name for the former setFile native method.
+       (setFile): New method.
+       (setDirectory): Implemented.
+       (connectSignals): New native method.
+       (setFilenameFilter): Improve comment.
+       (getGraphics): Comment.
+       (gtkHideFileDialog): New method.
+       (gtkDisposeFileDialog): New method.
+       (gtkSetFilename): New method.
+       * java/awt/Dialog.java (show): Block on modal dialogs, but only
+       for FileDialog for now.
+       (hide): New method.
+       (dispose): New method.
+       * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
+       (Java_gnu_java_awt_peer_gtk_GtkFileDialog_create): Replace
+       deprecated creation functions.  Make dialog modal.  Add it to the
+       window group.
+       (Java_gnu_java_awt_peer_gtk_GtkFileDialog_connectSignals): New
+       function.
+       (Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_gtkFileSelectionSetFilename):
+       Rename to...
+       (Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile): New
+       name.
+       (window_closed): New function.
+       (ok_clicked): New function.
+       (cancel_clicked): New function.
+
 2004-01-08  Michael Koch  <konqueror@gmx.de>
 
        * javax/swing/JLayeredPane.java: Revert changes to standard
index 07422ac..dc2c8b0 100644 (file)
@@ -38,13 +38,21 @@ exception statement from your version. */
 
 package gnu.java.awt.peer.gtk;
 
+import java.awt.AWTEvent;
+import java.awt.Dialog;
 import java.awt.FileDialog;
 import java.awt.Graphics;
+import java.awt.event.WindowEvent;
 import java.awt.peer.FileDialogPeer;
 import java.io.FilenameFilter;
 
 public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
 {
+  static final String FS = System.getProperty("file.separator");
+  
+  private String currentFile = null;
+  private String currentDirectory = null;
+
   native void create ();
 
   public GtkFileDialogPeer (FileDialog fd)
@@ -52,21 +60,134 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
     super (fd);
   }
 
-  public void setDirectory (String directory)
+  native void connectJObject ();
+  native void connectSignals ();
+  native void nativeSetFile (String file);
+
+  public void setFile (String fileName)
   {
-    setFile (directory);
+    /* If nothing changed do nothing.  This usually happens because
+       the only way we have to set the file name in FileDialog is by
+       calling its SetFile which will call us back. */
+    if ((fileName == null && currentFile == null)
+        || (fileName != null && fileName.equals (currentFile)))
+      return;
+
+    if (fileName == null || fileName.equals (""))
+      {
+        currentFile = "";
+        nativeSetFile ("");
+        return;
+      }
+
+    // Remove any directory path from the filename
+    int sepIndex = fileName.lastIndexOf (FS);
+    if (sepIndex < 0)
+      {
+        currentFile = fileName;
+        nativeSetFile (fileName);
+      }
+    else
+      {
+        if (fileName.length() > (sepIndex + 1))
+         {
+           String fn = fileName.substring (sepIndex + 1);
+            currentFile = fn;
+            nativeSetFile (fn);
+         }
+       else
+         {
+            currentFile = "";
+            nativeSetFile ("");
+         }
+      }
   }
 
-  public native void setFile (String file);
-  public native void connectJObject ();
+  public void setDirectory (String directory)
+  {
+    /* If nothing changed so nothing.  This usually happens because
+       the only way we have to set the directory in FileDialog is by
+       calling its setDirectory which will call us back. */
+    if ((directory == null && currentDirectory == null)
+        || (directory != null && directory.equals (currentDirectory)))
+      return;
+
+    if (directory == null || directory.equals (""))
+      {
+        currentDirectory = FS;
+        nativeSetFile (FS);
+       return;
+      }
+      
+    currentDirectory = directory;
+
+    // Gtk expects the directory to end with a file separator
+    if (directory.substring (directory.length () - 1).equals (FS))
+      nativeSetFile (directory);
+    else
+      nativeSetFile (directory + FS);
+  }
 
   public void setFilenameFilter (FilenameFilter filter)
   {
-    /* GTK has no filters. */
+    /* GTK has no filter callbacks yet.  It works by setting a pattern
+     * (see gtk_file_selection_complete), which we can't convert
+     * to the callback paradigm. With GTK-2.4 there will be a
+     * gtk_file_filter_add_custom function that we can use. */
   }
 
   public Graphics getGraphics ()
   {
+    // GtkFileDialog will repaint by itself
     return null;
   }
+  
+  void gtkHideFileDialog () 
+  {
+    ((Dialog) awtComponent).hide();
+  }
+  
+  void gtkDisposeFileDialog () 
+  {
+    ((Dialog) awtComponent).dispose();
+  }
+
+  /* Callback to set the file and directory values when the user is finished
+   * with the dialog.
+   */
+  void gtkSetFilename (String fileName)
+  {
+    FileDialog fd = (FileDialog) awtWidget;
+    if (fileName == null)
+      {
+        currentFile = null;
+        fd.setFile(null);
+        return;
+      }
+
+    int sepIndex = fileName.lastIndexOf (FS);
+    if (sepIndex < 0)
+      {
+        /* This should never happen on Unix (all paths start with '/') */
+       currentFile = fileName;
+      }
+    else
+      {
+        if (fileName.length() > (sepIndex + 1))
+         {
+           String fn = fileName.substring (sepIndex + 1);
+           currentFile = fn;
+         }
+       else
+         {
+            currentFile = null;
+         }
+
+        String dn = fileName.substring (0, sepIndex + 1);
+        currentDirectory = dn;
+        fd.setDirectory(dn);
+      }
+
+    fd.setFile (currentFile);
+  }
 }
index ac2e6ed..fd1eb4f 100644 (file)
@@ -78,10 +78,15 @@ private boolean resizable = true;
   */
 private String title;
 
-  /**
-   * This field indicates whether the dialog is undecorated or not.
-   */
-  private boolean undecorated = false;
+/**
+  * This field indicates whether the dialog is undecorated or not.
+  */
+private boolean undecorated = false;
+
+/**
+  * Indicates that we are blocked for modality in show
+  */
+private boolean blocked = false;
 
 /*************************************************************************/
 
@@ -380,11 +385,78 @@ addNotify()
 
 /**
   * Makes this dialog visible and brings it to the front.
+  * If the dialog is modal and is not already visible, this call will not
+  *  return until the dialog is hidden by someone calling hide or dispose.
+  * If this is the event dispatching thread we must ensure that another event
+  *  thread runs while the one which invoked this method is blocked. 
   */
-public void
+public synchronized void
 show()
 {
   super.show();
+  if (isModal())
+    {
+      // If already shown (and blocked) just return
+      if (blocked)
+       return;
+
+      /* FIXME: Currently this thread may block forever if it called from
+         the event dispatch thread, so we only do this for FileDialog which
+         only depends on a signal which is delivered in the Gtk thread.
+         Remove this test when we add code to start another event
+         dispatch thread. */
+      if ((Thread.currentThread () instanceof EventDispatchThread) &&
+          !(this instanceof FileDialog))
+        return;
+      
+      try 
+        {
+         blocked = true;
+         wait ();
+         blocked = false;
+        } 
+      catch (InterruptedException e)
+        {
+         blocked = false;
+         return;
+        }
+    }  
+}
+
+/*************************************************************************/
+
+/**
+  * Hides the Dialog and then
+  * causes show() to return if it is currently blocked.
+  */
+
+public synchronized void 
+hide ()
+{
+  if (blocked)
+    {
+      notifyAll ();
+    }
+
+  super.hide();
+}
+
+/*************************************************************************/
+
+/**
+  * Disposes the Dialog and then causes show() to return
+  * if it is currently blocked.
+  */
+
+public synchronized void 
+dispose ()
+{
+  if (blocked)
+    {
+      notifyAll ();
+    }
+
+  super.dispose();
 }
 
 /*************************************************************************/
index 47a08ae..9e84dde 100644 (file)
@@ -37,8 +37,17 @@ exception statement from your version. */
 
 
 #include "gtkpeer.h"
+#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
 #include "gnu_java_awt_peer_gtk_GtkFileDialogPeer.h"
 
+static void window_closed (GtkDialog *dialog,
+                           gint responseId,
+                           jobject peer_obj);
+static void ok_clicked (GtkButton *button,
+                       jobject peer_obj);
+static void cancel_clicked (GtkButton *button,
+                           jobject peer_obj);
+
 /*
  * Make a new file selection dialog
  */
@@ -54,7 +63,13 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_create
 
   gdk_threads_enter ();
   
-  widget = gtk_type_new (gtk_file_selection_get_type ());
+  widget = gtk_file_selection_new ("");
+  /* GtkFileSelect is not modal by default */
+  gtk_window_set_modal (GTK_WINDOW (widget), TRUE);
+
+  /* We must add this window to the group so input in the others are
+     disable while it is being shown */
+  gtk_window_group_add_window (global_gtk_window_group, GTK_WINDOW (widget));
 
   gdk_threads_leave ();
 
@@ -76,12 +91,44 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_connectJObject
   gdk_threads_leave ();
 }
 
+JNIEXPORT void JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_connectSignals
+  (JNIEnv *env, jobject obj)
+{
+  void *ptr = NSA_GET_PTR (env, obj);
+  jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
+  g_assert (gref);
+
+  gdk_threads_enter ();
+
+  gtk_widget_realize (GTK_WIDGET (ptr));
+
+  /* connect buttons to handlers */
+
+  g_signal_connect (G_OBJECT (GTK_DIALOG (ptr)),
+                    "response", 
+                   GTK_SIGNAL_FUNC (window_closed), *gref);
+
+  g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (ptr)->ok_button),
+                    "clicked", 
+                   GTK_SIGNAL_FUNC (ok_clicked), *gref);
+
+  g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (ptr)->cancel_button),
+                    "clicked", 
+                   GTK_SIGNAL_FUNC (cancel_clicked), *gref);
+                   
+  gdk_threads_leave ();
+
+  /* Connect the superclass signals.  */
+  Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, obj);
+}
+
 /*
  * Set the filename in the file selection dialog.
  */
 
 JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_gtkFileSelectionSetFilenam
+Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFil
     (JNIEnv *env, jobject obj, jstring filename)
 {
   void *ptr;
@@ -89,9 +136,112 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_gtkFileSelectionSetFilename
 
   ptr = NSA_GET_PTR (env, obj);
     
-  str = (*env)->GetStringUTFChars (env, filename, 0);      
+  str = (*env)->GetStringUTFChars (env, filename, 0);
+     
   gdk_threads_enter ();
+
   gtk_file_selection_set_filename (GTK_FILE_SELECTION (ptr), str);
+
   gdk_threads_leave ();
+
   (*env)->ReleaseStringUTFChars (env, filename, str);
 }
+
+static void
+window_closed (GtkDialog *dialog __attribute__((unused)),
+               gint responseId,
+               jobject peer_obj)
+{
+  static int isIDSet = 0;
+  static jmethodID disposeID;
+  void *ptr;
+
+  // We only need this for the case when the user closed the window
+  if (responseId != GTK_RESPONSE_DELETE_EVENT)
+    return;
+
+  ptr = NSA_GET_PTR (gdk_env, peer_obj);
+  
+  if (!isIDSet)
+    {
+      jclass cx = (*gdk_env)->GetObjectClass (gdk_env, peer_obj);
+      disposeID = (*gdk_env)->GetMethodID (gdk_env, cx, "gtkDisposeFileDialog", "()V");
+      isIDSet = 1;
+    }
+    
+  gdk_threads_leave ();
+
+  /* We can dispose of the dialog now (and unblock show) */
+  (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, disposeID);
+
+  gdk_threads_enter ();
+}
+
+static void
+ok_clicked (GtkButton *button __attribute__((unused)),
+                       jobject peer_obj)
+{
+  static int isIDSet = 0;
+  static jmethodID gtkSetFilenameID;
+  static jmethodID hideID;
+  void *ptr;
+  G_CONST_RETURN gchar *fileName;
+
+  ptr = NSA_GET_PTR (gdk_env, peer_obj);
+  
+  fileName = gtk_file_selection_get_filename (
+               GTK_FILE_SELECTION (GTK_WIDGET (ptr)));
+  
+  if (!isIDSet)
+    {
+      jclass cx = (*gdk_env)->GetObjectClass (gdk_env, peer_obj);
+      hideID = (*gdk_env)->GetMethodID (gdk_env, cx, "gtkHideFileDialog", "()V");
+      gtkSetFilenameID = (*gdk_env)->GetMethodID (gdk_env, cx,
+                                   "gtkSetFilename", "(Ljava.lang.String;)V");
+      isIDSet = 1;
+    }
+    
+  gdk_threads_leave ();
+  
+  /* Set the Java object field 'file' with this value. */
+  jstring str_fileName = (*gdk_env)->NewStringUTF (gdk_env, fileName);
+  (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, gtkSetFilenameID, str_fileName);
+
+  /* We can hide the dialog now (and unblock show) */
+  (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, hideID);
+
+  gdk_threads_enter ();
+}
+
+static void
+cancel_clicked (GtkButton *button __attribute__((unused)),
+                           jobject peer_obj)
+{
+  static int isIDSet = 0;
+  static jmethodID gtkSetFilenameID;
+  static jmethodID hideID;
+  void *ptr;
+
+  ptr = NSA_GET_PTR (gdk_env, peer_obj);
+  
+  if (!isIDSet)
+    {
+      jclass cx = (*gdk_env)->GetObjectClass (gdk_env, peer_obj);
+      hideID = (*gdk_env)->GetMethodID (gdk_env, cx, "gtkHideFileDialog", "()V");
+      gtkSetFilenameID = (*gdk_env)->GetMethodID (gdk_env, cx,
+                                   "gtkSetFilename", "(Ljava.lang.String;)V");
+      isIDSet = 1;
+    }
+    
+  gdk_threads_leave ();
+
+  /* Set the Java object field 'file' with the null value. */
+  (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, gtkSetFilenameID, NULL);
+
+  /* We can hide the dialog now (and unblock show) */
+  (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, hideID);
+
+  gdk_threads_enter ();
+}
+
+