J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package javax.swing; |
| 27 | |
| 28 | import javax.swing.event.*; |
| 29 | import javax.swing.filechooser.*; |
| 30 | import javax.swing.plaf.FileChooserUI; |
| 31 | |
| 32 | import javax.accessibility.*; |
| 33 | |
| 34 | import java.io.File; |
| 35 | import java.io.ObjectOutputStream; |
| 36 | import java.io.IOException; |
| 37 | |
| 38 | import java.util.Vector; |
| 39 | import java.awt.AWTEvent; |
| 40 | import java.awt.Component; |
| 41 | import java.awt.Container; |
| 42 | import java.awt.BorderLayout; |
| 43 | import java.awt.Window; |
| 44 | import java.awt.Dialog; |
| 45 | import java.awt.Frame; |
| 46 | import java.awt.GraphicsEnvironment; |
| 47 | import java.awt.HeadlessException; |
| 48 | import java.awt.EventQueue; |
| 49 | import java.awt.Toolkit; |
| 50 | import java.awt.event.*; |
| 51 | import java.beans.PropertyChangeListener; |
| 52 | import java.beans.PropertyChangeEvent; |
| 53 | import java.lang.ref.WeakReference; |
| 54 | |
| 55 | /** |
| 56 | * <code>JFileChooser</code> provides a simple mechanism for the user to |
| 57 | * choose a file. |
| 58 | * For information about using <code>JFileChooser</code>, see |
| 59 | * <a |
| 60 | href="http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>, |
| 61 | * a section in <em>The Java Tutorial</em>. |
| 62 | * |
| 63 | * <p> |
| 64 | * |
| 65 | * The following code pops up a file chooser for the user's home directory that |
| 66 | * sees only .jpg and .gif images: |
| 67 | * <pre> |
| 68 | * JFileChooser chooser = new JFileChooser(); |
| 69 | * FileNameExtensionFilter filter = new FileNameExtensionFilter( |
| 70 | * "JPG & GIF Images", "jpg", "gif"); |
| 71 | * chooser.setFileFilter(filter); |
| 72 | * int returnVal = chooser.showOpenDialog(parent); |
| 73 | * if(returnVal == JFileChooser.APPROVE_OPTION) { |
| 74 | * System.out.println("You chose to open this file: " + |
| 75 | * chooser.getSelectedFile().getName()); |
| 76 | * } |
| 77 | * </pre> |
| 78 | * <p> |
| 79 | * <strong>Warning:</strong> Swing is not thread safe. For more |
| 80 | * information see <a |
| 81 | * href="package-summary.html#threading">Swing's Threading |
| 82 | * Policy</a>. |
| 83 | * |
| 84 | * @beaninfo |
| 85 | * attribute: isContainer false |
| 86 | * description: A component which allows for the interactive selection of a file. |
| 87 | * |
| 88 | * @author Jeff Dinkins |
| 89 | * |
| 90 | */ |
| 91 | public class JFileChooser extends JComponent implements Accessible { |
| 92 | |
| 93 | /** |
| 94 | * @see #getUIClassID |
| 95 | * @see #readObject |
| 96 | */ |
| 97 | private static final String uiClassID = "FileChooserUI"; |
| 98 | |
| 99 | // ************************ |
| 100 | // ***** Dialog Types ***** |
| 101 | // ************************ |
| 102 | |
| 103 | /** |
| 104 | * Type value indicating that the <code>JFileChooser</code> supports an |
| 105 | * "Open" file operation. |
| 106 | */ |
| 107 | public static final int OPEN_DIALOG = 0; |
| 108 | |
| 109 | /** |
| 110 | * Type value indicating that the <code>JFileChooser</code> supports a |
| 111 | * "Save" file operation. |
| 112 | */ |
| 113 | public static final int SAVE_DIALOG = 1; |
| 114 | |
| 115 | /** |
| 116 | * Type value indicating that the <code>JFileChooser</code> supports a |
| 117 | * developer-specified file operation. |
| 118 | */ |
| 119 | public static final int CUSTOM_DIALOG = 2; |
| 120 | |
| 121 | |
| 122 | // ******************************** |
| 123 | // ***** Dialog Return Values ***** |
| 124 | // ******************************** |
| 125 | |
| 126 | /** |
| 127 | * Return value if cancel is chosen. |
| 128 | */ |
| 129 | public static final int CANCEL_OPTION = 1; |
| 130 | |
| 131 | /** |
| 132 | * Return value if approve (yes, ok) is chosen. |
| 133 | */ |
| 134 | public static final int APPROVE_OPTION = 0; |
| 135 | |
| 136 | /** |
| 137 | * Return value if an error occured. |
| 138 | */ |
| 139 | public static final int ERROR_OPTION = -1; |
| 140 | |
| 141 | |
| 142 | // ********************************** |
| 143 | // ***** JFileChooser properties ***** |
| 144 | // ********************************** |
| 145 | |
| 146 | |
| 147 | /** Instruction to display only files. */ |
| 148 | public static final int FILES_ONLY = 0; |
| 149 | |
| 150 | /** Instruction to display only directories. */ |
| 151 | public static final int DIRECTORIES_ONLY = 1; |
| 152 | |
| 153 | /** Instruction to display both files and directories. */ |
| 154 | public static final int FILES_AND_DIRECTORIES = 2; |
| 155 | |
| 156 | /** Instruction to cancel the current selection. */ |
| 157 | public static final String CANCEL_SELECTION = "CancelSelection"; |
| 158 | |
| 159 | /** |
| 160 | * Instruction to approve the current selection |
| 161 | * (same as pressing yes or ok). |
| 162 | */ |
| 163 | public static final String APPROVE_SELECTION = "ApproveSelection"; |
| 164 | |
| 165 | /** Identifies change in the text on the approve (yes, ok) button. */ |
| 166 | public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty"; |
| 167 | |
| 168 | /** |
| 169 | * Identifies change in the tooltip text for the approve (yes, ok) |
| 170 | * button. |
| 171 | */ |
| 172 | public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty"; |
| 173 | |
| 174 | /** Identifies change in the mnemonic for the approve (yes, ok) button. */ |
| 175 | public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty"; |
| 176 | |
| 177 | /** Instruction to display the control buttons. */ |
| 178 | public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty"; |
| 179 | |
| 180 | /** Identifies user's directory change. */ |
| 181 | public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged"; |
| 182 | |
| 183 | /** Identifies change in user's single-file selection. */ |
| 184 | public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty"; |
| 185 | |
| 186 | /** Identifies change in user's multiple-file selection. */ |
| 187 | public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty"; |
| 188 | |
| 189 | /** Enables multiple-file selections. */ |
| 190 | public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty"; |
| 191 | |
| 192 | /** |
| 193 | * Says that a different object is being used to find available drives |
| 194 | * on the system. |
| 195 | */ |
| 196 | public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged"; |
| 197 | |
| 198 | /** |
| 199 | * Says that a different object is being used to retrieve file |
| 200 | * information. |
| 201 | */ |
| 202 | public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged"; |
| 203 | |
| 204 | /** Identifies a change in the display-hidden-files property. */ |
| 205 | public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged"; |
| 206 | |
| 207 | /** User changed the kind of files to display. */ |
| 208 | public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged"; |
| 209 | |
| 210 | /** |
| 211 | * Identifies a change in the kind of selection (single, |
| 212 | * multiple, etc.). |
| 213 | */ |
| 214 | public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged"; |
| 215 | |
| 216 | /** |
| 217 | * Says that a different accessory component is in use |
| 218 | * (for example, to preview files). |
| 219 | */ |
| 220 | public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty"; |
| 221 | |
| 222 | /** |
| 223 | * Identifies whether a the AcceptAllFileFilter is used or not. |
| 224 | */ |
| 225 | public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged"; |
| 226 | |
| 227 | /** Identifies a change in the dialog title. */ |
| 228 | public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty"; |
| 229 | |
| 230 | /** |
| 231 | * Identifies a change in the type of files displayed (files only, |
| 232 | * directories only, or both files and directories). |
| 233 | */ |
| 234 | public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty"; |
| 235 | |
| 236 | /** |
| 237 | * Identifies a change in the list of predefined file filters |
| 238 | * the user can choose from. |
| 239 | */ |
| 240 | public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty"; |
| 241 | |
| 242 | // ****************************** |
| 243 | // ***** instance variables ***** |
| 244 | // ****************************** |
| 245 | |
| 246 | private String dialogTitle = null; |
| 247 | private String approveButtonText = null; |
| 248 | private String approveButtonToolTipText = null; |
| 249 | private int approveButtonMnemonic = 0; |
| 250 | |
| 251 | private Vector filters = new Vector(5); |
| 252 | private JDialog dialog = null; |
| 253 | private int dialogType = OPEN_DIALOG; |
| 254 | private int returnValue = ERROR_OPTION; |
| 255 | private JComponent accessory = null; |
| 256 | |
| 257 | private FileView fileView = null; |
| 258 | |
| 259 | // uiFileView is not serialized, as it is initialized |
| 260 | // by updateUI() after deserialization |
| 261 | private transient FileView uiFileView = null; |
| 262 | |
| 263 | private boolean controlsShown = true; |
| 264 | |
| 265 | private boolean useFileHiding = true; |
| 266 | private static final String SHOW_HIDDEN_PROP = "awt.file.showHiddenFiles"; |
| 267 | |
| 268 | // Listens to changes in the native setting for showing hidden files. |
| 269 | // The Listener is removed and the native setting is ignored if |
| 270 | // setFileHidingEnabled() is ever called. |
| 271 | private transient PropertyChangeListener showFilesListener = null; |
| 272 | |
| 273 | private int fileSelectionMode = FILES_ONLY; |
| 274 | |
| 275 | private boolean multiSelectionEnabled = false; |
| 276 | |
| 277 | private boolean useAcceptAllFileFilter = true; |
| 278 | |
| 279 | private boolean dragEnabled = false; |
| 280 | |
| 281 | private FileFilter fileFilter = null; |
| 282 | |
| 283 | private FileSystemView fileSystemView = null; |
| 284 | |
| 285 | private File currentDirectory = null; |
| 286 | private File selectedFile = null; |
| 287 | private File[] selectedFiles; |
| 288 | |
| 289 | // ************************************* |
| 290 | // ***** JFileChooser Constructors ***** |
| 291 | // ************************************* |
| 292 | |
| 293 | /** |
| 294 | * Constructs a <code>JFileChooser</code> pointing to the user's |
| 295 | * default directory. This default depends on the operating system. |
| 296 | * It is typically the "My Documents" folder on Windows, and the |
| 297 | * user's home directory on Unix. |
| 298 | */ |
| 299 | public JFileChooser() { |
| 300 | this((File) null, (FileSystemView) null); |
| 301 | } |
| 302 | |
| 303 | /** |
| 304 | * Constructs a <code>JFileChooser</code> using the given path. |
| 305 | * Passing in a <code>null</code> |
| 306 | * string causes the file chooser to point to the user's default directory. |
| 307 | * This default depends on the operating system. It is |
| 308 | * typically the "My Documents" folder on Windows, and the user's |
| 309 | * home directory on Unix. |
| 310 | * |
| 311 | * @param currentDirectoryPath a <code>String</code> giving the path |
| 312 | * to a file or directory |
| 313 | */ |
| 314 | public JFileChooser(String currentDirectoryPath) { |
| 315 | this(currentDirectoryPath, (FileSystemView) null); |
| 316 | } |
| 317 | |
| 318 | /** |
| 319 | * Constructs a <code>JFileChooser</code> using the given <code>File</code> |
| 320 | * as the path. Passing in a <code>null</code> file |
| 321 | * causes the file chooser to point to the user's default directory. |
| 322 | * This default depends on the operating system. It is |
| 323 | * typically the "My Documents" folder on Windows, and the user's |
| 324 | * home directory on Unix. |
| 325 | * |
| 326 | * @param currentDirectory a <code>File</code> object specifying |
| 327 | * the path to a file or directory |
| 328 | */ |
| 329 | public JFileChooser(File currentDirectory) { |
| 330 | this(currentDirectory, (FileSystemView) null); |
| 331 | } |
| 332 | |
| 333 | /** |
| 334 | * Constructs a <code>JFileChooser</code> using the given |
| 335 | * <code>FileSystemView</code>. |
| 336 | */ |
| 337 | public JFileChooser(FileSystemView fsv) { |
| 338 | this((File) null, fsv); |
| 339 | } |
| 340 | |
| 341 | |
| 342 | /** |
| 343 | * Constructs a <code>JFileChooser</code> using the given current directory |
| 344 | * and <code>FileSystemView</code>. |
| 345 | */ |
| 346 | public JFileChooser(File currentDirectory, FileSystemView fsv) { |
| 347 | setup(fsv); |
| 348 | setCurrentDirectory(currentDirectory); |
| 349 | } |
| 350 | |
| 351 | /** |
| 352 | * Constructs a <code>JFileChooser</code> using the given current directory |
| 353 | * path and <code>FileSystemView</code>. |
| 354 | */ |
| 355 | public JFileChooser(String currentDirectoryPath, FileSystemView fsv) { |
| 356 | setup(fsv); |
| 357 | if(currentDirectoryPath == null) { |
| 358 | setCurrentDirectory(null); |
| 359 | } else { |
| 360 | setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath)); |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /** |
| 365 | * Performs common constructor initialization and setup. |
| 366 | */ |
| 367 | protected void setup(FileSystemView view) { |
| 368 | installShowFilesListener(); |
| 369 | |
| 370 | if(view == null) { |
| 371 | view = FileSystemView.getFileSystemView(); |
| 372 | } |
| 373 | setFileSystemView(view); |
| 374 | updateUI(); |
| 375 | if(isAcceptAllFileFilterUsed()) { |
| 376 | setFileFilter(getAcceptAllFileFilter()); |
| 377 | } |
| 378 | enableEvents(AWTEvent.MOUSE_EVENT_MASK); |
| 379 | } |
| 380 | |
| 381 | private void installShowFilesListener() { |
| 382 | // Track native setting for showing hidden files |
| 383 | Toolkit tk = Toolkit.getDefaultToolkit(); |
| 384 | Object showHiddenProperty = tk.getDesktopProperty(SHOW_HIDDEN_PROP); |
| 385 | if (showHiddenProperty instanceof Boolean) { |
| 386 | useFileHiding = !((Boolean)showHiddenProperty).booleanValue(); |
| 387 | showFilesListener = new WeakPCL(this); |
| 388 | tk.addPropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener); |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /** |
| 393 | * Sets the <code>dragEnabled</code> property, |
| 394 | * which must be <code>true</code> to enable |
| 395 | * automatic drag handling (the first part of drag and drop) |
| 396 | * on this component. |
| 397 | * The <code>transferHandler</code> property needs to be set |
| 398 | * to a non-<code>null</code> value for the drag to do |
| 399 | * anything. The default value of the <code>dragEnabled</code> |
| 400 | * property |
| 401 | * is <code>false</code>. |
| 402 | * |
| 403 | * <p> |
| 404 | * |
| 405 | * When automatic drag handling is enabled, |
| 406 | * most look and feels begin a drag-and-drop operation |
| 407 | * whenever the user presses the mouse button over an item |
| 408 | * and then moves the mouse a few pixels. |
| 409 | * Setting this property to <code>true</code> |
| 410 | * can therefore have a subtle effect on |
| 411 | * how selections behave. |
| 412 | * |
| 413 | * <p> |
| 414 | * |
| 415 | * Some look and feels might not support automatic drag and drop; |
| 416 | * they will ignore this property. You can work around such |
| 417 | * look and feels by modifying the component |
| 418 | * to directly call the <code>exportAsDrag</code> method of a |
| 419 | * <code>TransferHandler</code>. |
| 420 | * |
| 421 | * @param b the value to set the <code>dragEnabled</code> property to |
| 422 | * @exception HeadlessException if |
| 423 | * <code>b</code> is <code>true</code> and |
| 424 | * <code>GraphicsEnvironment.isHeadless()</code> |
| 425 | * returns <code>true</code> |
| 426 | * @see java.awt.GraphicsEnvironment#isHeadless |
| 427 | * @see #getDragEnabled |
| 428 | * @see #setTransferHandler |
| 429 | * @see TransferHandler |
| 430 | * @since 1.4 |
| 431 | * |
| 432 | * @beaninfo |
| 433 | * description: determines whether automatic drag handling is enabled |
| 434 | * bound: false |
| 435 | */ |
| 436 | public void setDragEnabled(boolean b) { |
| 437 | if (b && GraphicsEnvironment.isHeadless()) { |
| 438 | throw new HeadlessException(); |
| 439 | } |
| 440 | dragEnabled = b; |
| 441 | } |
| 442 | |
| 443 | /** |
| 444 | * Gets the value of the <code>dragEnabled</code> property. |
| 445 | * |
| 446 | * @return the value of the <code>dragEnabled</code> property |
| 447 | * @see #setDragEnabled |
| 448 | * @since 1.4 |
| 449 | */ |
| 450 | public boolean getDragEnabled() { |
| 451 | return dragEnabled; |
| 452 | } |
| 453 | |
| 454 | // ***************************** |
| 455 | // ****** File Operations ****** |
| 456 | // ***************************** |
| 457 | |
| 458 | /** |
| 459 | * Returns the selected file. This can be set either by the |
| 460 | * programmer via <code>setSelectedFile</code> or by a user action, such as |
| 461 | * either typing the filename into the UI or selecting the |
| 462 | * file from a list in the UI. |
| 463 | * |
| 464 | * @see #setSelectedFile |
| 465 | * @return the selected file |
| 466 | */ |
| 467 | public File getSelectedFile() { |
| 468 | return selectedFile; |
| 469 | } |
| 470 | |
| 471 | /** |
| 472 | * Sets the selected file. If the file's parent directory is |
| 473 | * not the current directory, changes the current directory |
| 474 | * to be the file's parent directory. |
| 475 | * |
| 476 | * @beaninfo |
| 477 | * preferred: true |
| 478 | * bound: true |
| 479 | * |
| 480 | * @see #getSelectedFile |
| 481 | * |
| 482 | * @param file the selected file |
| 483 | */ |
| 484 | public void setSelectedFile(File file) { |
| 485 | File oldValue = selectedFile; |
| 486 | selectedFile = file; |
| 487 | if(selectedFile != null) { |
| 488 | if (file.isAbsolute() && !getFileSystemView().isParent(getCurrentDirectory(), selectedFile)) { |
| 489 | setCurrentDirectory(selectedFile.getParentFile()); |
| 490 | } |
| 491 | if (!isMultiSelectionEnabled() || selectedFiles == null || selectedFiles.length == 1) { |
| 492 | ensureFileIsVisible(selectedFile); |
| 493 | } |
| 494 | } |
| 495 | firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue, selectedFile); |
| 496 | } |
| 497 | |
| 498 | /** |
| 499 | * Returns a list of selected files if the file chooser is |
| 500 | * set to allow multiple selection. |
| 501 | */ |
| 502 | public File[] getSelectedFiles() { |
| 503 | if(selectedFiles == null) { |
| 504 | return new File[0]; |
| 505 | } else { |
| 506 | return (File[]) selectedFiles.clone(); |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | /** |
| 511 | * Sets the list of selected files if the file chooser is |
| 512 | * set to allow multiple selection. |
| 513 | * |
| 514 | * @beaninfo |
| 515 | * bound: true |
| 516 | * description: The list of selected files if the chooser is in multiple selection mode. |
| 517 | */ |
| 518 | public void setSelectedFiles(File[] selectedFiles) { |
| 519 | File[] oldValue = this.selectedFiles; |
| 520 | if (selectedFiles == null || selectedFiles.length == 0) { |
| 521 | selectedFiles = null; |
| 522 | this.selectedFiles = null; |
| 523 | setSelectedFile(null); |
| 524 | } else { |
| 525 | this.selectedFiles = selectedFiles.clone(); |
| 526 | setSelectedFile(this.selectedFiles[0]); |
| 527 | } |
| 528 | firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles); |
| 529 | } |
| 530 | |
| 531 | /** |
| 532 | * Returns the current directory. |
| 533 | * |
| 534 | * @return the current directory |
| 535 | * @see #setCurrentDirectory |
| 536 | */ |
| 537 | public File getCurrentDirectory() { |
| 538 | return currentDirectory; |
| 539 | } |
| 540 | |
| 541 | /** |
| 542 | * Sets the current directory. Passing in <code>null</code> sets the |
| 543 | * file chooser to point to the user's default directory. |
| 544 | * This default depends on the operating system. It is |
| 545 | * typically the "My Documents" folder on Windows, and the user's |
| 546 | * home directory on Unix. |
| 547 | * |
| 548 | * If the file passed in as <code>currentDirectory</code> is not a |
| 549 | * directory, the parent of the file will be used as the currentDirectory. |
| 550 | * If the parent is not traversable, then it will walk up the parent tree |
| 551 | * until it finds a traversable directory, or hits the root of the |
| 552 | * file system. |
| 553 | * |
| 554 | * @beaninfo |
| 555 | * preferred: true |
| 556 | * bound: true |
| 557 | * description: The directory that the JFileChooser is showing files of. |
| 558 | * |
| 559 | * @param dir the current directory to point to |
| 560 | * @see #getCurrentDirectory |
| 561 | */ |
| 562 | public void setCurrentDirectory(File dir) { |
| 563 | File oldValue = currentDirectory; |
| 564 | |
| 565 | if (dir != null && !dir.exists()) { |
| 566 | dir = currentDirectory; |
| 567 | } |
| 568 | if (dir == null) { |
| 569 | dir = getFileSystemView().getDefaultDirectory(); |
| 570 | } |
| 571 | if (currentDirectory != null) { |
| 572 | /* Verify the toString of object */ |
| 573 | if (this.currentDirectory.equals(dir)) { |
| 574 | return; |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | File prev = null; |
| 579 | while (!isTraversable(dir) && prev != dir) { |
| 580 | prev = dir; |
| 581 | dir = getFileSystemView().getParentDirectory(dir); |
| 582 | } |
| 583 | currentDirectory = dir; |
| 584 | |
| 585 | firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, currentDirectory); |
| 586 | } |
| 587 | |
| 588 | /** |
| 589 | * Changes the directory to be set to the parent of the |
| 590 | * current directory. |
| 591 | * |
| 592 | * @see #getCurrentDirectory |
| 593 | */ |
| 594 | public void changeToParentDirectory() { |
| 595 | selectedFile = null; |
| 596 | File oldValue = getCurrentDirectory(); |
| 597 | setCurrentDirectory(getFileSystemView().getParentDirectory(oldValue)); |
| 598 | } |
| 599 | |
| 600 | /** |
| 601 | * Tells the UI to rescan its files list from the current directory. |
| 602 | */ |
| 603 | public void rescanCurrentDirectory() { |
| 604 | getUI().rescanCurrentDirectory(this); |
| 605 | } |
| 606 | |
| 607 | /** |
| 608 | * Makes sure that the specified file is viewable, and |
| 609 | * not hidden. |
| 610 | * |
| 611 | * @param f a File object |
| 612 | */ |
| 613 | public void ensureFileIsVisible(File f) { |
| 614 | getUI().ensureFileIsVisible(this, f); |
| 615 | } |
| 616 | |
| 617 | // ************************************** |
| 618 | // ***** JFileChooser Dialog methods ***** |
| 619 | // ************************************** |
| 620 | |
| 621 | /** |
| 622 | * Pops up an "Open File" file chooser dialog. Note that the |
| 623 | * text that appears in the approve button is determined by |
| 624 | * the L&F. |
| 625 | * |
| 626 | * @param parent the parent component of the dialog, |
| 627 | * can be <code>null</code>; |
| 628 | * see <code>showDialog</code> for details |
| 629 | * @return the return state of the file chooser on popdown: |
| 630 | * <ul> |
| 631 | * <li>JFileChooser.CANCEL_OPTION |
| 632 | * <li>JFileChooser.APPROVE_OPTION |
| 633 | * <li>JFileChooser.ERROR_OPTION if an error occurs or the |
| 634 | * dialog is dismissed |
| 635 | * </ul> |
| 636 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| 637 | * returns true. |
| 638 | * @see java.awt.GraphicsEnvironment#isHeadless |
| 639 | * @see #showDialog |
| 640 | */ |
| 641 | public int showOpenDialog(Component parent) throws HeadlessException { |
| 642 | setDialogType(OPEN_DIALOG); |
| 643 | return showDialog(parent, null); |
| 644 | } |
| 645 | |
| 646 | /** |
| 647 | * Pops up a "Save File" file chooser dialog. Note that the |
| 648 | * text that appears in the approve button is determined by |
| 649 | * the L&F. |
| 650 | * |
| 651 | * @param parent the parent component of the dialog, |
| 652 | * can be <code>null</code>; |
| 653 | * see <code>showDialog</code> for details |
| 654 | * @return the return state of the file chooser on popdown: |
| 655 | * <ul> |
| 656 | * <li>JFileChooser.CANCEL_OPTION |
| 657 | * <li>JFileChooser.APPROVE_OPTION |
| 658 | * <li>JFileChooser.ERROR_OPTION if an error occurs or the |
| 659 | * dialog is dismissed |
| 660 | * </ul> |
| 661 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| 662 | * returns true. |
| 663 | * @see java.awt.GraphicsEnvironment#isHeadless |
| 664 | * @see #showDialog |
| 665 | */ |
| 666 | public int showSaveDialog(Component parent) throws HeadlessException { |
| 667 | setDialogType(SAVE_DIALOG); |
| 668 | return showDialog(parent, null); |
| 669 | } |
| 670 | |
| 671 | /** |
| 672 | * Pops a custom file chooser dialog with a custom approve button. |
| 673 | * For example, the following code |
| 674 | * pops up a file chooser with a "Run Application" button |
| 675 | * (instead of the normal "Save" or "Open" button): |
| 676 | * <pre> |
| 677 | * filechooser.showDialog(parentFrame, "Run Application"); |
| 678 | * </pre> |
| 679 | * |
| 680 | * Alternatively, the following code does the same thing: |
| 681 | * <pre> |
| 682 | * JFileChooser chooser = new JFileChooser(null); |
| 683 | * chooser.setApproveButtonText("Run Application"); |
| 684 | * chooser.showDialog(parentFrame, null); |
| 685 | * </pre> |
| 686 | * |
| 687 | * <!--PENDING(jeff) - the following method should be added to the api: |
| 688 | * showDialog(Component parent);--> |
| 689 | * <!--PENDING(kwalrath) - should specify modality and what |
| 690 | * "depends" means.--> |
| 691 | * |
| 692 | * <p> |
| 693 | * |
| 694 | * The <code>parent</code> argument determines two things: |
| 695 | * the frame on which the open dialog depends and |
| 696 | * the component whose position the look and feel |
| 697 | * should consider when placing the dialog. If the parent |
| 698 | * is a <code>Frame</code> object (such as a <code>JFrame</code>) |
| 699 | * then the dialog depends on the frame and |
| 700 | * the look and feel positions the dialog |
| 701 | * relative to the frame (for example, centered over the frame). |
| 702 | * If the parent is a component, then the dialog |
| 703 | * depends on the frame containing the component, |
| 704 | * and is positioned relative to the component |
| 705 | * (for example, centered over the component). |
| 706 | * If the parent is <code>null</code>, then the dialog depends on |
| 707 | * no visible window, and it's placed in a |
| 708 | * look-and-feel-dependent position |
| 709 | * such as the center of the screen. |
| 710 | * |
| 711 | * @param parent the parent component of the dialog; |
| 712 | * can be <code>null</code> |
| 713 | * @param approveButtonText the text of the <code>ApproveButton</code> |
| 714 | * @return the return state of the file chooser on popdown: |
| 715 | * <ul> |
| 716 | * <li>JFileChooser.CANCEL_OPTION |
| 717 | * <li>JFileChooser.APPROVE_OPTION |
| 718 | * <li>JFileCHooser.ERROR_OPTION if an error occurs or the |
| 719 | * dialog is dismissed |
| 720 | * </ul> |
| 721 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| 722 | * returns true. |
| 723 | * @see java.awt.GraphicsEnvironment#isHeadless |
| 724 | */ |
| 725 | public int showDialog(Component parent, String approveButtonText) |
| 726 | throws HeadlessException { |
| 727 | if(approveButtonText != null) { |
| 728 | setApproveButtonText(approveButtonText); |
| 729 | setDialogType(CUSTOM_DIALOG); |
| 730 | } |
| 731 | dialog = createDialog(parent); |
| 732 | dialog.addWindowListener(new WindowAdapter() { |
| 733 | public void windowClosing(WindowEvent e) { |
| 734 | returnValue = CANCEL_OPTION; |
| 735 | } |
| 736 | }); |
| 737 | returnValue = ERROR_OPTION; |
| 738 | rescanCurrentDirectory(); |
| 739 | |
| 740 | dialog.show(); |
| 741 | firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null); |
| 742 | dialog.dispose(); |
| 743 | dialog = null; |
| 744 | return returnValue; |
| 745 | } |
| 746 | |
| 747 | /** |
| 748 | * Creates and returns a new <code>JDialog</code> wrapping |
| 749 | * <code>this</code> centered on the <code>parent</code> |
| 750 | * in the <code>parent</code>'s frame. |
| 751 | * This method can be overriden to further manipulate the dialog, |
| 752 | * to disable resizing, set the location, etc. Example: |
| 753 | * <pre> |
| 754 | * class MyFileChooser extends JFileChooser { |
| 755 | * protected JDialog createDialog(Component parent) throws HeadlessException { |
| 756 | * JDialog dialog = super.createDialog(parent); |
| 757 | * dialog.setLocation(300, 200); |
| 758 | * dialog.setResizable(false); |
| 759 | * return dialog; |
| 760 | * } |
| 761 | * } |
| 762 | * </pre> |
| 763 | * |
| 764 | * @param parent the parent component of the dialog; |
| 765 | * can be <code>null</code> |
| 766 | * @return a new <code>JDialog</code> containing this instance |
| 767 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| 768 | * returns true. |
| 769 | * @see java.awt.GraphicsEnvironment#isHeadless |
| 770 | * @since 1.4 |
| 771 | */ |
| 772 | protected JDialog createDialog(Component parent) throws HeadlessException { |
| 773 | String title = getUI().getDialogTitle(this); |
| 774 | putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, |
| 775 | title); |
| 776 | |
| 777 | JDialog dialog; |
| 778 | Window window = JOptionPane.getWindowForComponent(parent); |
| 779 | if (window instanceof Frame) { |
| 780 | dialog = new JDialog((Frame)window, title, true); |
| 781 | } else { |
| 782 | dialog = new JDialog((Dialog)window, title, true); |
| 783 | } |
| 784 | dialog.setComponentOrientation(this.getComponentOrientation()); |
| 785 | |
| 786 | Container contentPane = dialog.getContentPane(); |
| 787 | contentPane.setLayout(new BorderLayout()); |
| 788 | contentPane.add(this, BorderLayout.CENTER); |
| 789 | |
| 790 | if (JDialog.isDefaultLookAndFeelDecorated()) { |
| 791 | boolean supportsWindowDecorations = |
| 792 | UIManager.getLookAndFeel().getSupportsWindowDecorations(); |
| 793 | if (supportsWindowDecorations) { |
| 794 | dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG); |
| 795 | } |
| 796 | } |
| 797 | dialog.pack(); |
| 798 | dialog.setLocationRelativeTo(parent); |
| 799 | |
| 800 | return dialog; |
| 801 | } |
| 802 | |
| 803 | // ************************** |
| 804 | // ***** Dialog Options ***** |
| 805 | // ************************** |
| 806 | |
| 807 | /** |
| 808 | * Returns the value of the <code>controlButtonsAreShown</code> |
| 809 | * property. |
| 810 | * |
| 811 | * @return the value of the <code>controlButtonsAreShown</code> |
| 812 | * property |
| 813 | * |
| 814 | * @see #setControlButtonsAreShown |
| 815 | * @since 1.3 |
| 816 | */ |
| 817 | public boolean getControlButtonsAreShown() { |
| 818 | return controlsShown; |
| 819 | } |
| 820 | |
| 821 | |
| 822 | /** |
| 823 | * Sets the property |
| 824 | * that indicates whether the <i>approve</i> and <i>cancel</i> |
| 825 | * buttons are shown in the file chooser. This property |
| 826 | * is <code>true</code> by default. Look and feels |
| 827 | * that always show these buttons will ignore the value |
| 828 | * of this property. |
| 829 | * This method fires a property-changed event, |
| 830 | * using the string value of |
| 831 | * <code>CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY</code> |
| 832 | * as the name of the property. |
| 833 | * |
| 834 | * @param b <code>false</code> if control buttons should not be |
| 835 | * shown; otherwise, <code>true</code> |
| 836 | * |
| 837 | * @beaninfo |
| 838 | * preferred: true |
| 839 | * bound: true |
| 840 | * description: Sets whether the approve & cancel buttons are shown. |
| 841 | * |
| 842 | * @see #getControlButtonsAreShown |
| 843 | * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY |
| 844 | * @since 1.3 |
| 845 | */ |
| 846 | public void setControlButtonsAreShown(boolean b) { |
| 847 | if(controlsShown == b) { |
| 848 | return; |
| 849 | } |
| 850 | boolean oldValue = controlsShown; |
| 851 | controlsShown = b; |
| 852 | firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, oldValue, controlsShown); |
| 853 | } |
| 854 | |
| 855 | /** |
| 856 | * Returns the type of this dialog. The default is |
| 857 | * <code>JFileChooser.OPEN_DIALOG</code>. |
| 858 | * |
| 859 | * @return the type of dialog to be displayed: |
| 860 | * <ul> |
| 861 | * <li>JFileChooser.OPEN_DIALOG |
| 862 | * <li>JFileChooser.SAVE_DIALOG |
| 863 | * <li>JFileChooser.CUSTOM_DIALOG |
| 864 | * </ul> |
| 865 | * |
| 866 | * @see #setDialogType |
| 867 | */ |
| 868 | public int getDialogType() { |
| 869 | return dialogType; |
| 870 | } |
| 871 | |
| 872 | /** |
| 873 | * Sets the type of this dialog. Use <code>OPEN_DIALOG</code> when you |
| 874 | * want to bring up a file chooser that the user can use to open a file. |
| 875 | * Likewise, use <code>SAVE_DIALOG</code> for letting the user choose |
| 876 | * a file for saving. |
| 877 | * Use <code>CUSTOM_DIALOG</code> when you want to use the file |
| 878 | * chooser in a context other than "Open" or "Save". |
| 879 | * For instance, you might want to bring up a file chooser that allows |
| 880 | * the user to choose a file to execute. Note that you normally would not |
| 881 | * need to set the <code>JFileChooser</code> to use |
| 882 | * <code>CUSTOM_DIALOG</code> |
| 883 | * since a call to <code>setApproveButtonText</code> does this for you. |
| 884 | * The default dialog type is <code>JFileChooser.OPEN_DIALOG</code>. |
| 885 | * |
| 886 | * @param dialogType the type of dialog to be displayed: |
| 887 | * <ul> |
| 888 | * <li>JFileChooser.OPEN_DIALOG |
| 889 | * <li>JFileChooser.SAVE_DIALOG |
| 890 | * <li>JFileChooser.CUSTOM_DIALOG |
| 891 | * </ul> |
| 892 | * |
| 893 | * @exception IllegalArgumentException if <code>dialogType</code> is |
| 894 | * not legal |
| 895 | * @beaninfo |
| 896 | * preferred: true |
| 897 | * bound: true |
| 898 | * description: The type (open, save, custom) of the JFileChooser. |
| 899 | * enum: |
| 900 | * OPEN_DIALOG JFileChooser.OPEN_DIALOG |
| 901 | * SAVE_DIALOG JFileChooser.SAVE_DIALOG |
| 902 | * CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG |
| 903 | * |
| 904 | * @see #getDialogType |
| 905 | * @see #setApproveButtonText |
| 906 | */ |
| 907 | // PENDING(jeff) - fire button text change property |
| 908 | public void setDialogType(int dialogType) { |
| 909 | if(this.dialogType == dialogType) { |
| 910 | return; |
| 911 | } |
| 912 | if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) { |
| 913 | throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType); |
| 914 | } |
| 915 | int oldValue = this.dialogType; |
| 916 | this.dialogType = dialogType; |
| 917 | if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) { |
| 918 | setApproveButtonText(null); |
| 919 | } |
| 920 | firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType); |
| 921 | } |
| 922 | |
| 923 | /** |
| 924 | * Sets the string that goes in the <code>JFileChooser</code> window's |
| 925 | * title bar. |
| 926 | * |
| 927 | * @param dialogTitle the new <code>String</code> for the title bar |
| 928 | * |
| 929 | * @beaninfo |
| 930 | * preferred: true |
| 931 | * bound: true |
| 932 | * description: The title of the JFileChooser dialog window. |
| 933 | * |
| 934 | * @see #getDialogTitle |
| 935 | * |
| 936 | */ |
| 937 | public void setDialogTitle(String dialogTitle) { |
| 938 | String oldValue = this.dialogTitle; |
| 939 | this.dialogTitle = dialogTitle; |
| 940 | if(dialog != null) { |
| 941 | dialog.setTitle(dialogTitle); |
| 942 | } |
| 943 | firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle); |
| 944 | } |
| 945 | |
| 946 | /** |
| 947 | * Gets the string that goes in the <code>JFileChooser</code>'s titlebar. |
| 948 | * |
| 949 | * @see #setDialogTitle |
| 950 | */ |
| 951 | public String getDialogTitle() { |
| 952 | return dialogTitle; |
| 953 | } |
| 954 | |
| 955 | // ************************************ |
| 956 | // ***** JFileChooser View Options ***** |
| 957 | // ************************************ |
| 958 | |
| 959 | |
| 960 | |
| 961 | /** |
| 962 | * Sets the tooltip text used in the <code>ApproveButton</code>. |
| 963 | * If <code>null</code>, the UI object will determine the button's text. |
| 964 | * |
| 965 | * @beaninfo |
| 966 | * preferred: true |
| 967 | * bound: true |
| 968 | * description: The tooltip text for the ApproveButton. |
| 969 | * |
| 970 | * @param toolTipText the tooltip text for the approve button |
| 971 | * @see #setApproveButtonText |
| 972 | * @see #setDialogType |
| 973 | * @see #showDialog |
| 974 | */ |
| 975 | public void setApproveButtonToolTipText(String toolTipText) { |
| 976 | if(approveButtonToolTipText == toolTipText) { |
| 977 | return; |
| 978 | } |
| 979 | String oldValue = approveButtonToolTipText; |
| 980 | approveButtonToolTipText = toolTipText; |
| 981 | firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText); |
| 982 | } |
| 983 | |
| 984 | |
| 985 | /** |
| 986 | * Returns the tooltip text used in the <code>ApproveButton</code>. |
| 987 | * If <code>null</code>, the UI object will determine the button's text. |
| 988 | * |
| 989 | * @return the tooltip text used for the approve button |
| 990 | * |
| 991 | * @see #setApproveButtonText |
| 992 | * @see #setDialogType |
| 993 | * @see #showDialog |
| 994 | */ |
| 995 | public String getApproveButtonToolTipText() { |
| 996 | return approveButtonToolTipText; |
| 997 | } |
| 998 | |
| 999 | /** |
| 1000 | * Returns the approve button's mnemonic. |
| 1001 | * @return an integer value for the mnemonic key |
| 1002 | * |
| 1003 | * @see #setApproveButtonMnemonic |
| 1004 | */ |
| 1005 | public int getApproveButtonMnemonic() { |
| 1006 | return approveButtonMnemonic; |
| 1007 | } |
| 1008 | |
| 1009 | /** |
| 1010 | * Sets the approve button's mnemonic using a numeric keycode. |
| 1011 | * |
| 1012 | * @param mnemonic an integer value for the mnemonic key |
| 1013 | * |
| 1014 | * @beaninfo |
| 1015 | * preferred: true |
| 1016 | * bound: true |
| 1017 | * description: The mnemonic key accelerator for the ApproveButton. |
| 1018 | * |
| 1019 | * @see #getApproveButtonMnemonic |
| 1020 | */ |
| 1021 | public void setApproveButtonMnemonic(int mnemonic) { |
| 1022 | if(approveButtonMnemonic == mnemonic) { |
| 1023 | return; |
| 1024 | } |
| 1025 | int oldValue = approveButtonMnemonic; |
| 1026 | approveButtonMnemonic = mnemonic; |
| 1027 | firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic); |
| 1028 | } |
| 1029 | |
| 1030 | /** |
| 1031 | * Sets the approve button's mnemonic using a character. |
| 1032 | * @param mnemonic a character value for the mnemonic key |
| 1033 | * |
| 1034 | * @see #getApproveButtonMnemonic |
| 1035 | */ |
| 1036 | public void setApproveButtonMnemonic(char mnemonic) { |
| 1037 | int vk = (int) mnemonic; |
| 1038 | if(vk >= 'a' && vk <='z') { |
| 1039 | vk -= ('a' - 'A'); |
| 1040 | } |
| 1041 | setApproveButtonMnemonic(vk); |
| 1042 | } |
| 1043 | |
| 1044 | |
| 1045 | /** |
| 1046 | * Sets the text used in the <code>ApproveButton</code> in the |
| 1047 | * <code>FileChooserUI</code>. |
| 1048 | * |
| 1049 | * @beaninfo |
| 1050 | * preferred: true |
| 1051 | * bound: true |
| 1052 | * description: The text that goes in the ApproveButton. |
| 1053 | * |
| 1054 | * @param approveButtonText the text used in the <code>ApproveButton</code> |
| 1055 | * |
| 1056 | * @see #getApproveButtonText |
| 1057 | * @see #setDialogType |
| 1058 | * @see #showDialog |
| 1059 | */ |
| 1060 | // PENDING(jeff) - have ui set this on dialog type change |
| 1061 | public void setApproveButtonText(String approveButtonText) { |
| 1062 | if(this.approveButtonText == approveButtonText) { |
| 1063 | return; |
| 1064 | } |
| 1065 | String oldValue = this.approveButtonText; |
| 1066 | this.approveButtonText = approveButtonText; |
| 1067 | firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText); |
| 1068 | } |
| 1069 | |
| 1070 | /** |
| 1071 | * Returns the text used in the <code>ApproveButton</code> in the |
| 1072 | * <code>FileChooserUI</code>. |
| 1073 | * If <code>null</code>, the UI object will determine the button's text. |
| 1074 | * |
| 1075 | * Typically, this would be "Open" or "Save". |
| 1076 | * |
| 1077 | * @return the text used in the <code>ApproveButton</code> |
| 1078 | * |
| 1079 | * @see #setApproveButtonText |
| 1080 | * @see #setDialogType |
| 1081 | * @see #showDialog |
| 1082 | */ |
| 1083 | public String getApproveButtonText() { |
| 1084 | return approveButtonText; |
| 1085 | } |
| 1086 | |
| 1087 | /** |
| 1088 | * Gets the list of user choosable file filters. |
| 1089 | * |
| 1090 | * @return a <code>FileFilter</code> array containing all the choosable |
| 1091 | * file filters |
| 1092 | * |
| 1093 | * @see #addChoosableFileFilter |
| 1094 | * @see #removeChoosableFileFilter |
| 1095 | * @see #resetChoosableFileFilters |
| 1096 | */ |
| 1097 | public FileFilter[] getChoosableFileFilters() { |
| 1098 | FileFilter[] filterArray = new FileFilter[filters.size()]; |
| 1099 | filters.copyInto(filterArray); |
| 1100 | return filterArray; |
| 1101 | } |
| 1102 | |
| 1103 | /** |
| 1104 | * Adds a filter to the list of user choosable file filters. |
| 1105 | * For information on setting the file selection mode, see |
| 1106 | * {@link #setFileSelectionMode setFileSelectionMode}. |
| 1107 | * |
| 1108 | * @param filter the <code>FileFilter</code> to add to the choosable file |
| 1109 | * filter list |
| 1110 | * |
| 1111 | * @beaninfo |
| 1112 | * preferred: true |
| 1113 | * bound: true |
| 1114 | * description: Adds a filter to the list of user choosable file filters. |
| 1115 | * |
| 1116 | * @see #getChoosableFileFilters |
| 1117 | * @see #removeChoosableFileFilter |
| 1118 | * @see #resetChoosableFileFilters |
| 1119 | * @see #setFileSelectionMode |
| 1120 | */ |
| 1121 | public void addChoosableFileFilter(FileFilter filter) { |
| 1122 | if(filter != null && !filters.contains(filter)) { |
| 1123 | FileFilter[] oldValue = getChoosableFileFilters(); |
| 1124 | filters.addElement(filter); |
| 1125 | firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| 1126 | if (fileFilter == null && filters.size() == 1) { |
| 1127 | setFileFilter(filter); |
| 1128 | } |
| 1129 | } |
| 1130 | } |
| 1131 | |
| 1132 | /** |
| 1133 | * Removes a filter from the list of user choosable file filters. Returns |
| 1134 | * true if the file filter was removed. |
| 1135 | * |
| 1136 | * @see #addChoosableFileFilter |
| 1137 | * @see #getChoosableFileFilters |
| 1138 | * @see #resetChoosableFileFilters |
| 1139 | */ |
| 1140 | public boolean removeChoosableFileFilter(FileFilter f) { |
| 1141 | if(filters.contains(f)) { |
| 1142 | if(getFileFilter() == f) { |
| 1143 | setFileFilter(null); |
| 1144 | } |
| 1145 | FileFilter[] oldValue = getChoosableFileFilters(); |
| 1146 | filters.removeElement(f); |
| 1147 | firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| 1148 | return true; |
| 1149 | } else { |
| 1150 | return false; |
| 1151 | } |
| 1152 | } |
| 1153 | |
| 1154 | /** |
| 1155 | * Resets the choosable file filter list to its starting state. Normally, |
| 1156 | * this removes all added file filters while leaving the |
| 1157 | * <code>AcceptAll</code> file filter. |
| 1158 | * |
| 1159 | * @see #addChoosableFileFilter |
| 1160 | * @see #getChoosableFileFilters |
| 1161 | * @see #removeChoosableFileFilter |
| 1162 | */ |
| 1163 | public void resetChoosableFileFilters() { |
| 1164 | FileFilter[] oldValue = getChoosableFileFilters(); |
| 1165 | setFileFilter(null); |
| 1166 | filters.removeAllElements(); |
| 1167 | if(isAcceptAllFileFilterUsed()) { |
| 1168 | addChoosableFileFilter(getAcceptAllFileFilter()); |
| 1169 | } |
| 1170 | firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| 1171 | } |
| 1172 | |
| 1173 | /** |
| 1174 | * Returns the <code>AcceptAll</code> file filter. |
| 1175 | * For example, on Microsoft Windows this would be All Files (*.*). |
| 1176 | */ |
| 1177 | public FileFilter getAcceptAllFileFilter() { |
| 1178 | FileFilter filter = null; |
| 1179 | if(getUI() != null) { |
| 1180 | filter = getUI().getAcceptAllFileFilter(this); |
| 1181 | } |
| 1182 | return filter; |
| 1183 | } |
| 1184 | |
| 1185 | /** |
| 1186 | * Returns whether the <code>AcceptAll FileFilter</code> is used. |
| 1187 | * @return true if the <code>AcceptAll FileFilter</code> is used |
| 1188 | * @see #setAcceptAllFileFilterUsed |
| 1189 | * @since 1.3 |
| 1190 | */ |
| 1191 | public boolean isAcceptAllFileFilterUsed() { |
| 1192 | return useAcceptAllFileFilter; |
| 1193 | } |
| 1194 | |
| 1195 | /** |
| 1196 | * Determines whether the <code>AcceptAll FileFilter</code> is used |
| 1197 | * as an available choice in the choosable filter list. |
| 1198 | * If false, the <code>AcceptAll</code> file filter is removed from |
| 1199 | * the list of available file filters. |
| 1200 | * If true, the <code>AcceptAll</code> file filter will become the |
| 1201 | * the actively used file filter. |
| 1202 | * |
| 1203 | * @beaninfo |
| 1204 | * preferred: true |
| 1205 | * bound: true |
| 1206 | * description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list. |
| 1207 | * |
| 1208 | * @see #isAcceptAllFileFilterUsed |
| 1209 | * @see #getAcceptAllFileFilter |
| 1210 | * @see #setFileFilter |
| 1211 | * @since 1.3 |
| 1212 | */ |
| 1213 | public void setAcceptAllFileFilterUsed(boolean b) { |
| 1214 | boolean oldValue = useAcceptAllFileFilter; |
| 1215 | useAcceptAllFileFilter = b; |
| 1216 | if(!b) { |
| 1217 | removeChoosableFileFilter(getAcceptAllFileFilter()); |
| 1218 | } else { |
| 1219 | removeChoosableFileFilter(getAcceptAllFileFilter()); |
| 1220 | addChoosableFileFilter(getAcceptAllFileFilter()); |
| 1221 | } |
| 1222 | firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue, useAcceptAllFileFilter); |
| 1223 | } |
| 1224 | |
| 1225 | /** |
| 1226 | * Returns the accessory component. |
| 1227 | * |
| 1228 | * @return this JFileChooser's accessory component, or null |
| 1229 | * @see #setAccessory |
| 1230 | */ |
| 1231 | public JComponent getAccessory() { |
| 1232 | return accessory; |
| 1233 | } |
| 1234 | |
| 1235 | /** |
| 1236 | * Sets the accessory component. An accessory is often used to show a |
| 1237 | * preview image of the selected file; however, it can be used for anything |
| 1238 | * that the programmer wishes, such as extra custom file chooser controls. |
| 1239 | * |
| 1240 | * <p> |
| 1241 | * Note: if there was a previous accessory, you should unregister |
| 1242 | * any listeners that the accessory might have registered with the |
| 1243 | * file chooser. |
| 1244 | * |
| 1245 | * @beaninfo |
| 1246 | * preferred: true |
| 1247 | * bound: true |
| 1248 | * description: Sets the accessory component on the JFileChooser. |
| 1249 | */ |
| 1250 | public void setAccessory(JComponent newAccessory) { |
| 1251 | JComponent oldValue = accessory; |
| 1252 | accessory = newAccessory; |
| 1253 | firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory); |
| 1254 | } |
| 1255 | |
| 1256 | /** |
| 1257 | * Sets the <code>JFileChooser</code> to allow the user to just |
| 1258 | * select files, just select |
| 1259 | * directories, or select both files and directories. The default is |
| 1260 | * <code>JFilesChooser.FILES_ONLY</code>. |
| 1261 | * |
| 1262 | * @param mode the type of files to be displayed: |
| 1263 | * <ul> |
| 1264 | * <li>JFileChooser.FILES_ONLY |
| 1265 | * <li>JFileChooser.DIRECTORIES_ONLY |
| 1266 | * <li>JFileChooser.FILES_AND_DIRECTORIES |
| 1267 | * </ul> |
| 1268 | * |
| 1269 | * @exception IllegalArgumentException if <code>mode</code> is an |
| 1270 | * illegal file selection mode |
| 1271 | * @beaninfo |
| 1272 | * preferred: true |
| 1273 | * bound: true |
| 1274 | * description: Sets the types of files that the JFileChooser can choose. |
| 1275 | * enum: FILES_ONLY JFileChooser.FILES_ONLY |
| 1276 | * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY |
| 1277 | * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES |
| 1278 | * |
| 1279 | * |
| 1280 | * @see #getFileSelectionMode |
| 1281 | */ |
| 1282 | public void setFileSelectionMode(int mode) { |
| 1283 | if(fileSelectionMode == mode) { |
| 1284 | return; |
| 1285 | } |
| 1286 | |
| 1287 | if ((mode == FILES_ONLY) || (mode == DIRECTORIES_ONLY) || (mode == FILES_AND_DIRECTORIES)) { |
| 1288 | int oldValue = fileSelectionMode; |
| 1289 | fileSelectionMode = mode; |
| 1290 | firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode); |
| 1291 | } else { |
| 1292 | throw new IllegalArgumentException("Incorrect Mode for file selection: " + mode); |
| 1293 | } |
| 1294 | } |
| 1295 | |
| 1296 | /** |
| 1297 | * Returns the current file-selection mode. The default is |
| 1298 | * <code>JFilesChooser.FILES_ONLY</code>. |
| 1299 | * |
| 1300 | * @return the type of files to be displayed, one of the following: |
| 1301 | * <ul> |
| 1302 | * <li>JFileChooser.FILES_ONLY |
| 1303 | * <li>JFileChooser.DIRECTORIES_ONLY |
| 1304 | * <li>JFileChooser.FILES_AND_DIRECTORIES |
| 1305 | * </ul> |
| 1306 | * @see #setFileSelectionMode |
| 1307 | */ |
| 1308 | public int getFileSelectionMode() { |
| 1309 | return fileSelectionMode; |
| 1310 | } |
| 1311 | |
| 1312 | /** |
| 1313 | * Convenience call that determines if files are selectable based on the |
| 1314 | * current file selection mode. |
| 1315 | * |
| 1316 | * @see #setFileSelectionMode |
| 1317 | * @see #getFileSelectionMode |
| 1318 | */ |
| 1319 | public boolean isFileSelectionEnabled() { |
| 1320 | return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES)); |
| 1321 | } |
| 1322 | |
| 1323 | /** |
| 1324 | * Convenience call that determines if directories are selectable based |
| 1325 | * on the current file selection mode. |
| 1326 | * |
| 1327 | * @see #setFileSelectionMode |
| 1328 | * @see #getFileSelectionMode |
| 1329 | */ |
| 1330 | public boolean isDirectorySelectionEnabled() { |
| 1331 | return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES)); |
| 1332 | } |
| 1333 | |
| 1334 | /** |
| 1335 | * Sets the file chooser to allow multiple file selections. |
| 1336 | * |
| 1337 | * @param b true if multiple files may be selected |
| 1338 | * @beaninfo |
| 1339 | * bound: true |
| 1340 | * description: Sets multiple file selection mode. |
| 1341 | * |
| 1342 | * @see #isMultiSelectionEnabled |
| 1343 | */ |
| 1344 | public void setMultiSelectionEnabled(boolean b) { |
| 1345 | if(multiSelectionEnabled == b) { |
| 1346 | return; |
| 1347 | } |
| 1348 | boolean oldValue = multiSelectionEnabled; |
| 1349 | multiSelectionEnabled = b; |
| 1350 | firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, oldValue, multiSelectionEnabled); |
| 1351 | } |
| 1352 | |
| 1353 | /** |
| 1354 | * Returns true if multiple files can be selected. |
| 1355 | * @return true if multiple files can be selected |
| 1356 | * @see #setMultiSelectionEnabled |
| 1357 | */ |
| 1358 | public boolean isMultiSelectionEnabled() { |
| 1359 | return multiSelectionEnabled; |
| 1360 | } |
| 1361 | |
| 1362 | |
| 1363 | /** |
| 1364 | * Returns true if hidden files are not shown in the file chooser; |
| 1365 | * otherwise, returns false. |
| 1366 | * |
| 1367 | * @return the status of the file hiding property |
| 1368 | * @see #setFileHidingEnabled |
| 1369 | */ |
| 1370 | public boolean isFileHidingEnabled() { |
| 1371 | return useFileHiding; |
| 1372 | } |
| 1373 | |
| 1374 | /** |
| 1375 | * Sets file hiding on or off. If true, hidden files are not shown |
| 1376 | * in the file chooser. The job of determining which files are |
| 1377 | * shown is done by the <code>FileView</code>. |
| 1378 | * |
| 1379 | * @beaninfo |
| 1380 | * preferred: true |
| 1381 | * bound: true |
| 1382 | * description: Sets file hiding on or off. |
| 1383 | * |
| 1384 | * @param b the boolean value that determines whether file hiding is |
| 1385 | * turned on |
| 1386 | * @see #isFileHidingEnabled |
| 1387 | */ |
| 1388 | public void setFileHidingEnabled(boolean b) { |
| 1389 | // Dump showFilesListener since we'll ignore it from now on |
| 1390 | if (showFilesListener != null) { |
| 1391 | Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener); |
| 1392 | showFilesListener = null; |
| 1393 | } |
| 1394 | boolean oldValue = useFileHiding; |
| 1395 | useFileHiding = b; |
| 1396 | firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding); |
| 1397 | } |
| 1398 | |
| 1399 | /** |
| 1400 | * Sets the current file filter. The file filter is used by the |
| 1401 | * file chooser to filter out files from the user's view. |
| 1402 | * |
| 1403 | * @beaninfo |
| 1404 | * preferred: true |
| 1405 | * bound: true |
| 1406 | * description: Sets the File Filter used to filter out files of type. |
| 1407 | * |
| 1408 | * @param filter the new current file filter to use |
| 1409 | * @see #getFileFilter |
| 1410 | */ |
| 1411 | public void setFileFilter(FileFilter filter) { |
| 1412 | FileFilter oldValue = fileFilter; |
| 1413 | fileFilter = filter; |
| 1414 | if (filter != null) { |
| 1415 | if (isMultiSelectionEnabled() && selectedFiles != null && selectedFiles.length > 0) { |
| 1416 | Vector fList = new Vector(); |
| 1417 | boolean failed = false; |
| 1418 | for (int i = 0; i < selectedFiles.length; i++) { |
| 1419 | if (filter.accept(selectedFiles[i])) { |
| 1420 | fList.add(selectedFiles[i]); |
| 1421 | } else { |
| 1422 | failed = true; |
| 1423 | } |
| 1424 | } |
| 1425 | if (failed) { |
| 1426 | setSelectedFiles((fList.size() == 0) ? null : (File[])fList.toArray(new File[fList.size()])); |
| 1427 | } |
| 1428 | } else if (selectedFile != null && !filter.accept(selectedFile)) { |
| 1429 | setSelectedFile(null); |
| 1430 | } |
| 1431 | } |
| 1432 | firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter); |
| 1433 | } |
| 1434 | |
| 1435 | |
| 1436 | /** |
| 1437 | * Returns the currently selected file filter. |
| 1438 | * |
| 1439 | * @return the current file filter |
| 1440 | * @see #setFileFilter |
| 1441 | * @see #addChoosableFileFilter |
| 1442 | */ |
| 1443 | public FileFilter getFileFilter() { |
| 1444 | return fileFilter; |
| 1445 | } |
| 1446 | |
| 1447 | /** |
| 1448 | * Sets the file view to used to retrieve UI information, such as |
| 1449 | * the icon that represents a file or the type description of a file. |
| 1450 | * |
| 1451 | * @beaninfo |
| 1452 | * preferred: true |
| 1453 | * bound: true |
| 1454 | * description: Sets the File View used to get file type information. |
| 1455 | * |
| 1456 | * @see #getFileView |
| 1457 | */ |
| 1458 | public void setFileView(FileView fileView) { |
| 1459 | FileView oldValue = this.fileView; |
| 1460 | this.fileView = fileView; |
| 1461 | firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView); |
| 1462 | } |
| 1463 | |
| 1464 | /** |
| 1465 | * Returns the current file view. |
| 1466 | * |
| 1467 | * @see #setFileView |
| 1468 | */ |
| 1469 | public FileView getFileView() { |
| 1470 | return fileView; |
| 1471 | } |
| 1472 | |
| 1473 | // ****************************** |
| 1474 | // *****FileView delegation ***** |
| 1475 | // ****************************** |
| 1476 | |
| 1477 | // NOTE: all of the following methods attempt to delegate |
| 1478 | // first to the client set fileView, and if <code>null</code> is returned |
| 1479 | // (or there is now client defined fileView) then calls the |
| 1480 | // UI's default fileView. |
| 1481 | |
| 1482 | /** |
| 1483 | * Returns the filename. |
| 1484 | * @param f the <code>File</code> |
| 1485 | * @return the <code>String</code> containing the filename for |
| 1486 | * <code>f</code> |
| 1487 | * @see FileView#getName |
| 1488 | */ |
| 1489 | public String getName(File f) { |
| 1490 | String filename = null; |
| 1491 | if(f != null) { |
| 1492 | if(getFileView() != null) { |
| 1493 | filename = getFileView().getName(f); |
| 1494 | } |
| 1495 | if(filename == null && uiFileView != null) { |
| 1496 | filename = uiFileView.getName(f); |
| 1497 | } |
| 1498 | } |
| 1499 | return filename; |
| 1500 | } |
| 1501 | |
| 1502 | /** |
| 1503 | * Returns the file description. |
| 1504 | * @param f the <code>File</code> |
| 1505 | * @return the <code>String</code> containing the file description for |
| 1506 | * <code>f</code> |
| 1507 | * @see FileView#getDescription |
| 1508 | */ |
| 1509 | public String getDescription(File f) { |
| 1510 | String description = null; |
| 1511 | if(f != null) { |
| 1512 | if(getFileView() != null) { |
| 1513 | description = getFileView().getDescription(f); |
| 1514 | } |
| 1515 | if(description == null && uiFileView != null) { |
| 1516 | description = uiFileView.getDescription(f); |
| 1517 | } |
| 1518 | } |
| 1519 | return description; |
| 1520 | } |
| 1521 | |
| 1522 | /** |
| 1523 | * Returns the file type. |
| 1524 | * @param f the <code>File</code> |
| 1525 | * @return the <code>String</code> containing the file type description for |
| 1526 | * <code>f</code> |
| 1527 | * @see FileView#getTypeDescription |
| 1528 | */ |
| 1529 | public String getTypeDescription(File f) { |
| 1530 | String typeDescription = null; |
| 1531 | if(f != null) { |
| 1532 | if(getFileView() != null) { |
| 1533 | typeDescription = getFileView().getTypeDescription(f); |
| 1534 | } |
| 1535 | if(typeDescription == null && uiFileView != null) { |
| 1536 | typeDescription = uiFileView.getTypeDescription(f); |
| 1537 | } |
| 1538 | } |
| 1539 | return typeDescription; |
| 1540 | } |
| 1541 | |
| 1542 | /** |
| 1543 | * Returns the icon for this file or type of file, depending |
| 1544 | * on the system. |
| 1545 | * @param f the <code>File</code> |
| 1546 | * @return the <code>Icon</code> for this file, or type of file |
| 1547 | * @see FileView#getIcon |
| 1548 | */ |
| 1549 | public Icon getIcon(File f) { |
| 1550 | Icon icon = null; |
| 1551 | if (f != null) { |
| 1552 | if(getFileView() != null) { |
| 1553 | icon = getFileView().getIcon(f); |
| 1554 | } |
| 1555 | if(icon == null && uiFileView != null) { |
| 1556 | icon = uiFileView.getIcon(f); |
| 1557 | } |
| 1558 | } |
| 1559 | return icon; |
| 1560 | } |
| 1561 | |
| 1562 | /** |
| 1563 | * Returns true if the file (directory) can be visited. |
| 1564 | * Returns false if the directory cannot be traversed. |
| 1565 | * @param f the <code>File</code> |
| 1566 | * @return true if the file/directory can be traversed, otherwise false |
| 1567 | * @see FileView#isTraversable |
| 1568 | */ |
| 1569 | public boolean isTraversable(File f) { |
| 1570 | Boolean traversable = null; |
| 1571 | if (f != null) { |
| 1572 | if (getFileView() != null) { |
| 1573 | traversable = getFileView().isTraversable(f); |
| 1574 | } |
| 1575 | if (traversable == null && uiFileView != null) { |
| 1576 | traversable = uiFileView.isTraversable(f); |
| 1577 | } |
| 1578 | if (traversable == null) { |
| 1579 | traversable = getFileSystemView().isTraversable(f); |
| 1580 | } |
| 1581 | } |
| 1582 | return (traversable != null && traversable.booleanValue()); |
| 1583 | } |
| 1584 | |
| 1585 | /** |
| 1586 | * Returns true if the file should be displayed. |
| 1587 | * @param f the <code>File</code> |
| 1588 | * @return true if the file should be displayed, otherwise false |
| 1589 | * @see FileFilter#accept |
| 1590 | */ |
| 1591 | public boolean accept(File f) { |
| 1592 | boolean shown = true; |
| 1593 | if(f != null && fileFilter != null) { |
| 1594 | shown = fileFilter.accept(f); |
| 1595 | } |
| 1596 | return shown; |
| 1597 | } |
| 1598 | |
| 1599 | /** |
| 1600 | * Sets the file system view that the <code>JFileChooser</code> uses for |
| 1601 | * accessing and creating file system resources, such as finding |
| 1602 | * the floppy drive and getting a list of root drives. |
| 1603 | * @param fsv the new <code>FileSystemView</code> |
| 1604 | * |
| 1605 | * @beaninfo |
| 1606 | * expert: true |
| 1607 | * bound: true |
| 1608 | * description: Sets the FileSytemView used to get filesystem information. |
| 1609 | * |
| 1610 | * @see FileSystemView |
| 1611 | */ |
| 1612 | public void setFileSystemView(FileSystemView fsv) { |
| 1613 | FileSystemView oldValue = fileSystemView; |
| 1614 | fileSystemView = fsv; |
| 1615 | firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView); |
| 1616 | } |
| 1617 | |
| 1618 | /** |
| 1619 | * Returns the file system view. |
| 1620 | * @return the <code>FileSystemView</code> object |
| 1621 | * @see #setFileSystemView |
| 1622 | */ |
| 1623 | public FileSystemView getFileSystemView() { |
| 1624 | return fileSystemView; |
| 1625 | } |
| 1626 | |
| 1627 | // ************************** |
| 1628 | // ***** Event Handling ***** |
| 1629 | // ************************** |
| 1630 | |
| 1631 | /** |
| 1632 | * Called by the UI when the user hits the Approve button |
| 1633 | * (labeled "Open" or "Save", by default). This can also be |
| 1634 | * called by the programmer. |
| 1635 | * This method causes an action event to fire |
| 1636 | * with the command string equal to |
| 1637 | * <code>APPROVE_SELECTION</code>. |
| 1638 | * |
| 1639 | * @see #APPROVE_SELECTION |
| 1640 | */ |
| 1641 | public void approveSelection() { |
| 1642 | returnValue = APPROVE_OPTION; |
| 1643 | if(dialog != null) { |
| 1644 | dialog.setVisible(false); |
| 1645 | } |
| 1646 | fireActionPerformed(APPROVE_SELECTION); |
| 1647 | } |
| 1648 | |
| 1649 | /** |
| 1650 | * Called by the UI when the user chooses the Cancel button. |
| 1651 | * This can also be called by the programmer. |
| 1652 | * This method causes an action event to fire |
| 1653 | * with the command string equal to |
| 1654 | * <code>CANCEL_SELECTION</code>. |
| 1655 | * |
| 1656 | * @see #CANCEL_SELECTION |
| 1657 | */ |
| 1658 | public void cancelSelection() { |
| 1659 | returnValue = CANCEL_OPTION; |
| 1660 | if(dialog != null) { |
| 1661 | dialog.setVisible(false); |
| 1662 | } |
| 1663 | fireActionPerformed(CANCEL_SELECTION); |
| 1664 | } |
| 1665 | |
| 1666 | /** |
| 1667 | * Adds an <code>ActionListener</code> to the file chooser. |
| 1668 | * |
| 1669 | * @param l the listener to be added |
| 1670 | * |
| 1671 | * @see #approveSelection |
| 1672 | * @see #cancelSelection |
| 1673 | */ |
| 1674 | public void addActionListener(ActionListener l) { |
| 1675 | listenerList.add(ActionListener.class, l); |
| 1676 | } |
| 1677 | |
| 1678 | /** |
| 1679 | * Removes an <code>ActionListener</code> from the file chooser. |
| 1680 | * |
| 1681 | * @param l the listener to be removed |
| 1682 | * |
| 1683 | * @see #addActionListener |
| 1684 | */ |
| 1685 | public void removeActionListener(ActionListener l) { |
| 1686 | listenerList.remove(ActionListener.class, l); |
| 1687 | } |
| 1688 | |
| 1689 | /** |
| 1690 | * Returns an array of all the action listeners |
| 1691 | * registered on this file chooser. |
| 1692 | * |
| 1693 | * @return all of this file chooser's <code>ActionListener</code>s |
| 1694 | * or an empty |
| 1695 | * array if no action listeners are currently registered |
| 1696 | * |
| 1697 | * @see #addActionListener |
| 1698 | * @see #removeActionListener |
| 1699 | * |
| 1700 | * @since 1.4 |
| 1701 | */ |
| 1702 | public ActionListener[] getActionListeners() { |
| 1703 | return (ActionListener[])listenerList.getListeners( |
| 1704 | ActionListener.class); |
| 1705 | } |
| 1706 | |
| 1707 | /** |
| 1708 | * Notifies all listeners that have registered interest for |
| 1709 | * notification on this event type. The event instance |
| 1710 | * is lazily created using the <code>command</code> parameter. |
| 1711 | * |
| 1712 | * @see EventListenerList |
| 1713 | */ |
| 1714 | protected void fireActionPerformed(String command) { |
| 1715 | // Guaranteed to return a non-null array |
| 1716 | Object[] listeners = listenerList.getListenerList(); |
| 1717 | long mostRecentEventTime = EventQueue.getMostRecentEventTime(); |
| 1718 | int modifiers = 0; |
| 1719 | AWTEvent currentEvent = EventQueue.getCurrentEvent(); |
| 1720 | if (currentEvent instanceof InputEvent) { |
| 1721 | modifiers = ((InputEvent)currentEvent).getModifiers(); |
| 1722 | } else if (currentEvent instanceof ActionEvent) { |
| 1723 | modifiers = ((ActionEvent)currentEvent).getModifiers(); |
| 1724 | } |
| 1725 | ActionEvent e = null; |
| 1726 | // Process the listeners last to first, notifying |
| 1727 | // those that are interested in this event |
| 1728 | for (int i = listeners.length-2; i>=0; i-=2) { |
| 1729 | if (listeners[i]==ActionListener.class) { |
| 1730 | // Lazily create the event: |
| 1731 | if (e == null) { |
| 1732 | e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, |
| 1733 | command, mostRecentEventTime, |
| 1734 | modifiers); |
| 1735 | } |
| 1736 | ((ActionListener)listeners[i+1]).actionPerformed(e); |
| 1737 | } |
| 1738 | } |
| 1739 | } |
| 1740 | |
| 1741 | private static class WeakPCL implements PropertyChangeListener { |
| 1742 | WeakReference<JFileChooser> jfcRef; |
| 1743 | |
| 1744 | public WeakPCL(JFileChooser jfc) { |
| 1745 | jfcRef = new WeakReference(jfc); |
| 1746 | } |
| 1747 | public void propertyChange(PropertyChangeEvent ev) { |
| 1748 | assert ev.getPropertyName().equals(SHOW_HIDDEN_PROP); |
| 1749 | JFileChooser jfc = jfcRef.get(); |
| 1750 | if (jfc == null) { |
| 1751 | // Our JFileChooser is no longer around, so we no longer need to |
| 1752 | // listen for PropertyChangeEvents. |
| 1753 | Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, this); |
| 1754 | } |
| 1755 | else { |
| 1756 | boolean oldValue = jfc.useFileHiding; |
| 1757 | jfc.useFileHiding = !((Boolean)ev.getNewValue()).booleanValue(); |
| 1758 | jfc.firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, jfc.useFileHiding); |
| 1759 | } |
| 1760 | } |
| 1761 | } |
| 1762 | |
| 1763 | // ********************************* |
| 1764 | // ***** Pluggable L&F methods ***** |
| 1765 | // ********************************* |
| 1766 | |
| 1767 | /** |
| 1768 | * Resets the UI property to a value from the current look and feel. |
| 1769 | * |
| 1770 | * @see JComponent#updateUI |
| 1771 | */ |
| 1772 | public void updateUI() { |
| 1773 | if (isAcceptAllFileFilterUsed()) { |
| 1774 | removeChoosableFileFilter(getAcceptAllFileFilter()); |
| 1775 | } |
| 1776 | FileChooserUI ui = ((FileChooserUI)UIManager.getUI(this)); |
| 1777 | if (fileSystemView == null) { |
| 1778 | // We were probably deserialized |
| 1779 | setFileSystemView(FileSystemView.getFileSystemView()); |
| 1780 | } |
| 1781 | setUI(ui); |
| 1782 | |
| 1783 | uiFileView = getUI().getFileView(this); |
| 1784 | if(isAcceptAllFileFilterUsed()) { |
| 1785 | addChoosableFileFilter(getAcceptAllFileFilter()); |
| 1786 | } |
| 1787 | } |
| 1788 | |
| 1789 | /** |
| 1790 | * Returns a string that specifies the name of the L&F class |
| 1791 | * that renders this component. |
| 1792 | * |
| 1793 | * @return the string "FileChooserUI" |
| 1794 | * @see JComponent#getUIClassID |
| 1795 | * @see UIDefaults#getUI |
| 1796 | * @beaninfo |
| 1797 | * expert: true |
| 1798 | * description: A string that specifies the name of the L&F class. |
| 1799 | */ |
| 1800 | public String getUIClassID() { |
| 1801 | return uiClassID; |
| 1802 | } |
| 1803 | |
| 1804 | /** |
| 1805 | * Gets the UI object which implements the L&F for this component. |
| 1806 | * |
| 1807 | * @return the FileChooserUI object that implements the FileChooserUI L&F |
| 1808 | */ |
| 1809 | public FileChooserUI getUI() { |
| 1810 | return (FileChooserUI) ui; |
| 1811 | } |
| 1812 | |
| 1813 | /** |
| 1814 | * See <code>readObject</code> and <code>writeObject</code> in |
| 1815 | * <code>JComponent</code> for more |
| 1816 | * information about serialization in Swing. |
| 1817 | */ |
| 1818 | private void readObject(java.io.ObjectInputStream in) |
| 1819 | throws IOException, ClassNotFoundException { |
| 1820 | in.defaultReadObject(); |
| 1821 | installShowFilesListener(); |
| 1822 | } |
| 1823 | |
| 1824 | /** |
| 1825 | * See <code>readObject</code> and <code>writeObject</code> in |
| 1826 | * <code>JComponent</code> for more |
| 1827 | * information about serialization in Swing. |
| 1828 | */ |
| 1829 | private void writeObject(ObjectOutputStream s) throws IOException { |
| 1830 | FileSystemView fsv = null; |
| 1831 | |
| 1832 | if (isAcceptAllFileFilterUsed()) { |
| 1833 | //The AcceptAllFileFilter is UI specific, it will be reset by |
| 1834 | //updateUI() after deserialization |
| 1835 | removeChoosableFileFilter(getAcceptAllFileFilter()); |
| 1836 | } |
| 1837 | if (fileSystemView.equals(FileSystemView.getFileSystemView())) { |
| 1838 | //The default FileSystemView is platform specific, it will be |
| 1839 | //reset by updateUI() after deserialization |
| 1840 | fsv = fileSystemView; |
| 1841 | fileSystemView = null; |
| 1842 | } |
| 1843 | s.defaultWriteObject(); |
| 1844 | if (fsv != null) { |
| 1845 | fileSystemView = fsv; |
| 1846 | } |
| 1847 | if (isAcceptAllFileFilterUsed()) { |
| 1848 | addChoosableFileFilter(getAcceptAllFileFilter()); |
| 1849 | } |
| 1850 | if (getUIClassID().equals(uiClassID)) { |
| 1851 | byte count = JComponent.getWriteObjCounter(this); |
| 1852 | JComponent.setWriteObjCounter(this, --count); |
| 1853 | if (count == 0 && ui != null) { |
| 1854 | ui.installUI(this); |
| 1855 | } |
| 1856 | } |
| 1857 | } |
| 1858 | |
| 1859 | |
| 1860 | /** |
| 1861 | * Returns a string representation of this <code>JFileChooser</code>. |
| 1862 | * This method |
| 1863 | * is intended to be used only for debugging purposes, and the |
| 1864 | * content and format of the returned string may vary between |
| 1865 | * implementations. The returned string may be empty but may not |
| 1866 | * be <code>null</code>. |
| 1867 | * |
| 1868 | * @return a string representation of this <code>JFileChooser</code> |
| 1869 | */ |
| 1870 | protected String paramString() { |
| 1871 | String approveButtonTextString = (approveButtonText != null ? |
| 1872 | approveButtonText: ""); |
| 1873 | String dialogTitleString = (dialogTitle != null ? |
| 1874 | dialogTitle: ""); |
| 1875 | String dialogTypeString; |
| 1876 | if (dialogType == OPEN_DIALOG) { |
| 1877 | dialogTypeString = "OPEN_DIALOG"; |
| 1878 | } else if (dialogType == SAVE_DIALOG) { |
| 1879 | dialogTypeString = "SAVE_DIALOG"; |
| 1880 | } else if (dialogType == CUSTOM_DIALOG) { |
| 1881 | dialogTypeString = "CUSTOM_DIALOG"; |
| 1882 | } else dialogTypeString = ""; |
| 1883 | String returnValueString; |
| 1884 | if (returnValue == CANCEL_OPTION) { |
| 1885 | returnValueString = "CANCEL_OPTION"; |
| 1886 | } else if (returnValue == APPROVE_OPTION) { |
| 1887 | returnValueString = "APPROVE_OPTION"; |
| 1888 | } else if (returnValue == ERROR_OPTION) { |
| 1889 | returnValueString = "ERROR_OPTION"; |
| 1890 | } else returnValueString = ""; |
| 1891 | String useFileHidingString = (useFileHiding ? |
| 1892 | "true" : "false"); |
| 1893 | String fileSelectionModeString; |
| 1894 | if (fileSelectionMode == FILES_ONLY) { |
| 1895 | fileSelectionModeString = "FILES_ONLY"; |
| 1896 | } else if (fileSelectionMode == DIRECTORIES_ONLY) { |
| 1897 | fileSelectionModeString = "DIRECTORIES_ONLY"; |
| 1898 | } else if (fileSelectionMode == FILES_AND_DIRECTORIES) { |
| 1899 | fileSelectionModeString = "FILES_AND_DIRECTORIES"; |
| 1900 | } else fileSelectionModeString = ""; |
| 1901 | String currentDirectoryString = (currentDirectory != null ? |
| 1902 | currentDirectory.toString() : ""); |
| 1903 | String selectedFileString = (selectedFile != null ? |
| 1904 | selectedFile.toString() : ""); |
| 1905 | |
| 1906 | return super.paramString() + |
| 1907 | ",approveButtonText=" + approveButtonTextString + |
| 1908 | ",currentDirectory=" + currentDirectoryString + |
| 1909 | ",dialogTitle=" + dialogTitleString + |
| 1910 | ",dialogType=" + dialogTypeString + |
| 1911 | ",fileSelectionMode=" + fileSelectionModeString + |
| 1912 | ",returnValue=" + returnValueString + |
| 1913 | ",selectedFile=" + selectedFileString + |
| 1914 | ",useFileHiding=" + useFileHidingString; |
| 1915 | } |
| 1916 | |
| 1917 | ///////////////// |
| 1918 | // Accessibility support |
| 1919 | //////////////// |
| 1920 | |
| 1921 | protected AccessibleContext accessibleContext = null; |
| 1922 | |
| 1923 | /** |
| 1924 | * Gets the AccessibleContext associated with this JFileChooser. |
| 1925 | * For file choosers, the AccessibleContext takes the form of an |
| 1926 | * AccessibleJFileChooser. |
| 1927 | * A new AccessibleJFileChooser instance is created if necessary. |
| 1928 | * |
| 1929 | * @return an AccessibleJFileChooser that serves as the |
| 1930 | * AccessibleContext of this JFileChooser |
| 1931 | */ |
| 1932 | public AccessibleContext getAccessibleContext() { |
| 1933 | if (accessibleContext == null) { |
| 1934 | accessibleContext = new AccessibleJFileChooser(); |
| 1935 | } |
| 1936 | return accessibleContext; |
| 1937 | } |
| 1938 | |
| 1939 | /** |
| 1940 | * This class implements accessibility support for the |
| 1941 | * <code>JFileChooser</code> class. It provides an implementation of the |
| 1942 | * Java Accessibility API appropriate to file chooser user-interface |
| 1943 | * elements. |
| 1944 | */ |
| 1945 | protected class AccessibleJFileChooser extends AccessibleJComponent { |
| 1946 | |
| 1947 | /** |
| 1948 | * Gets the role of this object. |
| 1949 | * |
| 1950 | * @return an instance of AccessibleRole describing the role of the |
| 1951 | * object |
| 1952 | * @see AccessibleRole |
| 1953 | */ |
| 1954 | public AccessibleRole getAccessibleRole() { |
| 1955 | return AccessibleRole.FILE_CHOOSER; |
| 1956 | } |
| 1957 | |
| 1958 | } // inner class AccessibleJFileChooser |
| 1959 | |
| 1960 | } |