001: package abbot.tester;
002:
003: import java.awt.*;
004: import java.awt.event.*;
005: import abbot.*;
006: import abbot.util.Bugs;
007:
008: /**
009: * Tester for the java.awt.FileDialog.
010: *
011: * @author Vrata Venet, European Space Agency, Madrid-Spain (av@iso.vilspa.esa.es)
012: * @author Tim Wall (twall:users.sf.net)
013: * NOTE: different platforms do different things when the dialog is hidden.
014: * w32 returns null for the file if FileDialog.hide is invoked; other
015: * platforms may leave the file as is. OSX (as of 1.4.2) won't let you hide
016: * the dialog.
017: */
018: public class FileDialogTester extends DialogTester {
019:
020: /**
021: * This sets the file path for the fd
022: */
023: public void actionSetFile(Component comp, final String file) {
024: if (null == file || "".equals(file))
025: throw new IllegalArgumentException(
026: "File name in FileDialog should be non-null and non-empty");
027: final FileDialog dialog = (FileDialog) comp;
028: invokeAndWait(new Runnable() {
029: public void run() {
030: dialog.setFile(file);
031: }
032: });
033: }
034:
035: public void actionSetDirectory(Component comp, final String dir) {
036: if (null == dir || "".equals(dir))
037: throw new IllegalArgumentException(
038: "File name in FileDialog should be non-null and non-empty");
039: final FileDialog dialog = (FileDialog) comp;
040: invokeAndWait(new Runnable() {
041: public void run() {
042: dialog.setDirectory(dir);
043: }
044: });
045: }
046:
047: /** Accept the currently selected file. */
048: public void actionAccept(Component comp) {
049: Log.debug("accept");
050: final FileDialog fd = (FileDialog) comp;
051: final String file = fd.getFile();
052: if (file == null)
053: throw new ActionFailedException("No file selected");
054:
055: // HACK:
056: // sun.awt.windows.WFileDialogPeer posts an InvocationEvent which sets
057: // the FileDialog's file to null when Dialog.hide is called.
058: // Install an event queue which can catch the posted event and ignore
059: // it. Only fully tested against sun.awt.windows.WFileDialogPeer.
060: FileDialogQueue queue = new FileDialogQueue();
061:
062: // OSX disposes the FileDialog after hide, which is an event we
063: // can spot
064: fd.addWindowListener(new WindowAdapter() {
065: public void windowClosed(WindowEvent e) {
066: fd.setFile(file);
067: fd.removeWindowListener(this );
068: }
069: });
070:
071: try {
072: fd.getToolkit().getSystemEventQueue().push(queue);
073:
074: // 1.4.2 bug workaround: FileDialog.hide doesn't work
075: if (Bugs.fileDialogRequiresDismiss()) {
076: actionKeyStroke(KeyEvent.VK_ESCAPE);
077: }
078: invokeAndWait(new Runnable() {
079: public void run() {
080: fd.setVisible(false);
081: }
082: });
083: fd.setFile(file);
084: } finally {
085: queue.dispose();
086: }
087: }
088:
089: private class FileDialogQueue extends EventQueue {
090: private boolean disposed = false;
091: private boolean installed = false;
092:
093: public void dispose() {
094: boolean remove = false;
095: synchronized (this ) {
096: if (!disposed) {
097: disposed = true;
098: remove = true;
099: }
100: }
101: if (remove) {
102: try {
103: pop();
104: } catch (java.util.EmptyStackException e) {
105: Log.warn(e);
106: }
107: }
108: }
109:
110: protected void dispatchEvent(AWTEvent e) {
111: synchronized (this ) {
112: if (!installed) {
113: installed = true;
114: String name = Thread.currentThread().getName();
115: Thread.currentThread().setName(
116: name + " (abbot FileDialogTester)");
117: }
118: }
119:
120: // Ignore FileDialogPeer events while disposing the dialog
121: if (e.paramString().indexOf("FileDialogPeer") != -1) {
122: Log.debug("ignoring peer event: " + e);
123: // Nothing else to handle, restore the original queue
124: dispose();
125: } else {
126: super .dispatchEvent(e);
127: }
128: }
129: }
130:
131: /** Close the file dialog without selecting a file. */
132: public void actionCancel(Component comp) {
133: final FileDialog fd = (FileDialog) comp;
134: if (Platform.isOSX()) {
135: // bug in OSX 1.4.2: activate causes another dialog to appear!
136: //activate(fd);
137: // Assume dialog has focus
138: actionKeyStroke(KeyEvent.VK_ESCAPE);
139: } else {
140: // the w32 native peer sets the file to null on dialog hide, but
141: // other platforms might not, so do it explicitly.
142: fd.setFile(null);
143: invokeAndWait(new Runnable() {
144: public void run() {
145: fd.setVisible(false);
146: }
147: });
148: }
149: }
150: }
|