mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 20:44:41 +02:00
7124337: [macosx] FileDialog fails to select multiple files
Reviewed-by: anthony, swingler
This commit is contained in:
parent
6d2f5978f7
commit
a4ab9d7050
8 changed files with 106 additions and 58 deletions
|
@ -34,6 +34,7 @@ import java.util.List;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import sun.awt.CausedFocusEvent.Cause;
|
import sun.awt.CausedFocusEvent.Cause;
|
||||||
|
import sun.awt.AWTAccessor;
|
||||||
import sun.java2d.pipe.Region;
|
import sun.java2d.pipe.Region;
|
||||||
|
|
||||||
class CFileDialog implements FileDialogPeer {
|
class CFileDialog implements FileDialogPeer {
|
||||||
|
@ -53,33 +54,40 @@ class CFileDialog implements FileDialogPeer {
|
||||||
title = " ";
|
title = " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
String userFileName = nativeRunFileDialog(title,
|
String[] userFileNames = nativeRunFileDialog(title,
|
||||||
dialogMode, navigateApps,
|
dialogMode,
|
||||||
|
target.isMultipleMode(),
|
||||||
|
navigateApps,
|
||||||
target.getFilenameFilter() != null,
|
target.getFilenameFilter() != null,
|
||||||
target.getDirectory(),
|
target.getDirectory(),
|
||||||
target.getFile());
|
target.getFile());
|
||||||
|
|
||||||
File file = null;
|
String directory = null;
|
||||||
if (userFileName != null) {
|
String file = null;
|
||||||
// the dialog wasn't cancelled
|
File[] files = null;
|
||||||
file = new File(userFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file != null) {
|
if (userFileNames != null) {
|
||||||
// make sure directory always ends in '/'
|
// the dialog wasn't cancelled
|
||||||
String parent = file.getParent();
|
int filesNumber = userFileNames.length;
|
||||||
if (!parent.endsWith(File.separator)) {
|
files = new File[filesNumber];
|
||||||
parent = parent + File.separator;
|
for (int i = 0; i < filesNumber; i++) {
|
||||||
|
files[i] = new File(userFileNames[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store results back in component
|
directory = files[0].getParent();
|
||||||
target.setDirectory(parent);
|
// make sure directory always ends in '/'
|
||||||
target.setFile(file.getName());
|
if (!directory.endsWith(File.separator)) {
|
||||||
} else {
|
directory = directory + File.separator;
|
||||||
// setting file name to null is how we tell
|
}
|
||||||
// java client that user hit the cancel button
|
|
||||||
target.setFile(null);
|
file = files[0].getName(); // pick any file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store results back in component
|
||||||
|
AWTAccessor.FileDialogAccessor accessor = AWTAccessor.getFileDialogAccessor();
|
||||||
|
accessor.setDirectory(target, directory);
|
||||||
|
accessor.setFile(target, file);
|
||||||
|
accessor.setFiles(target, files);
|
||||||
} finally {
|
} finally {
|
||||||
// Java2 Dialog waits for hide to let show() return
|
// Java2 Dialog waits for hide to let show() return
|
||||||
target.dispose();
|
target.dispose();
|
||||||
|
@ -133,8 +141,8 @@ class CFileDialog implements FileDialogPeer {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private native String nativeRunFileDialog(String title, int mode,
|
private native String[] nativeRunFileDialog(String title, int mode,
|
||||||
boolean shouldNavigateApps, boolean hasFilenameFilter,
|
boolean multipleMode, boolean shouldNavigateApps, boolean hasFilenameFilter,
|
||||||
String directory, String file);
|
String directory, String file);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,11 +46,14 @@
|
||||||
// File dialog's mode
|
// File dialog's mode
|
||||||
jint fMode;
|
jint fMode;
|
||||||
|
|
||||||
|
// Indicates whether the user can select multiple files
|
||||||
|
BOOL fMultipleMode;
|
||||||
|
|
||||||
// Should we navigate into apps?
|
// Should we navigate into apps?
|
||||||
BOOL fNavigateApps;
|
BOOL fNavigateApps;
|
||||||
|
|
||||||
// panel's filename
|
// Contains the absolute paths of the selected files as URLs
|
||||||
NSString *fReturnedFilename;
|
NSArray *fURLs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocator
|
// Allocator
|
||||||
|
@ -60,6 +63,7 @@
|
||||||
directory:(NSString *)inPath
|
directory:(NSString *)inPath
|
||||||
file:(NSString *)inFile
|
file:(NSString *)inFile
|
||||||
mode:(jint)inMode
|
mode:(jint)inMode
|
||||||
|
multipleMode:(BOOL)inMultipleMode
|
||||||
shouldNavigate:(BOOL)inNavigateApps
|
shouldNavigate:(BOOL)inNavigateApps
|
||||||
withEnv:(JNIEnv*)env;
|
withEnv:(JNIEnv*)env;
|
||||||
|
|
||||||
|
@ -69,7 +73,7 @@
|
||||||
// Get dialog return value
|
// Get dialog return value
|
||||||
- (BOOL) userClickedOK;
|
- (BOOL) userClickedOK;
|
||||||
|
|
||||||
// Filename user chose
|
// Returns the absolute paths of the selected files as URLs
|
||||||
- (NSString *) filename;
|
- (NSArray *) URLs;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
directory:(NSString *)inPath
|
directory:(NSString *)inPath
|
||||||
file:(NSString *)inFile
|
file:(NSString *)inFile
|
||||||
mode:(jint)inMode
|
mode:(jint)inMode
|
||||||
|
multipleMode:(BOOL)inMultipleMode
|
||||||
shouldNavigate:(BOOL)inNavigateApps
|
shouldNavigate:(BOOL)inNavigateApps
|
||||||
withEnv:(JNIEnv*)env;
|
withEnv:(JNIEnv*)env;
|
||||||
{
|
{
|
||||||
|
@ -54,6 +55,7 @@
|
||||||
fTitle = inTitle;
|
fTitle = inTitle;
|
||||||
[fTitle retain];
|
[fTitle retain];
|
||||||
fMode = inMode;
|
fMode = inMode;
|
||||||
|
fMultipleMode = inMultipleMode;
|
||||||
fNavigateApps = inNavigateApps;
|
fNavigateApps = inNavigateApps;
|
||||||
fPanelResult = NSCancelButton;
|
fPanelResult = NSCancelButton;
|
||||||
}
|
}
|
||||||
|
@ -79,8 +81,8 @@
|
||||||
[fTitle release];
|
[fTitle release];
|
||||||
fTitle = nil;
|
fTitle = nil;
|
||||||
|
|
||||||
[fReturnedFilename release];
|
[fURLs release];
|
||||||
fReturnedFilename = nil;
|
fURLs = nil;
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
@ -105,7 +107,7 @@
|
||||||
|
|
||||||
if (fMode == java_awt_FileDialog_LOAD) {
|
if (fMode == java_awt_FileDialog_LOAD) {
|
||||||
NSOpenPanel *openPanel = (NSOpenPanel *)thePanel;
|
NSOpenPanel *openPanel = (NSOpenPanel *)thePanel;
|
||||||
[openPanel setAllowsMultipleSelection:NO];
|
[openPanel setAllowsMultipleSelection:fMultipleMode];
|
||||||
[openPanel setCanChooseFiles:YES];
|
[openPanel setCanChooseFiles:YES];
|
||||||
[openPanel setCanChooseDirectories:NO];
|
[openPanel setCanChooseDirectories:NO];
|
||||||
[openPanel setCanCreateDirectories:YES];
|
[openPanel setCanCreateDirectories:YES];
|
||||||
|
@ -114,8 +116,16 @@
|
||||||
[thePanel setDelegate:self];
|
[thePanel setDelegate:self];
|
||||||
fPanelResult = [thePanel runModalForDirectory:fDirectory file:fFile];
|
fPanelResult = [thePanel runModalForDirectory:fDirectory file:fFile];
|
||||||
[thePanel setDelegate:nil];
|
[thePanel setDelegate:nil];
|
||||||
fReturnedFilename = [thePanel filename];
|
|
||||||
[fReturnedFilename retain];
|
if ([self userClickedOK]) {
|
||||||
|
if (fMode == java_awt_FileDialog_LOAD) {
|
||||||
|
NSOpenPanel *openPanel = (NSOpenPanel *)thePanel;
|
||||||
|
fURLs = [openPanel URLs];
|
||||||
|
} else {
|
||||||
|
fURLs = [NSArray arrayWithObject:[thePanel URL]];
|
||||||
|
}
|
||||||
|
[fURLs retain];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[self disposer];
|
[self disposer];
|
||||||
|
@ -158,8 +168,8 @@
|
||||||
return fPanelResult == NSOKButton;
|
return fPanelResult == NSOKButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)filename {
|
- (NSArray *)URLs {
|
||||||
return [[fReturnedFilename retain] autorelease];
|
return [[fURLs retain] autorelease];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -167,13 +177,14 @@
|
||||||
* Class: sun_lwawt_macosx_CFileDialog
|
* Class: sun_lwawt_macosx_CFileDialog
|
||||||
* Method: nativeRunFileDialog
|
* Method: nativeRunFileDialog
|
||||||
* Signature: (Ljava/lang/String;ILjava/io/FilenameFilter;
|
* Signature: (Ljava/lang/String;ILjava/io/FilenameFilter;
|
||||||
* Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
* Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jobjectArray JNICALL
|
||||||
Java_sun_lwawt_macosx_CFileDialog_nativeRunFileDialog
|
Java_sun_lwawt_macosx_CFileDialog_nativeRunFileDialog
|
||||||
(JNIEnv *env, jobject peer, jstring title, jint mode, jboolean navigateApps, jboolean hasFilter, jstring directory, jstring file)
|
(JNIEnv *env, jobject peer, jstring title, jint mode, jboolean multipleMode,
|
||||||
|
jboolean navigateApps, jboolean hasFilter, jstring directory, jstring file)
|
||||||
{
|
{
|
||||||
jstring returnValue = NULL;
|
jobjectArray returnValue = NULL;
|
||||||
|
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
NSString *dialogTitle = JNFJavaToNSString(env, title);
|
NSString *dialogTitle = JNFJavaToNSString(env, title);
|
||||||
|
@ -187,6 +198,7 @@ JNF_COCOA_ENTER(env);
|
||||||
directory:JNFJavaToNSString(env, directory)
|
directory:JNFJavaToNSString(env, directory)
|
||||||
file:JNFJavaToNSString(env, file)
|
file:JNFJavaToNSString(env, file)
|
||||||
mode:mode
|
mode:mode
|
||||||
|
multipleMode:multipleMode
|
||||||
shouldNavigate:navigateApps
|
shouldNavigate:navigateApps
|
||||||
withEnv:env];
|
withEnv:env];
|
||||||
|
|
||||||
|
@ -196,8 +208,18 @@ JNF_COCOA_ENTER(env);
|
||||||
waitUntilDone:YES];
|
waitUntilDone:YES];
|
||||||
|
|
||||||
if ([dialogDelegate userClickedOK]) {
|
if ([dialogDelegate userClickedOK]) {
|
||||||
NSString *filename = [dialogDelegate filename];
|
NSArray *urls = [dialogDelegate URLs];
|
||||||
returnValue = JNFNSToJavaString(env, filename);
|
jsize count = [urls count];
|
||||||
|
|
||||||
|
jclass stringClass = (*env)->FindClass(env, "java/lang/String");
|
||||||
|
returnValue = (*env)->NewObjectArray(env, count, stringClass, NULL);
|
||||||
|
(*env)->DeleteLocalRef(env, stringClass);
|
||||||
|
|
||||||
|
[urls enumerateObjectsUsingBlock:^(id url, NSUInteger index, BOOL *stop) {
|
||||||
|
jstring filename = JNFNormalizedJavaStringForPath(env, [url path]);
|
||||||
|
(*env)->SetObjectArrayElement(env, returnValue, index, filename);
|
||||||
|
(*env)->DeleteLocalRef(env, filename);
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
[dialogDelegate release];
|
[dialogDelegate release];
|
||||||
|
|
|
@ -147,8 +147,8 @@ public class FileDialog extends Dialog {
|
||||||
static {
|
static {
|
||||||
AWTAccessor.setFileDialogAccessor(
|
AWTAccessor.setFileDialogAccessor(
|
||||||
new AWTAccessor.FileDialogAccessor() {
|
new AWTAccessor.FileDialogAccessor() {
|
||||||
public void setFiles(FileDialog fileDialog, String directory, String files[]) {
|
public void setFiles(FileDialog fileDialog, File files[]) {
|
||||||
fileDialog.setFiles(directory, files);
|
fileDialog.setFiles(files);
|
||||||
}
|
}
|
||||||
public void setFile(FileDialog fileDialog, String file) {
|
public void setFile(FileDialog fileDialog, String file) {
|
||||||
fileDialog.file = ("".equals(file)) ? null : file;
|
fileDialog.file = ("".equals(file)) ? null : file;
|
||||||
|
@ -446,13 +446,9 @@ public class FileDialog extends Dialog {
|
||||||
* @see #getFiles
|
* @see #getFiles
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
private void setFiles(String directory, String files[]) {
|
private void setFiles(File files[]) {
|
||||||
synchronized (getObjectLock()) {
|
synchronized (getObjectLock()) {
|
||||||
int filesNumber = (files != null) ? files.length : 0;
|
this.files = files;
|
||||||
this.files = new File[filesNumber];
|
|
||||||
for (int i = 0; i < filesNumber; i++) {
|
|
||||||
this.files[i] = new File(directory, files[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.awt.geom.Point2D;
|
||||||
import java.awt.peer.ComponentPeer;
|
import java.awt.peer.ComponentPeer;
|
||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AWTAccessor utility class.
|
* The AWTAccessor utility class.
|
||||||
* The main purpose of this class is to enable accessing
|
* The main purpose of this class is to enable accessing
|
||||||
|
@ -455,7 +457,7 @@ public final class AWTAccessor {
|
||||||
/*
|
/*
|
||||||
* Sets the files the user selects
|
* Sets the files the user selects
|
||||||
*/
|
*/
|
||||||
void setFiles(FileDialog fileDialog, String directory, String files[]);
|
void setFiles(FileDialog fileDialog, File files[]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the file the user selects
|
* Sets the file the user selects
|
||||||
|
|
|
@ -73,7 +73,7 @@ class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer {
|
||||||
if (filenames == null) {
|
if (filenames == null) {
|
||||||
accessor.setDirectory(fd, null);
|
accessor.setDirectory(fd, null);
|
||||||
accessor.setFile(fd, null);
|
accessor.setFile(fd, null);
|
||||||
accessor.setFiles(fd, null, null);
|
accessor.setFiles(fd, null);
|
||||||
} else {
|
} else {
|
||||||
// Fix 6987233: add the trailing slash if it's absent
|
// Fix 6987233: add the trailing slash if it's absent
|
||||||
String with_separator = directory;
|
String with_separator = directory;
|
||||||
|
@ -83,7 +83,13 @@ class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer {
|
||||||
}
|
}
|
||||||
accessor.setDirectory(fd, with_separator);
|
accessor.setDirectory(fd, with_separator);
|
||||||
accessor.setFile(fd, filenames[0]);
|
accessor.setFile(fd, filenames[0]);
|
||||||
accessor.setFiles(fd, directory, filenames);
|
|
||||||
|
int filesNumber = (filenames != null) ? filenames.length : 0;
|
||||||
|
File[] files = new File[filesNumber];
|
||||||
|
for (int i = 0; i < filesNumber; i++) {
|
||||||
|
files[i] = new File(directory, filenames[i]);
|
||||||
|
}
|
||||||
|
accessor.setFiles(fd, files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -396,11 +396,18 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
|
||||||
savedFile = file.substring(index+1);
|
savedFile = file.substring(index+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String[] fileNames = fileList.getSelectedItems();
|
||||||
|
int filesNumber = (fileNames != null) ? fileNames.length : 0;
|
||||||
|
File[] files = new File[filesNumber];
|
||||||
|
for (int i = 0; i < filesNumber; i++) {
|
||||||
|
files[i] = new File(savedDir, fileNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
|
AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
|
||||||
|
|
||||||
fileDialogAccessor.setDirectory(target, savedDir);
|
fileDialogAccessor.setDirectory(target, savedDir);
|
||||||
fileDialogAccessor.setFile(target, savedFile);
|
fileDialogAccessor.setFile(target, savedFile);
|
||||||
fileDialogAccessor.setFiles(target, savedDir, fileList.getSelectedItems());
|
fileDialogAccessor.setFiles(target, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -419,7 +426,7 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe
|
||||||
|
|
||||||
fileDialogAccessor.setDirectory(target, null);
|
fileDialogAccessor.setDirectory(target, null);
|
||||||
fileDialogAccessor.setFile(target, null);
|
fileDialogAccessor.setFile(target, null);
|
||||||
fileDialogAccessor.setFiles(target, null, null);
|
fileDialogAccessor.setFiles(target, null);
|
||||||
|
|
||||||
handleQuitButton();
|
handleQuitButton();
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,13 +139,16 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
|
||||||
|
|
||||||
String jDirectory = null;
|
String jDirectory = null;
|
||||||
String jFile = null;
|
String jFile = null;
|
||||||
String jFiles[] = null;
|
File[] jFiles = null;
|
||||||
|
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
jDirectory = wFiles[0];
|
jDirectory = wFiles[0];
|
||||||
jFiles = new String[wFiles.length - 1];
|
int filesNumber = wFiles.length - 1;
|
||||||
System.arraycopy(wFiles, 1, jFiles, 0, jFiles.length);
|
jFiles = new File[filesNumber];
|
||||||
jFile = jFiles[1]; // choose any file
|
for (int i = 0; i < filesNumber; i++) {
|
||||||
|
jFiles[i] = new File(jDirectory, wFiles[i + 1]);
|
||||||
|
}
|
||||||
|
jFile = wFiles[1]; // choose any file
|
||||||
} else {
|
} else {
|
||||||
int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
|
int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
|
@ -155,7 +158,7 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
|
||||||
jDirectory = wFiles[0].substring(0, index + 1);
|
jDirectory = wFiles[0].substring(0, index + 1);
|
||||||
jFile = wFiles[0].substring(index + 1);
|
jFile = wFiles[0].substring(index + 1);
|
||||||
}
|
}
|
||||||
jFiles = new String[] { jFile };
|
jFiles = new File[] { new File(jDirectory, jFile) };
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileDialog fileDialog = (FileDialog)target;
|
final FileDialog fileDialog = (FileDialog)target;
|
||||||
|
@ -163,7 +166,7 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
|
||||||
|
|
||||||
fileDialogAccessor.setDirectory(fileDialog, jDirectory);
|
fileDialogAccessor.setDirectory(fileDialog, jDirectory);
|
||||||
fileDialogAccessor.setFile(fileDialog, jFile);
|
fileDialogAccessor.setFile(fileDialog, jFile);
|
||||||
fileDialogAccessor.setFiles(fileDialog, jDirectory, jFiles);
|
fileDialogAccessor.setFiles(fileDialog, jFiles);
|
||||||
|
|
||||||
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
|
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -178,7 +181,7 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
|
||||||
final FileDialog fileDialog = (FileDialog)target;
|
final FileDialog fileDialog = (FileDialog)target;
|
||||||
|
|
||||||
AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
|
AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
|
||||||
AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null, null);
|
AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null);
|
||||||
|
|
||||||
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
|
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue