1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt.windows; 26 27 import java.awt.*; 28 import java.awt.dnd.DropTarget; 29 import java.awt.peer.*; 30 import java.io.File; 31 import java.io.FilenameFilter; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import java.util.ResourceBundle; 35 import java.util.MissingResourceException; 36 import java.util.Vector; 37 import sun.awt.CausedFocusEvent; 38 import sun.awt.AWTAccessor; 39 40 final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { 41 42 static { 43 initIDs(); 44 } 45 46 private WComponentPeer parent; 47 private FilenameFilter fileFilter; 48 49 private Vector<WWindowPeer> blockedWindows = new Vector<>(); 50 51 //Needed to fix 4152317 52 private static native void setFilterString(String allFilter); 53 54 @Override 55 public void setFilenameFilter(FilenameFilter filter) { 56 this.fileFilter = filter; 57 } 58 59 boolean checkFilenameFilter(String filename) { 60 FileDialog fileDialog = (FileDialog)target; 61 if (fileFilter == null) { 62 return true; 63 } 64 File file = new File(filename); 65 return fileFilter.accept(new File(file.getParent()), file.getName()); 66 } 67 68 // Toolkit & peer internals 69 WFileDialogPeer(FileDialog target) { 70 super(target); 71 } 72 73 @Override 74 void create(WComponentPeer parent) { 75 this.parent = parent; 76 } 77 78 // don't use checkCreation() from WComponentPeer to avoid hwnd check 79 @Override 80 protected void checkCreation() { 81 } 82 83 @Override 84 void initialize() { 85 setFilenameFilter(((FileDialog) target).getFilenameFilter()); 86 } 87 88 private native void _dispose(); 89 @Override 90 protected void disposeImpl() { 91 WToolkit.targetDisposedPeer(target, this); 92 _dispose(); 93 } 94 95 private native void _show(); 96 private native void _hide(); 97 98 @Override 99 public void show() { 100 new Thread(new Runnable() { 101 @Override 102 public void run() { 103 _show(); 104 } 105 }).start(); 106 } 107 108 @Override 109 void hide() { 110 _hide(); 111 } 112 113 // called from native code when the dialog is shown or hidden 114 void setHWnd(long hwnd) { 115 if (this.hwnd == hwnd) { 116 return; 117 } 118 this.hwnd = hwnd; 119 for (WWindowPeer window : blockedWindows) { 120 if (hwnd != 0) { 121 window.modalDisable((Dialog)target, hwnd); 122 } else { 123 window.modalEnable((Dialog)target); 124 } 125 } 126 } 127 128 /* 129 * The function converts the file names (the buffer parameter) 130 * in the Windows format into the Java format and saves the results 131 * into the FileDialog instance. 132 * 133 * If it's the multi-select mode, the buffer contains the current 134 * directory followed by the short names of the files. 135 * The directory and file name strings are NULL separated. 136 * If it's the single-select mode, the buffer doesn't have the NULL 137 * separator between the path and the file name. 138 * 139 * NOTE: This method is called by privileged threads. 140 * DO NOT INVOKE CLIENT CODE ON THIS THREAD! 141 */ 142 void handleSelected(final char[] buffer) 143 { 144 String[] wFiles = (new String(buffer)).split("\0"); // NULL is the delimiter 145 boolean multiple = (wFiles.length > 1); 146 147 String jDirectory = null; 148 String jFile = null; 149 File[] jFiles = null; 150 151 if (multiple) { 152 jDirectory = wFiles[0]; 153 int filesNumber = wFiles.length - 1; 154 jFiles = new File[filesNumber]; 155 for (int i = 0; i < filesNumber; i++) { 156 jFiles[i] = new File(jDirectory, wFiles[i + 1]); 157 } 158 jFile = wFiles[1]; // choose any file 159 } else { 160 int index = wFiles[0].lastIndexOf(java.io.File.separatorChar); 161 if (index == -1) { 162 jDirectory = "."+java.io.File.separator; 163 jFile = wFiles[0]; 164 } else { 165 jDirectory = wFiles[0].substring(0, index + 1); 166 jFile = wFiles[0].substring(index + 1); 167 } 168 jFiles = new File[] { new File(jDirectory, jFile) }; 169 } 170 171 final FileDialog fileDialog = (FileDialog)target; 172 AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor(); 173 174 fileDialogAccessor.setDirectory(fileDialog, jDirectory); 175 fileDialogAccessor.setFile(fileDialog, jFile); 176 fileDialogAccessor.setFiles(fileDialog, jFiles); 177 178 WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { 179 @Override 180 public void run() { 181 fileDialog.setVisible(false); 182 } 183 }); 184 } // handleSelected() 185 186 // NOTE: This method is called by privileged threads. 187 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 188 void handleCancel() { 189 final FileDialog fileDialog = (FileDialog)target; 190 191 AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null); 192 AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null); 193 AWTAccessor.getFileDialogAccessor().setDirectory(fileDialog, null); 194 195 WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { 196 @Override 197 public void run() { 198 fileDialog.setVisible(false); 199 } 200 }); 201 } // handleCancel() 202 203 //This whole static block is a part of 4152317 fix 204 static { 205 String filterString = AccessController.doPrivileged( 206 new PrivilegedAction<String>() { 207 @Override 208 public String run() { 209 try { 210 ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization"); 211 return rb.getString("allFiles"); 212 } catch (MissingResourceException e) { 213 return "All Files"; 214 } 215 } 216 }); 217 setFilterString(filterString); 218 } 219 220 void blockWindow(WWindowPeer window) { 221 blockedWindows.add(window); 222 // if this dialog hasn't got an HWND, notification is 223 // postponed until setHWnd() is called 224 if (hwnd != 0) { 225 window.modalDisable((Dialog)target, hwnd); 226 } 227 } 228 void unblockWindow(WWindowPeer window) { 229 blockedWindows.remove(window); 230 // if this dialog hasn't got an HWND or has been already 231 // closed, don't send notification 232 if (hwnd != 0) { 233 window.modalEnable((Dialog)target); 234 } 235 } 236 237 @Override 238 public void blockWindows(java.util.List<Window> toBlock) { 239 for (Window w : toBlock) { 240 WWindowPeer wp = (WWindowPeer)AWTAccessor.getComponentAccessor().getPeer(w); 241 if (wp != null) { 242 blockWindow(wp); 243 } 244 } 245 } 246 247 @Override 248 public native void toFront(); 249 @Override 250 public native void toBack(); 251 252 // unused methods. Overridden to disable this functionality as 253 // it requires HWND which is not available for FileDialog 254 @Override 255 public void updateAlwaysOnTopState() {} 256 @Override 257 public void setDirectory(String dir) {} 258 @Override 259 public void setFile(String file) {} 260 @Override 261 public void setTitle(String title) {} 262 263 @Override 264 public void setResizable(boolean resizable) {} 265 @Override 266 void enable() {} 267 @Override 268 void disable() {} 269 @Override 270 public void reshape(int x, int y, int width, int height) {} 271 public boolean handleEvent(Event e) { return false; } 272 @Override 273 public void setForeground(Color c) {} 274 @Override 275 public void setBackground(Color c) {} 276 @Override 277 public void setFont(Font f) {} 278 @Override 279 public void updateMinimumSize() {} 280 @Override 281 public void updateIconImages() {} 282 public boolean requestFocus(boolean temporary, 283 boolean focusedWindowChangeAllowed) { 284 return false; 285 } 286 287 @Override 288 public boolean requestFocus 289 (Component lightweightChild, boolean temporary, 290 boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) 291 { 292 return false; 293 } 294 295 @Override 296 void start() {} 297 @Override 298 public void beginValidate() {} 299 @Override 300 public void endValidate() {} 301 void invalidate(int x, int y, int width, int height) {} 302 @Override 303 public void addDropTarget(DropTarget dt) {} 304 @Override 305 public void removeDropTarget(DropTarget dt) {} 306 @Override 307 public void updateFocusableWindowState() {} 308 @Override 309 public void setZOrder(ComponentPeer above) {} 310 311 /** 312 * Initialize JNI field and method ids 313 */ 314 private static native void initIDs(); 315 316 // The effects are not supported for system dialogs. 317 @Override 318 public void applyShape(sun.java2d.pipe.Region shape) {} 319 @Override 320 public void setOpacity(float opacity) {} 321 @Override 322 public void setOpaque(boolean isOpaque) {} 323 public void updateWindow(java.awt.image.BufferedImage backBuffer) {} 324 325 // the file/print dialogs are native dialogs and 326 // the native system does their own rendering 327 @Override 328 public void createScreenSurface(boolean isResize) {} 329 @Override 330 public void replaceSurfaceData() {} 331 332 public boolean isMultipleMode() { 333 FileDialog fileDialog = (FileDialog)target; 334 return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog); 335 } 336 }