001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package javax.swing;
018:
019: import java.awt.Component;
020: import java.awt.Dialog;
021: import java.awt.Frame;
022: import java.awt.HeadlessException;
023: import java.awt.Window;
024: import java.awt.event.ActionEvent;
025: import java.awt.event.ActionListener;
026: import java.io.File;
027: import java.util.Collection;
028: import java.util.LinkedList;
029: import javax.accessibility.Accessible;
030: import javax.accessibility.AccessibleContext;
031: import javax.accessibility.AccessibleRole;
032: import javax.swing.filechooser.FileFilter;
033: import javax.swing.filechooser.FileSystemView;
034: import javax.swing.filechooser.FileView;
035: import javax.swing.plaf.FileChooserUI;
036: import org.apache.harmony.x.swing.Utilities;
037:
038: import org.apache.harmony.x.swing.internal.nls.Messages;
039:
040: /**
041: * <p>
042: * <i>JFileChooser</i>
043: * </p>
044: * <h3>Implementation Notes:</h3>
045: * <ul>
046: * <li>The <code>serialVersionUID</code> fields are explicitly declared as a performance
047: * optimization, not as a guarantee of serialization compatibility.</li>
048: * </ul>
049: */
050: public class JFileChooser extends JComponent implements Accessible {
051: private static final long serialVersionUID = 1049148651561366602L;
052:
053: public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged";
054:
055: public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
056:
057: public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty";
058:
059: public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
060:
061: public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
062:
063: public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
064:
065: public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty";
066:
067: public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty";
068:
069: public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
070:
071: public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
072:
073: public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
074:
075: public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
076:
077: public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
078:
079: public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
080:
081: public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
082:
083: public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty";
084:
085: public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty";
086:
087: public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty";
088:
089: public static final String APPROVE_SELECTION = "ApproveSelection";
090:
091: public static final String CANCEL_SELECTION = "CancelSelection";
092:
093: public static final int ERROR_OPTION = -1;
094:
095: public static final int APPROVE_OPTION = 0;
096:
097: public static final int CANCEL_OPTION = 1;
098:
099: public static final int OPEN_DIALOG = 0;
100:
101: public static final int SAVE_DIALOG = 1;
102:
103: public static final int CUSTOM_DIALOG = 2;
104:
105: public static final int FILES_ONLY = 0;
106:
107: public static final int DIRECTORIES_ONLY = 1;
108:
109: public static final int FILES_AND_DIRECTORIES = 2;
110:
111: private static final String UI_CLASS_ID = "FileChooserUI";
112:
113: private File currentDirectory;
114:
115: private FileSystemView fileSystemView;
116:
117: private FileView fileView;
118:
119: private boolean dragEnabled;
120:
121: private boolean controlButtonsAreShown = true;
122:
123: private int dialogType = OPEN_DIALOG;
124:
125: private String dialogTitle;
126:
127: private boolean fileHidingEnabled = true;
128:
129: private FileFilter fileFilter;
130:
131: private boolean multiSelectionEnabled;
132:
133: private File selectedFile;
134:
135: private JComponent accessory;
136:
137: private File[] selectedFiles = new File[0];
138:
139: private Collection<FileFilter> choosableFileFilters = new LinkedList<FileFilter>();
140:
141: private String approveButtonText;
142:
143: private String approveButtonToolTipText;
144:
145: private int approveButtonMnemonic;
146:
147: private int fileSelectionMode = FILES_ONLY;
148:
149: private boolean acceptAllFileFilterUsed = true;
150:
151: private int chooseResult;
152:
153: private JDialog fileChooserDialog;
154:
155: protected class AccessibleJFileChooser extends AccessibleJComponent {
156: private static final long serialVersionUID = -6919995775059834138L;
157:
158: @Override
159: public AccessibleRole getAccessibleRole() {
160: return AccessibleRole.FILE_CHOOSER;
161: }
162: }
163:
164: public JFileChooser() {
165: this ((String) null);
166: }
167:
168: public JFileChooser(final String currentDirectoryPath) {
169: this (currentDirectoryPath, null);
170: }
171:
172: public JFileChooser(final File currentDirectory) {
173: this (currentDirectory, null);
174: }
175:
176: public JFileChooser(final FileSystemView fsv) {
177: this ((File) null, fsv);
178: }
179:
180: public JFileChooser(final String currentDirectoryPath,
181: final FileSystemView fsv) {
182: this (currentDirectoryPath != null ? new File(
183: currentDirectoryPath) : null, fsv);
184: }
185:
186: public JFileChooser(final File currentDirectory,
187: final FileSystemView fsv) {
188: setup(fsv);
189: setCurrentDirectory(currentDirectory);
190: }
191:
192: public boolean accept(final File file) {
193: return fileFilter != null ? fileFilter.accept(file) : true;
194: }
195:
196: public void addActionListener(final ActionListener l) {
197: listenerList.add(ActionListener.class, l);
198: }
199:
200: public void removeActionListener(final ActionListener l) {
201: listenerList.remove(ActionListener.class, l);
202: }
203:
204: public ActionListener[] getActionListeners() {
205: return listenerList.getListeners(ActionListener.class);
206: }
207:
208: public void addChoosableFileFilter(final FileFilter filter) {
209: FileFilter[] oldValue = toFileFilterArray(choosableFileFilters);
210: if (choosableFileFilters.contains(filter)) {
211: return;
212: }
213: choosableFileFilters.add(filter);
214: firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
215: oldValue, toFileFilterArray(choosableFileFilters));
216: setFileFilter(filter);
217: }
218:
219: public boolean removeChoosableFileFilter(final FileFilter filter) {
220: FileFilter[] oldValue = toFileFilterArray(choosableFileFilters);
221: boolean result = choosableFileFilters.remove(filter);
222: firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
223: oldValue, toFileFilterArray(choosableFileFilters));
224: return result;
225: }
226:
227: public void resetChoosableFileFilters() {
228: FileFilter[] oldValue = toFileFilterArray(choosableFileFilters);
229: choosableFileFilters.clear();
230: if (isAcceptAllFileFilterUsed()) {
231: choosableFileFilters.add(getAcceptAllFileFilter());
232: }
233: firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
234: oldValue, toFileFilterArray(choosableFileFilters));
235: }
236:
237: public FileFilter[] getChoosableFileFilters() {
238: return toFileFilterArray(choosableFileFilters);
239: }
240:
241: public void approveSelection() {
242: chooseResult = APPROVE_OPTION;
243: fireActionPerformed(APPROVE_SELECTION);
244: if (fileChooserDialog != null) {
245: fileChooserDialog.dispose();
246: }
247: }
248:
249: public void cancelSelection() {
250: chooseResult = CANCEL_OPTION;
251: fireActionPerformed(CANCEL_SELECTION);
252: if (fileChooserDialog != null) {
253: fileChooserDialog.dispose();
254: }
255: }
256:
257: public void changeToParentDirectory() {
258: if (currentDirectory != null
259: && !fileSystemView.isRoot(currentDirectory)) {
260: setCurrentDirectory(fileSystemView
261: .getParentDirectory(currentDirectory));
262: }
263: }
264:
265: public void ensureFileIsVisible(final File f) {
266: getUI().ensureFileIsVisible(this , f);
267: }
268:
269: public FileFilter getAcceptAllFileFilter() {
270: return getUI().getAcceptAllFileFilter(this );
271: }
272:
273: public boolean isAcceptAllFileFilterUsed() {
274: return acceptAllFileFilterUsed;
275: }
276:
277: public void setAcceptAllFileFilterUsed(final boolean accept) {
278: boolean oldValue = acceptAllFileFilterUsed;
279: acceptAllFileFilterUsed = accept;
280: firePropertyChange(
281: ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue,
282: accept);
283: if (!accept) {
284: choosableFileFilters.remove(getAcceptAllFileFilter());
285: } else if (!choosableFileFilters
286: .contains(getAcceptAllFileFilter())) {
287: choosableFileFilters.add(getAcceptAllFileFilter());
288: }
289: }
290:
291: @Override
292: public AccessibleContext getAccessibleContext() {
293: if (accessibleContext == null) {
294: accessibleContext = new AccessibleJFileChooser();
295: }
296: return accessibleContext;
297: }
298:
299: public JComponent getAccessory() {
300: return accessory;
301: }
302:
303: public void setAccessory(final JComponent accessory) {
304: JComponent oldValue = this .accessory;
305: this .accessory = accessory;
306: firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue,
307: accessory);
308: }
309:
310: public int getApproveButtonMnemonic() {
311: return approveButtonMnemonic;
312: }
313:
314: public void setApproveButtonMnemonic(final char mnemonic) {
315: setApproveButtonMnemonic(Utilities.keyCharToKeyCode(mnemonic));
316: }
317:
318: public void setApproveButtonMnemonic(final int mnemonic) {
319: int oldValue = approveButtonMnemonic;
320: approveButtonMnemonic = mnemonic;
321: firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY,
322: oldValue, mnemonic);
323: }
324:
325: public String getApproveButtonText() {
326: return approveButtonText;
327: }
328:
329: public void setApproveButtonText(final String approveButtonText) {
330: String oldValue = this .approveButtonText;
331: this .approveButtonText = approveButtonText;
332: firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY,
333: oldValue, approveButtonText);
334: if (approveButtonText != null
335: && !approveButtonText.equals(getUI()
336: .getApproveButtonText(this ))) {
337: // setDialogType(CUSTOM_DIALOG);
338: }
339: }
340:
341: public String getApproveButtonToolTipText() {
342: return approveButtonToolTipText;
343: }
344:
345: public void setApproveButtonToolTipText(final String toolTipText) {
346: String oldValue = this .approveButtonToolTipText;
347: this .approveButtonToolTipText = toolTipText;
348: firePropertyChange(
349: APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY,
350: oldValue, toolTipText);
351: }
352:
353: public boolean getControlButtonsAreShown() {
354: return controlButtonsAreShown;
355: }
356:
357: public void setControlButtonsAreShown(final boolean shown) {
358: boolean oldValue = controlButtonsAreShown;
359: controlButtonsAreShown = shown;
360: firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY,
361: oldValue, shown);
362: }
363:
364: public File getCurrentDirectory() {
365: return currentDirectory;
366: }
367:
368: public void setCurrentDirectory(final File dir) {
369: File oldValue = currentDirectory;
370: if (dir != null && dir.exists()) {
371: if (!dir.isDirectory()) {
372: File parent = fileSystemView.getParentDirectory(dir);
373: while (parent != null && !isTraversable(parent)
374: && !fileSystemView.isRoot(parent)) {
375: parent = fileSystemView.getParentDirectory(parent);
376: }
377: if (parent != null) {
378: currentDirectory = parent;
379: }
380: } else {
381: currentDirectory = dir;
382: }
383: }
384: if (currentDirectory == null) {
385: currentDirectory = fileSystemView.getDefaultDirectory();
386: }
387: firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue,
388: currentDirectory);
389: }
390:
391: public String getDialogTitle() {
392: return dialogTitle;
393: }
394:
395: public void setDialogTitle(final String dialogTitle) {
396: String oldValue = this .dialogTitle;
397: this .dialogTitle = dialogTitle;
398: firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue,
399: dialogTitle);
400: }
401:
402: public int getDialogType() {
403: return dialogType;
404: }
405:
406: public void setDialogType(final int dialogType) {
407: if (dialogType != OPEN_DIALOG && dialogType != SAVE_DIALOG
408: && dialogType != CUSTOM_DIALOG) {
409: throw new IllegalArgumentException(Messages
410: .getString("swing.11")); //$NON-NLS-1$
411: }
412: int oldValue = this .dialogType;
413: this .dialogType = dialogType;
414: firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue,
415: dialogType);
416: }
417:
418: public boolean getDragEnabled() {
419: return dragEnabled;
420: }
421:
422: public void setDragEnabled(final boolean enabled) {
423: dragEnabled = enabled;
424: }
425:
426: public FileFilter getFileFilter() {
427: return fileFilter;
428: }
429:
430: public void setFileFilter(final FileFilter filter) {
431: FileFilter oldValue = fileFilter;
432: fileFilter = filter;
433: firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue,
434: filter);
435: }
436:
437: public int getFileSelectionMode() {
438: return fileSelectionMode;
439: }
440:
441: public void setFileSelectionMode(final int mode) {
442: if (mode != FILES_ONLY && mode != DIRECTORIES_ONLY
443: && mode != FILES_AND_DIRECTORIES) {
444: throw new IllegalArgumentException(Messages
445: .getString("swing.12")); //$NON-NLS-1$
446: }
447: int oldValue = fileSelectionMode;
448: fileSelectionMode = mode;
449: firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY,
450: oldValue, mode);
451: }
452:
453: public FileSystemView getFileSystemView() {
454: return fileSystemView;
455: }
456:
457: public void setFileSystemView(final FileSystemView fsv) {
458: FileSystemView oldValue = fileSystemView;
459: fileSystemView = fsv;
460: firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue,
461: fsv);
462: }
463:
464: public FileView getFileView() {
465: return fileView;
466: }
467:
468: public void setFileView(final FileView fileView) {
469: FileView oldValue = this .fileView;
470: this .fileView = fileView;
471: firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue,
472: fileView);
473: }
474:
475: public Icon getIcon(final File f) {
476: Icon result = fileView != null ? fileView.getIcon(f) : null;
477: return result != null ? result : getUI().getFileView(this )
478: .getIcon(f);
479: }
480:
481: public String getDescription(final File f) {
482: String result = fileView != null ? fileView.getDescription(f)
483: : null;
484: return result != null ? result : getUI().getFileView(this )
485: .getDescription(f);
486: }
487:
488: public String getTypeDescription(final File f) {
489: String result = fileView != null ? fileView
490: .getTypeDescription(f) : null;
491: return result != null ? result : getUI().getFileView(this )
492: .getTypeDescription(f);
493: }
494:
495: public String getName(final File f) {
496: String result = fileView != null ? fileView.getName(f) : null;
497: return result != null ? result : getUI().getFileView(this )
498: .getName(f);
499: }
500:
501: public File getSelectedFile() {
502: return selectedFile;
503: }
504:
505: public void setSelectedFile(final File file) {
506: File oldValue = selectedFile;
507: selectedFile = file;
508: firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue,
509: file);
510: }
511:
512: public File[] getSelectedFiles() {
513: return selectedFiles;
514: }
515:
516: public void setSelectedFiles(final File[] selectedFiles) {
517: File[] oldValue = this .selectedFiles;
518: this .selectedFiles = new File[selectedFiles.length];
519: System.arraycopy(selectedFiles, 0, this .selectedFiles, 0,
520: selectedFiles.length);
521: if (selectedFiles.length > 0) {
522: setSelectedFile(selectedFiles[0]);
523: } else {
524: setSelectedFile(null);
525: }
526: firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue,
527: selectedFiles);
528: }
529:
530: public FileChooserUI getUI() {
531: return (FileChooserUI) ui;
532: }
533:
534: @Override
535: public void updateUI() {
536: setUI(UIManager.getUI(this ));
537: }
538:
539: @Override
540: public String getUIClassID() {
541: return UI_CLASS_ID;
542: }
543:
544: public boolean isDirectorySelectionEnabled() {
545: return fileSelectionMode == DIRECTORIES_ONLY
546: || fileSelectionMode == FILES_AND_DIRECTORIES;
547: }
548:
549: public boolean isFileHidingEnabled() {
550: return fileHidingEnabled;
551: }
552:
553: public void setFileHidingEnabled(final boolean enabled) {
554: boolean oldValue = fileHidingEnabled;
555: fileHidingEnabled = enabled;
556: firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue,
557: enabled);
558: }
559:
560: public boolean isFileSelectionEnabled() {
561: return fileSelectionMode == FILES_ONLY
562: || fileSelectionMode == FILES_AND_DIRECTORIES;
563: }
564:
565: public boolean isMultiSelectionEnabled() {
566: return multiSelectionEnabled;
567: }
568:
569: public void setMultiSelectionEnabled(final boolean enabled) {
570: boolean oldValue = multiSelectionEnabled;
571: multiSelectionEnabled = enabled;
572: firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY,
573: oldValue, enabled);
574: }
575:
576: public boolean isTraversable(final File f) {
577: Boolean result = fileView != null ? fileView.isTraversable(f)
578: : getUI().getFileView(this ).isTraversable(f);
579: return result != null ? result.booleanValue() : true;
580: }
581:
582: public void rescanCurrentDirectory() {
583: getUI().rescanCurrentDirectory(this );
584: }
585:
586: public int showDialog(final Component parent,
587: final String approveButtonText) {
588: setApproveButtonText(approveButtonText);
589: setDialogTitle(approveButtonText);
590: fileChooserDialog = createDialog(parent);
591: chooseResult = ERROR_OPTION;
592: fileChooserDialog.setVisible(true);
593: return chooseResult;
594: }
595:
596: public int showOpenDialog(final Component parent) {
597: setDialogType(OPEN_DIALOG);
598: return showDialog(parent, getUI().getApproveButtonText(this ));
599: }
600:
601: public int showSaveDialog(final Component parent) {
602: setDialogType(SAVE_DIALOG);
603: return showDialog(parent, getUI().getApproveButtonText(this ));
604: }
605:
606: protected void fireActionPerformed(final String command) {
607: ActionListener[] listeners = getActionListeners();
608: if (listeners.length > 0) {
609: ActionEvent event = new ActionEvent(this ,
610: ActionEvent.ACTION_PERFORMED, command);
611: for (int i = 0; i < listeners.length; i++) {
612: listeners[i].actionPerformed(event);
613: }
614: }
615: }
616:
617: protected JDialog createDialog(final Component parent)
618: throws HeadlessException {
619: Window ancestingWindow = parent instanceof Window ? (Window) parent
620: : SwingUtilities.getWindowAncestor(parent);
621: final JDialog result;
622: if (ancestingWindow instanceof Frame) {
623: result = new JDialog((Frame) ancestingWindow);
624: } else if (ancestingWindow instanceof Dialog) {
625: result = new JDialog((Dialog) ancestingWindow);
626: } else {
627: result = new JDialog();
628: }
629: result.setModal(true);
630: result.setLocationRelativeTo(parent);
631: result.setTitle(getDialogTitle());
632: result.getContentPane().add(this );
633: if (JDialog.isDefaultLookAndFeelDecorated()) {
634: result.getRootPane().setWindowDecorationStyle(
635: JRootPane.FILE_CHOOSER_DIALOG);
636: }
637: result.pack();
638: return result;
639: }
640:
641: protected void setup(final FileSystemView view) {
642: setFileSystemView(view != null ? view : FileSystemView
643: .getFileSystemView());
644: updateUI();
645: if (isAcceptAllFileFilterUsed()) {
646: addChoosableFileFilter(getAcceptAllFileFilter());
647: }
648: setName(null);
649: }
650:
651: private FileFilter[] toFileFilterArray(
652: final Collection<FileFilter> fileFilterList) {
653: return fileFilterList.toArray(new FileFilter[fileFilterList
654: .size()]);
655: }
656: }
|