diff --git a/src/share/classes/java/awt/FileDialog.java b/src/share/classes/java/awt/FileDialog.java
index 973ba4e16ee2f07cbb7565b15ebecdb13489ab12..34cd2f8179a372a708b22b57e13309d8f1b7f700 100644
--- a/src/share/classes/java/awt/FileDialog.java
+++ b/src/share/classes/java/awt/FileDialog.java
@@ -28,6 +28,8 @@ import java.awt.peer.FileDialogPeer;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.File;
+import sun.awt.AWTAccessor;
/**
* The FileDialog
class displays a dialog window
@@ -93,6 +95,25 @@ public class FileDialog extends Dialog {
*/
String file;
+ /**
+ * Contains the File instances for all the files that the user selects.
+ *
+ * @serial
+ * @see getFiles
+ * @since 1.7
+ */
+ private File[] files;
+
+ /**
+ * Represents whether the file dialog allows the multiple file selection.
+ *
+ * @serial
+ * @see #setMultipleMode
+ * @see #isMultipleMode
+ * @since 1.7
+ */
+ private boolean multipleMode = false;
+
/*
* The filter used as the file dialog's filename filter.
* The file dialog will only be displaying files whose
@@ -123,6 +144,26 @@ public class FileDialog extends Dialog {
}
}
+ static {
+ AWTAccessor.setFileDialogAccessor(
+ new AWTAccessor.FileDialogAccessor() {
+ public void setFiles(FileDialog fileDialog, String directory, String files[]) {
+ fileDialog.setFiles(directory, files);
+ }
+ public void setFile(FileDialog fileDialog, String file) {
+ fileDialog.file = ("".equals(file)) ? null : file;
+ }
+ public void setDirectory(FileDialog fileDialog, String directory) {
+ fileDialog.dir = ("".equals(directory)) ? null : directory;
+ }
+ public boolean isMultipleMode(FileDialog fileDialog) {
+ synchronized (fileDialog.getObjectLock()) {
+ return fileDialog.multipleMode;
+ }
+ }
+ });
+ }
+
/**
* Initialize JNI field and method IDs for fields that may be
accessed from C.
@@ -370,6 +411,51 @@ public class FileDialog extends Dialog {
return file;
}
+ /**
+ * Returns files that the user selects.
+ *
+ * If the user cancels the file dialog,
+ * then the method returns an empty array.
+ *
+ * @return files that the user selects or an empty array
+ * if the user cancels the file dialog.
+ * @see #setFile(String)
+ * @see #getFile
+ * @since 1.7
+ */
+ public File[] getFiles() {
+ synchronized (getObjectLock()) {
+ if (files != null) {
+ return files.clone();
+ } else {
+ return new File[0];
+ }
+ }
+ }
+
+ /**
+ * Stores the names of all the files that the user selects.
+ *
+ * Note that the method is private and it's intended to be used
+ * by the peers through the AWTAccessor API.
+ *
+ * @param directory the current directory
+ * @param files the array that contains the short names of
+ * all the files that the user selects.
+ *
+ * @see #getFiles
+ * @since 1.7
+ */
+ private void setFiles(String directory, String files[]) {
+ synchronized (getObjectLock()) {
+ int filesNumber = (files != null) ? files.length : 0;
+ this.files = new File[filesNumber];
+ for (int i = 0; i < filesNumber; i++) {
+ this.files[i] = new File(directory, files[i]);
+ }
+ }
+ }
+
/**
* Sets the selected file for this file dialog window to be the
* specified file. This file becomes the default file if it is set
@@ -380,7 +466,8 @@ public class FileDialog extends Dialog {
* as the file.
*
* @param file the file being set
- * @see java.awt.FileDialog#getFile
+ * @see #getFile
+ * @see #getFiles
*/
public void setFile(String file) {
this.file = (file != null && file.equals("")) ? null : file;
@@ -390,6 +477,34 @@ public class FileDialog extends Dialog {
}
}
+ /**
+ * Enables or disables multiple file selection for the file dialog.
+ *
+ * @param enable if {@code true}, multiple file selection is enabled;
+ * {@code false} - disabled.
+ * @see #isMultipleMode
+ * @since 1.7
+ */
+ public void setMultipleMode(boolean enable) {
+ synchronized (getObjectLock()) {
+ this.multipleMode = enable;
+ }
+ }
+
+ /**
+ * Returns whether the file dialog allows the multiple file selection.
+ *
+ * @return {@code true} if the file dialog allows the multiple
+ * file selection; {@code false} otherwise.
+ * @see #setMultipleMode
+ * @since 1.7
+ */
+ public boolean isMultipleMode() {
+ synchronized (getObjectLock()) {
+ return multipleMode;
+ }
+ }
+
/**
* Determines this file dialog's filename filter. A filename filter
* allows the user to specify which files appear in the file dialog
diff --git a/src/share/classes/sun/awt/AWTAccessor.java b/src/share/classes/sun/awt/AWTAccessor.java
index 964e3e0e7ecf1ede260b05cc5a25f5211ced1990..79a75937c253491eef87b0ecc47a2000a29b2184 100644
--- a/src/share/classes/sun/awt/AWTAccessor.java
+++ b/src/share/classes/sun/awt/AWTAccessor.java
@@ -390,6 +390,30 @@ public final class AWTAccessor {
boolean isTrayIconPopup(PopupMenu popupMenu);
}
+ /*
+ * An accessor for the FileDialog class
+ */
+ public interface FileDialogAccessor {
+ /*
+ * Sets the files the user selects
+ */
+ void setFiles(FileDialog fileDialog, String directory, String files[]);
+
+ /*
+ * Sets the file the user selects
+ */
+ void setFile(FileDialog fileDialog, String file);
+
+ /*
+ * Sets the directory the user selects
+ */
+ void setDirectory(FileDialog fileDialog, String directory);
+
+ /*
+ * Returns whether the file dialog allows the multiple file selection.
+ */
+ boolean isMultipleMode(FileDialog fileDialog);
+ }
/*
* The java.awt.Component class accessor object.
@@ -431,6 +455,11 @@ public final class AWTAccessor {
*/
private static PopupMenuAccessor popupMenuAccessor;
+ /*
+ * The java.awt.FileDialog class accessor object.
+ */
+ private static FileDialogAccessor fileDialogAccessor;
+
/*
* Set an accessor object for the java.awt.Component class.
*/
@@ -567,4 +596,22 @@ public final class AWTAccessor {
}
return popupMenuAccessor;
}
+
+ /*
+ * Set an accessor object for the java.awt.FileDialog class.
+ */
+ public static void setFileDialogAccessor(FileDialogAccessor fda) {
+ fileDialogAccessor = fda;
+ }
+
+ /*
+ * Retrieve the accessor object for the java.awt.FileDialog class.
+ */
+ public static FileDialogAccessor getFileDialogAccessor() {
+ if (fileDialogAccessor == null) {
+ unsafe.ensureClassInitialized(FileDialog.class);
+ }
+ return fileDialogAccessor;
+ }
+
}
diff --git a/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java b/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java
index a50437a1ee8bf0ead2d41f20dadc770d8284c2ba..24acdee572103e84ed8371a9800c8179c6f95152 100644
--- a/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java
+++ b/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java
@@ -37,6 +37,7 @@ import javax.swing.plaf.ComponentUI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.util.logging.PlatformLogger;
+import sun.awt.AWTAccessor;
class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XFileDialogPeer");
@@ -171,6 +172,10 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
filterField = new TextField();
selectionField = new TextField();
+ boolean isMultipleMode =
+ AWTAccessor.getFileDialogAccessor().isMultipleMode(target);
+ fileList.setMultipleMode(isMultipleMode);
+
// the insets used by the components in the fileDialog
Insets noInset = new Insets(0, 0, 0, 0);
Insets textFieldInset = new Insets(0, 8, 0, 8);
@@ -380,7 +385,8 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
* handle the selection event
*/
void handleSelection(String file) {
- int index = file.lastIndexOf('/');
+
+ int index = file.lastIndexOf(java.io.File.separatorChar);
if (index == -1) {
savedDir = this.dir;
@@ -389,8 +395,12 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
savedDir = file.substring(0, index+1);
savedFile = file.substring(index+1);
}
- target.setDirectory(savedDir);
- target.setFile(savedFile);
+
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(target, savedDir);
+ fileDialogAccessor.setFile(target, savedFile);
+ fileDialogAccessor.setFiles(target, savedDir, fileList.getSelectedItems());
}
/**
@@ -404,8 +414,13 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
setFilterField(null);
directoryList.clear();
fileList.clear();
- target.setFile(null);
- target.setDirectory(null);
+
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(target, null);
+ fileDialogAccessor.setFile(target, null);
+ fileDialogAccessor.setFiles(target, null, null);
+
handleQuitButton();
}
diff --git a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
index bc4e8470f4c7cdb42ed538c7ff80b66ccddfa012..e5843dda7d5960e60d12dd5e18d8f05c2c8903a4 100644
--- a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
+++ b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java
@@ -117,26 +117,57 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
}
}
- // NOTE: This method is called by privileged threads.
- // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
- void handleSelected(final String file) {
- final FileDialog fileDialog = (FileDialog)target;
- WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
- public void run() {
- int index = file.lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/
- String dir;
+ /*
+ * The function converts the file names (the buffer parameter)
+ * in the Windows format into the Java format and saves the results
+ * into the FileDialog instance.
+ *
+ * If it's the multi-select mode, the buffer contains the current
+ * directory followed by the short names of the files.
+ * The directory and file name strings are NULL separated.
+ * If it's the single-select mode, the buffer doesn't have the NULL
+ * separator between the path and the file name.
+ *
+ * NOTE: This method is called by privileged threads.
+ * DO NOT INVOKE CLIENT CODE ON THIS THREAD!
+ */
+ void handleSelected(final char[] buffer)
+ {
+ String[] wFiles = (new String(buffer)).split("\0"); // NULL is the delimiter
+ boolean multiple = (wFiles.length > 1);
- if (index == -1) {
- dir = "."+java.io.File.separator;
- fileDialog.setFile(file);
- }
- else {
- dir = file.substring(0, index + 1);
- fileDialog.setFile(file.substring(index + 1));
- }
- fileDialog.setDirectory(dir);
- fileDialog.hide();
+ String jDirectory = null;
+ String jFile = null;
+ String jFiles[] = null;
+
+ if (multiple) {
+ jDirectory = wFiles[0];
+ jFiles = new String[wFiles.length - 1];
+ System.arraycopy(wFiles, 1, jFiles, 0, jFiles.length);
+ jFile = jFiles[1]; // choose any file
+ } else {
+ int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
+ if (index == -1) {
+ jDirectory = "."+java.io.File.separator;
+ jFile = wFiles[0];
+ } else {
+ jDirectory = wFiles[0].substring(0, index + 1);
+ jFile = wFiles[0].substring(index + 1);
}
+ jFiles = new String[] { jFile };
+ }
+
+ final FileDialog fileDialog = (FileDialog)target;
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(fileDialog, jDirectory);
+ fileDialogAccessor.setFile(fileDialog, jFile);
+ fileDialogAccessor.setFiles(fileDialog, jDirectory, jFiles);
+
+ WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
+ public void run() {
+ fileDialog.hide();
+ }
});
} // handleSelected()
@@ -144,11 +175,14 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
void handleCancel() {
final FileDialog fileDialog = (FileDialog)target;
+
+ AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
+ AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null, null);
+
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
- public void run() {
- fileDialog.setFile(null);
- fileDialog.hide();
- }
+ public void run() {
+ fileDialog.hide();
+ }
});
} // handleCancel()
@@ -244,4 +278,9 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
public void createScreenSurface(boolean isResize) {}
@Override
public void replaceSurfaceData() {}
+
+ public boolean isMultipleMode() {
+ FileDialog fileDialog = (FileDialog)target;
+ return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog);
+ }
}
diff --git a/src/windows/native/sun/windows/awt_FileDialog.cpp b/src/windows/native/sun/windows/awt_FileDialog.cpp
index 080e8d42741e4aa1912cc0651978cb6c6f288138..8d81cf8aa2602c46704c489055d6c40421f12f7a 100644
--- a/src/windows/native/sun/windows/awt_FileDialog.cpp
+++ b/src/windows/native/sun/windows/awt_FileDialog.cpp
@@ -44,6 +44,7 @@ jmethodID AwtFileDialog::setHWndMID;
jmethodID AwtFileDialog::handleSelectedMID;
jmethodID AwtFileDialog::handleCancelMID;
jmethodID AwtFileDialog::checkFilenameFilterMID;
+jmethodID AwtFileDialog::isMultipleModeMID;
/* FileDialog ids */
jfieldID AwtFileDialog::modeID;
@@ -57,6 +58,13 @@ static TCHAR s_fileFilterString[MAX_FILTER_STRING];
/* Non-localized suffix of the filter string */
static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
+// Default limit of the output buffer.
+#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1
+#define MULTIPLE_MODE_BUFFER_LIMIT 32768
+
+// The name of the property holding the pointer to the OPENFILENAME structure.
+static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
+
/***********************************************************************/
void
@@ -140,6 +148,8 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
FileDialogWndProc);
::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast See the dialog box (usually in upper left corner) for instructionsMultipleMode
+
+
Bug ID: 6467204