KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > metal > MetalFileChooserUI


1 /*
2  * @(#)MetalFileChooserUI.java 1.83 04/03/30
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing.plaf.metal;
9
10 import javax.swing.*;
11 import javax.swing.border.EmptyBorder JavaDoc;
12 import javax.swing.filechooser.*;
13 import javax.swing.event.*;
14 import javax.swing.plaf.*;
15 import javax.swing.plaf.basic.*;
16 import javax.swing.table.*;
17 import java.awt.*;
18 import java.awt.event.*;
19 import java.beans.*;
20 import java.io.File JavaDoc;
21 import java.io.FileNotFoundException JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.util.*;
24
25 import sun.awt.shell.ShellFolder;
26 import sun.swing.*;
27 import com.sun.java.swing.SwingUtilities2;
28
29 /**
30  * Metal L&F implementation of a FileChooser.
31  *
32  * @version 1.83 03/30/04
33  * @author Jeff Dinkins
34  */

35 public class MetalFileChooserUI extends BasicFileChooserUI {
36
37     // Much of the Metal UI for JFilechooser is just a copy of
38
// the windows implementation, but using Metal themed buttons, lists,
39
// icons, etc. We are planning a complete rewrite, and hence we've
40
// made most things in this class private.
41

42     private JLabel lookInLabel;
43     private JComboBox directoryComboBox;
44     private DirectoryComboBoxModel directoryComboBoxModel;
45     private Action directoryComboBoxAction = new DirectoryComboBoxAction();
46
47     private FilterComboBoxModel filterComboBoxModel;
48
49     private JTextField fileNameTextField;
50
51     private FilePane filePane;
52     private JToggleButton listViewButton;
53     private JToggleButton detailsViewButton;
54
55     private boolean useShellFolder;
56
57     private JButton approveButton;
58     private JButton cancelButton;
59
60     private JPanel buttonPanel;
61     private JPanel bottomPanel;
62
63     private JComboBox filterComboBox;
64
65     private static final Dimension hstrut5 = new Dimension(5, 1);
66     private static final Dimension hstrut11 = new Dimension(11, 1);
67
68     private static final Dimension vstrut5 = new Dimension(1, 5);
69
70     private static final Insets shrinkwrap = new Insets(0,0,0,0);
71
72     // Preferred and Minimum sizes for the dialog box
73
private static int PREF_WIDTH = 500;
74     private static int PREF_HEIGHT = 326;
75     private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);
76
77     private static int MIN_WIDTH = 500;
78     private static int MIN_HEIGHT = 326;
79     private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);
80
81     private static int LIST_PREF_WIDTH = 405;
82     private static int LIST_PREF_HEIGHT = 135;
83     private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);
84
85     // Labels, mnemonics, and tooltips (oh my!)
86
private int lookInLabelMnemonic = 0;
87     private String JavaDoc lookInLabelText = null;
88     private String JavaDoc saveInLabelText = null;
89
90     private int fileNameLabelMnemonic = 0;
91     private String JavaDoc fileNameLabelText = null;
92
93     private int filesOfTypeLabelMnemonic = 0;
94     private String JavaDoc filesOfTypeLabelText = null;
95
96     private String JavaDoc upFolderToolTipText = null;
97     private String JavaDoc upFolderAccessibleName = null;
98
99     private String JavaDoc homeFolderToolTipText = null;
100     private String JavaDoc homeFolderAccessibleName = null;
101
102     private String JavaDoc newFolderToolTipText = null;
103     private String JavaDoc newFolderAccessibleName = null;
104
105     private String JavaDoc listViewButtonToolTipText = null;
106     private String JavaDoc listViewButtonAccessibleName = null;
107
108     private String JavaDoc detailsViewButtonToolTipText = null;
109     private String JavaDoc detailsViewButtonAccessibleName = null;
110
111     //
112
// ComponentUI Interface Implementation methods
113
//
114
public static ComponentUI createUI(JComponent c) {
115         return new MetalFileChooserUI JavaDoc((JFileChooser) c);
116     }
117
118     public MetalFileChooserUI(JFileChooser filechooser) {
119     super(filechooser);
120     }
121
122     public void installUI(JComponent c) {
123     super.installUI(c);
124     }
125
126     public void uninstallComponents(JFileChooser fc) {
127     fc.removeAll();
128     bottomPanel = null;
129     buttonPanel = null;
130     }
131
132     private class MetalFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {
133     public JFileChooser getFileChooser() {
134         return MetalFileChooserUI.this.getFileChooser();
135     }
136
137     public BasicDirectoryModel getModel() {
138         return MetalFileChooserUI.this.getModel();
139     }
140
141     public JPanel createList() {
142         return MetalFileChooserUI.this.createList(getFileChooser());
143     }
144
145     public JPanel createDetailsView() {
146         return MetalFileChooserUI.this.createDetailsView(getFileChooser());
147     }
148
149     public boolean isDirectorySelected() {
150         return MetalFileChooserUI.this.isDirectorySelected();
151     }
152
153     public File JavaDoc getDirectory() {
154         return MetalFileChooserUI.this.getDirectory();
155     }
156
157     public Action getChangeToParentDirectoryAction() {
158         return MetalFileChooserUI.this.getChangeToParentDirectoryAction();
159     }
160
161     public Action getApproveSelectionAction() {
162         return MetalFileChooserUI.this.getApproveSelectionAction();
163     }
164
165     public Action getNewFolderAction() {
166         return MetalFileChooserUI.this.getNewFolderAction();
167     }
168
169     public MouseListener createDoubleClickListener(JList list) {
170         return MetalFileChooserUI.this.createDoubleClickListener(getFileChooser(),
171                                      list);
172     }
173
174     public ListSelectionListener createListSelectionListener() {
175         return MetalFileChooserUI.this.createListSelectionListener(getFileChooser());
176     }
177     }
178
179     public void installComponents(JFileChooser fc) {
180     FileSystemView fsv = fc.getFileSystemView();
181
182     fc.setBorder(new EmptyBorder JavaDoc(12, 12, 11, 11));
183     fc.setLayout(new BorderLayout(0, 11));
184
185     filePane = new FilePane(new MetalFileChooserUIAccessor());
186     fc.addPropertyChangeListener(filePane);
187
188     updateUseShellFolder();
189
190     // ********************************* //
191
// **** Construct the top panel **** //
192
// ********************************* //
193

194     // Directory manipulation buttons
195
JPanel topPanel = new JPanel(new BorderLayout(11, 0));
196     JPanel topButtonPanel = new JPanel();
197     topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.LINE_AXIS));
198     topPanel.add(topButtonPanel, BorderLayout.AFTER_LINE_ENDS);
199
200     // Add the top panel to the fileChooser
201
fc.add(topPanel, BorderLayout.NORTH);
202
203     // ComboBox Label
204
lookInLabel = new JLabel(lookInLabelText);
205         lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
206     topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS);
207
208     // CurrentDir ComboBox
209
directoryComboBox = new JComboBox() {
210         public Dimension getPreferredSize() {
211         Dimension d = super.getPreferredSize();
212         // Must be small enough to not affect total width.
213
d.width = 150;
214         return d;
215         }
216     };
217     directoryComboBox.getAccessibleContext().setAccessibleDescription(lookInLabelText);
218     directoryComboBox.putClientProperty( "JComboBox.isTableCellEditor", Boolean.TRUE );
219     lookInLabel.setLabelFor(directoryComboBox);
220     directoryComboBoxModel = createDirectoryComboBoxModel(fc);
221     directoryComboBox.setModel(directoryComboBoxModel);
222     directoryComboBox.addActionListener(directoryComboBoxAction);
223     directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
224     directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
225     directoryComboBox.setAlignmentY(JComponent.TOP_ALIGNMENT);
226     directoryComboBox.setMaximumRowCount(8);
227
228     topPanel.add(directoryComboBox, BorderLayout.CENTER);
229
230     // Up Button
231
JButton upFolderButton = new JButton(getChangeToParentDirectoryAction());
232     upFolderButton.setText(null);
233     upFolderButton.setIcon(upFolderIcon);
234         upFolderButton.setToolTipText(upFolderToolTipText);
235         upFolderButton.getAccessibleContext().setAccessibleName(upFolderAccessibleName);
236     upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
237     upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
238     upFolderButton.setMargin(shrinkwrap);
239
240     topButtonPanel.add(upFolderButton);
241     topButtonPanel.add(Box.createRigidArea(hstrut5));
242
243     // Home Button
244
File JavaDoc homeDir = fsv.getHomeDirectory();
245     String JavaDoc toolTipText = homeFolderToolTipText;
246     if (fsv.isRoot(homeDir)) {
247         toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop".
248
}
249
250
251
252
253     JButton b = new JButton(homeFolderIcon);
254         b.setToolTipText(toolTipText);
255         b.getAccessibleContext().setAccessibleName(homeFolderAccessibleName);
256     b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
257     b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
258     b.setMargin(shrinkwrap);
259
260     b.addActionListener(getGoHomeAction());
261     topButtonPanel.add(b);
262     topButtonPanel.add(Box.createRigidArea(hstrut5));
263
264     // New Directory Button
265
if (!UIManager.getBoolean("FileChooser.readOnly")) {
266         b = new JButton(filePane.getNewFolderAction());
267         b.setText(null);
268         b.setIcon(newFolderIcon);
269         b.setToolTipText(newFolderToolTipText);
270         b.getAccessibleContext().setAccessibleName(newFolderAccessibleName);
271         b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
272         b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
273         b.setMargin(shrinkwrap);
274     }
275     topButtonPanel.add(b);
276     topButtonPanel.add(Box.createRigidArea(hstrut5));
277
278     // View button group
279
ButtonGroup viewButtonGroup = new ButtonGroup();
280
281     // List Button
282
listViewButton = new JToggleButton(listViewIcon);
283         listViewButton.setToolTipText(listViewButtonToolTipText);
284         listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName);
285     listViewButton.setSelected(true);
286     listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
287     listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
288     listViewButton.setMargin(shrinkwrap);
289     listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));
290     topButtonPanel.add(listViewButton);
291     viewButtonGroup.add(listViewButton);
292
293     // Details Button
294
detailsViewButton = new JToggleButton(detailsViewIcon);
295         detailsViewButton.setToolTipText(detailsViewButtonToolTipText);
296         detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName);
297     detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
298     detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
299     detailsViewButton.setMargin(shrinkwrap);
300     detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));
301     topButtonPanel.add(detailsViewButton);
302     viewButtonGroup.add(detailsViewButton);
303
304     filePane.addPropertyChangeListener(new PropertyChangeListener() {
305         public void propertyChange(PropertyChangeEvent e) {
306         if ("viewType".equals(e.getPropertyName())) {
307             int viewType = filePane.getViewType();
308             switch (viewType) {
309               case FilePane.VIEWTYPE_LIST:
310             listViewButton.setSelected(true);
311             break;
312
313               case FilePane.VIEWTYPE_DETAILS:
314             detailsViewButton.setSelected(true);
315             break;
316             }
317         }
318         }
319     });
320
321     // ************************************** //
322
// ******* Add the directory pane ******* //
323
// ************************************** //
324
fc.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
325     JComponent accessory = fc.getAccessory();
326     if(accessory != null) {
327         getAccessoryPanel().add(accessory);
328     }
329     filePane.setPreferredSize(LIST_PREF_SIZE);
330     fc.add(filePane, BorderLayout.CENTER);
331
332     // ********************************** //
333
// **** Construct the bottom panel ** //
334
// ********************************** //
335
JPanel bottomPanel = getBottomPanel();
336     bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
337     fc.add(bottomPanel, BorderLayout.SOUTH);
338
339     // FileName label and textfield
340
JPanel fileNamePanel = new JPanel();
341     fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS));
342     bottomPanel.add(fileNamePanel);
343     bottomPanel.add(Box.createRigidArea(vstrut5));
344
345         AlignedLabel fileNameLabel = new AlignedLabel(fileNameLabelText);
346         fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);
347     fileNamePanel.add(fileNameLabel);
348
349     fileNameTextField = new JTextField(35) {
350         public Dimension getMaximumSize() {
351         return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
352         }
353     };
354     fileNamePanel.add(fileNameTextField);
355     fileNameLabel.setLabelFor(fileNameTextField);
356         fileNameTextField.addFocusListener(
357         new FocusAdapter() {
358         public void focusGained(FocusEvent e) {
359             if (!getFileChooser().isMultiSelectionEnabled()) {
360             filePane.clearSelection();
361             }
362         }
363         }
364         );
365     if (fc.isMultiSelectionEnabled()) {
366         setFileName(fileNameString(fc.getSelectedFiles()));
367     } else {
368         setFileName(fileNameString(fc.getSelectedFile()));
369     }
370
371
372     // Filetype label and combobox
373
JPanel filesOfTypePanel = new JPanel();
374     filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS));
375     bottomPanel.add(filesOfTypePanel);
376
377         AlignedLabel filesOfTypeLabel = new AlignedLabel(filesOfTypeLabelText);
378         filesOfTypeLabel.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
379     filesOfTypePanel.add(filesOfTypeLabel);
380
381     filterComboBoxModel = createFilterComboBoxModel();
382     fc.addPropertyChangeListener(filterComboBoxModel);
383     filterComboBox = new JComboBox(filterComboBoxModel);
384     filterComboBox.getAccessibleContext().setAccessibleDescription(filesOfTypeLabelText);
385     filesOfTypeLabel.setLabelFor(filterComboBox);
386     filterComboBox.setRenderer(createFilterComboBoxRenderer());
387     filesOfTypePanel.add(filterComboBox);
388
389     // buttons
390
getButtonPanel().setLayout(new ButtonAreaLayout());
391
392     approveButton = new JButton(getApproveButtonText(fc));
393     // Note: Metal does not use mnemonics for approve and cancel
394
approveButton.addActionListener(getApproveSelectionAction());
395     approveButton.setToolTipText(getApproveButtonToolTipText(fc));
396     getButtonPanel().add(approveButton);
397
398     cancelButton = new JButton(cancelButtonText);
399     cancelButton.setToolTipText(cancelButtonToolTipText);
400     cancelButton.addActionListener(getCancelSelectionAction());
401     getButtonPanel().add(cancelButton);
402
403     if(fc.getControlButtonsAreShown()) {
404         addControlButtons();
405     }
406
407     groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel });
408     }
409
410     private void updateUseShellFolder() {
411     // Decide whether to use the ShellFolder class to populate shortcut
412
// panel and combobox.
413
JFileChooser fc = getFileChooser();
414     Boolean JavaDoc prop =
415         (Boolean JavaDoc)fc.getClientProperty("FileChooser.useShellFolder");
416     if (prop != null) {
417         useShellFolder = prop.booleanValue();
418     } else {
419         // See if FileSystemView.getRoots() returns the desktop folder,
420
// i.e. the normal Windows hierarchy.
421
useShellFolder = false;
422         File JavaDoc[] roots = fc.getFileSystemView().getRoots();
423         if (roots != null && roots.length == 1) {
424         File JavaDoc[] cbFolders = (File JavaDoc[])ShellFolder.get("fileChooserComboBoxFolders");
425         if (cbFolders != null && cbFolders.length > 0 && roots[0] == cbFolders[0]) {
426             useShellFolder = true;
427         }
428         }
429     }
430     }
431
432     protected JPanel getButtonPanel() {
433     if (buttonPanel == null) {
434         buttonPanel = new JPanel();
435     }
436     return buttonPanel;
437     }
438
439     protected JPanel getBottomPanel() {
440     if(bottomPanel == null) {
441         bottomPanel = new JPanel();
442     }
443     return bottomPanel;
444     }
445
446     protected void installStrings(JFileChooser fc) {
447     super.installStrings(fc);
448
449         Locale l = fc.getLocale();
450
451     lookInLabelMnemonic = UIManager.getInt("FileChooser.lookInLabelMnemonic");
452     lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
453     saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);
454     
455     fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic");
456     fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);
457     
458     filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic");
459     filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l);
460     
461     upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText",l);
462     upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l);
463     
464     homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText",l);
465     homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l);
466     
467     newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);
468     newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);
469     
470     listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l);
471     listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l);
472     
473     detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l);
474     detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l);
475     }
476
477     protected void installListeners(JFileChooser fc) {
478     super.installListeners(fc);
479         ActionMap actionMap = getActionMap();
480         SwingUtilities.replaceUIActionMap(fc, actionMap);
481     }
482
483     protected ActionMap getActionMap() {
484         return createActionMap();
485     }
486
487     protected ActionMap createActionMap() {
488         ActionMap map = new ActionMapUIResource();
489     FilePane.addActionsToMap(map, filePane.getActions());
490         return map;
491     }
492
493     protected JPanel createList(JFileChooser fc) {
494     return filePane.createList();
495     }
496
497     protected JPanel createDetailsView(JFileChooser fc) {
498     return filePane.createDetailsView();
499     }
500
501     /**
502      * Creates a selection listener for the list of files and directories.
503      *
504      * @param fc a <code>JFileChooser</code>
505      * @return a <code>ListSelectionListener</code>
506      */

