    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) 2002, 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 package com.sun.java.swing.plaf.gtk;
      26
      27 import java.awt.*;
      28 import java.awt.event.*;
      29 import java.beans.*;
      30 import java.io.File;
      31 import java.io.IOException;
      32 import java.text.MessageFormat;
      33 import java.util.*;
      34
      35 import javax.swing.*;
      36 import javax.swing.border.*;
      37 import javax.swing.filechooser.*;
      38 import javax.swing.event.*;
      39 import javax.swing.plaf.*;
      40 import javax.swing.plaf.basic.BasicDirectoryModel;
      41 import javax.swing.table.*;
      42 import javax.accessibility.*;
      43
      44 import sun.swing.SwingUtilities2;
      45
      46 import sun.swing.plaf.synth.*;
      47 import sun.swing.FilePane;
      48 import sun.awt.shell.ShellFolder;
      49
      50 /**
      51  * GTK FileChooserUI.
      52  *
      53  * @author Leif Samuelsson
      54  * @author Jeff Dinkins
      55  */
      56 class GTKFileChooserUI extends SynthFileChooserUI {
      57
      58     // The accessoryPanel is a container to place the JFileChooser accessory component
      59     private JPanel accessoryPanel = null;
      60
      61     private String newFolderButtonText = null;
      62     private String newFolderErrorSeparator = null;
      63     private String newFolderErrorText = null;
      64     private String newFolderDialogText = null;
      65     private String newFolderNoDirectoryErrorTitleText = null;
      66     private String newFolderNoDirectoryErrorText = null;
      67
      68     private String deleteFileButtonText = null;
      69     private String renameFileButtonText = null;
      70
      71     private String newFolderButtonToolTipText = null;
      72     private String deleteFileButtonToolTipText = null;
      73     private String renameFileButtonToolTipText = null;
      74
      75     private int newFolderButtonMnemonic = 0;
      76     private int deleteFileButtonMnemonic = 0;
      77     private int renameFileButtonMnemonic = 0;
      78     private int foldersLabelMnemonic = 0;
      79     private int filesLabelMnemonic = 0;
      80
      81     private String renameFileDialogText = null;
      82     private String renameFileErrorTitle = null;
      83     private String renameFileErrorText = null;
      84
      85     private JComboBox<FileFilter> filterComboBox;
      86     private FilterComboBoxModel filterComboBoxModel;
      87
      88     // From Motif
      89
      90     private JPanel rightPanel;
      91     private JList<File> directoryList;
      92     private JList<File> fileList;
      93
      94     private JLabel pathField;
      95     private JTextField fileNameTextField;
      96
      97     private static final Dimension hstrut3 = new Dimension(3, 1);
      98     private static final Dimension vstrut10 = new Dimension(1, 10);
      99
     100     private static Dimension prefListSize = new Dimension(75, 150);
     101
     102     private static Dimension PREF_SIZE = new Dimension(435, 360);
     103     private static final int MIN_WIDTH = 200;
     104     private static final int MIN_HEIGHT = 300;
     105
     106     private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1);
     107
     108     private static Dimension MAX_SIZE = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
     109
     110     private static final Insets buttonMargin = new Insets(3, 3, 3, 3);
     111
     112     private String filesLabelText = null;
     113     private String foldersLabelText = null;
     114     private String pathLabelText = null;
     115     private String filterLabelText = null;
     116
     117     private int pathLabelMnemonic = 0;
     118     private int filterLabelMnemonic = 0;
     119
     120     private JComboBox<File> directoryComboBox;
     121     private DirectoryComboBoxModel directoryComboBoxModel;
     122     private Action directoryComboBoxAction = new DirectoryComboBoxAction();
     123     private JPanel bottomButtonPanel;
     124     private GTKDirectoryModel model = null;
     125     private Action newFolderAction;
     126     private boolean readOnly;
     127     private boolean showDirectoryIcons;
     128     private boolean showFileIcons;
     129     private GTKFileView fileView = new GTKFileView();
     130     private PropertyChangeListener gtkFCPropertyChangeListener;
     131     private Action approveSelectionAction = new GTKApproveSelectionAction();
     132     private GTKDirectoryListModel directoryListModel;
     133
     134     public GTKFileChooserUI(JFileChooser filechooser) {
     135         super(filechooser);
     136     }
     137
     138     protected ActionMap createActionMap() {
     139         ActionMap map = new ActionMapUIResource();
     140         map.put("approveSelection", getApproveSelectionAction());
     141         map.put("cancelSelection", getCancelSelectionAction());
     142         map.put("Go Up", getChangeToParentDirectoryAction());
     143         map.put("fileNameCompletion", getFileNameCompletionAction());
     144         return map;
     145     }
     146
     147     @SuppressWarnings("deprecation")
     148     public String getFileName() {
     149         JFileChooser fc = getFileChooser();
     150         String typedInName = fileNameTextField != null ?
     151             fileNameTextField.getText() : null;
     152
     153         if (!fc.isMultiSelectionEnabled()) {
     154             return typedInName;
     155         }
     156
     157         int mode = fc.getFileSelectionMode();
     158         JList<File> list = mode == JFileChooser.DIRECTORIES_ONLY ?
     159             directoryList : fileList;
     160         Object[] files = list.getSelectedValues();
     161         int len = files.length;
     162         Vector<String> result = new Vector<String>(len + 1);
     163
     164         // we return all selected file names
     165         for (int i = 0; i < len; i++) {
     166             File file = (File)files[i];
     167             result.add(file.getName());
     168         }
     169         // plus the file name typed into the text field, if not already there
     170         if (typedInName != null && !result.contains(typedInName)) {
     171             result.add(typedInName);
     172         }
     173
     174         StringBuilder sb = new StringBuilder();
     175         len = result.size();
     176
     177         // construct the resulting string
     178         for (int i=0; i<len; i++) {
     179             if (i > 0) {
     180                 sb.append(" ");
     181             }
     182             if (len > 1) {
     183                 sb.append("\"");
     184             }
     185             sb.append(result.get(i));
     186             if (len > 1) {
     187                 sb.append("\"");
     188             }
     189         }
     190         return sb.toString();
     191     }
     192
     193     public void setFileName(String fileName) {
     194         if (fileNameTextField != null) {
     195             fileNameTextField.setText(fileName);
     196         }
     197     }
     198
     199 //     public String getDirectoryName() {
     200 //      return pathField.getText();
     201 //     }
     202
     203     public void setDirectoryName(String dirname) {
     204         pathField.setText(dirname);
     205     }
     206
     207     public void ensureFileIsVisible(JFileChooser fc, File f) {
     208         // PENDING
     209     }
     210
     211     public void rescanCurrentDirectory(JFileChooser fc) {
     212         getModel().validateFileCache();
     213     }
     214
     215     public JPanel getAccessoryPanel() {
     216         return accessoryPanel;
     217     }
     218
     219     // ***********************
     220     // * FileView operations *
     221     // ***********************
     222
     223     public FileView getFileView(JFileChooser fc) {
     224         return fileView;
     225     }
     226
     227     private class GTKFileView extends BasicFileView {
     228         public GTKFileView() {
     229             iconCache = null;
     230         }
     231
     232         public void clearIconCache() {
     233         }
     234
     235         public Icon getCachedIcon(File f) {
     236             return null;
     237         }
     238
     239         public void cacheIcon(File f, Icon i) {
     240         }
     241
     242         public Icon getIcon(File f) {
     243             return (f != null && f.isDirectory()) ? directoryIcon : fileIcon;
     244         }
     245     }
     246
     247
     248     private void updateDefaultButton() {
     249         JFileChooser filechooser = getFileChooser();
     250         JRootPane root = SwingUtilities.getRootPane(filechooser);
     251         if (root == null) {
     252             return;
     253         }
     254
     255         if (filechooser.getControlButtonsAreShown()) {
     256             if (root.getDefaultButton() == null) {
     257                 root.setDefaultButton(getApproveButton(filechooser));
     258                 getCancelButton(filechooser).setDefaultCapable(false);
     259             }
     260         } else {
     261             if (root.getDefaultButton() == getApproveButton(filechooser)) {
     262                 root.setDefaultButton(null);
     263             }
     264         }
     265     }
     266
     267     protected void doSelectedFileChanged(PropertyChangeEvent e) {
     268         super.doSelectedFileChanged(e);
     269         File f = (File) e.getNewValue();
     270         if (f != null) {
     271             setFileName(getFileChooser().getName(f));
     272         }
     273     }
     274
     275     protected void doDirectoryChanged(PropertyChangeEvent e) {
     276         directoryList.clearSelection();
     277         ListSelectionModel sm = directoryList.getSelectionModel();
     278         if (sm instanceof DefaultListSelectionModel) {
     279             ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
     280             sm.setAnchorSelectionIndex(0);
     281         }
     282         fileList.clearSelection();
     283         sm = fileList.getSelectionModel();
     284         if (sm instanceof DefaultListSelectionModel) {
     285             ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
     286             sm.setAnchorSelectionIndex(0);
     287         }
     288
     289         File currentDirectory = getFileChooser().getCurrentDirectory();
     290         if (currentDirectory != null) {
     291             try {
     292                 setDirectoryName(ShellFolder.getNormalizedFile((File)e.getNewValue()).getPath());
     293             } catch (IOException ioe) {
     294                 setDirectoryName(((File)e.getNewValue()).getAbsolutePath());
     295             }
     296             if ((getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) && !getFileChooser().isMultiSelectionEnabled()) {
     297                 setFileName(pathField.getText());
     298             }
     299             directoryComboBoxModel.addItem(currentDirectory);
     300             directoryListModel.directoryChanged();
     301         }
     302         super.doDirectoryChanged(e);
     303     }
     304
     305     protected void doAccessoryChanged(PropertyChangeEvent e) {
     306         if (getAccessoryPanel() != null) {
     307             if (e.getOldValue() != null) {
     308                 getAccessoryPanel().remove((JComponent)e.getOldValue());
     309             }
     310             JComponent accessory = (JComponent)e.getNewValue();
     311             if (accessory != null) {
     312                 getAccessoryPanel().add(accessory, BorderLayout.CENTER);
     313                 getAccessoryPanel().setPreferredSize(accessory.getPreferredSize());
     314                 getAccessoryPanel().setMaximumSize(MAX_SIZE);
     315             } else {
     316                 getAccessoryPanel().setPreferredSize(ZERO_ACC_SIZE);
     317                 getAccessoryPanel().setMaximumSize(ZERO_ACC_SIZE);
     318             }
     319         }
     320     }
     321
     322     protected void doFileSelectionModeChanged(PropertyChangeEvent e) {
     323         directoryList.clearSelection();
     324         rightPanel.setVisible(((Integer)e.getNewValue()).intValue() != JFileChooser.DIRECTORIES_ONLY);
     325
     326         super.doFileSelectionModeChanged(e);
     327     }
     328
     329     protected void doMultiSelectionChanged(PropertyChangeEvent e) {
     330         if (getFileChooser().isMultiSelectionEnabled()) {
     331             fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
     332         } else {
     333             fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     334             fileList.clearSelection();
     335         }
     336
     337         super.doMultiSelectionChanged(e);
     338     }
     339
     340     protected void doControlButtonsChanged(PropertyChangeEvent e) {
     341         super.doControlButtonsChanged(e);
     342
     343         JFileChooser filechooser = getFileChooser();
     344         if (filechooser.getControlButtonsAreShown()) {
     345             filechooser.add(bottomButtonPanel, BorderLayout.SOUTH);
     346         } else {
     347             filechooser.remove(bottomButtonPanel);
     348         }
     349         updateDefaultButton();
     350     }
     351
     352     protected void doAncestorChanged(PropertyChangeEvent e) {
     353         if (e.getOldValue() == null && e.getNewValue() != null) {
     354             // Ancestor was added, set initial focus
     355             fileNameTextField.selectAll();
     356             fileNameTextField.requestFocus();
     357             updateDefaultButton();
     358         }
     359
     360         super.doAncestorChanged(e);
     361     }
     362
     363
     364
     365     // ********************************************
     366     // ************ Create Listeners **************
     367     // ********************************************
     368
     369     public ListSelectionListener createListSelectionListener(JFileChooser fc) {
     370         return new SelectionListener();
     371     }
     372
     373     class DoubleClickListener extends MouseAdapter {
     374         JList<?> list;
     375         public  DoubleClickListener(JList<?> list) {
     376             this.list = list;
     377         }
     378
     379         public void mouseClicked(MouseEvent e) {
     380             if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
     381                 int index = list.locationToIndex(e.getPoint());
     382                 if (index >= 0) {
     383                     File f = (File) list.getModel().getElementAt(index);
     384                     try {
     385                         // Strip trailing ".."
     386                         f = ShellFolder.getNormalizedFile(f);
     387                     } catch (IOException ex) {
     388                         // That's ok, we'll use f as is
     389                     }
     390                     if (getFileChooser().isTraversable(f)) {
     391                         list.clearSelection();
     392                         if (getFileChooser().getCurrentDirectory().equals(f)){
     393                             rescanCurrentDirectory(getFileChooser());
     394                         } else {
     395                             getFileChooser().setCurrentDirectory(f);
     396                         }
     397                     } else {
     398                         getFileChooser().approveSelection();
     399                     }
     400                 }
     401             }
     402         }
     403
     404         public void mouseEntered(MouseEvent evt) {
     405             if (list != null) {
     406                 TransferHandler th1 = getFileChooser().getTransferHandler();
     407                 TransferHandler th2 = list.getTransferHandler();
     408                 if (th1 != th2) {
     409                     list.setTransferHandler(th1);
     410                 }
     411                 if (getFileChooser().getDragEnabled() != list.getDragEnabled()) {
     412                     list.setDragEnabled(getFileChooser().getDragEnabled());
     413                 }
     414             }
     415         }
     416     }
     417
     418     protected MouseListener createDoubleClickListener(JFileChooser fc, JList<?> list) {
     419         return new DoubleClickListener(list);
     420     }
     421
     422
     423
     424     @SuppressWarnings("deprecation")
     425     protected class SelectionListener implements ListSelectionListener {
     426         public void valueChanged(ListSelectionEvent e) {
     427             if (!e.getValueIsAdjusting()) {
     428                 JFileChooser chooser = getFileChooser();
     429                 JList<?> list = (JList) e.getSource();
     430
     431                 if (chooser.isMultiSelectionEnabled()) {
     432                     File[] files = null;
     433                     Object[] objects = list.getSelectedValues();
     434                     if (objects != null) {
     435                         if (objects.length == 1
     436                             && ((File)objects[0]).isDirectory()
     437                             && chooser.isTraversable(((File)objects[0]))
     438                             && (chooser.getFileSelectionMode() != JFileChooser.DIRECTORIES_ONLY
     439                                 || !chooser.getFileSystemView().isFileSystem(((File)objects[0])))) {
     440                             setDirectorySelected(true);
     441                             setDirectory(((File)objects[0]));
     442                         } else {
     443                             ArrayList<File> fList = new ArrayList<File>(objects.length);
     444                             for (Object object : objects) {
     445                                 File f = (File) object;
     446                                 if ((chooser.isFileSelectionEnabled() && f.isFile())
     447                                     || (chooser.isDirectorySelectionEnabled() && f.isDirectory())) {
     448                                     fList.add(f);
     449                                 }
     450                             }
     451                             if (fList.size() > 0) {
     452                                 files = fList.toArray(new File[fList.size()]);
     453                             }
     454                             setDirectorySelected(false);
     455                         }
     456                     }
     457                     chooser.setSelectedFiles(files);
     458                 } else {
     459                     File file = (File)list.getSelectedValue();
     460                     if (file != null
     461                         && file.isDirectory()
     462                         && chooser.isTraversable(file)
     463                         && (chooser.getFileSelectionMode() == JFileChooser.FILES_ONLY
     464                             || !chooser.getFileSystemView().isFileSystem(file))) {
     465
     466                         setDirectorySelected(true);
     467                         setDirectory(file);
     468                     } else {
     469                         setDirectorySelected(false);
     470                         if (file != null) {
     471                             chooser.setSelectedFile(file);
     472                         }
     473                     }
     474                 }
     475             }
     476         }
     477     }
     478
     479
     480     //
     481     // ComponentUI Interface Implementation methods
     482     //
     483     public static ComponentUI createUI(JComponent c) {
     484         return new GTKFileChooserUI((JFileChooser)c);
     485     }
     486
     487     public void installUI(JComponent c) {
     488         accessoryPanel = new JPanel(new BorderLayout(10, 10));
     489         accessoryPanel.setName("GTKFileChooser.accessoryPanel");
     490
     491         super.installUI(c);
     492     }
     493
     494     public void uninstallUI(JComponent c) {
     495         c.removePropertyChangeListener(filterComboBoxModel);
     496         super.uninstallUI(c);
     497
     498         if (accessoryPanel != null) {
     499             accessoryPanel.removeAll();
     500         }
     501         accessoryPanel = null;
     502         getFileChooser().removeAll();
     503     }
     504
     505     public void installComponents(JFileChooser fc) {
     506         super.installComponents(fc);
     507
     508         boolean leftToRight = fc.getComponentOrientation().isLeftToRight();
     509
     510         fc.setLayout(new BorderLayout());
     511         fc.setAlignmentX(JComponent.CENTER_ALIGNMENT);
     512
     513         // Top row of buttons
     514         JPanel topButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
     515         topButtonPanel.setBorder(new EmptyBorder(10, 10, 0, 10));
     516         topButtonPanel.setName("GTKFileChooser.topButtonPanel");
     517
     518         if (!UIManager.getBoolean("FileChooser.readOnly")) {
     519             JButton newFolderButton = new JButton(getNewFolderAction());
     520             newFolderButton.setName("GTKFileChooser.newFolderButton");
     521             newFolderButton.setMnemonic(newFolderButtonMnemonic);
     522             newFolderButton.setToolTipText(newFolderButtonToolTipText);
     523             newFolderButton.setText(newFolderButtonText);
     524             topButtonPanel.add(newFolderButton);
     525         }
     526         JButton deleteFileButton = new JButton(deleteFileButtonText);
     527         deleteFileButton.setName("GTKFileChooser.deleteFileButton");
     528         deleteFileButton.setMnemonic(deleteFileButtonMnemonic);
     529         deleteFileButton.setToolTipText(deleteFileButtonToolTipText);
     530         deleteFileButton.setEnabled(false);
     531         topButtonPanel.add(deleteFileButton);
     532
     533         RenameFileAction rfa = new RenameFileAction();
     534         JButton renameFileButton = new JButton(rfa);
     535         if (readOnly) {
     536             rfa.setEnabled(false);
     537         }
     538         renameFileButton.setText(renameFileButtonText);
     539         renameFileButton.setName("GTKFileChooser.renameFileButton");
     540         renameFileButton.setMnemonic(renameFileButtonMnemonic);
     541         renameFileButton.setToolTipText(renameFileButtonToolTipText);
     542         topButtonPanel.add(renameFileButton);
     543
     544         fc.add(topButtonPanel, BorderLayout.NORTH);
     545
     546
     547         JPanel interior = new JPanel();
     548         interior.setBorder(new EmptyBorder(0, 10, 10, 10));
     549         interior.setName("GTKFileChooser.interiorPanel");
     550         align(interior);
     551         interior.setLayout(new BoxLayout(interior, BoxLayout.PAGE_AXIS));
     552
     553         fc.add(interior, BorderLayout.CENTER);
     554
     555         @SuppressWarnings("serial") // anonymous class
     556         JPanel comboBoxPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,
     557                                                          0, 0) {
     558             public void layoutContainer(Container target) {
     559                 super.layoutContainer(target);
     560                 JComboBox<?> comboBox = directoryComboBox;
     561                 if (comboBox.getWidth() > target.getWidth()) {
     562                     comboBox.setBounds(0, comboBox.getY(), target.getWidth(),
     563                                        comboBox.getHeight());
     564                 }
     565             }
     566         });
     567         comboBoxPanel.setBorder(new EmptyBorder(0, 0, 4, 0));
     568         comboBoxPanel.setName("GTKFileChooser.directoryComboBoxPanel");
     569         // CurrentDir ComboBox
     570         directoryComboBoxModel = createDirectoryComboBoxModel(fc);
     571         directoryComboBox = new JComboBox<>(directoryComboBoxModel);
     572         directoryComboBox.setName("GTKFileChooser.directoryComboBox");
     573         directoryComboBox.putClientProperty( "JComboBox.lightweightKeyboardNavigation", "Lightweight" );
     574         directoryComboBox.addActionListener(directoryComboBoxAction);
     575         directoryComboBox.setMaximumRowCount(8);
     576         comboBoxPanel.add(directoryComboBox);
     577         interior.add(comboBoxPanel);
     578
     579
     580         // CENTER: left, right, accessory
     581         JPanel centerPanel = new JPanel(new BorderLayout());
     582         centerPanel.setName("GTKFileChooser.centerPanel");
     583
     584         // SPLIT PANEL: left, right
     585         JSplitPane splitPanel = new JSplitPane();
     586         splitPanel.setName("GTKFileChooser.splitPanel");
     587         splitPanel.setDividerLocation((PREF_SIZE.width-8)/2);
     588
     589         // left panel - Filter & directoryList
     590         JPanel leftPanel = new JPanel(new GridBagLayout());
     591         leftPanel.setName("GTKFileChooser.directoryListPanel");
     592
     593         // Add the Directory List
     594         // Create a label that looks like button (should be a table header)
     595         TableCellRenderer headerRenderer = new JTableHeader().getDefaultRenderer();
     596         JLabel directoryListLabel =
     597             (JLabel)headerRenderer.getTableCellRendererComponent(null, foldersLabelText,
     598                                                                      false, false, 0, 0);
     599         directoryListLabel.setName("GTKFileChooser.directoryListLabel");
     600         leftPanel.add(directoryListLabel, new GridBagConstraints(
     601                           0, 0, 1, 1, 1, 0, GridBagConstraints.WEST,
     602                           GridBagConstraints.HORIZONTAL,
     603                           new Insets(0, 0, 0, 0), 0, 0));
     604         leftPanel.add(createDirectoryList(), new GridBagConstraints(
     605                           0, 1, 1, 1, 1, 1, GridBagConstraints.EAST,
     606                           GridBagConstraints.BOTH,
     607                           new Insets(0, 0, 0, 0), 0, 0));
     608         directoryListLabel.setDisplayedMnemonic(foldersLabelMnemonic);
     609         directoryListLabel.setLabelFor(directoryList);
     610
     611         // create files list
     612         rightPanel = new JPanel(new GridBagLayout());
     613         rightPanel.setName("GTKFileChooser.fileListPanel");
     614
     615         headerRenderer = new JTableHeader().getDefaultRenderer();
     616         JLabel fileListLabel =
     617             (JLabel)headerRenderer.getTableCellRendererComponent(null, filesLabelText,
     618                                                                      false, false, 0, 0);
     619         fileListLabel.setName("GTKFileChooser.fileListLabel");
     620         rightPanel.add(fileListLabel, new GridBagConstraints(
     621                           0, 0, 1, 1, 1, 0, GridBagConstraints.WEST,
     622                           GridBagConstraints.HORIZONTAL,
     623                           new Insets(0, 0, 0, 0), 0, 0));
     624         rightPanel.add(createFilesList(), new GridBagConstraints(
     625                           0, 1, 1, 1, 1, 1, GridBagConstraints.EAST,
     626                           GridBagConstraints.BOTH,
     627                           new Insets(0, 0, 0, 0), 0, 0));
     628         fileListLabel.setDisplayedMnemonic(filesLabelMnemonic);
     629         fileListLabel.setLabelFor(fileList);
     630
     631         splitPanel.add(leftPanel,  leftToRight ? JSplitPane.LEFT : JSplitPane.RIGHT);
     632         splitPanel.add(rightPanel, leftToRight ? JSplitPane.RIGHT : JSplitPane.LEFT);
     633         centerPanel.add(splitPanel, BorderLayout.CENTER);
     634
     635         JComponent accessoryPanel = getAccessoryPanel();
     636         JComponent accessory = fc.getAccessory();
     637         if (accessoryPanel != null) {
     638             if (accessory == null) {
     639                 accessoryPanel.setPreferredSize(ZERO_ACC_SIZE);
     640                 accessoryPanel.setMaximumSize(ZERO_ACC_SIZE);
     641             } else {
     642                 getAccessoryPanel().add(accessory, BorderLayout.CENTER);
     643                 accessoryPanel.setPreferredSize(accessory.getPreferredSize());
     644                 accessoryPanel.setMaximumSize(MAX_SIZE);
     645             }
     646             align(accessoryPanel);
     647             centerPanel.add(accessoryPanel, BorderLayout.AFTER_LINE_ENDS);
     648         }
     649         interior.add(centerPanel);
     650         interior.add(Box.createRigidArea(vstrut10));
     651
     652         JPanel pathFieldPanel = new JPanel(new FlowLayout(FlowLayout.LEADING,
     653                                                           0, 0));
     654         pathFieldPanel.setBorder(new EmptyBorder(0, 0, 4, 0));
     655         JLabel pathFieldLabel = new JLabel(pathLabelText);
     656         pathFieldLabel.setName("GTKFileChooser.pathFieldLabel");
     657         pathFieldLabel.setDisplayedMnemonic(pathLabelMnemonic);
     658         align(pathFieldLabel);
     659         pathFieldPanel.add(pathFieldLabel);
     660         pathFieldPanel.add(Box.createRigidArea(hstrut3));
     661
     662         File currentDirectory = fc.getCurrentDirectory();
     663         String curDirName = null;
     664         if (currentDirectory != null) {
     665             curDirName = currentDirectory.getPath();
     666         }
     667         @SuppressWarnings("serial") // anonymous class
     668         JLabel tmp = new JLabel(curDirName) {
     669             public Dimension getMaximumSize() {
     670                 Dimension d = super.getMaximumSize();
     671                 d.height = getPreferredSize().height;
     672                 return d;
     673             }
     674         };
     675         pathField =  tmp;
     676         pathField.setName("GTKFileChooser.pathField");
     677         align(pathField);
     678         pathFieldPanel.add(pathField);
     679         interior.add(pathFieldPanel);
     680
     681         // add the fileName field
     682         @SuppressWarnings("serial") // anonymous class
     683         JTextField tmp2 = new JTextField() {
     684             public Dimension getMaximumSize() {
     685                 Dimension d = super.getMaximumSize();
     686                 d.height = getPreferredSize().height;
     687                 return d;
     688             }
     689         };
     690         fileNameTextField = tmp2;
     691
     692         pathFieldLabel.setLabelFor(fileNameTextField);
     693
     694         Set<AWTKeyStroke> forwardTraversalKeys = fileNameTextField.getFocusTraversalKeys(
     695             KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
     696         forwardTraversalKeys = new HashSet<AWTKeyStroke>(forwardTraversalKeys);
     697         forwardTraversalKeys.remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
     698         fileNameTextField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardTraversalKeys);
     699
     700         fileNameTextField.setName("GTKFileChooser.fileNameTextField");
     701         fileNameTextField.getActionMap().put("fileNameCompletionAction", getFileNameCompletionAction());
     702         fileNameTextField.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "fileNameCompletionAction");
     703         interior.add(fileNameTextField);
     704
     705         // Add the filter combo box
     706         JPanel panel = new JPanel();
     707         panel.setLayout(new FlowLayout(FlowLayout.LEADING, 0, 0));
     708         panel.setBorder(new EmptyBorder(0, 0, 4, 0));
     709         JLabel filterLabel = new JLabel(filterLabelText);
     710         filterLabel.setName("GTKFileChooser.filterLabel");
     711         filterLabel.setDisplayedMnemonic(filterLabelMnemonic);
     712         panel.add(filterLabel);
     713
     714         filterComboBoxModel = createFilterComboBoxModel();
     715         fc.addPropertyChangeListener(filterComboBoxModel);
     716         filterComboBox = new JComboBox<>(filterComboBoxModel);
     717         filterComboBox.setRenderer(createFilterComboBoxRenderer());
     718         filterLabel.setLabelFor(filterComboBox);
     719
     720         interior.add(Box.createRigidArea(vstrut10));
     721         interior.add(panel);
     722         interior.add(filterComboBox);
     723
     724         // Add buttons
     725         bottomButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
     726         bottomButtonPanel.setName("GTKFileChooser.bottomButtonPanel");
     727         align(bottomButtonPanel);
     728
     729         JPanel pnButtons = new JPanel(new GridLayout(1, 2, 5, 0));
     730
     731         JButton cancelButton = getCancelButton(fc);
     732         align(cancelButton);
     733         cancelButton.setMargin(buttonMargin);
     734         pnButtons.add(cancelButton);
     735
     736         JButton approveButton = getApproveButton(fc);
     737         align(approveButton);
     738         approveButton.setMargin(buttonMargin);
     739         pnButtons.add(approveButton);
     740
     741         bottomButtonPanel.add(pnButtons);
     742
     743         if (fc.getControlButtonsAreShown()) {
     744             fc.add(bottomButtonPanel, BorderLayout.SOUTH);
     745         }
     746     }
     747
     748     protected void installListeners(JFileChooser fc) {
     749         super.installListeners(fc);
     750
     751         gtkFCPropertyChangeListener = new GTKFCPropertyChangeListener();
     752         fc.addPropertyChangeListener(gtkFCPropertyChangeListener);
     753     }
     754
     755     private int getMnemonic(String key, Locale l) {
     756         return SwingUtilities2.getUIDefaultsInt(key, l);
     757     }
     758
     759     protected void uninstallListeners(JFileChooser fc) {
     760         super.uninstallListeners(fc);
     761
     762         if (gtkFCPropertyChangeListener != null) {
     763             fc.removePropertyChangeListener(gtkFCPropertyChangeListener);
     764         }
     765     }
     766
     767     private class GTKFCPropertyChangeListener implements PropertyChangeListener {
     768         public void propertyChange(PropertyChangeEvent e) {
     769             String prop = e.getPropertyName();
     770             if (prop.equals("GTKFileChooser.showDirectoryIcons")) {
     771                 showDirectoryIcons = Boolean.TRUE.equals(e.getNewValue());
     772             } else if (prop.equals("GTKFileChooser.showFileIcons")) {
     773                 showFileIcons      = Boolean.TRUE.equals(e.getNewValue());
     774             }
     775         }
     776     }
     777
     778     protected void installDefaults(JFileChooser fc) {
     779         super.installDefaults(fc);
     780         readOnly = UIManager.getBoolean("FileChooser.readOnly");
     781         showDirectoryIcons =
     782             Boolean.TRUE.equals(fc.getClientProperty("GTKFileChooser.showDirectoryIcons"));
     783         showFileIcons =
     784             Boolean.TRUE.equals(fc.getClientProperty("GTKFileChooser.showFileIcons"));
     785     }
     786
     787     protected void installIcons(JFileChooser fc) {
     788         directoryIcon    = UIManager.getIcon("FileView.directoryIcon");
     789         fileIcon         = UIManager.getIcon("FileView.fileIcon");
     790     }
     791
     792     protected void installStrings(JFileChooser fc) {
     793         super.installStrings(fc);
     794
     795         Locale l = fc.getLocale();
     796
     797         newFolderDialogText = UIManager.getString("FileChooser.newFolderDialogText", l);
     798         newFolderErrorText = UIManager.getString("FileChooser.newFolderErrorText",l);
     799         newFolderErrorSeparator = UIManager.getString("FileChooser.newFolderErrorSeparator",l);
     800         newFolderButtonText = UIManager.getString("FileChooser.newFolderButtonText", l);
     801         newFolderNoDirectoryErrorTitleText = UIManager.getString("FileChooser.newFolderNoDirectoryErrorTitleText", l);
     802         newFolderNoDirectoryErrorText = UIManager.getString("FileChooser.newFolderNoDirectoryErrorText", l);
     803         deleteFileButtonText = UIManager.getString("FileChooser.deleteFileButtonText", l);
     804         renameFileButtonText = UIManager.getString("FileChooser.renameFileButtonText", l);
     805
     806         newFolderButtonMnemonic = getMnemonic("FileChooser.newFolderButtonMnemonic", l);
     807         deleteFileButtonMnemonic = getMnemonic("FileChooser.deleteFileButtonMnemonic", l);
     808         renameFileButtonMnemonic = getMnemonic("FileChooser.renameFileButtonMnemonic", l);
     809
     810         newFolderButtonToolTipText = UIManager.getString("FileChooser.newFolderButtonToolTipText", l);
     811         deleteFileButtonToolTipText = UIManager.getString("FileChooser.deleteFileButtonToolTipText", l);
     812         renameFileButtonToolTipText = UIManager.getString("FileChooser.renameFileButtonToolTipText", l);
     813
     814         renameFileDialogText = UIManager.getString("FileChooser.renameFileDialogText", l);
     815         renameFileErrorTitle = UIManager.getString("FileChooser.renameFileErrorTitle", l);
     816         renameFileErrorText = UIManager.getString("FileChooser.renameFileErrorText", l);
     817
     818         foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l);
     819         foldersLabelMnemonic = getMnemonic("FileChooser.foldersLabelMnemonic", l);
     820
     821         filesLabelText = UIManager.getString("FileChooser.filesLabelText",l);
     822         filesLabelMnemonic = getMnemonic("FileChooser.filesLabelMnemonic", l);
     823
     824         pathLabelText = UIManager.getString("FileChooser.pathLabelText",l);
     825         pathLabelMnemonic = getMnemonic("FileChooser.pathLabelMnemonic", l);
     826
     827         filterLabelText = UIManager.getString("FileChooser.filterLabelText", l);
     828         filterLabelMnemonic = UIManager.getInt("FileChooser.filterLabelMnemonic");
     829     }
     830
     831     protected void uninstallStrings(JFileChooser fc) {
     832         super.uninstallStrings(fc);
     833
     834         newFolderButtonText = null;
     835         deleteFileButtonText = null;
     836         renameFileButtonText = null;
     837
     838         newFolderButtonToolTipText = null;
     839         deleteFileButtonToolTipText = null;
     840         renameFileButtonToolTipText = null;
     841
     842         renameFileDialogText = null;
     843         renameFileErrorTitle = null;
     844         renameFileErrorText = null;
     845
     846         foldersLabelText = null;
     847         filesLabelText = null;
     848
     849         pathLabelText = null;
     850
     851         newFolderDialogText = null;
     852         newFolderErrorText = null;
     853         newFolderErrorSeparator = null;
     854     }
     855
     856     protected JScrollPane createFilesList() {
     857         fileList = new JList<>();
     858         fileList.setName("GTKFileChooser.fileList");
     859         fileList.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, filesLabelText);
     860
     861         if (getFileChooser().isMultiSelectionEnabled()) {
     862             fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
     863         } else {
     864             fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     865         }
     866
     867         fileList.setModel(new GTKFileListModel());
     868         fileList.getSelectionModel().removeSelectionInterval(0, 0);
     869         fileList.setCellRenderer(new FileCellRenderer());
     870         fileList.addListSelectionListener(createListSelectionListener(getFileChooser()));
     871         fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList));
     872         align(fileList);
     873         JScrollPane scrollpane = new JScrollPane(fileList);
     874     scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     875         scrollpane.setName("GTKFileChooser.fileListScrollPane");
     876         scrollpane.setPreferredSize(prefListSize);
     877         scrollpane.setMaximumSize(MAX_SIZE);
     878         align(scrollpane);
     879         return scrollpane;
     880     }
     881
     882     protected JScrollPane createDirectoryList() {
     883         directoryList = new JList<>();
     884         directoryList.setName("GTKFileChooser.directoryList");
     885         directoryList.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, foldersLabelText);
     886         align(directoryList);
     887
     888         directoryList.setCellRenderer(new DirectoryCellRenderer());
     889         directoryListModel = new GTKDirectoryListModel();
     890         directoryList.getSelectionModel().removeSelectionInterval(0, 0);
     891         directoryList.setModel(directoryListModel);
     892         directoryList.addMouseListener(createDoubleClickListener(getFileChooser(), directoryList));
     893         directoryList.addListSelectionListener(createListSelectionListener(getFileChooser()));
     894
     895         JScrollPane scrollpane = new JScrollPane(directoryList);
     896     scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     897         scrollpane.setName("GTKFileChooser.directoryListScrollPane");
     898         scrollpane.setMaximumSize(MAX_SIZE);
     899         scrollpane.setPreferredSize(prefListSize);
     900         align(scrollpane);
     901         return scrollpane;
     902     }
     903
     904     protected void createModel() {
     905         model = new GTKDirectoryModel();
     906     }
     907
     908     public BasicDirectoryModel getModel() {
     909         return model;
     910     }
     911
     912     public Action getApproveSelectionAction() {
     913         return approveSelectionAction;
     914     }
     915
     916     @SuppressWarnings("serial") // Superclass is not serializable across versions
     917     private class GTKDirectoryModel extends BasicDirectoryModel {
     918         FileSystemView fsv;
     919         private Comparator<File> fileComparator = new Comparator<File>() {
     920             public int compare(File o, File o1) {
     921                 return fsv.getSystemDisplayName(o).compareTo(fsv.getSystemDisplayName(o1));
     922             }
     923         };
     924
     925         public GTKDirectoryModel() {
     926             super(getFileChooser());
     927         }
     928
     929         protected void sort(Vector<? extends File> v) {
     930             fsv = getFileChooser().getFileSystemView();
     931             Collections.sort(v, fileComparator);
     932         }
     933     }
     934
     935     @SuppressWarnings("serial") // Superclass is not serializable across versions
     936     protected class GTKDirectoryListModel extends AbstractListModel<File> implements ListDataListener {
     937         File curDir;
     938         public GTKDirectoryListModel() {
     939             getModel().addListDataListener(this);
     940             directoryChanged();
     941         }
     942
     943         public int getSize() {
     944             return getModel().getDirectories().size() + 1;
     945         }
     946
     947         @Override
     948         public File getElementAt(int index) {
     949             return index > 0 ? getModel().getDirectories().elementAt(index - 1):
     950                     curDir;
     951         }
     952
     953         public void intervalAdded(ListDataEvent e) {
     954             fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
     955         }
     956
     957         public void intervalRemoved(ListDataEvent e) {
     958             fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
     959         }
     960
     961         // PENDING - this is inefficient - should sent out
     962         // incremental adjustment values instead of saying that the
     963         // whole list has changed.
     964         public void fireContentsChanged() {
     965             fireContentsChanged(this, 0, getModel().getDirectories().size()-1);
     966         }
     967
     968         // PENDING - fire the correct interval changed - currently sending
     969         // out that everything has changed
     970         public void contentsChanged(ListDataEvent e) {
     971             fireContentsChanged();
     972         }
     973
     974         private void directoryChanged() {
     975             curDir = getFileChooser().getFileSystemView().createFileObject(
     976                     getFileChooser().getCurrentDirectory(), ".");
     977         }
     978     }
     979
     980     @SuppressWarnings("serial") // Superclass is not serializable across versions
     981     protected class GTKFileListModel extends AbstractListModel<File> implements ListDataListener {
     982         public GTKFileListModel() {
     983             getModel().addListDataListener(this);
     984         }
     985
     986         public int getSize() {
     987             return getModel().getFiles().size();
     988         }
     989
     990         public boolean contains(Object o) {
     991             return getModel().getFiles().contains(o);
     992         }
     993
     994         public int indexOf(Object o) {
     995             return getModel().getFiles().indexOf(o);
     996         }
     997
     998         @Override
     999         public File getElementAt(int index) {
    1000             return getModel().getFiles().elementAt(index);
    1001         }
    1002
    1003         public void intervalAdded(ListDataEvent e) {
    1004             fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
    1005         }
    1006
    1007         public void intervalRemoved(ListDataEvent e) {
    1008             fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
    1009         }
    1010
    1011         // PENDING - this is inefficient - should sent out
    1012         // incremental adjustment values instead of saying that the
    1013         // whole list has changed.
    1014         public void fireContentsChanged() {
    1015             fireContentsChanged(this, 0, getModel().getFiles().size()-1);
    1016         }
    1017
    1018         // PENDING - fire the interval changed
    1019         public void contentsChanged(ListDataEvent e) {
    1020             fireContentsChanged();
    1021         }
    1022     }
    1023
    1024
    1025     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1026     protected class FileCellRenderer extends DefaultListCellRenderer  {
    1027         public Component getListCellRendererComponent(JList<?> list, Object value, int index,
    1028                                                       boolean isSelected, boolean cellHasFocus) {
    1029
    1030             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    1031             setText(getFileChooser().getName((File) value));
    1032             if (showFileIcons) {
    1033                 setIcon(getFileChooser().getIcon((File)value));
    1034             }
    1035             return this;
    1036         }
    1037     }
    1038
    1039     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1040     protected class DirectoryCellRenderer extends DefaultListCellRenderer  {
    1041         public Component getListCellRendererComponent(JList<?> list, Object value, int index,
    1042                                                       boolean isSelected, boolean cellHasFocus) {
    1043
    1044             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    1045
    1046             if (showDirectoryIcons) {
    1047                 setIcon(getFileChooser().getIcon((File)value));
    1048                 setText(getFileChooser().getName((File)value));
    1049             } else {
    1050                 setText(getFileChooser().getName((File)value) + "/");
    1051             }
    1052             return this;
    1053         }
    1054     }
    1055
    1056     @Override
    1057     public Dimension getPreferredSize(JComponent c) {
    1058         Dimension prefSize = new Dimension(PREF_SIZE);
    1059         JComponent accessory = getFileChooser().getAccessory();
    1060         if (accessory != null) {
    1061             prefSize.width += accessory.getPreferredSize().width + 20;
    1062         }
    1063         Dimension d = c.getLayout().preferredLayoutSize(c);
    1064         if (d != null) {
    1065             return new Dimension(d.width < prefSize.width ? prefSize.width : d.width,
    1066                                  d.height < prefSize.height ? prefSize.height : d.height);
    1067         } else {
    1068             return prefSize;
    1069         }
    1070     }
    1071
    1072     @Override
    1073     public Dimension getMinimumSize(JComponent x) {
    1074         return new Dimension(MIN_WIDTH, MIN_HEIGHT);
    1075     }
    1076
    1077     @Override
    1078     public Dimension getMaximumSize(JComponent x) {
    1079         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    1080     }
    1081
    1082     protected void align(JComponent c) {
    1083         c.setAlignmentX(JComponent.LEFT_ALIGNMENT);
    1084         c.setAlignmentY(JComponent.TOP_ALIGNMENT);
    1085     }
    1086
    1087     public Action getNewFolderAction() {
    1088         if (newFolderAction == null) {
    1089             newFolderAction = new NewFolderAction();
    1090             newFolderAction.setEnabled(!readOnly);
    1091         }
    1092         return newFolderAction;
    1093     }
    1094
    1095     //
    1096     // DataModel for DirectoryComboxbox
    1097     //
    1098     protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
    1099         return new DirectoryComboBoxModel();
    1100     }
    1101
    1102     /**
    1103      * Data model for a type-face selection combo-box.
    1104      */
    1105     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1106     protected class DirectoryComboBoxModel extends AbstractListModel<File> implements ComboBoxModel<File> {
    1107         Vector<File> directories = new Vector<File>();
    1108         File selectedDirectory = null;
    1109         JFileChooser chooser = getFileChooser();
    1110         FileSystemView fsv = chooser.getFileSystemView();
    1111
    1112         public DirectoryComboBoxModel() {
    1113             // Add the current directory to the model, and make it the
    1114             // selectedDirectory
    1115             File dir = getFileChooser().getCurrentDirectory();
    1116             if (dir != null) {
    1117                 addItem(dir);
    1118             }
    1119         }
    1120
    1121         /**
    1122          * Adds the directory to the model and sets it to be selected,
    1123          * additionally clears out the previous selected directory and
    1124          * the paths leading up to it, if any.
    1125          */
    1126         private void addItem(File directory) {
    1127
    1128             if (directory == null) {
    1129                 return;
    1130             }
    1131
    1132             int oldSize = directories.size();
    1133             directories.clear();
    1134             if (oldSize > 0) {
    1135                 fireIntervalRemoved(this, 0, oldSize);
    1136             }
    1137
    1138             // Get the canonical (full) path. This has the side
    1139             // benefit of removing extraneous chars from the path,
    1140             // for example /foo/bar/ becomes /foo/bar
    1141             File canonical;
    1142             try {
    1143                 canonical = fsv.createFileObject(ShellFolder.getNormalizedFile(directory).getPath());
    1144             } catch (IOException e) {
    1145                 // Maybe drive is not ready. Can't abort here.
    1146                 canonical = directory;
    1147             }
    1148
    1149             // create File instances of each directory leading up to the top
    1150             File f = canonical;
    1151             do {
    1152                 directories.add(f);
    1153             } while ((f = f.getParentFile()) != null);
    1154             int newSize = directories.size();
    1155             if (newSize > 0) {
    1156                 fireIntervalAdded(this, 0, newSize);
    1157             }
    1158             setSelectedItem(canonical);
    1159         }
    1160
    1161         public void setSelectedItem(File selectedDirectory) {
    1162             this.selectedDirectory = selectedDirectory;
    1163             fireContentsChanged(this, -1, -1);
    1164         }
    1165
    1166         public File getSelectedItem() {
    1167             return selectedDirectory;
    1168         }
    1169
    1170         public int getSize() {
    1171             return directories.size();
    1172         }
    1173
    1174         @Override
    1175         public File getElementAt(int index) {
    1176             return directories.elementAt(index);
    1177         }
    1178     }
    1179
    1180     /**
    1181      * Acts when DirectoryComboBox has changed the selected item.
    1182      */
    1183     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1184     protected class DirectoryComboBoxAction extends AbstractAction {
    1185         protected DirectoryComboBoxAction() {
    1186             super("DirectoryComboBoxAction");
    1187         }
    1188
    1189         public void actionPerformed(ActionEvent e) {
    1190             File f = directoryComboBox.getSelectedItem();
    1191             getFileChooser().setCurrentDirectory(f);
    1192         }
    1193     }
    1194
    1195     /**
    1196      * Creates a new folder.
    1197      */
    1198     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1199     private class NewFolderAction extends AbstractAction {
    1200         protected NewFolderAction() {
    1201             super(FilePane.ACTION_NEW_FOLDER);
    1202         }
    1203         public void actionPerformed(ActionEvent e) {
    1204             if (readOnly) {
    1205                 return;
    1206             }
    1207             JFileChooser fc = getFileChooser();
    1208             File currentDirectory = fc.getCurrentDirectory();
    1209             String dirName = JOptionPane.showInputDialog(fc,
    1210                     newFolderDialogText, newFolderButtonText,
    1211                     JOptionPane.PLAIN_MESSAGE);
    1212
    1213             if (dirName != null) {
    1214                 if (!currentDirectory.exists()) {
    1215                     JOptionPane.showMessageDialog(fc,
    1216                             MessageFormat.format(newFolderNoDirectoryErrorText, dirName),
    1217                             newFolderNoDirectoryErrorTitleText, JOptionPane.ERROR_MESSAGE);
    1218                     return;
    1219                 }
    1220
    1221                 File newDir = fc.getFileSystemView().createFileObject
    1222                         (currentDirectory, dirName);
    1223                 if (newDir == null || !newDir.mkdir()) {
    1224                     JOptionPane.showMessageDialog(fc,
    1225                             newFolderErrorText + newFolderErrorSeparator + " \"" +
    1226                             dirName + "\"",
    1227                             newFolderErrorText, JOptionPane.ERROR_MESSAGE);
    1228                 }
    1229                 fc.rescanCurrentDirectory();
    1230             }
    1231         }
    1232     }
    1233
    1234     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1235     private class GTKApproveSelectionAction extends ApproveSelectionAction {
    1236         public void actionPerformed(ActionEvent e) {
    1237             if (isDirectorySelected()) {
    1238                 File dir = getDirectory();
    1239                 try {
    1240                     // Strip trailing ".."
    1241                     if (dir != null) {
    1242                         dir = ShellFolder.getNormalizedFile(dir);
    1243                     }
    1244                 } catch (IOException ex) {
    1245                     // Ok, use f as is
    1246                 }
    1247                 if (getFileChooser().getCurrentDirectory().equals(dir)) {
    1248                     directoryList.clearSelection();
    1249                     fileList.clearSelection();
    1250                     ListSelectionModel sm = fileList.getSelectionModel();
    1251                     if (sm instanceof DefaultListSelectionModel) {
    1252                         ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
    1253                         sm.setAnchorSelectionIndex(0);
    1254                     }
    1255                     rescanCurrentDirectory(getFileChooser());
    1256                     return;
    1257                 }
    1258             }
    1259             super.actionPerformed(e);
    1260         }
    1261     }
    1262
    1263     /**
    1264      * Renames file
    1265      */
    1266     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1267     private class RenameFileAction extends AbstractAction {
    1268         protected RenameFileAction() {
    1269             super(FilePane.ACTION_EDIT_FILE_NAME);
    1270         }
    1271         public void actionPerformed(ActionEvent e) {
    1272             if (getFileName().equals("")) {
    1273                 return;
    1274             }
    1275             JFileChooser fc = getFileChooser();
    1276             File currentDirectory = fc.getCurrentDirectory();
    1277             String newFileName = (String) JOptionPane.showInputDialog
    1278                    (fc, new MessageFormat(renameFileDialogText).format
    1279                            (new Object[] { getFileName() }),
    1280                            renameFileButtonText, JOptionPane.PLAIN_MESSAGE, null, null,
    1281                            getFileName());
    1282
    1283             if (newFileName != null) {
    1284                 File oldFile = fc.getFileSystemView().createFileObject
    1285                         (currentDirectory, getFileName());
    1286                 File newFile = fc.getFileSystemView().createFileObject
    1287                         (currentDirectory, newFileName);
    1288                 if (oldFile == null || newFile == null ||
    1289                         !getModel().renameFile(oldFile, newFile)) {
    1290                     JOptionPane.showMessageDialog(fc,
    1291                             new MessageFormat(renameFileErrorText).
    1292                             format(new Object[] { getFileName(), newFileName}),
    1293                             renameFileErrorTitle, JOptionPane.ERROR_MESSAGE);
    1294                 } else {
    1295                     setFileName(getFileChooser().getName(newFile));
    1296                     fc.rescanCurrentDirectory();
    1297                 }
    1298             }
    1299         }
    1300     }
    1301
    1302     //
    1303     // Renderer for Filter ComboBox
    1304     //
    1305     protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
    1306         return new FilterComboBoxRenderer();
    1307     }
    1308
    1309     /**
    1310      * Render different filters
    1311      */
    1312     @SuppressWarnings("serial") // Superclass is not serializable across versions
    1313     public class FilterComboBoxRenderer extends DefaultListCellRenderer {
    1314         public String getName() {
    1315             // As SynthComboBoxRenderer's are asked for a size BEFORE they
    1316             // are parented getName is overriden to force the name to be
    1317             // ComboBox.renderer if it isn't set. If we didn't do this the
    1318             // wrong style could be used for size calculations.
    1319             String name = super.getName();
    1320             if (name == null) {
    1321                 return "ComboBox.renderer";
    1322             }
    1323             return name;
    1324         }
    1325
    1326         public Component getListCellRendererComponent(JList<?> list, Object value,
    1327                                                       int index, boolean isSelected,
    1328                                                       boolean cellHasFocus) {
    1329
    1330             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    1331
    1332             setName("ComboBox.listRenderer");
    1333
    1334             if (value != null) {
    1335                 if (value instanceof FileFilter) {
    1336                     setText(((FileFilter) value).getDescription());
    1337                 }
    1338             } else {
    1339                 setText("");
    1340             }
    1341
    1342             return this;
    1343         }
    1344     }
    1345
    1346     //
    1347     // DataModel for Filter Combobox
    1348     //
    1349     protected FilterComboBoxModel createFilterComboBoxModel() {
    1350         return new FilterComboBoxModel();
    1351     }
    1352
    1353     /**
    1354      * Data model for filter combo-box.
    1355      */
    1356     @SuppressWarnings("serial") // JDK implementation class
    1357     protected class FilterComboBoxModel extends AbstractListModel<FileFilter>
    1358             implements ComboBoxModel<FileFilter>, PropertyChangeListener {
    1359         protected FileFilter[] filters;
    1360
    1361         protected FilterComboBoxModel() {
    1362             super();
    1363             filters = getFileChooser().getChoosableFileFilters();
    1364         }
    1365
    1366         public void propertyChange(PropertyChangeEvent e) {
    1367             String prop = e.getPropertyName();
    1368             if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
    1369                 filters = (FileFilter[]) e.getNewValue();
    1370                 fireContentsChanged(this, -1, -1);
    1371             } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
    1372                 fireContentsChanged(this, -1, -1);
    1373             }
    1374         }
    1375
    1376         public void setSelectedItem(FileFilter filter) {
    1377             if (filter != null) {
    1378                 getFileChooser().setFileFilter(filter);
    1379                 fireContentsChanged(this, -1, -1);
    1380             }
    1381         }
    1382
    1383         public FileFilter getSelectedItem() {
    1384             // Ensure that the current filter is in the list.
    1385             // NOTE: we shouldnt' have to do this, since JFileChooser adds
    1386             // the filter to the choosable filters list when the filter
    1387             // is set. Lets be paranoid just in case someone overrides
    1388             // setFileFilter in JFileChooser.
    1389             FileFilter currentFilter = getFileChooser().getFileFilter();
    1390             boolean found = false;
    1391             if (currentFilter != null) {
    1392                 for (FileFilter filter : filters) {
    1393                     if (filter == currentFilter) {
    1394                         found = true;
    1395                     }
    1396                 }
    1397                 if (found == false) {
    1398                     getFileChooser().addChoosableFileFilter(currentFilter);
    1399                 }
    1400             }
    1401             return getFileChooser().getFileFilter();
    1402         }
    1403
    1404         public int getSize() {
    1405             if (filters != null) {
    1406                 return filters.length;
    1407             } else {
    1408                 return 0;
    1409             }
    1410         }
    1411
    1412         @Override
    1413         public FileFilter getElementAt(int index) {
    1414             if (index > getSize() - 1) {
    1415                 // This shouldn't happen. Try to recover gracefully.
    1416                 return getFileChooser().getFileFilter();
    1417             }
    1418             if (filters != null) {
    1419                 return filters[index];
    1420             } else {
    1421                 return null;
    1422             }
    1423         }
    1424     }
    1425 }
    --- EOF ---