    rev 48858 : Work in progress for JDK-6303622
    Use generic in Swing components like JComboBox
    1. Added generic return type and parameter type for JComboBox.
    2. Modified JList related classes as well.
    3. Reverted the changes made to "getSelectedValues" as suggested by Joe.
    4. Modified files that were failing on Linux and Mac as well.

       1 /*
       2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25
      26 package com.sun.java.swing.plaf.windows;
      27
      28 import javax.swing.*;
      29 import javax.swing.border.*;
      30 import javax.swing.filechooser.*;
      31 import javax.swing.event.*;
      32 import javax.swing.plaf.*;
      33 import javax.swing.plaf.basic.*;
      34 import java.awt.*;
      35 import java.awt.event.*;
      36 import java.awt.image.BufferedImage;
      37 import java.beans.*;
      38 import java.io.File;
      39 import java.io.FileNotFoundException;
      40 import java.io.IOException;
      41 import java.util.*;
      42 import java.security.AccessController;
      43 import java.security.PrivilegedAction;
      44
      45 import sun.awt.shell.ShellFolder;
      46 import sun.swing.*;
      47
      48 import javax.accessibility.*;
      49
      50 /**
      51  * Windows {@literal L&F} implementation of a FileChooser.
      52  *
      53  * @author Jeff Dinkins
      54  */
      55 public class WindowsFileChooserUI extends BasicFileChooserUI {
      56
      57     // The following are private because the implementation of the
      58     // Windows FileChooser L&F is not complete yet.
      59
      60     private JPanel centerPanel;
      61
      62     private JLabel lookInLabel;
      63     private JComboBox<File> directoryComboBox;
      64     private DirectoryComboBoxModel directoryComboBoxModel;
      65     private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();
      66
      67     private FilterComboBoxModel filterComboBoxModel;
      68
      69     private JTextField filenameTextField;
      70     private FilePane filePane;
      71     private WindowsPlacesBar placesBar;
      72
      73     private JButton approveButton;
      74     private JButton cancelButton;
      75
      76     private JPanel buttonPanel;
      77     private JPanel bottomPanel;
      78
      79     private JComboBox<FileFilter> filterComboBox;
      80
      81     private static final Dimension hstrut10 = new Dimension(10, 1);
      82
      83     private static final Dimension vstrut4  = new Dimension(1, 4);
      84     private static final Dimension vstrut6  = new Dimension(1, 6);
      85     private static final Dimension vstrut8  = new Dimension(1, 8);
      86
      87     private static final Insets shrinkwrap = new Insets(0,0,0,0);
      88
      89     // Preferred and Minimum sizes for the dialog box
      90     private static int PREF_WIDTH = 425;
      91     private static int PREF_HEIGHT = 245;
      92     private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);
      93
      94     private static int MIN_WIDTH = 425;
      95     private static int MIN_HEIGHT = 245;
      96
      97     private static int LIST_PREF_WIDTH = 444;
      98     private static int LIST_PREF_HEIGHT = 138;
      99     private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);
     100
     101     // Labels, mnemonics, and tooltips (oh my!)
     102     private int    lookInLabelMnemonic = 0;
     103     private String lookInLabelText = null;
     104     private String saveInLabelText = null;
     105
     106     private int    fileNameLabelMnemonic = 0;
     107     private String fileNameLabelText = null;
     108     private int    folderNameLabelMnemonic = 0;
     109     private String folderNameLabelText = null;
     110
     111     private int    filesOfTypeLabelMnemonic = 0;
     112     private String filesOfTypeLabelText = null;
     113
     114     private String upFolderToolTipText = null;
     115     private String upFolderAccessibleName = null;
     116
     117     private String newFolderToolTipText = null;
     118     private String newFolderAccessibleName = null;
     119
     120     private String viewMenuButtonToolTipText = null;
     121     private String viewMenuButtonAccessibleName = null;
     122
     123     private BasicFileView fileView = new WindowsFileView();
     124
     125     private JLabel fileNameLabel;
     126
     127     private void populateFileNameLabel() {
     128         if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
     129             fileNameLabel.setText(folderNameLabelText);
     130             fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic);
     131         } else {
     132             fileNameLabel.setText(fileNameLabelText);
     133             fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);
     134         }
     135     }
     136
     137     //
     138     // ComponentUI Interface Implementation methods
     139     //
     140     public static ComponentUI createUI(JComponent c) {
     141         return new WindowsFileChooserUI((JFileChooser) c);
     142     }
     143
     144     public WindowsFileChooserUI(JFileChooser filechooser) {
     145         super(filechooser);
     146     }
     147
     148     public void installUI(JComponent c) {
     149         super.installUI(c);
     150     }
     151
     152     public void uninstallComponents(JFileChooser fc) {
     153         fc.removeAll();
     154     }
     155
     156     private class WindowsFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {
     157         public JFileChooser getFileChooser() {
     158             return WindowsFileChooserUI.this.getFileChooser();
     159         }
     160
     161         public BasicDirectoryModel getModel() {
     162             return WindowsFileChooserUI.this.getModel();
     163         }
     164
     165         public JPanel createList() {
     166             return WindowsFileChooserUI.this.createList(getFileChooser());
     167         }
     168
     169         public JPanel createDetailsView() {
     170             return WindowsFileChooserUI.this.createDetailsView(getFileChooser());
     171         }
     172
     173         public boolean isDirectorySelected() {
     174             return WindowsFileChooserUI.this.isDirectorySelected();
     175         }
     176
     177         public File getDirectory() {
     178             return WindowsFileChooserUI.this.getDirectory();
     179         }
     180
     181         public Action getChangeToParentDirectoryAction() {
     182             return WindowsFileChooserUI.this.getChangeToParentDirectoryAction();
     183         }
     184
     185         public Action getApproveSelectionAction() {
     186             return WindowsFileChooserUI.this.getApproveSelectionAction();
     187         }
     188
     189         public Action getNewFolderAction() {
     190             return WindowsFileChooserUI.this.getNewFolderAction();
     191         }
     192
     193         public MouseListener createDoubleClickListener(JList<?> list) {
     194             return WindowsFileChooserUI.this.createDoubleClickListener(getFileChooser(),
     195                                                                        list);
     196         }
     197
     198         public ListSelectionListener createListSelectionListener() {
     199             return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser());
     200         }
     201     }
     202
     203     public void installComponents(JFileChooser fc) {
     204         filePane = new FilePane(new WindowsFileChooserUIAccessor());
     205         fc.addPropertyChangeListener(filePane);
     206
     207         FileSystemView fsv = fc.getFileSystemView();
     208
     209         fc.setBorder(new EmptyBorder(4, 10, 10, 10));
     210         fc.setLayout(new BorderLayout(8, 8));
     211
     212         updateUseShellFolder();
     213
     214         // ********************************* //
     215         // **** Construct the top panel **** //
     216         // ********************************* //
     217
     218         // Directory manipulation buttons
     219         JToolBar topPanel = new JToolBar();
     220         topPanel.setFloatable(false);
     221         topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
     222
     223         // Add the top panel to the fileChooser
     224         fc.add(topPanel, BorderLayout.NORTH);
     225
     226         // ComboBox Label
     227         @SuppressWarnings("serial") // anonymous class
     228         JLabel tmp1 = new JLabel(lookInLabelText, JLabel.TRAILING) {
     229             public Dimension getPreferredSize() {
     230                 return getMinimumSize();
     231             }
     232
     233             public Dimension getMinimumSize() {
     234                 Dimension d = super.getPreferredSize();
     235                 if (placesBar != null) {
     236                     d.width = Math.max(d.width, placesBar.getWidth());
     237                 }
     238                 return d;
     239             }
     240         };
     241         lookInLabel = tmp1;
     242         lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
     243         lookInLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
     244         lookInLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT);
     245         topPanel.add(lookInLabel);
     246         topPanel.add(Box.createRigidArea(new Dimension(8,0)));
     247
     248         // CurrentDir ComboBox
     249         @SuppressWarnings("serial") // anonymous class
     250         JComboBox<File> tmp2 = new JComboBox<File>() {
     251             public Dimension getMinimumSize() {
     252                 Dimension d = super.getMinimumSize();
     253                 d.width = 60;
     254                 return d;
     255             }
     256
     257             public Dimension getPreferredSize() {
     258                 Dimension d = super.getPreferredSize();
     259                 // Must be small enough to not affect total width.
     260                 d.width = 150;
     261                 return d;
     262             }
     263         };
     264         directoryComboBox = tmp2;
     265         directoryComboBox.putClientProperty( "JComboBox.lightweightKeyboardNavigation", "Lightweight" );
     266         lookInLabel.setLabelFor(directoryComboBox);
     267         directoryComboBoxModel = createDirectoryComboBoxModel(fc);
     268         directoryComboBox.setModel(directoryComboBoxModel);
     269         directoryComboBox.addActionListener(directoryComboBoxAction);
     270         directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
     271         directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
     272         directoryComboBox.setAlignmentY(JComponent.CENTER_ALIGNMENT);
     273         directoryComboBox.setMaximumRowCount(8);
     274
     275         topPanel.add(directoryComboBox);
     276         topPanel.add(Box.createRigidArea(hstrut10));
     277
     278         // Up Button
     279         JButton upFolderButton = createToolButton(getChangeToParentDirectoryAction(), upFolderIcon,
     280             upFolderToolTipText, upFolderAccessibleName);
     281         topPanel.add(upFolderButton);
     282
     283         // New Directory Button
     284         if (!UIManager.getBoolean("FileChooser.readOnly")) {
     285             JButton newFolderButton = createToolButton(filePane.getNewFolderAction(), newFolderIcon,
     286                 newFolderToolTipText, newFolderAccessibleName);
     287             topPanel.add(newFolderButton);
     288         }
     289
     290         // View button group
     291         ButtonGroup viewButtonGroup = new ButtonGroup();
     292
     293         // Popup Menu
     294         final JPopupMenu viewTypePopupMenu = new JPopupMenu();
     295
     296         final JRadioButtonMenuItem listViewMenuItem = new JRadioButtonMenuItem(
     297                 filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));
     298         listViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_LIST);
     299         viewTypePopupMenu.add(listViewMenuItem);
     300         viewButtonGroup.add(listViewMenuItem);
     301
     302         final JRadioButtonMenuItem detailsViewMenuItem = new JRadioButtonMenuItem(
     303                 filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));
     304         detailsViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_DETAILS);
     305         viewTypePopupMenu.add(detailsViewMenuItem);
     306         viewButtonGroup.add(detailsViewMenuItem);
     307
     308         // Create icon for viewMenuButton
     309         BufferedImage image = new BufferedImage(viewMenuIcon.getIconWidth() + 7, viewMenuIcon.getIconHeight(),
     310                 BufferedImage.TYPE_INT_ARGB);
     311         Graphics graphics = image.getGraphics();
     312         viewMenuIcon.paintIcon(filePane, graphics, 0, 0);
     313         int x = image.getWidth() - 5;
     314         int y = image.getHeight() / 2 - 1;
     315         graphics.setColor(Color.BLACK);
     316         graphics.fillPolygon(new int[]{x, x + 5, x + 2}, new int[]{y, y, y + 3}, 3);
     317
     318         // Details Button
     319         final JButton viewMenuButton = createToolButton(null, new ImageIcon(image), viewMenuButtonToolTipText,
     320                 viewMenuButtonAccessibleName);
     321
     322         viewMenuButton.addMouseListener(new MouseAdapter() {
     323             public void mousePressed(MouseEvent e) {
     324                 if (SwingUtilities.isLeftMouseButton(e) && !viewMenuButton.isSelected()) {
     325                     viewMenuButton.setSelected(true);
     326
     327                     viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight());
     328                 }
     329             }
     330         });
     331         viewMenuButton.addKeyListener(new KeyAdapter() {
     332             public void keyPressed(KeyEvent e) {
     333                 // Forbid keyboard actions if the button is not in rollover state
     334                 if (e.getKeyCode() == KeyEvent.VK_SPACE && viewMenuButton.getModel().isRollover()) {
     335                     viewMenuButton.setSelected(true);
     336
     337                     viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight());
     338                 }
     339             }
     340         });
     341         viewTypePopupMenu.addPopupMenuListener(new PopupMenuListener() {
     342             public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
     343             }
     344
     345             public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
     346                 SwingUtilities.invokeLater(new Runnable() {
     347                     public void run() {
     348                         viewMenuButton.setSelected(false);
     349                     }
     350                 });
     351             }
     352
     353             public void popupMenuCanceled(PopupMenuEvent e) {
     354             }
     355         });
     356
     357         topPanel.add(viewMenuButton);
     358
     359         topPanel.add(Box.createRigidArea(new Dimension(80, 0)));
     360
     361         filePane.addPropertyChangeListener(new PropertyChangeListener() {
     362             public void propertyChange(PropertyChangeEvent e) {
     363                 if ("viewType".equals(e.getPropertyName())) {
     364                     switch (filePane.getViewType()) {
     365                         case FilePane.VIEWTYPE_LIST:
     366                             listViewMenuItem.setSelected(true);
     367                             break;
     368
     369                         case FilePane.VIEWTYPE_DETAILS:
     370                             detailsViewMenuItem.setSelected(true);
     371                             break;
     372                     }
     373                 }
     374             }
     375         });
     376
     377         // ************************************** //
     378         // ******* Add the directory pane ******* //
     379         // ************************************** //
     380         centerPanel = new JPanel(new BorderLayout());
     381         centerPanel.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
     382         JComponent accessory = fc.getAccessory();
     383         if(accessory != null) {
     384             getAccessoryPanel().add(accessory);
     385         }
     386         filePane.setPreferredSize(LIST_PREF_SIZE);
     387         centerPanel.add(filePane, BorderLayout.CENTER);
     388         fc.add(centerPanel, BorderLayout.CENTER);
     389
     390         // ********************************** //
     391         // **** Construct the bottom panel ** //
     392         // ********************************** //
     393         getBottomPanel().setLayout(new BoxLayout(getBottomPanel(), BoxLayout.LINE_AXIS));
     394
     395         // Add the bottom panel to file chooser
     396         centerPanel.add(getBottomPanel(), BorderLayout.SOUTH);
     397
     398         // labels
     399         JPanel labelPanel = new JPanel();
     400         labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
     401         labelPanel.add(Box.createRigidArea(vstrut4));
     402
     403         fileNameLabel = new JLabel();
     404         populateFileNameLabel();
     405         fileNameLabel.setAlignmentY(0);
     406         labelPanel.add(fileNameLabel);
     407
     408         labelPanel.add(Box.createRigidArea(new Dimension(1,12)));
     409
     410         JLabel ftl = new JLabel(filesOfTypeLabelText);
     411         ftl.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
     412         labelPanel.add(ftl);
     413
     414         getBottomPanel().add(labelPanel);
     415         getBottomPanel().add(Box.createRigidArea(new Dimension(15, 0)));
     416
     417         // file entry and filters
     418         JPanel fileAndFilterPanel = new JPanel();
     419         fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
     420         fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel, BoxLayout.Y_AXIS));
     421
     422         @SuppressWarnings("serial") // anonymous class
     423         JTextField tmp3 = new JTextField(35) {
     424             public Dimension getMaximumSize() {
     425                 return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
     426             }
     427         };
     428         filenameTextField = tmp3;
     429
     430         fileNameLabel.setLabelFor(filenameTextField);
     431         filenameTextField.addFocusListener(
     432             new FocusAdapter() {
     433                 public void focusGained(FocusEvent e) {
     434                     if (!getFileChooser().isMultiSelectionEnabled()) {
     435                         filePane.clearSelection();
     436                     }
     437                 }
     438             }
     439         );
     440
     441         if (fc.isMultiSelectionEnabled()) {
     442             setFileName(fileNameString(fc.getSelectedFiles()));
     443         } else {
     444             setFileName(fileNameString(fc.getSelectedFile()));
     445         }
     446
     447         fileAndFilterPanel.add(filenameTextField);
     448         fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
     449
     450         filterComboBoxModel = createFilterComboBoxModel();
     451         fc.addPropertyChangeListener(filterComboBoxModel);
     452         filterComboBox = new JComboBox<FileFilter>(filterComboBoxModel);
     453         ftl.setLabelFor(filterComboBox);
     454         filterComboBox.setRenderer(createFilterComboBoxRenderer());
     455         fileAndFilterPanel.add(filterComboBox);
     456
     457         getBottomPanel().add(fileAndFilterPanel);
     458         getBottomPanel().add(Box.createRigidArea(new Dimension(30, 0)));
     459
     460         // buttons
     461         getButtonPanel().setLayout(new BoxLayout(getButtonPanel(), BoxLayout.Y_AXIS));
     462
     463         @SuppressWarnings("serial") // anonymous class
     464         JButton tmp4 = new JButton(getApproveButtonText(fc)) {
     465             public Dimension getMaximumSize() {
     466                 return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
     467                        approveButton.getPreferredSize() : cancelButton.getPreferredSize();
     468             }
     469         };
     470         approveButton = tmp4;
     471         Insets buttonMargin = approveButton.getMargin();
     472         buttonMargin = new InsetsUIResource(buttonMargin.top,    buttonMargin.left  + 5,
     473                                             buttonMargin.bottom, buttonMargin.right + 5);
     474         approveButton.setMargin(buttonMargin);
     475         approveButton.setMnemonic(getApproveButtonMnemonic(fc));
     476         approveButton.addActionListener(getApproveSelectionAction());
     477         approveButton.setToolTipText(getApproveButtonToolTipText(fc));
     478         getButtonPanel().add(Box.createRigidArea(vstrut6));
     479         getButtonPanel().add(approveButton);
     480         getButtonPanel().add(Box.createRigidArea(vstrut4));
     481
     482         @SuppressWarnings("serial") // anonymous class
     483         JButton tmp5 = new JButton(cancelButtonText) {
     484             public Dimension getMaximumSize() {
     485                 return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
     486                        approveButton.getPreferredSize() : cancelButton.getPreferredSize();
     487             }
     488         };
     489         cancelButton = tmp5;
     490         cancelButton.setMargin(buttonMargin);
     491         cancelButton.setToolTipText(cancelButtonToolTipText);
     492         cancelButton.addActionListener(getCancelSelectionAction());
     493         getButtonPanel().add(cancelButton);
     494
     495         if(fc.getControlButtonsAreShown()) {
     496             addControlButtons();
     497         }
     498     }
     499
     500     private void updateUseShellFolder() {
     501         // Decide whether to use the ShellFolder class to populate shortcut
     502         // panel and combobox.
     503         JFileChooser fc = getFileChooser();
     504
     505         if (FilePane.usesShellFolder(fc)) {
     506             if (placesBar == null && !UIManager.getBoolean("FileChooser.noPlacesBar")) {
     507                 placesBar = new WindowsPlacesBar(fc, XPStyle.getXP() != null);
     508                 fc.add(placesBar, BorderLayout.BEFORE_LINE_BEGINS);
     509                 fc.addPropertyChangeListener(placesBar);
     510             }
     511         } else {
     512             if (placesBar != null) {
     513                 fc.remove(placesBar);
     514                 fc.removePropertyChangeListener(placesBar);
     515                 placesBar = null;
     516             }
     517         }
     518     }
     519
     520     protected JPanel getButtonPanel() {
     521         if(buttonPanel == null) {
     522             buttonPanel = new JPanel();
     523         }
     524         return buttonPanel;
     525     }
     526
     527     protected JPanel getBottomPanel() {
     528         if(bottomPanel == null) {
     529             bottomPanel = new JPanel();
     530         }
     531         return bottomPanel;
     532     }
     533
     534     protected void installStrings(JFileChooser fc) {
     535         super.installStrings(fc);
     536
     537         Locale l = fc.getLocale();
     538
     539         lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);
     540         lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
     541         saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);
     542
     543         fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);
     544         fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);
     545         folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);
     546         folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l);
     547
     548         filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);
     549         filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l);
     550
     551         upFolderToolTipText =  UIManager.getString("FileChooser.upFolderToolTipText",l);
     552         upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l);
     553
     554         newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);
     555         newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);
     556
     557         viewMenuButtonToolTipText = UIManager.getString("FileChooser.viewMenuButtonToolTipText",l);
     558         viewMenuButtonAccessibleName = UIManager.getString("FileChooser.viewMenuButtonAccessibleName",l);
     559     }
     560
     561     private Integer getMnemonic(String key, Locale l) {
     562         return SwingUtilities2.getUIDefaultsInt(key, l);
     563     }
     564
     565     protected void installListeners(JFileChooser fc) {
     566         super.installListeners(fc);
     567         ActionMap actionMap = getActionMap();
     568         SwingUtilities.replaceUIActionMap(fc, actionMap);
     569     }
     570
     571     protected ActionMap getActionMap() {
     572         return createActionMap();
     573     }
     574
     575     protected ActionMap createActionMap() {
     576         ActionMap map = new ActionMapUIResource();
     577         FilePane.addActionsToMap(map, filePane.getActions());
     578         return map;
     579     }
     580
     581     protected JPanel createList(JFileChooser fc) {
     582         return filePane.createList();
     583     }
     584
     585     protected JPanel createDetailsView(JFileChooser fc) {
     586         return filePane.createDetailsView();
     587     }
     588
     589     /**
     590      * Creates a selection listener for the list of files and directories.
     591      *
     592      * @param fc a <code>JFileChooser</code>
     593      * @return a <code>ListSelectionListener</code>
     594      */
     595     public ListSelectionListener createListSelectionListener(JFileChooser fc) {
     596         return super.createListSelectionListener(fc);
     597     }
     598
     599     // Obsolete class, not used in this version.
     600     @SuppressWarnings("serial")
     601     protected class WindowsNewFolderAction extends NewFolderAction {
     602     }
     603
     604     // Obsolete class, not used in this version.
     605     protected class SingleClickListener extends MouseAdapter {
     606     }
     607
     608     // Obsolete class, not used in this version.
     609     @SuppressWarnings("serial") // Superclass is not serializable across versions
     610     protected class FileRenderer extends DefaultListCellRenderer  {
     611     }
     612
     613     public void uninstallUI(JComponent c) {
     614         // Remove listeners
     615         c.removePropertyChangeListener(filterComboBoxModel);
     616         c.removePropertyChangeListener(filePane);
     617         if (placesBar != null) {
     618             c.removePropertyChangeListener(placesBar);
     619         }
     620         cancelButton.removeActionListener(getCancelSelectionAction());
     621         approveButton.removeActionListener(getApproveSelectionAction());
     622         filenameTextField.removeActionListener(getApproveSelectionAction());
     623
     624         if (filePane != null) {
     625             filePane.uninstallUI();
     626             filePane = null;
     627         }
     628
     629         super.uninstallUI(c);
     630     }
     631
     632     /**
     633      * Returns the preferred size of the specified
     634      * <code>JFileChooser</code>.
     635      * The preferred size is at least as large,
     636      * in both height and width,
     637      * as the preferred size recommended
     638      * by the file chooser's layout manager.
     639      *
     640      * @param c  a <code>JFileChooser</code>
     641      * @return   a <code>Dimension</code> specifying the preferred
     642      *           width and height of the file chooser
     643      */
     644     @Override
     645     public Dimension getPreferredSize(JComponent c) {
     646         int prefWidth = PREF_SIZE.width;
     647         Dimension d = c.getLayout().preferredLayoutSize(c);
     648         if (d != null) {
     649             return new Dimension(d.width < prefWidth ? prefWidth : d.width,
     650                                  d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height);
     651         } else {
     652             return new Dimension(prefWidth, PREF_SIZE.height);
     653         }
     654     }
     655
     656     /**
     657      * Returns the minimum size of the <code>JFileChooser</code>.
     658      *
     659      * @param c  a <code>JFileChooser</code>
     660      * @return   a <code>Dimension</code> specifying the minimum
     661      *           width and height of the file chooser
     662      */
     663     @Override
     664     public Dimension getMinimumSize(JComponent c) {
     665         return new Dimension(MIN_WIDTH, MIN_HEIGHT);
     666     }
     667
     668     /**
     669      * Returns the maximum size of the <code>JFileChooser</code>.
     670      *
     671      * @param c  a <code>JFileChooser</code>
     672      * @return   a <code>Dimension</code> specifying the maximum
     673      *           width and height of the file chooser
     674      */
     675     @Override
     676     public Dimension getMaximumSize(JComponent c) {
     677         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
     678     }
     679
     680     private String fileNameString(File file) {
     681         if (file == null) {
     682             return null;
     683         } else {
     684             JFileChooser fc = getFileChooser();
     685             if ((fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) ||
     686                 (fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystemRoot(file))){
     687                 return file.getPath();
     688             } else {
     689                 return file.getName();
     690             }
     691         }
     692     }
     693
     694     private String fileNameString(File[] files) {
     695         StringBuilder buf = new StringBuilder();
     696         for (int i = 0; files != null && i < files.length; i++) {
     697             if (i > 0) {
     698                 buf.append(" ");
     699             }
     700             if (files.length > 1) {
     701                 buf.append("\"");
     702             }
     703             buf.append(fileNameString(files[i]));
     704             if (files.length > 1) {
     705                 buf.append("\"");
     706             }
     707         }
     708         return buf.toString();
     709     }
     710
     711     /* The following methods are used by the PropertyChange Listener */
     712
     713     private void doSelectedFileChanged(PropertyChangeEvent e) {
     714         File f = (File) e.getNewValue();
     715         JFileChooser fc = getFileChooser();
     716         if (f != null
     717             && ((fc.isFileSelectionEnabled() && !f.isDirectory())
     718                 || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {
     719
     720             setFileName(fileNameString(f));
     721         }
     722     }
     723
     724     private void doSelectedFilesChanged(PropertyChangeEvent e) {
     725         File[] files = (File[]) e.getNewValue();
     726         JFileChooser fc = getFileChooser();
     727         if (files != null
     728             && files.length > 0
     729             && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {
     730             setFileName(fileNameString(files));
     731         }
     732     }
     733
     734     private void doDirectoryChanged(PropertyChangeEvent e) {
     735         JFileChooser fc = getFileChooser();
     736         FileSystemView fsv = fc.getFileSystemView();
     737
     738         clearIconCache();
     739         File currentDirectory = fc.getCurrentDirectory();
     740         if(currentDirectory != null) {
     741             directoryComboBoxModel.addItem(currentDirectory);
     742
     743             if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
     744                 if (fsv.isFileSystem(currentDirectory)) {
     745                     setFileName(currentDirectory.getPath());
     746                 } else {
     747                     setFileName(null);
     748                 }
     749             }
     750         }
     751     }
     752
     753     private void doFilterChanged(PropertyChangeEvent e) {
     754         clearIconCache();
     755     }
     756
     757     private void doFileSelectionModeChanged(PropertyChangeEvent e) {
     758         if (fileNameLabel != null) {
     759             populateFileNameLabel();
     760         }
     761         clearIconCache();
     762
     763         JFileChooser fc = getFileChooser();
     764         File currentDirectory = fc.getCurrentDirectory();
     765         if (currentDirectory != null
     766             && fc.isDirectorySelectionEnabled()
     767             && !fc.isFileSelectionEnabled()
     768             && fc.getFileSystemView().isFileSystem(currentDirectory)) {
     769
     770             setFileName(currentDirectory.getPath());
     771         } else {
     772             setFileName(null);
     773         }
     774     }
     775
     776     private void doAccessoryChanged(PropertyChangeEvent e) {
     777         if(getAccessoryPanel() != null) {
     778             if(e.getOldValue() != null) {
     779                 getAccessoryPanel().remove((JComponent) e.getOldValue());
     780             }
     781             JComponent accessory = (JComponent) e.getNewValue();
     782             if(accessory != null) {
     783                 getAccessoryPanel().add(accessory, BorderLayout.CENTER);
     784             }
     785         }
     786     }
     787
     788     private void doApproveButtonTextChanged(PropertyChangeEvent e) {
     789         JFileChooser chooser = getFileChooser();
     790         approveButton.setText(getApproveButtonText(chooser));
     791         approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
     792         approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
     793     }
     794
     795     private void doDialogTypeChanged(PropertyChangeEvent e) {
     796         JFileChooser chooser = getFileChooser();
     797         approveButton.setText(getApproveButtonText(chooser));
     798         approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
     799         approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
     800         if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
     801             lookInLabel.setText(saveInLabelText);
     802         } else {
     803             lookInLabel.setText(lookInLabelText);
     804         }
     805     }
     806
     807     private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {
     808         approveButton.setMnemonic(getApproveButtonMnemonic(getFileChooser()));
     809     }
     810
     811     private void doControlButtonsChanged(PropertyChangeEvent e) {
     812         if(getFileChooser().getControlButtonsAreShown()) {
     813             addControlButtons();
     814         } else {
     815             removeControlButtons();
     816         }
     817     }
     818
     819     /*
     820      * Listen for filechooser property changes, such as
     821      * the selected file changing, or the type of the dialog changing.
     822      */
     823     public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
     824         return new PropertyChangeListener() {
     825             public void propertyChange(PropertyChangeEvent e) {
     826                 String s = e.getPropertyName();
     827                 if(s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
     828                     doSelectedFileChanged(e);
     829                 } else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
     830                     doSelectedFilesChanged(e);
     831                 } else if(s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
     832                     doDirectoryChanged(e);
     833                 } else if(s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
     834                     doFilterChanged(e);
     835                 } else if(s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
     836                     doFileSelectionModeChanged(e);
     837                 } else if(s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
     838                     doAccessoryChanged(e);
     839                 } else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
     840                            s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
     841                     doApproveButtonTextChanged(e);
     842                 } else if(s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
     843                     doDialogTypeChanged(e);
     844                 } else if(s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
     845                     doApproveButtonMnemonicChanged(e);
     846                 } else if(s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
     847                     doControlButtonsChanged(e);
     848                 } else if (s == "FileChooser.useShellFolder") {
     849                     updateUseShellFolder();
     850                     doDirectoryChanged(e);
     851                 } else if (s.equals("componentOrientation")) {
     852                     ComponentOrientation o = (ComponentOrientation)e.getNewValue();
     853                     JFileChooser cc = (JFileChooser)e.getSource();
     854                     if (o != e.getOldValue()) {
     855                         cc.applyComponentOrientation(o);
     856                     }
     857                 } else if (s.equals("ancestor")) {
     858                     if (e.getOldValue() == null && e.getNewValue() != null) {
     859                         // Ancestor was added, set initial focus
     860                         filenameTextField.selectAll();
     861                         filenameTextField.requestFocus();
     862                     }
     863                 }
     864             }
     865         };
     866     }
     867
     868
     869     protected void removeControlButtons() {
     870         getBottomPanel().remove(getButtonPanel());
     871     }
     872
     873     protected void addControlButtons() {
     874         getBottomPanel().add(getButtonPanel());
     875     }
     876
     877     public void ensureFileIsVisible(JFileChooser fc, File f) {
     878         filePane.ensureFileIsVisible(fc, f);
     879     }
     880
     881     public void rescanCurrentDirectory(JFileChooser fc) {
     882         filePane.rescanCurrentDirectory();
     883     }
     884
     885     public String getFileName() {
     886         if(filenameTextField != null) {
     887             return filenameTextField.getText();
     888         } else {
     889             return null;
     890         }
     891     }
     892
     893     public void setFileName(String filename) {
     894         if(filenameTextField != null) {
     895             filenameTextField.setText(filename);
     896         }
     897     }
     898
     899     /**
     900      * Property to remember whether a directory is currently selected in the UI.
     901      * This is normally called by the UI on a selection event.
     902      *
     903      * @param directorySelected if a directory is currently selected.
     904      * @since 1.4
     905      */
     906     protected void setDirectorySelected(boolean directorySelected) {
     907         super.setDirectorySelected(directorySelected);
     908         JFileChooser chooser = getFileChooser();
     909         if(directorySelected) {
     910             approveButton.setText(directoryOpenButtonText);
     911             approveButton.setToolTipText(directoryOpenButtonToolTipText);
     912             approveButton.setMnemonic(directoryOpenButtonMnemonic);
     913         } else {
     914             approveButton.setText(getApproveButtonText(chooser));
     915             approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
     916             approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
     917         }
     918     }
     919
     920     public String getDirectoryName() {
     921         // PENDING(jeff) - get the name from the directory combobox
     922         return null;
     923     }
     924
     925     public void setDirectoryName(String dirname) {
     926         // PENDING(jeff) - set the name in the directory combobox
     927     }
     928
     929     protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
     930         return new DirectoryComboBoxRenderer();
     931     }
     932
     933     @SuppressWarnings("serial") // anonymous class
     934     private static JButton createToolButton(Action a, Icon defaultIcon, String toolTipText, String accessibleName) {
     935         final JButton result = new JButton(a);
     936
     937         result.setText(null);
     938         result.setIcon(defaultIcon);
     939         result.setToolTipText(toolTipText);
     940         result.setRequestFocusEnabled(false);
     941         result.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, accessibleName);
     942         result.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, Boolean.TRUE);
     943         result.setAlignmentX(JComponent.LEFT_ALIGNMENT);
     944         result.setAlignmentY(JComponent.CENTER_ALIGNMENT);
     945         result.setMargin(shrinkwrap);
     946         result.setFocusPainted(false);
     947
     948         result.setModel(new DefaultButtonModel() {
     949             public void setPressed(boolean b) {
     950                 // Forbid keyboard actions if the button is not in rollover state
     951                 if (!b || isRollover()) {
     952                     super.setPressed(b);
     953                 }
     954             }
     955
     956             public void setRollover(boolean b) {
     957                 if (b && !isRollover()) {
     958                     // Reset other buttons
     959                     for (Component component : result.getParent().getComponents()) {
     960                         if (component instanceof JButton && component != result) {
     961                             ((JButton) component).getModel().setRollover(false);
     962                         }
     963                     }
     964                 }
     965
     966                 super.setRollover(b);
     967             }
     968
     969             public void setSelected(boolean b) {
     970                 super.setSelected(b);
     971
     972                 if (b) {
     973                     stateMask |= PRESSED | ARMED;
     974                 } else {
     975                     stateMask &= ~(PRESSED | ARMED);
     976                 }
     977             }
     978         });
     979
     980         result.addFocusListener(new FocusAdapter() {
     981             public void focusGained(FocusEvent e) {
     982                 result.getModel().setRollover(true);
     983             }
     984
     985             public void focusLost(FocusEvent e) {
     986                 result.getModel().setRollover(false);
     987             }
     988         });
     989
     990         return result;
     991     }
     992
     993     //
     994     // Renderer for DirectoryComboBox
     995     //
     996     @SuppressWarnings("serial") // Superclass is not serializable across versions
     997     class DirectoryComboBoxRenderer extends DefaultListCellRenderer  {
     998         IndentIcon ii = new IndentIcon();
     999         public Component getListCellRendererComponent(JList<?> list, Object value,
    1000                                                       int index, boolean isSelected,
    1001                                                       boolean cellHasFocus) {
    1002
    1003             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    1004
    1005             if (value == null) {
    1006                 setText("");
    1007                 return this;
    1008             }
    1009             File directory = (File)value;
    1010             setText(getFileChooser().getName(directory));
    1011             Icon icon = getFileChooser().getIcon(directory);
    1012             ii.icon = icon;
    1013             ii.depth = directoryComboBoxModel.getDepth(index);
    1014             setIcon(ii);
    1015
    1016             return this;
    1017         }
    1018     }
    1019
    1020     static final int space = 10;
    1021     class IndentIcon implements Icon {
    1022
    1023         Icon icon = null;
    1024         int depth = 0;
    1025
    1026         public void paintIcon(Component c, Graphics g, int x, int y) {
    1027             if (c.getComponentOrientation().isLeftToRight()) {
    1028                 icon.paintIcon(c, g, x+depth*space, y);
    1029             } else {
    1030                 icon.paintIcon(c, g, x, y);
    1031             }
    1032         }
    1033
    1034         public int getIconWidth() {
    1035             return icon.getIconWidth() + depth*space;
    1036         }
    1037
    1038         public int getIconHeight() {
    1039             return icon.getIconHeight();
    1040         }
    1041
    1042     }
    1043
    1044     //
    1045     // DataModel for DirectoryComboxbox
    1046     //
    1047     protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
    1048         return new DirectoryComboBoxModel();
    1049     }
    1050
    1051     /**
    1052      * Data model for a type-face selection combo-box.
    1053      */
    1054     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1055     protected class DirectoryComboBoxModel extends AbstractListModel<File> implements ComboBoxModel<File> {
    1056         Vector<File> directories = new Vector<File>();
    1057         int[] depths = null;
    1058         File selectedDirectory = null;
    1059         JFileChooser chooser = getFileChooser();
    1060         FileSystemView fsv = chooser.getFileSystemView();
    1061
    1062         public DirectoryComboBoxModel() {
    1063             // Add the current directory to the model, and make it the
    1064             // selectedDirectory
    1065             File dir = getFileChooser().getCurrentDirectory();
    1066             if(dir != null) {
    1067                 addItem(dir);
    1068             }
    1069         }
    1070
    1071         /**
    1072          * Adds the directory to the model and sets it to be selected,
    1073          * additionally clears out the previous selected directory and
    1074          * the paths leading up to it, if any.
    1075          */
    1076         private void addItem(File directory) {
    1077
    1078             if(directory == null) {
    1079                 return;
    1080             }
    1081
    1082             boolean useShellFolder = FilePane.usesShellFolder(chooser);
    1083
    1084             directories.clear();
    1085
    1086             File[] baseFolders = (useShellFolder)
    1087                     ? (File[]) ShellFolder.get("fileChooserComboBoxFolders")
    1088                     : fsv.getRoots();
    1089             directories.addAll(Arrays.asList(baseFolders));
    1090
    1091             // Get the canonical (full) path. This has the side
    1092             // benefit of removing extraneous chars from the path,
    1093             // for example /foo/bar/ becomes /foo/bar
    1094             File canonical;
    1095             try {
    1096                 canonical = directory.getCanonicalFile();
    1097             } catch (IOException e) {
    1098                 // Maybe drive is not ready. Can't abort here.
    1099                 canonical = directory;
    1100             }
    1101
    1102             // create File instances of each directory leading up to the top
    1103             try {
    1104                 File sf = useShellFolder ? ShellFolder.getShellFolder(canonical)
    1105                                          : canonical;
    1106                 File f = sf;
    1107                 Vector<File> path = new Vector<File>(10);
    1108                 do {
    1109                     path.addElement(f);
    1110                 } while ((f = f.getParentFile()) != null);
    1111
    1112                 int pathCount = path.size();
    1113                 // Insert chain at appropriate place in vector
    1114                 for (int i = 0; i < pathCount; i++) {
    1115                     f = path.get(i);
    1116                     if (directories.contains(f)) {
    1117                         int topIndex = directories.indexOf(f);
    1118                         for (int j = i-1; j >= 0; j--) {
    1119                             directories.insertElementAt(path.get(j), topIndex+i-j);
    1120                         }
    1121                         break;
    1122                     }
    1123                 }
    1124                 calculateDepths();
    1125                 setSelectedItem(sf);
    1126             } catch (FileNotFoundException ex) {
    1127                 calculateDepths();
    1128             }
    1129         }
    1130
    1131         private void calculateDepths() {
    1132             depths = new int[directories.size()];
    1133             for (int i = 0; i < depths.length; i++) {
    1134                 File dir = directories.get(i);
    1135                 File parent = dir.getParentFile();
    1136                 depths[i] = 0;
    1137                 if (parent != null) {
    1138                     for (int j = i-1; j >= 0; j--) {
    1139                         if (parent.equals(directories.get(j))) {
    1140                             depths[i] = depths[j] + 1;
    1141                             break;
    1142                         }
    1143                     }
    1144                 }
    1145             }
    1146         }
    1147
    1148         public int getDepth(int i) {
    1149             return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;
    1150         }
    1151
    1152         public void setSelectedItem(File selectedDirectory) {
    1153             this.selectedDirectory = selectedDirectory;
    1154             fireContentsChanged(this, -1, -1);
    1155         }
    1156
    1157         public File getSelectedItem() {
    1158             return selectedDirectory;
    1159         }
    1160
    1161         public int getSize() {
    1162             return directories.size();
    1163         }
    1164
    1165         public File getElementAt(int index) {
    1166             return directories.elementAt(index);
    1167         }
    1168     }
    1169
    1170     //
    1171     // Renderer for Types ComboBox
    1172     //
    1173     protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
    1174         return new FilterComboBoxRenderer();
    1175     }
    1176
    1177     /**
    1178      * Render different type sizes and styles.
    1179      */
    1180     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1181     public class FilterComboBoxRenderer extends DefaultListCellRenderer {
    1182         public Component getListCellRendererComponent(JList<?> list,
    1183             Object value, int index, boolean isSelected,
    1184             boolean cellHasFocus) {
    1185
    1186             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    1187
    1188             if (value != null && value instanceof FileFilter) {
    1189                 setText(((FileFilter)value).getDescription());
    1190             }
    1191
    1192             return this;
    1193         }
    1194     }
    1195
    1196     //
    1197     // DataModel for Types Comboxbox
    1198     //
    1199     protected FilterComboBoxModel createFilterComboBoxModel() {
    1200         return new FilterComboBoxModel();
    1201     }
    1202
    1203     /**
    1204      * Data model for a type-face selection combo-box.
    1205      */
    1206     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1207     protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,
    1208             PropertyChangeListener {
    1209         protected FileFilter[] filters;
    1210         protected FilterComboBoxModel() {
    1211             super();
    1212             filters = getFileChooser().getChoosableFileFilters();
    1213         }
    1214
    1215         public void propertyChange(PropertyChangeEvent e) {
    1216             String prop = e.getPropertyName();
    1217             if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
    1218                 filters = (FileFilter[]) e.getNewValue();
    1219                 fireContentsChanged(this, -1, -1);
    1220             } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
    1221                 fireContentsChanged(this, -1, -1);
    1222             }
    1223         }
    1224
    1225         public void setSelectedItem(FileFilter filter) {
    1226             if(filter != null) {
    1227                 getFileChooser().setFileFilter(filter);
    1228                 fireContentsChanged(this, -1, -1);
    1229             }
    1230         }
    1231
    1232         public FileFilter getSelectedItem() {
    1233             // Ensure that the current filter is in the list.
    1234             // NOTE: we shouldnt' have to do this, since JFileChooser adds
    1235             // the filter to the choosable filters list when the filter
    1236             // is set. Lets be paranoid just in case someone overrides
    1237             // setFileFilter in JFileChooser.
    1238             FileFilter currentFilter = getFileChooser().getFileFilter();
    1239             boolean found = false;
    1240             if(currentFilter != null) {
    1241                 for (FileFilter filter : filters) {
    1242                     if (filter == currentFilter) {
    1243                         found = true;
    1244                     }
    1245                 }
    1246                 if(found == false) {
    1247                     getFileChooser().addChoosableFileFilter(currentFilter);
    1248                 }
    1249             }
    1250             return getFileChooser().getFileFilter();
    1251         }
    1252
    1253         public int getSize() {
    1254             if(filters != null) {
    1255                 return filters.length;
    1256             } else {
    1257                 return 0;
    1258             }
    1259         }
    1260
    1261         public FileFilter getElementAt(int index) {
    1262             if(index > getSize() - 1) {
    1263                 // This shouldn't happen. Try to recover gracefully.
    1264                 return getFileChooser().getFileFilter();
    1265             }
    1266             if(filters != null) {
    1267                 return filters[index];
    1268             } else {
    1269                 return null;
    1270             }
    1271         }
    1272     }
    1273
    1274     public void valueChanged(ListSelectionEvent e) {
    1275         JFileChooser fc = getFileChooser();
    1276         File f = fc.getSelectedFile();
    1277         if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) {
    1278             setFileName(fileNameString(f));
    1279         }
    1280     }
    1281
    1282     /**
    1283      * Acts when DirectoryComboBox has changed the selected item.
    1284      */
    1285     protected class DirectoryComboBoxAction implements ActionListener {
    1286
    1287
    1288
    1289
    1290         public void actionPerformed(ActionEvent e) {
    1291             File f = directoryComboBox.getSelectedItem();
    1292             getFileChooser().setCurrentDirectory(f);
    1293         }
    1294     }
    1295
    1296     protected JButton getApproveButton(JFileChooser fc) {
    1297         return approveButton;
    1298     }
    1299
    1300     public FileView getFileView(JFileChooser fc) {
    1301         return fileView;
    1302     }
    1303
    1304     // ***********************
    1305     // * FileView operations *
    1306     // ***********************
    1307     protected class WindowsFileView extends BasicFileView {
    1308         /* FileView type descriptions */
    1309
    1310         public Icon getIcon(File f) {
    1311             Icon icon = getCachedIcon(f);
    1312             if (icon != null) {
    1313                 return icon;
    1314             }
    1315             if (f != null) {
    1316                 icon = getFileChooser().getFileSystemView().getSystemIcon(f);
    1317             }
    1318             if (icon == null) {
    1319                 icon = super.getIcon(f);
    1320             }
    1321             cacheIcon(f, icon);
    1322             return icon;
    1323         }
    1324     }
    1325 }
    --- EOF ---