package abbot.tester;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.event.KeyEvent;
import abbot.Log;
import abbot.Platform;
/**
* Tester for the java.awt.FileDialog.
*
* @author Vrata Venet, European Space Agency, Madrid-Spain (av@iso.vilspa.esa.es)
* @author Tim Wall (twall:users.sf.net)
* NOTE: different platforms do different things when the dialog is hidden.
* w32 returns null for the file if FileDialog.hide is invoked; other
* platforms may leave the file as is. OSX (as of 1.4.2) won't let you hide
* the dialog.
*/
public class FileDialogTester extends DialogTester {
/**
* This sets the file path for the fd
*/
public void actionSetFile(Component comp, final String file) {
if (null == file || "".equals(file))
throw new IllegalArgumentException("File name in FileDialog should be non-null and non-empty");
final FileDialog dialog = (FileDialog) comp;
invokeAndWait(new Runnable() {
public void run() {
dialog.setFile(file);
}
});
}
public void actionSetDirectory(Component comp, final String dir) {
if (null == dir || "".equals(dir))
throw new IllegalArgumentException("File name in FileDialog should be non-null and non-empty");
final FileDialog dialog = (FileDialog) comp;
invokeAndWait(new Runnable() {
public void run() {
dialog.setDirectory(dir);
}
});
}
/** Accept the currently selected file. */
public void actionAccept(Component comp){
Log.debug("accept");
final FileDialog fd = (FileDialog)comp;
final String file = fd.getFile();
if (file == null)
throw new ActionFailedException("No file selected");
// HACK:
// sun.awt.windows.WFileDialogPeer posts an InvocationEvent which sets
// the FileDialog file to null when Dialog.hide is called.
// Install an event queue which can catch the posted event and ignore
// it. Only fully tested against sun.awt.windows.WFileDialogPeer.
FileDialogQueue queue = new FileDialogQueue();
try {
fd.getToolkit().getSystemEventQueue().push(queue);
// 1.4.2 bug workaround: FileDialog.hide doesn't work
if (Platform.isOSX())
actionKeyStroke(KeyEvent.VK_ESCAPE);
invokeAndWait(new Runnable() {
public void run() {
fd.hide();
}
});
waitForIdle();
fd.setFile(file);
}
finally {
queue.dispose();
}
}
private class FileDialogQueue extends EventQueue {
private boolean disposed = false;
private boolean installed = false;
public void dispose() {
boolean remove = false;
synchronized(this) {
if (!disposed) {
disposed = true;
remove = true;
}
}
if (remove) {
try { pop(); }
catch(java.util.EmptyStackException es) { }
}
}
protected void dispatchEvent(AWTEvent e) {
synchronized(this) {
if (!installed) {
installed = true;
String name = Thread.currentThread().getName();
Thread.currentThread().setName(name + " (abbot FileDialogTester)");
}
}
// Ignore FileDialogPeer events while disposing the dialog
if (e.paramString().indexOf("FileDialogPeer") != -1) {
Log.debug("ignoring peer event: " + e);
// Nothing else to handle, restore the original queue
dispose();
}
else {
super.dispatchEvent(e);
}
}
}
/** Close the file dialog without selecting a file. */
public void actionCancel(Component comp) {
final FileDialog fd = (FileDialog)comp;
if (Platform.isOSX()) {
// bug in OSX 1.4.2: activate causes another dialog to appear!
//activate(fd);
// Assume dialog has focus
actionKeyStroke(KeyEvent.VK_ESCAPE);
}
else {
// the w32 native peer sets the file to null on dialog hide, but
// other platforms might not, so do it explicitly.
fd.setFile(null);
invokeAndWait(new Runnable() {
public void run() {
fd.hide();
}
});
}
}
}