1 /* 2 * Copyright (c) 2011, 2020, 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 26 package sun.lwawt.macosx; 27 28 import java.awt.AWTEvent; 29 import java.awt.AWTException; 30 import java.awt.BufferCapabilities; 31 import java.awt.BufferCapabilities.FlipContents; 32 import java.awt.Color; 33 import java.awt.Component; 34 import java.awt.Dialog; 35 import java.awt.Dimension; 36 import java.awt.FileDialog; 37 import java.awt.Font; 38 import java.awt.FontMetrics; 39 import java.awt.Graphics; 40 import java.awt.GraphicsConfiguration; 41 import java.awt.Image; 42 import java.awt.Insets; 43 import java.awt.Point; 44 import java.awt.Window; 45 import java.awt.event.FocusEvent.Cause; 46 import java.awt.event.PaintEvent; 47 import java.awt.image.ColorModel; 48 import java.awt.image.VolatileImage; 49 import java.awt.peer.ComponentPeer; 50 import java.awt.peer.ContainerPeer; 51 import java.awt.peer.FileDialogPeer; 52 import java.io.File; 53 import java.io.FilenameFilter; 54 import java.security.AccessController; 55 import java.util.List; 56 57 import sun.awt.AWTAccessor; 58 import sun.java2d.pipe.Region; 59 import sun.security.action.GetBooleanAction; 60 61 class CFileDialog implements FileDialogPeer { 62 63 private class Task implements Runnable { 64 65 @Override 66 public void run() { 67 try { 68 boolean navigateApps = !AccessController.doPrivileged( 69 new GetBooleanAction("apple.awt.use-file-dialog-packages")); 70 boolean chooseDirectories = AccessController.doPrivileged( 71 new GetBooleanAction("apple.awt.fileDialogForDirectories")); 72 73 int dialogMode = target.getMode(); 74 String title = target.getTitle(); 75 if (title == null) { 76 title = " "; 77 } 78 79 String[] userFileNames = nativeRunFileDialog(title, 80 dialogMode, 81 target.isMultipleMode(), 82 navigateApps, 83 chooseDirectories, 84 target.getFilenameFilter() != null, 85 target.getDirectory(), 86 target.getFile()); 87 88 String directory = null; 89 String file = null; 90 File[] files = null; 91 92 if (userFileNames != null) { 93 // the dialog wasn't cancelled 94 int filesNumber = userFileNames.length; 95 files = new File[filesNumber]; 96 for (int i = 0; i < filesNumber; i++) { 97 files[i] = new File(userFileNames[i]); 98 } 99 100 directory = files[0].getParent(); 101 // make sure directory always ends in '/' 102 if (!directory.endsWith(File.separator)) { 103 directory = directory + File.separator; 104 } 105 106 file = files[0].getName(); // pick any file 107 } 108 109 // store results back in component 110 AWTAccessor.FileDialogAccessor accessor = AWTAccessor.getFileDialogAccessor(); 111 accessor.setDirectory(target, directory); 112 accessor.setFile(target, file); 113 accessor.setFiles(target, files); 114 } finally { 115 // Java2 Dialog waits for hide to let show() return 116 target.dispose(); 117 } 118 } 119 } 120 121 // The target FileDialog 122 private final FileDialog target; 123 124 CFileDialog(FileDialog target) { 125 this.target = target; 126 } 127 128 @Override 129 public void dispose() { 130 LWCToolkit.targetDisposedPeer(target, this); 131 // Unlike other peers, we do not have a native model pointer to 132 // dispose of because the save and open panels are never released by 133 // an application. 134 } 135 136 @Override 137 public void setVisible(boolean visible) { 138 if (visible) { 139 // Java2 Dialog class requires peer to run code in a separate thread 140 // and handles keeping the call modal 141 new Thread(null, new Task(), "FileDialog", 0, false).start(); 142 } 143 // We hide ourself before "show" returns - setVisible(false) 144 // doesn't apply 145 } 146 147 /** 148 * A callback method. 149 * If the file dialog has a file filter, ask it if inFilename is acceptable. 150 * If the dialog doesn't have a file filter return true. 151 */ 152 private boolean queryFilenameFilter(final String inFilename) { 153 boolean ret = false; 154 155 final FilenameFilter ff = target.getFilenameFilter(); 156 File fileObj = new File(inFilename); 157 158 // Directories are never filtered by the FileDialog. 159 if (!fileObj.isDirectory()) { 160 File directoryObj = new File(fileObj.getParent()); 161 String nameOnly = fileObj.getName(); 162 ret = ff.accept(directoryObj, nameOnly); 163 } 164 return ret; 165 } 166 167 private native String[] nativeRunFileDialog(String title, int mode, 168 boolean multipleMode, boolean shouldNavigateApps, 169 boolean canChooseDirectories, boolean hasFilenameFilter, 170 String directory, String file); 171 172 @Override 173 public void setDirectory(String dir) { 174 } 175 176 @Override 177 public void setFile(String file) { 178 } 179 180 @Override 181 public void setFilenameFilter(FilenameFilter filter) { 182 } 183 184 @Override 185 public void blockWindows(List<Window> windows) { 186 } 187 188 @Override 189 public void setResizable(boolean resizeable) { 190 } 191 192 @Override 193 public void setTitle(String title) { 194 } 195 196 @Override 197 public void repositionSecurityWarning() { 198 } 199 200 @Override 201 public void updateAlwaysOnTopState() { 202 } 203 204 @Override 205 public void setModalBlocked(Dialog blocker, boolean blocked) { 206 } 207 208 @Override 209 public void setOpacity(float opacity) { 210 } 211 212 @Override 213 public void setOpaque(boolean isOpaque) { 214 } 215 216 @Override 217 public void toBack() { 218 } 219 220 @Override 221 public void toFront() { 222 } 223 224 @Override 225 public void updateFocusableWindowState() { 226 } 227 228 @Override 229 public void updateIconImages() { 230 } 231 232 @Override 233 public void updateMinimumSize() { 234 } 235 236 @Override 237 public void updateWindow() { 238 } 239 240 @Override 241 public void beginLayout() { 242 } 243 244 @Override 245 public void beginValidate() { 246 } 247 248 @Override 249 public void endLayout() { 250 } 251 252 @Override 253 public void endValidate() { 254 } 255 256 @Override 257 public Insets getInsets() { 258 return new Insets(0, 0, 0, 0); 259 } 260 261 @Override 262 public void applyShape(Region shape) { 263 } 264 265 @Override 266 public boolean canDetermineObscurity() { 267 return false; 268 } 269 270 @Override 271 public void coalescePaintEvent(PaintEvent e) { 272 } 273 274 @Override 275 public void createBuffers(int numBuffers, BufferCapabilities caps) 276 throws AWTException { 277 } 278 279 @Override 280 public Image createImage(int width, int height) { 281 return null; 282 } 283 284 @Override 285 public VolatileImage createVolatileImage(int width, int height) { 286 return null; 287 } 288 289 @Override 290 public void destroyBuffers() { 291 } 292 293 @Override 294 public void flip(int x1, int y1, int x2, int y2, FlipContents flipAction) { 295 } 296 297 @Override 298 public Image getBackBuffer() { 299 return null; 300 } 301 302 @Override 303 public ColorModel getColorModel() { 304 return null; 305 } 306 307 @Override 308 public FontMetrics getFontMetrics(Font font) { 309 return null; 310 } 311 312 @Override 313 public Graphics getGraphics() { 314 return null; 315 } 316 317 @Override 318 public GraphicsConfiguration getGraphicsConfiguration() { 319 return null; 320 } 321 322 @Override 323 public Point getLocationOnScreen() { 324 return null; 325 } 326 327 @Override 328 public Dimension getMinimumSize() { 329 return target.getSize(); 330 } 331 332 @Override 333 public Dimension getPreferredSize() { 334 return getMinimumSize(); 335 } 336 337 @Override 338 public void handleEvent(AWTEvent e) { 339 } 340 341 @Override 342 public boolean handlesWheelScrolling() { 343 return false; 344 } 345 346 @Override 347 public boolean isFocusable() { 348 return false; 349 } 350 351 @Override 352 public boolean isObscured() { 353 return false; 354 } 355 356 @Override 357 public boolean isReparentSupported() { 358 return false; 359 } 360 361 @Override 362 public void layout() { 363 } 364 365 @Override 366 public void paint(Graphics g) { 367 } 368 369 @Override 370 public void print(Graphics g) { 371 } 372 373 @Override 374 public void reparent(ContainerPeer newContainer) { 375 } 376 377 @Override 378 public boolean requestFocus(Component lightweightChild, boolean temporary, 379 boolean focusedWindowChangeAllowed, long time, Cause cause) { 380 return false; 381 } 382 383 @Override 384 public void setBackground(Color c) { 385 } 386 387 @Override 388 public void setForeground(Color c) { 389 } 390 391 @Override 392 public void setBounds(int x, int y, int width, int height, int op) { 393 } 394 395 @Override 396 public void setEnabled(boolean e) { 397 } 398 399 @Override 400 public void setFont(Font f) { 401 } 402 403 @Override 404 public void setZOrder(ComponentPeer above) { 405 } 406 407 @Override 408 public void updateCursorImmediately() { 409 } 410 411 @Override 412 public boolean updateGraphicsData(GraphicsConfiguration gc) { 413 return false; 414 } 415 }