507     public ListSelectionListener createListSelectionListener(JFileChooser fc) {
508     return super.createListSelectionListener(fc);
509     }
510
511     // Obsolete class, not used in this version.
512
protected class SingleClickListener extends MouseAdapter {
513     public SingleClickListener(JList list) {
514     }
515     }
516
517     // Obsolete class, not used in this version.
518
protected class FileRenderer extends DefaultListCellRenderer {
519     }
520
521     public void uninstallUI(JComponent c) {
522     // Remove listeners
523
c.removePropertyChangeListener(filterComboBoxModel);
524     c.removePropertyChangeListener(filePane);
525     cancelButton.removeActionListener(getCancelSelectionAction());
526     approveButton.removeActionListener(getApproveSelectionAction());
527     fileNameTextField.removeActionListener(getApproveSelectionAction());
528
529     super.uninstallUI(c);
530     }
531
532     /**
533      * Returns the preferred size of the specified
534      * <code>JFileChooser</code>.
535      * The preferred size is at least as large,
536      * in both height and width,
537      * as the preferred size recommended
538      * by the file chooser's layout manager.
539      *
540      * @param c a <code>JFileChooser</code>
541      * @return a <code>Dimension</code> specifying the preferred
542      * width and height of the file chooser
543      */

544     public Dimension getPreferredSize(JComponent c) {
545     int prefWidth = PREF_SIZE.width;
546     Dimension d = c.getLayout().preferredLayoutSize(c);
547     if (d != null) {
548         return new Dimension(d.width < prefWidth ? prefWidth : d.width,
549                  d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height);
550     } else {
551         return new Dimension(prefWidth, PREF_SIZE.height);
552     }
553     }
554
555     /**
556      * Returns the minimum size of the <code>JFileChooser</code>.
557      *
558      * @param c a <code>JFileChooser</code>
559      * @return a <code>Dimension</code> specifying the minimum
560      * width and height of the file chooser
561      */

562     public Dimension getMinimumSize(JComponent c) {
563     return MIN_SIZE;
564     }
565
566     /**
567      * Returns the maximum size of the <code>JFileChooser</code>.
568      *
569      * @param c a <code>JFileChooser</code>
570      * @return a <code>Dimension</code> specifying the maximum
571      * width and height of the file chooser
572      */

573     public Dimension getMaximumSize(JComponent c) {
574     return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
575     }
576
577     private String JavaDoc fileNameString(File JavaDoc file) {
578     if (file == null) {
579         return null;
580     } else {
581         JFileChooser fc = getFileChooser();
582         if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
583         return file.getPath();
584         } else {
585         return file.getName();
586         }
587     }
588     }
589
590     private String JavaDoc fileNameString(File JavaDoc[] files) {
591     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
592     for (int i = 0; files != null && i < files.length; i++) {
593         if (i > 0) {
594         buf.append(" ");
595         }
596         if (files.length > 1) {
597         buf.append("\"");
598         }
599         buf.append(fileNameString(files[i]));
600         if (files.length > 1) {
601         buf.append("\"");
602         }
603     }
604     return buf.toString();
605     }
606
607     /* The following methods are used by the PropertyChange Listener */
608
609     private void doSelectedFileChanged(PropertyChangeEvent e) {
610     File JavaDoc f = (File JavaDoc) e.getNewValue();
611     JFileChooser fc = getFileChooser();
612     if (f != null
613         && ((fc.isFileSelectionEnabled() && !f.isDirectory())
614         || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {
615
616         setFileName(fileNameString(f));
617     }
618     }
619     
620     private void doSelectedFilesChanged(PropertyChangeEvent e) {
621     File JavaDoc[] files = (File JavaDoc[]) e.getNewValue();
622     JFileChooser fc = getFileChooser();
623     if (files != null
624         && files.length > 0
625         && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {
626         setFileName(fileNameString(files));
627     }
628     }
629     
630     private void doDirectoryChanged(PropertyChangeEvent e) {
631     JFileChooser fc = getFileChooser();
632     FileSystemView fsv = fc.getFileSystemView();
633
634     clearIconCache();
635     File JavaDoc currentDirectory = fc.getCurrentDirectory();
636     if(currentDirectory != null) {
637         directoryComboBoxModel.addItem(currentDirectory);
638
639         if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
640         if (fsv.isFileSystem(currentDirectory)) {
641             setFileName(currentDirectory.getPath());
642         } else {
643             setFileName(null);
644         }
645         }
646     }
647     }
648
649     private void doFilterChanged(PropertyChangeEvent e) {
650     clearIconCache();
651     }
652
653     private void doFileSelectionModeChanged(PropertyChangeEvent e) {
654     clearIconCache();
655
656     JFileChooser fc = getFileChooser();
657     File JavaDoc currentDirectory = fc.getCurrentDirectory();
658     if (currentDirectory != null
659         && fc.isDirectorySelectionEnabled()
660         && !fc.isFileSelectionEnabled()
661         && fc.getFileSystemView().isFileSystem(currentDirectory)) {
662
663         setFileName(currentDirectory.getPath());
664     } else {
665         setFileName(null);
666     }
667     }
668
669     private void doAccessoryChanged(PropertyChangeEvent e) {
670     if(getAccessoryPanel() != null) {
671         if(e.getOldValue() != null) {
672         getAccessoryPanel().remove((JComponent) e.getOldValue());
673         }
674         JComponent accessory = (JComponent) e.getNewValue();
675         if(accessory != null) {
676         getAccessoryPanel().add(accessory, BorderLayout.CENTER);
677         }
678     }
679     }
680
681     private void doApproveButtonTextChanged(PropertyChangeEvent e) {
682     JFileChooser chooser = getFileChooser();
683     approveButton.setText(getApproveButtonText(chooser));
684     approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
685     }
686
687     private void doDialogTypeChanged(PropertyChangeEvent e) {
688     JFileChooser chooser = getFileChooser();
689     approveButton.setText(getApproveButtonText(chooser));
690     approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
691     if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
692         lookInLabel.setText(saveInLabelText);
693     } else {
694         lookInLabel.setText(lookInLabelText);
695     }
696     }
697
698     private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {
699     // Note: Metal does not use mnemonics for approve and cancel
700
}
701
702     private void doControlButtonsChanged(PropertyChangeEvent e) {
703     if(getFileChooser().getControlButtonsAreShown()) {
704         addControlButtons();
705     } else {
706         removeControlButtons();
707     }
708     }
709
710     /*
711      * Listen for filechooser property changes, such as
712      * the selected file changing, or the type of the dialog changing.
713      */

714     public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
715     return new PropertyChangeListener() {
716         public void propertyChange(PropertyChangeEvent e) {
717         String JavaDoc s = e.getPropertyName();
718         if(s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
719             doSelectedFileChanged(e);
720         } else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
721             doSelectedFilesChanged(e);
722         } else if(s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
723             doDirectoryChanged(e);
724         } else if(s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
725             doFilterChanged(e);
726         } else if(s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
727             doFileSelectionModeChanged(e);
728         } else if(s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
729             doAccessoryChanged(e);
730         } else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
731                s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
732             doApproveButtonTextChanged(e);
733         } else if(s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
734             doDialogTypeChanged(e);
735         } else if(s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
736             doApproveButtonMnemonicChanged(e);
737         } else if(s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
738             doControlButtonsChanged(e);
739         } else if (s.equals("componentOrientation")) {
740             ComponentOrientation o = (ComponentOrientation)e.getNewValue();
741             JFileChooser cc = (JFileChooser)e.getSource();
742             if (o != (ComponentOrientation)e.getOldValue()) {
743             cc.applyComponentOrientation(o);
744             }
745         } else if (s == "FileChooser.useShellFolder") {
746             updateUseShellFolder();
747             doDirectoryChanged(e);
748         } else if (s.equals("ancestor")) {
749             if (e.getOldValue() == null && e.getNewValue() != null) {
750             // Ancestor was added, set initial focus
751
fileNameTextField.selectAll();
752             fileNameTextField.requestFocus();
753             }
754         }
755         }
756     };
757     }
758
759
760     protected void removeControlButtons() {
761     getBottomPanel().remove(getButtonPanel());
762     }
763
764     protected void addControlButtons() {
765     getBottomPanel().add(getButtonPanel());
766     }
767
768     public void ensureFileIsVisible(JFileChooser fc, File JavaDoc f) {
769     filePane.ensureFileIsVisible(fc, f);
770     }
771
772     public void rescanCurrentDirectory(JFileChooser fc) {
773     filePane.rescanCurrentDirectory();
774     }
775
776     public String JavaDoc getFileName() {
777     if (fileNameTextField != null) {
778         return fileNameTextField.getText();
779     } else {
780         return null;
781     }
782     }
783
784     public void setFileName(String JavaDoc filename) {
785     if (fileNameTextField != null) {
786         fileNameTextField.setText(filename);
787     }
788     }
789
790     /**
791      * Property to remember whether a directory is currently selected in the UI.
792      * This is normally called by the UI on a selection event.
793      *
794      * @param directorySelected if a directory is currently selected.
795      * @since 1.4
796      */

797     protected void setDirectorySelected(boolean directorySelected) {
798     super.setDirectorySelected(directorySelected);
799     JFileChooser chooser = getFileChooser();
800     if(directorySelected) {
801             if (approveButton != null) {
802             approveButton.setText(directoryOpenButtonText);
803             approveButton.setToolTipText(directoryOpenButtonToolTipText);
804             }
805     } else {
806             if (approveButton != null) {
807                 approveButton.setText(getApproveButtonText(chooser));
808                 approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
809             }
810     }
811     }
812
813     public String JavaDoc getDirectoryName() {
814     // PENDING(jeff) - get the name from the directory combobox
815
return null;
816     }
817
818     public void setDirectoryName(String JavaDoc dirname) {
819     // PENDING(jeff) - set the name in the directory combobox
820
}
821
822     protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
823     return new DirectoryComboBoxRenderer();
824     }
825
826     //
827
// Renderer for DirectoryComboBox
828
//
829
class DirectoryComboBoxRenderer extends DefaultListCellRenderer {
830     IndentIcon ii = new IndentIcon();
831     public Component getListCellRendererComponent(JList list, Object JavaDoc value,
832                               int index, boolean isSelected,
833                               boolean cellHasFocus) {
834
835         super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
836
837         if (value == null) {
838         setText("");
839         return this;
840         }
841         File JavaDoc directory = (File JavaDoc)value;
842         setText(getFileChooser().getName(directory));
843         Icon icon = getFileChooser().getIcon(directory);
844         ii.icon = icon;
845         ii.depth = directoryComboBoxModel.getDepth(index);
846         setIcon(ii);
847
848         return this;
849     }
850     }
851
852     final static int space = 10;
853     class IndentIcon implements Icon {
854
855     Icon icon = null;
856     int depth = 0;
857
858     public void paintIcon(Component c, Graphics g, int x, int y) {
859         if (c.getComponentOrientation().isLeftToRight()) {
860         icon.paintIcon(c, g, x+depth*space, y);
861         } else {
862         icon.paintIcon(c, g, x, y);
863         }
864     }
865
866     public int getIconWidth() {
867         return icon.getIconWidth() + depth*space;
868     }
869
870     public int getIconHeight() {
871         return icon.getIconHeight();
872     }
873
874     }
875
876     //
877
// DataModel for DirectoryComboxbox
878
//
879
protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
880     return new DirectoryComboBoxModel();
881     }
882
883     /**
884      * Data model for a type-face selection combo-box.
885      */

886     protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
887     Vector directories = new Vector();
888     int[] depths = null;
889     File JavaDoc selectedDirectory = null;
890     JFileChooser chooser = getFileChooser();
891     FileSystemView fsv = chooser.getFileSystemView();
892
893     public DirectoryComboBoxModel() {
894         // Add the current directory to the model, and make it the
895
// selectedDirectory
896
File JavaDoc dir = getFileChooser().getCurrentDirectory();
897         if(dir != null) {
898         addItem(dir);
899         }
900     }
901
902     /**
903      * Adds the directory to the model and sets it to be selected,
904      * additionally clears out the previous selected directory and
905      * the paths leading up to it, if any.
906      */

907     private void addItem(File JavaDoc directory) {
908
909         if(directory == null) {
910         return;
911         }
912
913         directories.clear();
914
915         File JavaDoc[] baseFolders;
916         if (useShellFolder) {
917         baseFolders = (File JavaDoc[])ShellFolder.get("fileChooserComboBoxFolders");
918         } else {
919         baseFolders = fsv.getRoots();
920         }
921         directories.addAll(Arrays.asList(baseFolders));
922
923         // Get the canonical (full) path. This has the side
924
// benefit of removing extraneous chars from the path,
925
// for example /foo/bar/ becomes /foo/bar
926
File JavaDoc canonical = null;
927         try {
928         canonical = directory.getCanonicalFile();
929         } catch (IOException JavaDoc e) {
930         // Maybe drive is not ready. Can't abort here.
931
canonical = directory;
932         }
933
934         // create File instances of each directory leading up to the top
935
try {
936         File JavaDoc sf = useShellFolder ? ShellFolder.getShellFolder(canonical)
937                      : canonical;
938         File JavaDoc f = sf;
939         Vector path = new Vector(10);
940         do {
941             path.addElement(f);
942         } while ((f = f.getParentFile()) != null);
943
944         int pathCount = path.size();
945         // Insert chain at appropriate place in vector
946
for (int i = 0; i < pathCount; i++) {
947             f = (File JavaDoc)path.get(i);
948             if (directories.contains(f)) {
949             int topIndex = directories.indexOf(f);
950             for (int j = i-1; j >= 0; j--) {
951                 directories.insertElementAt(path.get(j), topIndex+i-j);
952             }
953             break;
954             }
955         }
956         calculateDepths();
957         setSelectedItem(sf);
958         } catch (FileNotFoundException JavaDoc ex) {
959         calculateDepths();
960         }
961     }
962
963     private void calculateDepths() {
964         depths = new int[directories.size()];
965         for (int i = 0; i < depths.length; i++) {
966         File JavaDoc dir = (File JavaDoc)directories.get(i);
967         File JavaDoc parent = dir.getParentFile();
968         depths[i] = 0;
969         if (parent != null) {
970             for (int j = i-1; j >= 0; j--) {
971             if (parent.equals((File JavaDoc)directories.get(j))) {
972                 depths[i] = depths[j] + 1;
973                 break;
974             }
975             }
976         }
977         }
978     }
979
980     public int getDepth(int i) {
981         return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;
982     }
983
984     public void setSelectedItem(Object JavaDoc selectedDirectory) {
985         this.selectedDirectory = (File JavaDoc)selectedDirectory;
986             fireContentsChanged(this, -1, -1);
987     }
988
989     public Object JavaDoc getSelectedItem() {
990         return selectedDirectory;
991     }
992
993     public int getSize() {
994         return directories.size();
995     }
996
997     public Object JavaDoc getElementAt(int index) {
998         return directories.elementAt(index);
999     }
1000    }
1001
1002    //
1003
// Renderer for Types ComboBox
1004
//
1005
protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
1006    return new FilterComboBoxRenderer();
1007    }
1008
1009    /**
1010     * Render different type sizes and styles.
1011     */

