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