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