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