1012    public class FilterComboBoxRenderer extends DefaultListCellRenderer {
1013    public Component getListCellRendererComponent(JList list,
1014        Object JavaDoc value, int index, boolean isSelected,
1015        boolean cellHasFocus) {
1016
1017        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1018
1019        if (value != null && value instanceof FileFilter) {
1020        setText(((FileFilter)value).getDescription());
1021        }
1022
1023        return this;
1024    }
1025    }
1026
1027    //
1028
// DataModel for Types Comboxbox
1029
//
1030
protected FilterComboBoxModel createFilterComboBoxModel() {
1031    return new FilterComboBoxModel();
1032    }
1033
1034    /**
1035     * Data model for a type-face selection combo-box.
1036     */

1037    protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
1038    protected FileFilter[] filters;
1039    protected FilterComboBoxModel() {
1040        super();
1041        filters = getFileChooser().getChoosableFileFilters();
1042    }
1043
1044    public void propertyChange(PropertyChangeEvent e) {
1045        String JavaDoc prop = e.getPropertyName();
1046        if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
1047        filters = (FileFilter[]) e.getNewValue();
1048        fireContentsChanged(this, -1, -1);
1049        } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
1050        fireContentsChanged(this, -1, -1);
1051        }
1052    }
1053
1054    public void setSelectedItem(Object JavaDoc filter) {
1055        if(filter != null) {
1056        getFileChooser().setFileFilter((FileFilter) filter);
1057        setFileName(null);
1058        fireContentsChanged(this, -1, -1);
1059        }
1060    }
1061
1062    public Object JavaDoc getSelectedItem() {
1063        // Ensure that the current filter is in the list.
1064
// NOTE: we shouldnt' have to do this, since JFileChooser adds
1065
// the filter to the choosable filters list when the filter
1066
// is set. Lets be paranoid just in case someone overrides
1067
// setFileFilter in JFileChooser.
1068
FileFilter currentFilter = getFileChooser().getFileFilter();
1069        boolean found = false;
1070        if(currentFilter != null) {
1071        for(int i=0; i < filters.length; i++) {
1072            if(filters[i] == currentFilter) {
1073            found = true;
1074            }
1075        }
1076        if(found == false) {
1077            getFileChooser().addChoosableFileFilter(currentFilter);
1078        }
1079        }
1080        return getFileChooser().getFileFilter();
1081    }
1082
1083    public int getSize() {
1084        if(filters != null) {
1085        return filters.length;
1086        } else {
1087        return 0;
1088        }
1089    }
1090
1091    public Object JavaDoc getElementAt(int index) {
1092        if(index > getSize() - 1) {
1093        // This shouldn't happen. Try to recover gracefully.
1094
return getFileChooser().getFileFilter();
1095        }
1096        if(filters != null) {
1097        return filters[index];
1098        } else {
1099        return null;
1100        }
1101    }
1102    }
1103
1104    public void valueChanged(ListSelectionEvent e) {
1105    JFileChooser fc = getFileChooser();
1106    File JavaDoc f = fc.getSelectedFile();
1107    if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) {
1108        setFileName(fileNameString(f));
1109    }
1110    }
1111
1112    /**
1113     * Acts when DirectoryComboBox has changed the selected item.
1114     */

