001: /*
002: * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.awt.motif;
026:
027: import java.awt.*;
028: import java.awt.peer.*;
029: import java.io.*;
030: import java.awt.datatransfer.*;
031: import java.util.ArrayList;
032: import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
033:
034: public class MFileDialogPeer extends MDialogPeer implements
035: FileDialogPeer {
036: private FilenameFilter filter;
037: private String[] NativeFilteredFiles;
038:
039: native void create(MComponentPeer parent);
040:
041: void create(MComponentPeer parent, Object arg) {
042: create(parent);
043: }
044:
045: public MFileDialogPeer(FileDialog target) {
046: super (target);
047: FileDialog fdialog = (FileDialog) target;
048: String dir = fdialog.getDirectory();
049: String file = fdialog.getFile();
050: FilenameFilter filter = fdialog.getFilenameFilter();
051:
052: insets = new Insets(0, 0, 0, 0);
053: setDirectory(dir);
054: if (file != null) {
055: setFile(file);
056: }
057: setFilenameFilter(filter);
058: }
059:
060: native void pReshape(int x, int y, int width, int height);
061:
062: native void pDispose();
063:
064: native void pShow();
065:
066: native void pHide();
067:
068: native void setFileEntry(String dir, String file, String[] ffiles);
069:
070: native void insertReplaceFileDialogText(String l);
071:
072: public native void setFont(Font f);
073:
074: String getFilteredFile(String file) {
075: if (file == null) {
076: file = ((FileDialog) target).getFile();
077: }
078: String dir = ((FileDialog) target).getDirectory();
079: if (dir == null) {
080: dir = "./";
081: }
082: if (file == null) {
083: file = "";
084: }
085: if (filter != null && !filter.accept(new File(dir), file)) {
086: file = "";
087: }
088: return file;
089: }
090:
091: // NOTE: This method is called by privileged threads.
092: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
093: public void handleSelected(final String file) {
094: final FileDialog fileDialog = (FileDialog) target;
095: MToolkit.executeOnEventHandlerThread(fileDialog,
096: new Runnable() {
097: public void run() {
098: int index = file
099: .lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/
100: String dir;
101:
102: if (index == -1) {
103: dir = "." + java.io.File.separator;
104: fileDialog.setFile(file);
105: } else {
106: dir = file.substring(0, index + 1);
107: fileDialog.setFile(file
108: .substring(index + 1));
109: }
110: fileDialog.setDirectory(dir);
111: fileDialog.hide();
112: }
113: });
114: } // handleSelected()
115:
116: // NOTE: This method is called by privileged threads.
117: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
118: public void handleCancel() {
119: final FileDialog fileDialog = (FileDialog) target;
120: MToolkit.executeOnEventHandlerThread(fileDialog,
121: new Runnable() {
122: public void run() {
123: fileDialog.setFile(null);
124: fileDialog.hide();
125: }
126: });
127: } // handleCancel()
128:
129: // NOTE: This method is called by privileged threads.
130: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
131: public void handleQuit() {
132: final FileDialog fileDialog = (FileDialog) target;
133: MToolkit.executeOnEventHandlerThread(fileDialog,
134: new Runnable() {
135: public void run() {
136: fileDialog.hide();
137: }
138: });
139: } // handleQuit()
140:
141: public void setDirectory(String dir) {
142: String file = ((FileDialog) target).getFile();
143: setFileEntry((dir != null) ? dir : "./", (file != null) ? file
144: : "", null);
145: }
146:
147: public void setFile(String file) {
148: String dir = ((FileDialog) target).getDirectory();
149: if (dir == null) {
150: dir = "./";
151: }
152: setFileEntry((dir != null) ? dir : "./", getFilteredFile(null),
153: null);
154: }
155:
156: class DirectoryFilter implements FilenameFilter {
157: FilenameFilter userFilter;
158:
159: DirectoryFilter(FilenameFilter userFilter) {
160: this .userFilter = userFilter;
161: }
162:
163: public boolean accept(File parent, String name) {
164: File toTest = new File(parent, name);
165: if (toTest.isDirectory()) {
166: return false;
167: } else if (userFilter != null) {
168: return userFilter.accept(parent, name);
169: } else {
170: return true;
171: }
172: }
173: }
174:
175: public void doFilter(FilenameFilter filter, String dir) {
176: String d = (dir == null) ? (((FileDialog) target)
177: .getDirectory()) : (dir);
178: String f = getFilteredFile(null);
179: File df = new File((d != null) ? d : ".");
180: String[] files = df.list(new DirectoryFilter(filter));
181: String[] nffiles = NativeFilteredFiles;
182:
183: // At this point we have two file lists.
184: // The first one is a filtered list of files that we retrieve
185: // by using Java code and Java filter.
186: // The second one is a filtered list of files that we retrieve
187: // by using the native code and native pattern.
188: // We should find an intersection of these two lists. The result
189: // will be exactly what we expect to see in setFileEntry.
190: // For more details please see 4784704.
191: if (files != null) {
192: ArrayList filearr = new ArrayList();
193: if (nffiles != null) {
194: for (int j = 0; j < files.length; j++) {
195: for (int n = 0; n < nffiles.length; n++) {
196: if (files[j].equals(nffiles[n])) {
197: filearr.add(files[j]);
198: break;
199: }
200: }
201: }
202: }
203: files = new String[filearr.size()];
204: for (int i = 0; i < files.length; i++) {
205: files[i] = (String) filearr.get(i);
206: }
207: }
208: if (files == null || files.length == 0) {
209: files = new String[1];
210: files[0] = "";
211: }
212: setFileEntry((d != null) ? d : ".", (f != null) ? f : "", files);
213: }
214:
215: private boolean proceedFiltering(final String dir,
216: String[] nffiles, boolean isPrivileged) {
217: // Transfer the native filtered file list to the doFilter method.
218: NativeFilteredFiles = nffiles;
219: // If we are not on the Toolkit thread we can call doFilter() directly.
220: // If the filter is null no user code will be invoked
221: if (!isPrivileged || filter == null) {
222: try {
223: doFilter(filter, dir);
224: return true;
225: } catch (Exception e) {
226: e.printStackTrace();
227: return false;
228: }
229: }
230: // Otherwise we have to call user code on EvenDispatchThread
231: final ToolkitThreadBlockedHandler priveleged_lock = MToolkitThreadBlockedHandler
232: .getToolkitThreadBlockedHandler();
233: final boolean[] finished = new boolean[1];
234: final boolean[] result = new boolean[1];
235: finished[0] = false;
236: result[0] = false;
237:
238: // Use the same Toolkit blocking mechanism as in DnD.
239: priveleged_lock.lock();
240:
241: MToolkit.executeOnEventHandlerThread((FileDialog) target,
242: new Runnable() {
243: public void run() {
244: priveleged_lock.lock();
245: try {
246: doFilter(filter, dir);
247: result[0] = true;
248: } catch (Exception e) {
249: e.printStackTrace();
250: result[0] = false;
251: } finally {
252: finished[0] = true;
253: priveleged_lock.exit();
254: priveleged_lock.unlock();
255: }
256: }
257: });
258:
259: while (!finished[0]) {
260: priveleged_lock.enter();
261: }
262:
263: priveleged_lock.unlock();
264:
265: return result[0];
266: }
267:
268: public void setFilenameFilter(FilenameFilter filter) {
269: this .filter = filter;
270: FileDialog fdialog = (FileDialog) target;
271: String dir = fdialog.getDirectory();
272: String file = fdialog.getFile();
273: setFile(file);
274: doFilter(filter, null);
275: }
276:
277: // Called from native widget when paste key is pressed and we
278: // already own the selection (prevents Motif from hanging while
279: // waiting for the selection)
280: //
281: public void pasteFromClipboard() {
282: Clipboard clipboard = target.getToolkit().getSystemClipboard();
283:
284: Transferable content = clipboard.getContents(this );
285: if (content != null) {
286: try {
287: String data = (String) (content
288: .getTransferData(DataFlavor.stringFlavor));
289: insertReplaceFileDialogText(data);
290: } catch (Exception e) {
291: }
292: }
293: }
294:
295: // CAVEAT:
296: // Peer coalescing code turned over the fact that the following functions
297: // were being inherited from Dialog and were not implemented in awt_FileDialog.c
298: // Five methods decribed by the peer interface are at fault (setResizable, setTitle,
299: // toFront, toBack and handleFocusTraversalEvent). Additionally show has to be overridden
300: // as it was necessary to add a show function in MDialogPeer for modality flag passing.
301: // As a result we were winding up in awt_Dialog.c (now coalesced into awt_TopLevel).
302: // As Filedialogs are modal and its unclear to me that any of these functions
303: // can be called while the FD is on-screen let it go. RJM.
304: public void show() {
305: // must have our own show or we wind up in pShow for Window. Bad. Very bad.
306: setVisible(true);
307: setFilenameFilter(filter);
308: }
309:
310: /**
311: * MFileDialogPeer doesn't have native pData so we don't do restack on it
312: * @see java.awt.peer.ContainerPeer#restack
313: */
314: public void restack() {
315: }
316:
317: /**
318: * @see java.awt.peer.ContainerPeer#isRestackSupported
319: */
320: public boolean isRestackSupported() {
321: return false;
322: }
323: }
|