1 /* 2 * Copyright (c) 1995, 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 java.awt; 26 27 import java.awt.peer.FileDialogPeer; 28 import java.io.FilenameFilter; 29 import java.io.IOException; 30 import java.io.ObjectInputStream; 31 import java.io.File; 32 import sun.awt.AWTAccessor; 33 34 /** 35 * The <code>FileDialog</code> class displays a dialog window 36 * from which the user can select a file. 37 * <p> 38 * Since it is a modal dialog, when the application calls 39 * its <code>show</code> method to display the dialog, 40 * it blocks the rest of the application until the user has 41 * chosen a file. 42 * 43 * @see Window#show 44 * 45 * @author Sami Shaio 46 * @author Arthur van Hoff 47 * @since 1.0 48 */ 49 public class FileDialog extends Dialog { 50 51 /** 52 * This constant value indicates that the purpose of the file 53 * dialog window is to locate a file from which to read. 54 */ 55 public static final int LOAD = 0; 56 57 /** 58 * This constant value indicates that the purpose of the file 59 * dialog window is to locate a file to which to write. 60 */ 61 public static final int SAVE = 1; 62 63 /* 64 * There are two <code>FileDialog</code> modes: <code>LOAD</code> and 65 * <code>SAVE</code>. 66 * This integer will represent one or the other. 67 * If the mode is not specified it will default to <code>LOAD</code>. 68 * 69 * @serial 70 * @see getMode() 71 * @see setMode() 72 * @see java.awt.FileDialog#LOAD 73 * @see java.awt.FileDialog#SAVE 74 */ 75 int mode; 76 77 /* 78 * The string specifying the directory to display 79 * in the file dialog. This variable may be <code>null</code>. 80 * 81 * @serial 82 * @see getDirectory() 83 * @see setDirectory() 84 */ 85 String dir; 86 87 /* 88 * The string specifying the initial value of the 89 * filename text field in the file dialog. 90 * This variable may be <code>null</code>. 91 * 92 * @serial 93 * @see getFile() 94 * @see setFile() 95 */ 96 String file; 97 98 /** 99 * Contains the File instances for all the files that the user selects. 100 * 101 * @serial 102 * @see #getFiles 103 * @since 1.7 104 */ 105 private File[] files; 106 107 /** 108 * Represents whether the file dialog allows the multiple file selection. 109 * 110 * @serial 111 * @see #setMultipleMode 112 * @see #isMultipleMode 113 * @since 1.7 114 */ 115 private boolean multipleMode = false; 116 117 /* 118 * The filter used as the file dialog's filename filter. 119 * The file dialog will only be displaying files whose 120 * names are accepted by this filter. 121 * This variable may be <code>null</code>. 122 * 123 * @serial 124 * @see #getFilenameFilter() 125 * @see #setFilenameFilter() 126 * @see FileNameFilter 127 */ 128 FilenameFilter filter; 129 130 private static final String base = "filedlg"; 131 private static int nameCounter = 0; 132 133 /* 134 * JDK 1.1 serialVersionUID 135 */ 136 private static final long serialVersionUID = 5035145889651310422L; 137 138 139 static { 140 /* ensure that the necessary native libraries are loaded */ 141 Toolkit.loadLibraries(); 142 if (!GraphicsEnvironment.isHeadless()) { 143 initIDs(); 144 } 145 } 146 147 static { 148 AWTAccessor.setFileDialogAccessor( 149 new AWTAccessor.FileDialogAccessor() { 150 public void setFiles(FileDialog fileDialog, File files[]) { 151 fileDialog.setFiles(files); 152 } 153 public void setFile(FileDialog fileDialog, String file) { 154 fileDialog.file = ("".equals(file)) ? null : file; 155 } 156 public void setDirectory(FileDialog fileDialog, String directory) { 157 fileDialog.dir = ("".equals(directory)) ? null : directory; 158 } 159 public boolean isMultipleMode(FileDialog fileDialog) { 160 synchronized (fileDialog.getObjectLock()) { 161 return fileDialog.multipleMode; 162 } 163 } 164 }); 165 } 166 167 /** 168 * Initialize JNI field and method IDs for fields that may be 169 accessed from C. 170 */ 171 private static native void initIDs(); 172 173 /** 174 * Creates a file dialog for loading a file. The title of the 175 * file dialog is initially empty. This is a convenience method for 176 * <code>FileDialog(parent, "", LOAD)</code>. 177 * 178 * @param parent the owner of the dialog 179 * @since 1.1 180 */ 181 public FileDialog(Frame parent) { 182 this(parent, "", LOAD); 183 } 184 185 /** 186 * Creates a file dialog window with the specified title for loading 187 * a file. The files shown are those in the current directory. 188 * This is a convenience method for 189 * <code>FileDialog(parent, title, LOAD)</code>. 190 * 191 * @param parent the owner of the dialog 192 * @param title the title of the dialog 193 */ 194 public FileDialog(Frame parent, String title) { 195 this(parent, title, LOAD); 196 } 197 198 /** 199 * Creates a file dialog window with the specified title for loading 200 * or saving a file. 201 * <p> 202 * If the value of <code>mode</code> is <code>LOAD</code>, then the 203 * file dialog is finding a file to read, and the files shown are those 204 * in the current directory. If the value of 205 * <code>mode</code> is <code>SAVE</code>, the file dialog is finding 206 * a place to write a file. 207 * 208 * @param parent the owner of the dialog 209 * @param title the title of the dialog 210 * @param mode the mode of the dialog; either 211 * <code>FileDialog.LOAD</code> or <code>FileDialog.SAVE</code> 212 * @exception IllegalArgumentException if an illegal file 213 * dialog mode is supplied 214 * @see java.awt.FileDialog#LOAD 215 * @see java.awt.FileDialog#SAVE 216 */ 217 public FileDialog(Frame parent, String title, int mode) { 218 super(parent, title, true); 219 this.setMode(mode); 220 setLayout(null); 221 } 222 223 /** 224 * Creates a file dialog for loading a file. The title of the 225 * file dialog is initially empty. This is a convenience method for 226 * <code>FileDialog(parent, "", LOAD)</code>. 227 * 228 * @param parent the owner of the dialog 229 * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s 230 * <code>GraphicsConfiguration</code> 231 * is not from a screen device; 232 * @exception java.lang.IllegalArgumentException if <code>parent</code> 233 * is <code>null</code>; this exception is always thrown when 234 * <code>GraphicsEnvironment.isHeadless</code> 235 * returns <code>true</code> 236 * @see java.awt.GraphicsEnvironment#isHeadless 237 * @since 1.5 238 */ 239 public FileDialog(Dialog parent) { 240 this(parent, "", LOAD); 241 } 242 243 /** 244 * Creates a file dialog window with the specified title for loading 245 * a file. The files shown are those in the current directory. 246 * This is a convenience method for 247 * <code>FileDialog(parent, title, LOAD)</code>. 248 * 249 * @param parent the owner of the dialog 250 * @param title the title of the dialog; a <code>null</code> value 251 * will be accepted without causing a 252 * <code>NullPointerException</code> to be thrown 253 * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s 254 * <code>GraphicsConfiguration</code> 255 * is not from a screen device; 256 * @exception java.lang.IllegalArgumentException if <code>parent</code> 257 * is <code>null</code>; this exception is always thrown when 258 * <code>GraphicsEnvironment.isHeadless</code> 259 * returns <code>true</code> 260 * @see java.awt.GraphicsEnvironment#isHeadless 261 * @since 1.5 262 */ 263 public FileDialog(Dialog parent, String title) { 264 this(parent, title, LOAD); 265 } 266 267 /** 268 * Creates a file dialog window with the specified title for loading 269 * or saving a file. 270 * <p> 271 * If the value of <code>mode</code> is <code>LOAD</code>, then the 272 * file dialog is finding a file to read, and the files shown are those 273 * in the current directory. If the value of 274 * <code>mode</code> is <code>SAVE</code>, the file dialog is finding 275 * a place to write a file. 276 * 277 * @param parent the owner of the dialog 278 * @param title the title of the dialog; a <code>null</code> value 279 * will be accepted without causing a 280 * <code>NullPointerException</code> to be thrown 281 * @param mode the mode of the dialog; either 282 * <code>FileDialog.LOAD</code> or <code>FileDialog.SAVE</code> 283 * @exception java.lang.IllegalArgumentException if an illegal 284 * file dialog mode is supplied; 285 * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s 286 * <code>GraphicsConfiguration</code> 287 * is not from a screen device; 288 * @exception java.lang.IllegalArgumentException if <code>parent</code> 289 * is <code>null</code>; this exception is always thrown when 290 * <code>GraphicsEnvironment.isHeadless</code> 291 * returns <code>true</code> 292 * @see java.awt.GraphicsEnvironment#isHeadless 293 * @see java.awt.FileDialog#LOAD 294 * @see java.awt.FileDialog#SAVE 295 * @since 1.5 296 */ 297 public FileDialog(Dialog parent, String title, int mode) { 298 super(parent, title, true); 299 this.setMode(mode); 300 setLayout(null); 301 } 302 303 /** 304 * Constructs a name for this component. Called by <code>getName()</code> 305 * when the name is <code>null</code>. 306 */ 307 String constructComponentName() { 308 synchronized (FileDialog.class) { 309 return base + nameCounter++; 310 } 311 } 312 313 /** 314 * Creates the file dialog's peer. The peer allows us to change the look 315 * of the file dialog without changing its functionality. 316 */ 317 @SuppressWarnings("deprecation") 318 public void addNotify() { 319 synchronized(getTreeLock()) { 320 if (parent != null && parent.getPeer() == null) { 321 parent.addNotify(); 322 } 323 if (peer == null) 324 peer = getToolkit().createFileDialog(this); 325 super.addNotify(); 326 } 327 } 328 329 /** 330 * Indicates whether this file dialog box is for loading from a file 331 * or for saving to a file. 332 * 333 * @return the mode of this file dialog window, either 334 * <code>FileDialog.LOAD</code> or 335 * <code>FileDialog.SAVE</code> 336 * @see java.awt.FileDialog#LOAD 337 * @see java.awt.FileDialog#SAVE 338 * @see java.awt.FileDialog#setMode 339 */ 340 public int getMode() { 341 return mode; 342 } 343 344 /** 345 * Sets the mode of the file dialog. If <code>mode</code> is not 346 * a legal value, an exception will be thrown and <code>mode</code> 347 * will not be set. 348 * 349 * @param mode the mode for this file dialog, either 350 * <code>FileDialog.LOAD</code> or 351 * <code>FileDialog.SAVE</code> 352 * @see java.awt.FileDialog#LOAD 353 * @see java.awt.FileDialog#SAVE 354 * @see java.awt.FileDialog#getMode 355 * @exception IllegalArgumentException if an illegal file 356 * dialog mode is supplied 357 * @since 1.1 358 */ 359 public void setMode(int mode) { 360 switch (mode) { 361 case LOAD: 362 case SAVE: 363 this.mode = mode; 364 break; 365 default: 366 throw new IllegalArgumentException("illegal file dialog mode"); 367 } 368 } 369 370 /** 371 * Gets the directory of this file dialog. 372 * 373 * @return the (potentially <code>null</code> or invalid) 374 * directory of this <code>FileDialog</code> 375 * @see java.awt.FileDialog#setDirectory 376 */ 377 public String getDirectory() { 378 return dir; 379 } 380 381 /** 382 * Sets the directory of this file dialog window to be the 383 * specified directory. Specifying a <code>null</code> or an 384 * invalid directory implies an implementation-defined default. 385 * This default will not be realized, however, until the user 386 * has selected a file. Until this point, <code>getDirectory()</code> 387 * will return the value passed into this method. 388 * <p> 389 * Specifying "" as the directory is exactly equivalent to 390 * specifying <code>null</code> as the directory. 391 * 392 * @param dir the specified directory 393 * @see java.awt.FileDialog#getDirectory 394 */ 395 public void setDirectory(String dir) { 396 this.dir = (dir != null && dir.equals("")) ? null : dir; 397 FileDialogPeer peer = (FileDialogPeer)this.peer; 398 if (peer != null) { 399 peer.setDirectory(this.dir); 400 } 401 } 402 403 /** 404 * Gets the selected file of this file dialog. If the user 405 * selected <code>CANCEL</code>, the returned file is <code>null</code>. 406 * 407 * @return the currently selected file of this file dialog window, 408 * or <code>null</code> if none is selected 409 * @see java.awt.FileDialog#setFile 410 */ 411 public String getFile() { 412 return file; 413 } 414 415 /** 416 * Returns files that the user selects. 417 * <p> 418 * If the user cancels the file dialog, 419 * then the method returns an empty array. 420 * 421 * @return files that the user selects or an empty array 422 * if the user cancels the file dialog. 423 * @see #setFile(String) 424 * @see #getFile 425 * @since 1.7 426 */ 427 public File[] getFiles() { 428 synchronized (getObjectLock()) { 429 if (files != null) { 430 return files.clone(); 431 } else { 432 return new File[0]; 433 } 434 } 435 } 436 437 /** 438 * Stores the names of all the files that the user selects. 439 * 440 * Note that the method is private and it's intended to be used 441 * by the peers through the AWTAccessor API. 442 * 443 * @param files the array that contains the short names of 444 * all the files that the user selects. 445 * 446 * @see #getFiles 447 * @since 1.7 448 */ 449 private void setFiles(File files[]) { 450 synchronized (getObjectLock()) { 451 this.files = files; 452 } 453 } 454 455 /** 456 * Sets the selected file for this file dialog window to be the 457 * specified file. This file becomes the default file if it is set 458 * before the file dialog window is first shown. 459 * <p> 460 * When the dialog is shown, the specified file is selected. The kind of 461 * selection depends on the file existence, the dialog type, and the native 462 * platform. E.g., the file could be highlighted in the file list, or a 463 * file name editbox could be populated with the file name. 464 * <p> 465 * This method accepts either a full file path, or a file name with an 466 * extension if used together with the {@code setDirectory} method. 467 * <p> 468 * Specifying "" as the file is exactly equivalent to specifying 469 * {@code null} as the file. 470 * 471 * @param file the file being set 472 * @see #getFile 473 * @see #getFiles 474 */ 475 public void setFile(String file) { 476 this.file = (file != null && file.equals("")) ? null : file; 477 FileDialogPeer peer = (FileDialogPeer)this.peer; 478 if (peer != null) { 479 peer.setFile(this.file); 480 } 481 } 482 483 /** 484 * Enables or disables multiple file selection for the file dialog. 485 * 486 * @param enable if {@code true}, multiple file selection is enabled; 487 * {@code false} - disabled. 488 * @see #isMultipleMode 489 * @since 1.7 490 */ 491 public void setMultipleMode(boolean enable) { 492 synchronized (getObjectLock()) { 493 this.multipleMode = enable; 494 } 495 } 496 497 /** 498 * Returns whether the file dialog allows the multiple file selection. 499 * 500 * @return {@code true} if the file dialog allows the multiple 501 * file selection; {@code false} otherwise. 502 * @see #setMultipleMode 503 * @since 1.7 504 */ 505 public boolean isMultipleMode() { 506 synchronized (getObjectLock()) { 507 return multipleMode; 508 } 509 } 510 511 /** 512 * Determines this file dialog's filename filter. A filename filter 513 * allows the user to specify which files appear in the file dialog 514 * window. Filename filters do not function in Sun's reference 515 * implementation for Microsoft Windows. 516 * 517 * @return this file dialog's filename filter 518 * @see java.io.FilenameFilter 519 * @see java.awt.FileDialog#setFilenameFilter 520 */ 521 public FilenameFilter getFilenameFilter() { 522 return filter; 523 } 524 525 /** 526 * Sets the filename filter for this file dialog window to the 527 * specified filter. 528 * Filename filters do not function in Sun's reference 529 * implementation for Microsoft Windows. 530 * 531 * @param filter the specified filter 532 * @see java.io.FilenameFilter 533 * @see java.awt.FileDialog#getFilenameFilter 534 */ 535 public synchronized void setFilenameFilter(FilenameFilter filter) { 536 this.filter = filter; 537 FileDialogPeer peer = (FileDialogPeer)this.peer; 538 if (peer != null) { 539 peer.setFilenameFilter(filter); 540 } 541 } 542 543 /** 544 * Reads the <code>ObjectInputStream</code> and performs 545 * a backwards compatibility check by converting 546 * either a <code>dir</code> or a <code>file</code> 547 * equal to an empty string to <code>null</code>. 548 * 549 * @param s the <code>ObjectInputStream</code> to read 550 */ 551 private void readObject(ObjectInputStream s) 552 throws ClassNotFoundException, IOException 553 { 554 s.defaultReadObject(); 555 556 // 1.1 Compatibility: "" is not converted to null in 1.1 557 if (dir != null && dir.equals("")) { 558 dir = null; 559 } 560 if (file != null && file.equals("")) { 561 file = null; 562 } 563 } 564 565 /** 566 * Returns a string representing the state of this <code>FileDialog</code> 567 * window. This method is intended to be used only for debugging purposes, 568 * and the content and format of the returned string may vary between 569 * implementations. The returned string may be empty but may not be 570 * <code>null</code>. 571 * 572 * @return the parameter string of this file dialog window 573 */ 574 protected String paramString() { 575 String str = super.paramString(); 576 str += ",dir= " + dir; 577 str += ",file= " + file; 578 return str + ((mode == LOAD) ? ",load" : ",save"); 579 } 580 581 boolean postsOldMouseEvents() { 582 return false; 583 } 584 }