1115    protected class DirectoryComboBoxAction extends AbstractAction {
1116    protected DirectoryComboBoxAction() {
1117        super("DirectoryComboBoxAction");
1118    }
1119
1120    public void actionPerformed(ActionEvent e) {
1121            directoryComboBox.hidePopup();
1122        File JavaDoc f = (File JavaDoc)directoryComboBox.getSelectedItem();
1123            if (!getFileChooser().getCurrentDirectory().equals(f)) {
1124            getFileChooser().setCurrentDirectory(f);
1125            }
1126    }
1127    }
1128
1129    protected JButton getApproveButton(JFileChooser fc) {
1130    return approveButton;
1131    }
1132
1133
1134    /**
1135     * <code>ButtonAreaLayout</code> behaves in a similar manner to
1136     * <code>FlowLayout</code>. It lays out all components from left to
1137     * right, flushed right. The widths of all components will be set
1138     * to the largest preferred size width.
1139     */

1140    private static class ButtonAreaLayout implements LayoutManager {
1141    private int hGap = 5;
1142    private int topMargin = 17;
1143
1144    public void addLayoutComponent(String JavaDoc string, Component comp) {
1145    }
1146
1147    public void layoutContainer(Container container) {
1148        Component[] children = container.getComponents();
1149
1150        if (children != null && children.length > 0) {
1151        int numChildren = children.length;
1152        Dimension[] sizes = new Dimension[numChildren];
1153        Insets insets = container.getInsets();
1154        int yLocation = insets.top + topMargin;
1155        int maxWidth = 0;
1156
1157        for (int counter = 0; counter < numChildren; counter++) {
1158            sizes[counter] = children[counter].getPreferredSize();
1159            maxWidth = Math.max(maxWidth, sizes[counter].width);
1160        }
1161        int xLocation, xOffset;
1162        if (container.getComponentOrientation().isLeftToRight()) {
1163            xLocation = container.getSize().width - insets.left - maxWidth;
1164            xOffset = hGap + maxWidth;
1165        } else {
1166            xLocation = insets.left;
1167            xOffset = -(hGap + maxWidth);
1168        }
1169        for (int counter = numChildren - 1; counter >= 0; counter--) {
1170            children[counter].setBounds(xLocation, yLocation,
1171                        maxWidth, sizes[counter].height);
1172            xLocation -= xOffset;
1173        }
1174        }
1175    }
1176
1177    public Dimension minimumLayoutSize(Container c) {
1178        if (c != null) {
1179        Component[] children = c.getComponents();
1180
1181        if (children != null && children.length > 0) {
1182            int numChildren = children.length;
1183            int height = 0;
1184            Insets cInsets = c.getInsets();
1185            int extraHeight = topMargin + cInsets.top + cInsets.bottom;
1186            int extraWidth = cInsets.left + cInsets.right;
1187            int maxWidth = 0;
1188
1189            for (int counter = 0; counter < numChildren; counter++) {
1190            Dimension aSize = children[counter].getPreferredSize();
1191            height = Math.max(height, aSize.height);
1192            maxWidth = Math.max(maxWidth, aSize.width);
1193            }
1194            return new Dimension(extraWidth + numChildren * maxWidth +
1195                     (numChildren - 1) * hGap,
1196                     extraHeight + height);
1197        }
1198        }
1199        return new Dimension(0, 0);
1200    }
1201
1202    public Dimension preferredLayoutSize(Container c) {
1203        return minimumLayoutSize(c);
1204    }
1205
1206    public void removeLayoutComponent(Component c) { }
1207    }
1208
1209    private static void groupLabels(AlignedLabel[] group) {
1210    for (int i = 0; i < group.length; i++) {
1211        group[i].group = group;
1212    }
1213    }
1214
1215    private class AlignedLabel extends JLabel {
1216    private AlignedLabel[] group;
1217    private int maxWidth = 0;
1218
1219    AlignedLabel(String JavaDoc text) {
1220        super(text);
1221        setAlignmentX(JComponent.LEFT_ALIGNMENT);
1222    }
1223
1224    public Dimension getPreferredSize() {
1225        Dimension d = super.getPreferredSize();
1226        // Align the width with all other labels in group.
1227
return new Dimension(getMaxWidth() + 11, d.height);
1228    }
1229
1230    private int getMaxWidth() {
1231        if (maxWidth == 0 && group != null) {
1232        int max = 0;
1233        for (int i = 0; i < group.length; i++) {
1234            max = Math.max(group[i].getSuperPreferredWidth(), max);
1235        }
1236        for (int i = 0; i < group.length; i++) {
1237            group[i].maxWidth = max;
1238        }
1239        }
1240        return maxWidth;
1241    }
1242
1243    private int getSuperPreferredWidth() {
1244        return super.getPreferredSize().width;
1245    }
1246    }
1247}
1248
Popular Tags