1 /* |
|
2 * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 package sun.awt.motif; |
|
26 |
|
27 import java.awt.*; |
|
28 import java.awt.peer.*; |
|
29 import java.io.*; |
|
30 import java.awt.datatransfer.*; |
|
31 import java.util.ArrayList; |
|
32 import sun.awt.datatransfer.ToolkitThreadBlockedHandler; |
|
33 |
|
34 public class MFileDialogPeer extends MDialogPeer implements FileDialogPeer { |
|
35 private FilenameFilter filter; |
|
36 private String[] NativeFilteredFiles; |
|
37 native void create(MComponentPeer parent); |
|
38 void create(MComponentPeer parent, Object arg) { |
|
39 create(parent); |
|
40 } |
|
41 public MFileDialogPeer(FileDialog target) { |
|
42 super(target); |
|
43 FileDialog fdialog = (FileDialog)target; |
|
44 String dir = fdialog.getDirectory(); |
|
45 String file = fdialog.getFile(); |
|
46 FilenameFilter filter = fdialog.getFilenameFilter(); |
|
47 |
|
48 insets = new Insets(0, 0, 0, 0); |
|
49 setDirectory(dir); |
|
50 if (file != null) { |
|
51 setFile(file); |
|
52 } |
|
53 setFilenameFilter(filter); |
|
54 } |
|
55 native void pReshape(int x, int y, int width, int height); |
|
56 native void pDispose(); |
|
57 native void pShow(); |
|
58 native void pHide(); |
|
59 native void setFileEntry(String dir, String file, String[] ffiles); |
|
60 native void insertReplaceFileDialogText(String l); |
|
61 public native void setFont(Font f); |
|
62 |
|
63 String getFilteredFile(String file) { |
|
64 if (file == null) { |
|
65 file = ((FileDialog)target).getFile(); |
|
66 } |
|
67 String dir = ((FileDialog)target).getDirectory(); |
|
68 if (dir == null) { |
|
69 dir = "./"; |
|
70 } |
|
71 if (file == null) { |
|
72 file = ""; |
|
73 } |
|
74 if (filter != null && !filter.accept(new File(dir), file)) { |
|
75 file = ""; |
|
76 } |
|
77 return file; |
|
78 } |
|
79 // NOTE: This method is called by privileged threads. |
|
80 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
81 public void handleSelected(final String file) { |
|
82 final FileDialog fileDialog = (FileDialog)target; |
|
83 MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
|
84 public void run() { |
|
85 int index = file.lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/ |
|
86 String dir; |
|
87 |
|
88 if (index == -1) { |
|
89 dir = "."+java.io.File.separator; |
|
90 fileDialog.setFile(file); |
|
91 } else { |
|
92 dir = file.substring(0, index + 1); |
|
93 fileDialog.setFile(file.substring(index + 1)); |
|
94 } |
|
95 fileDialog.setDirectory(dir); |
|
96 fileDialog.hide(); |
|
97 } |
|
98 }); |
|
99 } // handleSelected() |
|
100 |
|
101 // NOTE: This method is called by privileged threads. |
|
102 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
103 public void handleCancel() { |
|
104 final FileDialog fileDialog = (FileDialog)target; |
|
105 MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
|
106 public void run() { |
|
107 fileDialog.setFile(null); |
|
108 fileDialog.hide(); |
|
109 } |
|
110 }); |
|
111 } // handleCancel() |
|
112 |
|
113 // NOTE: This method is called by privileged threads. |
|
114 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
115 public void handleQuit() { |
|
116 final FileDialog fileDialog = (FileDialog)target; |
|
117 MToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { |
|
118 public void run() { |
|
119 fileDialog.hide(); |
|
120 } |
|
121 }); |
|
122 } // handleQuit() |
|
123 |
|
124 public void setDirectory(String dir) { |
|
125 String file = ((FileDialog)target).getFile(); |
|
126 setFileEntry((dir != null) ? dir : "./", (file != null) ? file |
|
127 : "", null); |
|
128 } |
|
129 |
|
130 |
|
131 public void setFile(String file) { |
|
132 String dir = ((FileDialog)target).getDirectory(); |
|
133 if (dir == null) { |
|
134 dir = "./"; |
|
135 } |
|
136 setFileEntry((dir != null) ? dir : "./", getFilteredFile(null), null); |
|
137 } |
|
138 class DirectoryFilter implements FilenameFilter { |
|
139 FilenameFilter userFilter; |
|
140 DirectoryFilter(FilenameFilter userFilter) { |
|
141 this.userFilter = userFilter; |
|
142 } |
|
143 public boolean accept(File parent, String name) { |
|
144 File toTest = new File(parent, name); |
|
145 if (toTest.isDirectory()) { |
|
146 return false; |
|
147 } else if (userFilter != null) { |
|
148 return userFilter.accept(parent, name); |
|
149 } else { |
|
150 return true; |
|
151 } |
|
152 } |
|
153 } |
|
154 public void doFilter(FilenameFilter filter, String dir) { |
|
155 String d = (dir == null) ? (((FileDialog)target).getDirectory()):(dir); |
|
156 String f = getFilteredFile(null); |
|
157 File df = new File((d != null) ? d : "."); |
|
158 String[] files = df.list(new DirectoryFilter(filter)); |
|
159 String[] nffiles = NativeFilteredFiles; |
|
160 |
|
161 // At this point we have two file lists. |
|
162 // The first one is a filtered list of files that we retrieve |
|
163 // by using Java code and Java filter. |
|
164 // The second one is a filtered list of files that we retrieve |
|
165 // by using the native code and native pattern. |
|
166 // We should find an intersection of these two lists. The result |
|
167 // will be exactly what we expect to see in setFileEntry. |
|
168 // For more details please see 4784704. |
|
169 if ( files != null ) { |
|
170 ArrayList filearr = new ArrayList(); |
|
171 if (nffiles != null) { |
|
172 for (int j = 0; j < files.length; j++) { |
|
173 for (int n = 0; n < nffiles.length; n++) { |
|
174 if (files[j].equals(nffiles[n])) { |
|
175 filearr.add(files[j]); |
|
176 break; |
|
177 } |
|
178 } |
|
179 } |
|
180 } |
|
181 files = new String[filearr.size()]; |
|
182 for (int i = 0; i < files.length; i++) { |
|
183 files[i] = (String)filearr.get(i); |
|
184 } |
|
185 } |
|
186 if (files == null || files.length == 0) { |
|
187 files = new String[1]; |
|
188 files[0] = ""; |
|
189 } |
|
190 setFileEntry((d != null) ? d : ".", (f != null) ? f : "", files); |
|
191 } |
|
192 private boolean proceedFiltering(final String dir, String[] nffiles, |
|
193 boolean isPrivileged) |
|
194 { |
|
195 // Transfer the native filtered file list to the doFilter method. |
|
196 NativeFilteredFiles = nffiles; |
|
197 // If we are not on the Toolkit thread we can call doFilter() directly. |
|
198 // If the filter is null no user code will be invoked |
|
199 if (!isPrivileged || filter == null) { |
|
200 try { |
|
201 doFilter(filter, dir); |
|
202 return true; |
|
203 } catch(Exception e) { |
|
204 e.printStackTrace(); |
|
205 return false; |
|
206 } |
|
207 } |
|
208 // Otherwise we have to call user code on EvenDispatchThread |
|
209 final ToolkitThreadBlockedHandler priveleged_lock = |
|
210 MToolkitThreadBlockedHandler.getToolkitThreadBlockedHandler(); |
|
211 final boolean[] finished = new boolean[1]; |
|
212 final boolean[] result = new boolean[1]; |
|
213 finished[0] = false; |
|
214 result[0] = false; |
|
215 |
|
216 |
|
217 // Use the same Toolkit blocking mechanism as in DnD. |
|
218 priveleged_lock.lock(); |
|
219 |
|
220 MToolkit.executeOnEventHandlerThread((FileDialog)target, new Runnable() { |
|
221 public void run() { |
|
222 priveleged_lock.lock(); |
|
223 try { |
|
224 doFilter(filter, dir); |
|
225 result[0] = true; |
|
226 } catch (Exception e) { |
|
227 e.printStackTrace(); |
|
228 result[0] = false; |
|
229 } finally { |
|
230 finished[0] = true; |
|
231 priveleged_lock.exit(); |
|
232 priveleged_lock.unlock(); |
|
233 } |
|
234 } |
|
235 }); |
|
236 |
|
237 while (!finished[0]) { |
|
238 priveleged_lock.enter(); |
|
239 } |
|
240 |
|
241 priveleged_lock.unlock(); |
|
242 |
|
243 return result[0]; |
|
244 } |
|
245 |
|
246 public void setFilenameFilter(FilenameFilter filter) { |
|
247 this.filter = filter; |
|
248 FileDialog fdialog = (FileDialog)target; |
|
249 String dir = fdialog.getDirectory(); |
|
250 String file = fdialog.getFile(); |
|
251 setFile(file); |
|
252 doFilter(filter, null); |
|
253 } |
|
254 |
|
255 // Called from native widget when paste key is pressed and we |
|
256 // already own the selection (prevents Motif from hanging while |
|
257 // waiting for the selection) |
|
258 // |
|
259 public void pasteFromClipboard() { |
|
260 Clipboard clipboard = target.getToolkit().getSystemClipboard(); |
|
261 |
|
262 Transferable content = clipboard.getContents(this); |
|
263 if (content != null) { |
|
264 try { |
|
265 String data = (String)(content.getTransferData(DataFlavor.stringFlavor)); |
|
266 insertReplaceFileDialogText(data); |
|
267 } catch (Exception e) { |
|
268 } |
|
269 } |
|
270 } |
|
271 |
|
272 // CAVEAT: |
|
273 // Peer coalescing code turned over the fact that the following functions |
|
274 // were being inherited from Dialog and were not implemented in awt_FileDialog.c |
|
275 // Five methods decribed by the peer interface are at fault (setResizable, setTitle, |
|
276 // toFront, toBack and handleFocusTraversalEvent). Additionally show has to be overridden |
|
277 // as it was necessary to add a show function in MDialogPeer for modality flag passing. |
|
278 // As a result we were winding up in awt_Dialog.c (now coalesced into awt_TopLevel). |
|
279 // As Filedialogs are modal and its unclear to me that any of these functions |
|
280 // can be called while the FD is on-screen let it go. RJM. |
|
281 public void show() { |
|
282 // must have our own show or we wind up in pShow for Window. Bad. Very bad. |
|
283 setVisible(true); |
|
284 setFilenameFilter(filter); |
|
285 } |
|
286 |
|
287 /** |
|
288 * MFileDialogPeer doesn't have native pData so we don't do restack on it |
|
289 * @see java.awt.peer.ContainerPeer#restack |
|
290 */ |
|
291 public void restack() { |
|
292 } |
|
293 |
|
294 /** |
|
295 * @see java.awt.peer.ContainerPeer#isRestackSupported |
|
296 */ |
|
297 public boolean isRestackSupported() { |
|
298 return false; |
|
299 } |
|
300 } |
|