| /* |
| * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| package sun.awt.motif; |
| |
| import java.awt.*; |
| import java.awt.peer.*; |
| import java.io.*; |
| import java.awt.datatransfer.*; |
| import java.util.ArrayList; |
| import sun.awt.datatransfer.ToolkitThreadBlockedHandler; |
| |
| public class MFileDialogPeer extends MDialogPeer implements FileDialogPeer { |
| private FilenameFilter filter; |
| private String[] NativeFilteredFiles; |
| native void create(MComponentPeer parent); |
| void create(MComponentPeer parent, Object arg) { |
| create(parent); |
| } |
| public MFileDialogPeer(FileDialog target) { |
| super(target); |
| FileDialog fdialog = (FileDialog)target; |
| String dir = fdialog.getDirectory(); |
| String file = fdialog.getFile(); |
| FilenameFilter filter = fdialog.getFilenameFilter(); |
| |
| insets = new Insets(0, 0, 0, 0); |
| setDirectory(dir); |
| if (file != null) { |
| setFile(file); |
| } |
| setFilenameFilter(filter); |
| } |
| native void pReshape(int x, int y, int width, int height); |
| native void pDispose(); |
| native void pShow(); |
| native void pHide(); |
| native void setFileEntry(String dir, String file, String[] ffiles); |
| native void insertReplaceFileDialogText(String l); |
| public native void setFont(Font f); |
| |
| String getFilteredFile(String file) { |
| if (file == null) { |
| file = ((FileDialog)target).getFile(); |
| } |
| String dir = ((FileDialog)target).getDirectory(); |
| if (dir == null) { |
| dir = "./"; |
| } |
| if (file == null) { |
| file = ""; |
| } |
| if (filter != null && !filter.accept(new File(dir), file)) { |
| file = ""; |
| } |
| return file; |
| } |
| // NOTE: This method is called by privileged threads. |
| // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
| public void handleSelected(final String file) { |
| final FileDialog fileDialog = (FileDialog)target; |
| MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
| public void run() { |
| int index = file.lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/ |
| String dir; |
| |
| 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(); |
| } |
| }); |
| } // handleSelected() |
| |
| // NOTE: This method is called by privileged threads. |
| // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
| public void handleCancel() { |
| final FileDialog fileDialog = (FileDialog)target; |
| MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
| public void run() { |
| fileDialog.setFile(null); |
| fileDialog.hide(); |
| } |
| }); |
| } // handleCancel() |
| |
| // NOTE: This method is called by privileged threads. |
| // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
| public void handleQuit() { |
| final FileDialog fileDialog = (FileDialog)target; |
| MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
| public void run() { |
| fileDialog.hide(); |
| } |
| }); |
| } // handleQuit() |
| |
| public void setDirectory(String dir) { |
| String file = ((FileDialog)target).getFile(); |
| setFileEntry((dir != null) ? dir : "./", (file != null) ? file |
| : "", null); |
| } |
| |
| |
| public void setFile(String file) { |
| String dir = ((FileDialog)target).getDirectory(); |
| if (dir == null) { |
| dir = "./"; |
| } |
| setFileEntry((dir != null) ? dir : "./", getFilteredFile(null), null); |
| } |
| class DirectoryFilter implements FilenameFilter { |
| FilenameFilter userFilter; |
| DirectoryFilter(FilenameFilter userFilter) { |
| this.userFilter = userFilter; |
| } |
| public boolean accept(File parent, String name) { |
| File toTest = new File(parent, name); |
| if (toTest.isDirectory()) { |
| return false; |
| } else if (userFilter != null) { |
| return userFilter.accept(parent, name); |
| } else { |
| return true; |
| } |
| } |
| } |
| public void doFilter(FilenameFilter filter, String dir) { |
| String d = (dir == null) ? (((FileDialog)target).getDirectory()):(dir); |
| String f = getFilteredFile(null); |
| File df = new File((d != null) ? d : "."); |
| String[] files = df.list(new DirectoryFilter(filter)); |
| String[] nffiles = NativeFilteredFiles; |
| |
| // At this point we have two file lists. |
| // The first one is a filtered list of files that we retrieve |
| // by using Java code and Java filter. |
| // The second one is a filtered list of files that we retrieve |
| // by using the native code and native pattern. |
| // We should find an intersection of these two lists. The result |
| // will be exactly what we expect to see in setFileEntry. |
| // For more details please see 4784704. |
| if ( files != null ) { |
| ArrayList filearr = new ArrayList(); |
| if (nffiles != null) { |
| for (int j = 0; j < files.length; j++) { |
| for (int n = 0; n < nffiles.length; n++) { |
| if (files[j].equals(nffiles[n])) { |
| filearr.add(files[j]); |
| break; |
| } |
| } |
| } |
| } |
| files = new String[filearr.size()]; |
| for (int i = 0; i < files.length; i++) { |
| files[i] = (String)filearr.get(i); |
| } |
| } |
| if (files == null || files.length == 0) { |
| files = new String[1]; |
| files[0] = ""; |
| } |
| setFileEntry((d != null) ? d : ".", (f != null) ? f : "", files); |
| } |
| private boolean proceedFiltering(final String dir, String[] nffiles, |
| boolean isPrivileged) |
| { |
| // Transfer the native filtered file list to the doFilter method. |
| NativeFilteredFiles = nffiles; |
| // If we are not on the Toolkit thread we can call doFilter() directly. |
| // If the filter is null no user code will be invoked |
| if (!isPrivileged || filter == null) { |
| try { |
| doFilter(filter, dir); |
| return true; |
| } catch(Exception e) { |
| e.printStackTrace(); |
| return false; |
| } |
| } |
| // Otherwise we have to call user code on EvenDispatchThread |
| final ToolkitThreadBlockedHandler priveleged_lock = |
| MToolkitThreadBlockedHandler.getToolkitThreadBlockedHandler(); |
| final boolean[] finished = new boolean[1]; |
| final boolean[] result = new boolean[1]; |
| finished[0] = false; |
| result[0] = false; |
| |
| |
| // Use the same Toolkit blocking mechanism as in DnD. |
| priveleged_lock.lock(); |
| |
| MToolkit.executeOnEventHandlerThread((FileDialog)target, new Runnable() { |
| public void run() { |
| priveleged_lock.lock(); |
| try { |
| doFilter(filter, dir); |
| result[0] = true; |
| } catch (Exception e) { |
| e.printStackTrace(); |
| result[0] = false; |
| } finally { |
| finished[0] = true; |
| priveleged_lock.exit(); |
| priveleged_lock.unlock(); |
| } |
| } |
| }); |
| |
| while (!finished[0]) { |
| priveleged_lock.enter(); |
| } |
| |
| priveleged_lock.unlock(); |
| |
| return result[0]; |
| } |
| |
| public void setFilenameFilter(FilenameFilter filter) { |
| this.filter = filter; |
| FileDialog fdialog = (FileDialog)target; |
| String dir = fdialog.getDirectory(); |
| String file = fdialog.getFile(); |
| setFile(file); |
| doFilter(filter, null); |
| } |
| |
| // Called from native widget when paste key is pressed and we |
| // already own the selection (prevents Motif from hanging while |
| // waiting for the selection) |
| // |
| public void pasteFromClipboard() { |
| Clipboard clipboard = target.getToolkit().getSystemClipboard(); |
| |
| Transferable content = clipboard.getContents(this); |
| if (content != null) { |
| try { |
| String data = (String)(content.getTransferData(DataFlavor.stringFlavor)); |
| insertReplaceFileDialogText(data); |
| } catch (Exception e) { |
| } |
| } |
| } |
| |
| // CAVEAT: |
| // Peer coalescing code turned over the fact that the following functions |
| // were being inherited from Dialog and were not implemented in awt_FileDialog.c |
| // Five methods decribed by the peer interface are at fault (setResizable, setTitle, |
| // toFront, toBack and handleFocusTraversalEvent). Additionally show has to be overridden |
| // as it was necessary to add a show function in MDialogPeer for modality flag passing. |
| // As a result we were winding up in awt_Dialog.c (now coalesced into awt_TopLevel). |
| // As Filedialogs are modal and its unclear to me that any of these functions |
| // can be called while the FD is on-screen let it go. RJM. |
| public void show() { |
| // must have our own show or we wind up in pShow for Window. Bad. Very bad. |
| setVisible(true); |
| setFilenameFilter(filter); |
| } |
| |
| /** |
| * MFileDialogPeer doesn't have native pData so we don't do restack on it |
| * @see java.awt.peer.ContainerPeer#restack |
| */ |
| public void restack() { |
| } |
| |
| /** |
| * @see java.awt.peer.ContainerPeer#isRestackSupported |
| */ |
| public boolean isRestackSupported() { |
| return false; |
| } |
| } |