Package com.sun.java.swing.plaf.windows

Source Code of com.sun.java.swing.plaf.windows.WindowsFileChooserUI$WindowsFileView

/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
*/

/*
* @(#)WindowsFileChooserUI.java        1.82 08/09/23
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

package com.sun.java.swing.plaf.windows;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.table.*;
import javax.swing.text.Position;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;

import sun.awt.shell.ShellFolder;

/**
* Windows L&F implementation of a FileChooser.
*
* @version 1.82 09/23/08
* @author Jeff Dinkins
*/
public class WindowsFileChooserUI extends BasicFileChooserUI {

    // The following are private because the implementation of the
    // Windows FileChooser L&F is not complete yet.

    private static final String[] OS_NAMES =
                new String[] { "Windows 3.1", "Windows 95", "Windows NT",
                               "Windows 98", "Windows 2000", "Windows Me", "Windows XP" };
    private static int WIN_31 = 0;
    private static int WIN_95 = 1;
    private static int WIN_NT = 2;
    private static int WIN_98 = 3;
    private static int WIN_2k = 4;
    private static int WIN_Me = 5;
    private static int WIN_XP = 6;

    private static final int OS_LEVEL = getOsLevel();

    private static int getOsLevel() {
        String osName = System.getProperty("os.name");
        if (osName.equals(OS_NAMES[WIN_98]) &&
            System.getProperty("os.version").startsWith("4.9")) {
            return WIN_Me;
        }
        int level = OS_NAMES.length;
        while (level-- > 0)
         if (osName.equals(OS_NAMES[level]))
          return level;
        return WIN_2k;
    }

    private JPanel centerPanel;

    private JLabel lookInLabel;
    private JComboBox directoryComboBox;
    private DirectoryComboBoxModel directoryComboBoxModel;
    private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();

    private FilterComboBoxModel filterComboBoxModel;

    private JTextField filenameTextField;
    private ShortCutPanel shortCutPanel;
    private JToggleButton listViewButton;
    private JToggleButton detailsViewButton;
    private JPanel listViewPanel;
    private JPanel detailsViewPanel;
    private JPanel currentViewPanel;
    private FocusListener editorFocusListener = new FocusAdapter() {
        public void focusLost(FocusEvent e) {
            if (! e.isTemporary()) {
                applyEdit();
            }
        }
    };
    private boolean smallIconsView = false;
    private Border listViewBorder;
    private boolean useShellFolder;

    private ListSelectionModel listSelectionModel;
    private JList list;
    private JTable detailsTable;

    private JButton approveButton;
    private JButton cancelButton;

    private JPanel buttonPanel;
    private JPanel bottomPanel;

    private JComboBox filterComboBox;

    private static final Dimension hstrut10 = new Dimension(10, 1);
    private static final Dimension hstrut25 = new Dimension(25, 1);

    private static final Dimension vstrut1  = new Dimension(1, 1);
    private static final Dimension vstrut4  = new Dimension(1, 4);
    private static final Dimension vstrut5  = new Dimension(1, 5);
    private static final Dimension vstrut6  = new Dimension(1, 6);
    private static final Dimension vstrut8  = new Dimension(1, 8);

    private static final Insets shrinkwrap = new Insets(0,0,0,0);

    // Preferred and Minimum sizes for the dialog box
    private static int PREF_WIDTH = 425;
    private static int PREF_HEIGHT = 245;
    private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);

    private static int MIN_WIDTH = 425;
    private static int MIN_HEIGHT = 245;
    private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);

    private static int LIST_PREF_WIDTH = 444;
    private static int LIST_PREF_HEIGHT = 138;
    private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);

    private static final int COLUMN_FILENAME = 0;
    private static final int COLUMN_FILESIZE = 1;
    private static final int COLUMN_FILETYPE = 2;
    private static final int COLUMN_FILEDATE = 3;
    private static final int COLUMN_FILEATTR = 4;
    private static final int COLUMN_COLCOUNT = 5;

    private int[] COLUMN_WIDTHS = { 1507513013040 };

    // Labels, mnemonics, and tooltips (oh my!)
    private int    lookInLabelMnemonic = 0;
    private String lookInLabelText = null;
    private String saveInLabelText = null;

    private int    fileNameLabelMnemonic = 0;
    private String fileNameLabelText = null;

    private int    filesOfTypeLabelMnemonic = 0;
    private String filesOfTypeLabelText = null;

    private String upFolderToolTipText = null;
    private String upFolderAccessibleName = null;

    private String homeFolderToolTipText = null;
    private String homeFolderAccessibleName = null;

    private String newFolderToolTipText = null;
    private String newFolderAccessibleName = null;

    private String listViewButtonToolTipText = null;
    private String listViewButtonAccessibleName = null;

    private String detailsViewButtonToolTipText = null;
    private String detailsViewButtonAccessibleName = null;

    private String fileNameHeaderText = null;
    private String fileSizeHeaderText = null;
    private String fileTypeHeaderText = null;
    private String fileDateHeaderText = null;
    private String fileAttrHeaderText = null;

    private Action newFolderAction = new WindowsNewFolderAction();
    private File newFolderFile;
    private BasicFileView fileView = new WindowsFileView();

    //
    // ComponentUI Interface Implementation methods
    //
    public static ComponentUI createUI(JComponent c) {
        return new WindowsFileChooserUI((JFileChooser) c);
    }

    public WindowsFileChooserUI(JFileChooser filechooser) {
        super(filechooser);
    }

    public void installUI(JComponent c) {
        super.installUI(c);
    }

    public void uninstallComponents(JFileChooser fc) {
        fc.removeAll();
    }

    public void installComponents(JFileChooser fc) {
        FileSystemView fsv = fc.getFileSystemView();
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            listViewBorder = xp.getBorder("listview");
        } else {
            listViewBorder = new BevelBorder(BevelBorder.LOWERED,
                                             UIManager.getColor("ToolBar.highlight"),
                                             UIManager.getColor("ToolBar.background"),
                                             UIManager.getColor("ToolBar.darkShadow"),
                                             UIManager.getColor("ToolBar.shadow"));
        }

        fc.setBorder(new EmptyBorder(4, 10, 10, 10));
        fc.setLayout(new BorderLayout(8, 8));

        // ********************************* //
        // **** Construct the top panel **** //
        // ********************************* //

        // Directory manipulation buttons
        JToolBar topPanel = new JToolBar();
        topPanel.setFloatable(false);
        if (OS_LEVEL >= WIN_2k) {
            topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
        }

        // Add the top panel to the fileChooser
        fc.add(topPanel, BorderLayout.NORTH);

        // ComboBox Label
        lookInLabel = new JLabel(lookInLabelText);
        lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
        lookInLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        lookInLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        topPanel.add(Box.createRigidArea(new Dimension(14,0)));
        topPanel.add(lookInLabel);
        topPanel.add(Box.createRigidArea(new Dimension(29,0)));

        // CurrentDir ComboBox
        directoryComboBox = new JComboBox();
        directoryComboBox.putClientProperty( "JComboBox.lightweightKeyboardNavigation", "Lightweight" );
        lookInLabel.setLabelFor(directoryComboBox);
        directoryComboBoxModel = createDirectoryComboBoxModel(fc);
        directoryComboBox.setModel(directoryComboBoxModel);
        directoryComboBox.addActionListener(directoryComboBoxAction);
        directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
        directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        directoryComboBox.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        directoryComboBox.setMaximumRowCount(8);

        topPanel.add(directoryComboBox);
        topPanel.add(Box.createRigidArea(hstrut10));

        // Up Button
        JButton upFolderButton = new JButton(getChangeToParentDirectoryAction());
        upFolderButton.setText(null);
        upFolderButton.setIcon(upFolderIcon);
        upFolderButton.setToolTipText(upFolderToolTipText);
        upFolderButton.getAccessibleContext().setAccessibleName(upFolderAccessibleName);
        upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        upFolderButton.setMargin(shrinkwrap);
        upFolderButton.setFocusPainted(false);
        topPanel.add(upFolderButton);
        if (OS_LEVEL < WIN_2k) {
            topPanel.add(Box.createRigidArea(hstrut10));
        }

        JButton b;

        if (OS_LEVEL == WIN_98) {
            // Desktop Button
            File homeDir = fsv.getHomeDirectory();
            String toolTipText = homeFolderToolTipText;
            if (fsv.isRoot(homeDir)) {
                toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop".
            }
            b = new JButton(getFileView(fc).getIcon(homeDir));
            b.setToolTipText(toolTipText);
            b.getAccessibleContext().setAccessibleName(toolTipText);
            b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
            b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
            b.setMargin(shrinkwrap);
            b.setFocusPainted(false);
            b.addActionListener(getGoHomeAction());
            topPanel.add(b);
            topPanel.add(Box.createRigidArea(hstrut10));
        }

        // New Directory Button
        b = new JButton(getNewFolderAction());
        b.setText(null);
        b.setIcon(newFolderIcon);
        b.setToolTipText(newFolderToolTipText);
        b.getAccessibleContext().setAccessibleName(newFolderAccessibleName);
        b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        b.setMargin(shrinkwrap);
        b.setFocusPainted(false);
        topPanel.add(b);
        if (OS_LEVEL < WIN_2k) {
            topPanel.add(Box.createRigidArea(hstrut10));
        }

        // View button group
        ButtonGroup viewButtonGroup = new ButtonGroup();

        class ViewButtonListener implements ActionListener {
            JFileChooser fc;

            ViewButtonListener(JFileChooser fc) {
                this.fc = fc;
            }

            public void actionPerformed(ActionEvent e) {
                JToggleButton b = (JToggleButton)e.getSource();
                JPanel oldViewPanel = currentViewPanel;

                if (b == detailsViewButton) {
                    if (detailsViewPanel == null) {
                        detailsViewPanel = createDetailsView(fc);
                        detailsViewPanel.setPreferredSize(LIST_PREF_SIZE);
                    }
                    currentViewPanel = detailsViewPanel;
                } else {
                    currentViewPanel = listViewPanel;
                }
                if (currentViewPanel != oldViewPanel) {
                    centerPanel.remove(oldViewPanel);
                    centerPanel.add(currentViewPanel, BorderLayout.CENTER);
                    centerPanel.revalidate();
                    centerPanel.repaint();
                }
            }
        }

        ViewButtonListener viewButtonListener = new ViewButtonListener(fc);

        // List Button
        listViewButton = new JToggleButton(listViewIcon);
        listViewButton.setToolTipText(listViewButtonToolTipText);
        listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName);
        listViewButton.setFocusPainted(false);
        listViewButton.setSelected(true);
        listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        listViewButton.setMargin(shrinkwrap);
        listViewButton.addActionListener(viewButtonListener);
        topPanel.add(listViewButton);
        viewButtonGroup.add(listViewButton);

        // Details Button
        detailsViewButton = new JToggleButton(detailsViewIcon);
        detailsViewButton.setToolTipText(detailsViewButtonToolTipText);
        detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName);
        detailsViewButton.setFocusPainted(false);
        detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
        detailsViewButton.setMargin(shrinkwrap);
        detailsViewButton.addActionListener(viewButtonListener);
        topPanel.add(detailsViewButton);
        viewButtonGroup.add(detailsViewButton);

        updateUseShellFolder();

        // ************************************** //
        // ******* Add the directory pane ******* //
        // ************************************** //
        centerPanel = new JPanel(new BorderLayout());
        listViewPanel = createList(fc);
        listSelectionModel = list.getSelectionModel();
        listViewPanel.setPreferredSize(LIST_PREF_SIZE);
        centerPanel.add(listViewPanel, BorderLayout.CENTER);
        currentViewPanel = listViewPanel;
        centerPanel.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
        JComponent accessory = fc.getAccessory();
        if(accessory != null) {
            getAccessoryPanel().add(accessory);
        }
        fc.add(centerPanel, BorderLayout.CENTER);

        // ********************************** //
        // **** Construct the bottom panel ** //
        // ********************************** //
        getBottomPanel().setLayout(new BoxLayout(getBottomPanel(), BoxLayout.LINE_AXIS));

        // Add the bottom panel to file chooser
        centerPanel.add(getBottomPanel(), BorderLayout.SOUTH);

        // labels
        JPanel labelPanel = new JPanel();
        labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
        labelPanel.add(Box.createRigidArea(vstrut4));

        JLabel fnl = new JLabel(fileNameLabelText);
        fnl.setDisplayedMnemonic(fileNameLabelMnemonic);
        fnl.setAlignmentY(0);
        labelPanel.add(fnl);

        labelPanel.add(Box.createRigidArea(new Dimension(1,12)));

        JLabel ftl = new JLabel(filesOfTypeLabelText);
        ftl.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
        labelPanel.add(ftl);

        getBottomPanel().add(labelPanel);
        getBottomPanel().add(Box.createRigidArea(new Dimension(15, 0)));

        // file entry and filters
        JPanel fileAndFilterPanel = new JPanel();
        fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
        fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel, BoxLayout.Y_AXIS));


        filenameTextField = new JTextField(35) {
            public Dimension getMaximumSize() {
                return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
            }
        };

        fnl.setLabelFor(filenameTextField);
        filenameTextField.addFocusListener(
            new FocusAdapter() {
                public void focusGained(FocusEvent e) {
                    if (!getFileChooser().isMultiSelectionEnabled()) {
                        listSelectionModel.clearSelection();
                    }
                }
            }
        );

        if (fc.isMultiSelectionEnabled()) {
            setFileName(fileNameString(fc.getSelectedFiles()));
        } else {
            setFileName(fileNameString(fc.getSelectedFile()));
        }

        fileAndFilterPanel.add(filenameTextField);
        fileAndFilterPanel.add(Box.createRigidArea(vstrut8));

        filterComboBoxModel = createFilterComboBoxModel();
        fc.addPropertyChangeListener(filterComboBoxModel);
        filterComboBox = new JComboBox(filterComboBoxModel);
        ftl.setLabelFor(filterComboBox);
        filterComboBox.setRenderer(createFilterComboBoxRenderer());
        fileAndFilterPanel.add(filterComboBox);

        getBottomPanel().add(fileAndFilterPanel);
        getBottomPanel().add(Box.createRigidArea(hstrut10));

        // buttons
        getButtonPanel().setLayout(new BoxLayout(getButtonPanel(), BoxLayout.Y_AXIS));

        approveButton = new JButton(getApproveButtonText(fc)) {
            public Dimension getMaximumSize() {
                return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
                       approveButton.getPreferredSize() : cancelButton.getPreferredSize();
            }
        };
        approveButton.setMnemonic(getApproveButtonMnemonic(fc));
        approveButton.addActionListener(getApproveSelectionAction());
        approveButton.setToolTipText(getApproveButtonToolTipText(fc));
        getButtonPanel().add(Box.createRigidArea(vstrut4));
        getButtonPanel().add(approveButton);
        getButtonPanel().add(Box.createRigidArea(vstrut6));

        cancelButton = new JButton(cancelButtonText) {
            public Dimension getMaximumSize() {
                return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
                       approveButton.getPreferredSize() : cancelButton.getPreferredSize();
            }
        };
        cancelButton.setMnemonic(cancelButtonMnemonic);
        cancelButton.setToolTipText(cancelButtonToolTipText);
        cancelButton.addActionListener(getCancelSelectionAction());
        getButtonPanel().add(cancelButton);

        if(fc.getControlButtonsAreShown()) {
            addControlButtons();
        }
    }

    private void updateUseShellFolder() {
        // Decide whether to use the ShellFolder class to populate shortcut
        // panel and combobox.
        JFileChooser fc = getFileChooser();
        Boolean prop =
            (Boolean)fc.getClientProperty("FileChooser.useShellFolder");
        if (prop != null) {
            useShellFolder = prop.booleanValue();
        } else {
            useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView());
        }
        if (OS_LEVEL >= WIN_2k) {
            if (useShellFolder) {
                if (shortCutPanel == null) {
                    shortCutPanel = new ShortCutPanel();
                    fc.add(shortCutPanel, BorderLayout.BEFORE_LINE_BEGINS);
                }
            } else {
                if (shortCutPanel != null) {
                    fc.remove(shortCutPanel);
                    shortCutPanel = null;
                }
            }
        }
    }

    protected JPanel getButtonPanel() {
        if(buttonPanel == null) {
            buttonPanel = new JPanel();
        }
        return buttonPanel;
    }

    protected JPanel getBottomPanel() {
        if(bottomPanel == null) {
            bottomPanel = new JPanel();
        }
        return bottomPanel;
    }

    protected void installStrings(JFileChooser fc) {
        super.installStrings(fc);

        Locale l = fc.getLocale();

        lookInLabelMnemonic = UIManager.getInt("FileChooser.lookInLabelMnemonic");
        lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
        saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);

        fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic");
        fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);

        filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic");
        filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l);

        upFolderToolTipText =  UIManager.getString("FileChooser.upFolderToolTipText",l);
        upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l);

        homeFolderToolTipText =  UIManager.getString("FileChooser.homeFolderToolTipText",l);
        homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l);

        newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);
        newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);

        listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l);
        listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l);

        detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l);
        detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l);


        fileNameHeaderText = UIManager.getString("FileChooser.fileNameHeaderText",l);
        fileSizeHeaderText = UIManager.getString("FileChooser.fileSizeHeaderText",l);
        fileTypeHeaderText = UIManager.getString("FileChooser.fileTypeHeaderText",l);
        fileDateHeaderText = UIManager.getString("FileChooser.fileDateHeaderText",l);
        fileAttrHeaderText = UIManager.getString("FileChooser.fileAttrHeaderText",l);
    }

    protected void installListeners(JFileChooser fc) {
        super.installListeners(fc);
        ActionMap actionMap = getActionMap();
        SwingUtilities.replaceUIActionMap(fc, actionMap);
    }

    protected ActionMap getActionMap() {
        return createActionMap();
    }

    protected ActionMap createActionMap() {
        AbstractAction escAction = new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                if (editFile != null) {
                   cancelEdit();
                } else {
                   getFileChooser().cancelSelection();
                }
            }
            public boolean isEnabled(){
                return getFileChooser().isEnabled();
            }
        };
        ActionMap map = new ActionMapUIResource();
        map.put("approveSelection", getApproveSelectionAction());
        map.put("cancelSelection", escAction);
        map.put("Go Up", getChangeToParentDirectoryAction());
        return map;
    }

    class ShortCutPanel extends JToolBar implements ActionListener {
        JToggleButton[] buttons;
        File[] files;
        XPStyle xp = XPStyle.getXP();
        final Dimension buttonSize = new Dimension(83, (xp != null) ? 69 : 54);

        ShortCutPanel() {
            super(JToolBar.VERTICAL);
            setFloatable(false);
            putClientProperty("JToolBar.isRollover", Boolean.TRUE);
            if (xp != null) {
                putClientProperty("XPStyle.subClass", "placesbar");
                setBorder(new EmptyBorder(1, 1, 1, 1));
            } else {
                setBorder(listViewBorder);
            }
            Color bgColor = new Color(UIManager.getColor("ToolBar.shadow").getRGB());
            setBackground(bgColor);
            JFileChooser chooser = getFileChooser();
            FileSystemView fsv = chooser.getFileSystemView();

            files = (File[])ShellFolder.get("fileChooserShortcutPanelFolders");
            buttons = new JToggleButton[files.length];
            ButtonGroup buttonGroup = new ButtonGroup();
            for (int i = 0; i < files.length; i++) {
                if (fsv.isFileSystemRoot(files[i])) {
                    // Create special File wrapper for drive path
                    files[i] = fsv.createFileObject(files[i].getAbsolutePath());
                }

                String folderName = fsv.getSystemDisplayName(files[i]);
                int index = folderName.lastIndexOf(File.separatorChar);
                if (index >= 0 && index < folderName.length() - 1) {
                    folderName = folderName.substring(index + 1);
                }
                Icon icon = null;
                if (files[i] instanceof ShellFolder) {
                    // We want a large icon, fsv only gives us a small.
                    ShellFolder sf = (ShellFolder)files[i];
                    icon = new ImageIcon(sf.getIcon(true), sf.getFolderType());
                } else {
                    icon = fsv.getSystemIcon(files[i]);
                }
                buttons[i] = new JToggleButton(folderName, icon);
                if (xp != null) {
                    buttons[i].setIconTextGap(2);
                    buttons[i].setMargin(new Insets(2, 2, 2, 2));
                    buttons[i].setText("<html><center>"+folderName+"</center></html>");
                } else {
                    Color fgColor = new Color(UIManager.getColor("List.selectionForeground").getRGB());
                    buttons[i].setBackground(bgColor);
                    buttons[i].setForeground(fgColor);
                }
                buttons[i].setHorizontalTextPosition(JToggleButton.CENTER);
                buttons[i].setVerticalTextPosition(JToggleButton.BOTTOM);
                buttons[i].setAlignmentX(JComponent.CENTER_ALIGNMENT);
                buttons[i].setPreferredSize(buttonSize);
                buttons[i].setMaximumSize(buttonSize);
                buttons[i].addActionListener(this);
                add(buttons[i]);
                if (i < files.length-1 && xp != null) {
                    add(Box.createRigidArea(vstrut1));
                }
                buttonGroup.add(buttons[i]);
            }
            doDirectoryChanged(chooser.getCurrentDirectory());
        }

        void doDirectoryChanged(File f) {
            for (int i=0; i<buttons.length; i++) {
                buttons[i].setSelected(files[i].equals(f));
            }
        }

        public void actionPerformed(ActionEvent e) {
            JToggleButton b = (JToggleButton)e.getSource();
            for (int i=0; i<buttons.length; i++) {
                if (b == buttons[i]) {
                    getFileChooser().setCurrentDirectory(files[i]);
                    break;
                }
            }
        }

        public Dimension getPreferredSize() {
            Dimension min  = super.getMinimumSize();
            Dimension pref = super.getPreferredSize();
            if (min.height > pref.height) {
                pref = new Dimension(pref.width, min.height);
            }
            return pref;
        }
    } // class ShortCutPanel


    private void updateListRowCount() {
        if (smallIconsView) {
            list.setVisibleRowCount(getModel().getSize() / 3);
        } else {
            list.setVisibleRowCount(-1);
        }
    }

    protected JPanel createList(JFileChooser fc) {
        JPanel p = new JPanel(new BorderLayout());
        final JFileChooser fileChooser = fc;
        list = new JList() {
            public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
                ListModel model = getModel();
                int max = model.getSize();
                if (prefix == null || startIndex < 0 || startIndex >= max) {
                    throw new IllegalArgumentException();
                }
                // start search from the next element before/after the selected element
                boolean backwards = (bias == Position.Bias.Backward);
                for (int i = startIndex; backwards ? i >= 0 : i < max; i += (backwards ?  -1 : 1)) {
                    String filename = fileChooser.getName((File)model.getElementAt(i));
                    if (filename.regionMatches(true, 0, prefix, 0, prefix.length())) {
                        return i;
                    }
                }
                return -1;
            }
        };
        list.setCellRenderer(new FileRenderer());
        list.setLayoutOrientation(JList.VERTICAL_WRAP);

        updateListRowCount();

        getModel().addListDataListener(new ListDataListener() {
            public void intervalAdded(ListDataEvent e) {
                updateListRowCount();
            }
            public void intervalRemoved(ListDataEvent e) {
                updateListRowCount();
            }
            public void contentsChanged(ListDataEvent e) {
                updateListRowCount();
            }
        });

        if (fc.isMultiSelectionEnabled()) {
            list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        } else {
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        }
        list.setModel(getModel());
        list.addListSelectionListener(createListSelectionListener(fc));
        list.addMouseListener(createDoubleClickListener(fc, list));
        list.addMouseListener(createSingleClickListener(fc, list));
        getModel().addListDataListener(new ListDataListener() {
            public void contentsChanged(ListDataEvent e) {
                // Update the selection after JList has been updated
                new DelayedSelectionUpdater();
            }
            public void intervalAdded(ListDataEvent e) {
                int i0 = e.getIndex0();
                int i1 = e.getIndex1();
                if (i0 == i1) {
                    File file = (File)getModel().getElementAt(i0);
                    if (file.equals(newFolderFile)) {
                        new DelayedSelectionUpdater(file);
                        newFolderFile = null;
                    }
                }
            }
            public void intervalRemoved(ListDataEvent e) {
            }
        });

        JScrollPane scrollpane = new JScrollPane(list);
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            Color bg = xp.getColor("listview.fillcolor", null);
            if (bg != null) {
                list.setBackground(bg);
            }
        }
        if (listViewBorder != null) {
            scrollpane.setBorder(listViewBorder);
        }
        p.add(scrollpane, BorderLayout.CENTER);
        return p;
    }

    class DetailsTableModel extends AbstractTableModel implements ListDataListener {
        String[] columnNames = {
            fileNameHeaderText,
            fileSizeHeaderText,
            fileTypeHeaderText,
            fileDateHeaderText,
            fileAttrHeaderText
        };
        JFileChooser chooser;
        ListModel listModel;

        DetailsTableModel(JFileChooser fc) {
            this.chooser = fc;
            listModel = getModel();
            listModel.addListDataListener(this);
        }

        public int getRowCount() {
            return listModel.getSize();
        }

        public int getColumnCount() {
            return COLUMN_COLCOUNT;
        }

        public String getColumnName(int column) {
            return columnNames[column];
        }

        public Class getColumnClass(int column) {
            switch (column) {
              case COLUMN_FILENAME:
                  return File.class;
              case COLUMN_FILEDATE:
                  return Date.class;
              default:
                  return super.getColumnClass(column);
            }
        }

        public Object getValueAt(int row, int col) {
            // Note: It is very important to avoid getting info on drives, as
            // this will trigger "No disk in A:" and similar dialogs.
            //
            // Use (f.exists() && !chooser.getFileSystemView().isFileSystemRoot(f)) to
            // determine if it is safe to call methods directly on f.

            File f = (File)listModel.getElementAt(row);
            switch (col) {
              case COLUMN_FILENAME:
                  return f;

              case COLUMN_FILESIZE:
                  if (!f.exists() || f.isDirectory()) {
                      return null;
                  }
                  return (f.length() + 1023) / 1024 + "KiB";

              case COLUMN_FILETYPE:
                  if (!f.exists()) {
                      return null;
                  }
                  return chooser.getFileSystemView().getSystemTypeDescription(f);

              case COLUMN_FILEDATE:
                  if (!f.exists() || chooser.getFileSystemView().isFileSystemRoot(f)) {
                      return null;
                  }
                  long time = f.lastModified();
                  return (time == 0L) ? null : new Date(time);

              case COLUMN_FILEATTR:
                  if (!f.exists() || chooser.getFileSystemView().isFileSystemRoot(f)) {
                      return null;
                  }
                  String attributes = "";
                  if (!f.canWrite()) {
                      attributes += "R";
                  }
                  if (f.isHidden()) {
                      attributes += "H";
                  }
                  return attributes;
            }
            return null;
        }

        public void setValueAt(Object value, int row, int col) {
            if (col == COLUMN_FILENAME) {
                JFileChooser chooser = getFileChooser();
                File f = (File)getValueAt(row, col);
                String oldDisplayName = chooser.getName(f);
                String oldFileName = f.getName();
                String newDisplayName = ((String)value).trim();
                String newFileName;

                if (!newDisplayName.equals(oldDisplayName)) {
                    newFileName = newDisplayName;
                    //Check if extension is hidden from user
                    int i1 = oldFileName.length();
                    int i2 = oldDisplayName.length();
                    if (i1 > i2 && oldFileName.charAt(i2) == '.') {
                        newFileName = newDisplayName + oldFileName.substring(i2);
                    }

                    // rename
                    FileSystemView fsv = chooser.getFileSystemView();
                    File f2 = fsv.createFileObject(f.getParentFile(), newFileName);
                    if (!f2.exists() && WindowsFileChooserUI.this.getModel().renameFile(f, f2)) {
                        if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
                            if (chooser.isMultiSelectionEnabled()) {
                                chooser.setSelectedFiles(new File[] { f2 });
                            } else {
                                chooser.setSelectedFile(f2);
                            }
                        } else {
                            //Could be because of delay in updating Desktop folder
                            //chooser.setSelectedFile(null);
                        }
                    } else {
                        // PENDING(jeff) - show a dialog indicating failure
                    }
                }
            }
        }

        public boolean isCellEditable(int row, int column) {
            return (column == COLUMN_FILENAME);
        }

        public void contentsChanged(ListDataEvent e) {
            fireTableDataChanged();
        }
        public void intervalAdded(ListDataEvent e) {
            fireTableDataChanged();
        }
        public void intervalRemoved(ListDataEvent e) {
            fireTableDataChanged();
        }
    }

    class DetailsTableCellRenderer extends DefaultTableCellRenderer {
        JFileChooser chooser;
        DateFormat df;

        DetailsTableCellRenderer(JFileChooser chooser) {
            this.chooser = chooser;
            df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT,
                                                chooser.getLocale());
        }

        public void setBounds(int x, int y, int width, int height) {
            super.setBounds(x, y, Math.min(width, this.getPreferredSize().width+4), height);
        }

        public Component getTableCellRendererComponent(JTable table, Object value,
                              boolean isSelected, boolean hasFocus, int row, int column) {

            if (column == COLUMN_FILESIZE || column == COLUMN_FILEATTR) {
                setHorizontalAlignment(SwingConstants.TRAILING);
            } else {
                setHorizontalAlignment(SwingConstants.LEADING);
            }

            if (column == COLUMN_FILENAME && table.isRowSelected(row) && table.isFocusOwner()) {
                super.setForeground(table.getSelectionForeground());
                super.setBackground(table.getSelectionBackground());
            } else {
                super.setForeground(table.getForeground());
                super.setBackground(table.getBackground());
            }
            setFont(table.getFont());
            setValue(value);

            return this;
        }

        public void setValue(Object value) {
            setIcon(null);
            if (value instanceof File) {
                File file = (File)value;
                String fileName = chooser.getName(file);
                setText(fileName);
                Icon icon = chooser.getIcon(file);
                setIcon(icon);
            } else if (value instanceof Date) {
                setText((value == null) ? "" : df.format((Date)value));
            } else {
                super.setValue(value);
            }
        }
    }

    protected JPanel createDetailsView(JFileChooser fc) {
        final JFileChooser chooser = fc;
        JPanel p = new JPanel(new BorderLayout());

        DetailsTableModel detailsTableModel = new DetailsTableModel(chooser);

        detailsTable = new JTable(detailsTableModel) {
            // Handle Escape key events here
            protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE && getCellEditor() == null) {
                    // We are not editing, forward to filechooser.
                    chooser.dispatchEvent(e);
                    return true;
                }

                return super.processKeyBinding(ks, e, condition, pressed);
            }
        };

        detailsTable.setComponentOrientation(chooser.getComponentOrientation());
        detailsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        detailsTable.setShowGrid(false);
        detailsTable.setSelectionModel(listSelectionModel);
        detailsTable.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);

        Font font = detailsTable.getFont();
        detailsTable.setRowHeight(Math.max(font.getSize(), 19)+3);

        TableColumnModel columnModel = detailsTable.getColumnModel();
        TableColumn[] columns = new TableColumn[COLUMN_COLCOUNT];

        for (int i = 0; i < COLUMN_COLCOUNT; i++) {
            columns[i] = columnModel.getColumn(i);
            columns[i].setPreferredWidth(COLUMN_WIDTHS[i]);
        }

        TableCellRenderer cellRenderer = new DetailsTableCellRenderer(chooser);
        detailsTable.setDefaultRenderer(File.class, cellRenderer);
        detailsTable.setDefaultRenderer(Date.class, cellRenderer);
        detailsTable.setDefaultRenderer(Object.class, cellRenderer);

        // Install cell editor for editing file name
        final JTextField tf = new JTextField();
        tf.addFocusListener(editorFocusListener);
        columns[COLUMN_FILENAME].setCellEditor(new DefaultCellEditor(tf) {
            public boolean isCellEditable(EventObject e) {
                if (e instanceof MouseEvent) {
                    MouseEvent me = (MouseEvent)e;
                    int index = detailsTable.rowAtPoint(me.getPoint());
                    return (me.getClickCount() == 1 && detailsTable.isRowSelected(index));
                }
                return super.isCellEditable(e);
            }

            public Component getTableCellEditorComponent(JTable table, Object value,
                                                         boolean isSelected, int row, int column) {
                Component comp = super.getTableCellEditorComponent(table, value, isSelected, row, column);
                if (value instanceof File) {
                    tf.setText(chooser.getName((File)value));
                    tf.requestFocus();
                    tf.selectAll();
                }
                return comp;
            }
        });

        JList fakeList = new JList(detailsTableModel.listModel) {
            JTable table = detailsTable;

            public int locationToIndex(Point location) {
                return table.rowAtPoint(location);
            }

            public Rectangle getCellBounds(int index0, int index1) {
                Rectangle r0 = table.getCellRect(index0, COLUMN_FILENAME, false);
                Rectangle r1 = table.getCellRect(index1, COLUMN_FILENAME, false);
                return r0.union(r1);
            }

            public Object getSelectedValue() {
                return table.getValueAt(table.getSelectedRow(), COLUMN_FILENAME);
            }

            public Component add(Component comp) {
                if (comp instanceof JTextField) {
                    return table.add(comp);
                } else {
                    return super.add(comp);
                }
            }

            public void repaint() {
                if (table != null)
                    table.repaint();
            }

            public TransferHandler getTransferHandler() {
                if (table != null) {
                    return table.getTransferHandler();
                } else {
                    return super.getTransferHandler();
                }
            }

            public void setTransferHandler(TransferHandler newHandler) {
                if (table != null) {
                    table.setTransferHandler(newHandler);
                } else {
                    super.setTransferHandler(newHandler);
                }
            }

            public boolean getDragEnabled() {
                if (table != null) {
                    return table.getDragEnabled();
                } else {
                    return super.getDragEnabled();
                }
            }

            public void setDragEnabled(boolean b) {
                if (table != null) {
                    table.setDragEnabled(b);
                } else {
                    super.setDragEnabled(b);
                }
            }
        };

        fakeList.setSelectionModel(listSelectionModel);
        detailsTable.addMouseListener(createDoubleClickListener(chooser, fakeList));
        //detailsTable.addMouseListener(createSingleClickListener(chooser, fakeList));

        JScrollPane scrollpane = new JScrollPane(detailsTable);
        scrollpane.setComponentOrientation(chooser.getComponentOrientation());
        LookAndFeel.installColors(scrollpane.getViewport(), "Table.background", "Table.foreground");

        scrollpane.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                JScrollPane sp = (JScrollPane)e.getComponent();
                fixNameColumnWidth(sp.getViewport().getSize().width);
                sp.removeComponentListener(this);
            }
        });

        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            Color bg = xp.getColor("listview.fillcolor", null);
            if (bg != null) {
                list.setBackground(bg);
            }
        }
        if (listViewBorder != null) {
            scrollpane.setBorder(listViewBorder);
        }
        p.add(scrollpane, BorderLayout.CENTER);
        return p;
    }

    private void fixNameColumnWidth(int viewWidth) {
        TableColumn nameCol = detailsTable.getColumnModel().getColumn(COLUMN_FILENAME);
        int tableWidth = detailsTable.getPreferredSize().width;

        if (tableWidth < viewWidth) {
            nameCol.setPreferredWidth(nameCol.getPreferredWidth() + viewWidth - tableWidth);
        }
    }

    private class DelayedSelectionUpdater implements Runnable {
        File editFile;

        DelayedSelectionUpdater() {
            this(null);
        }

        DelayedSelectionUpdater(File editFile) {
            this.editFile = editFile;
            SwingUtilities.invokeLater(this);
        }

        public void run() {
            setFileSelected();
            if (editFile != null) {
                editFileName(getModel().indexOf(editFile));
                editFile = null;
            }
        }
    }


    /**
     * Creates a selection listener for the list of files and directories.
     *
     * @param fc a <code>JFileChooser</code>
     * @return a <code>ListSelectionListener</code>
     */
    public ListSelectionListener createListSelectionListener(JFileChooser fc) {
        return new SelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (!e.getValueIsAdjusting()) {
                    JFileChooser chooser = getFileChooser();
                    FileSystemView fsv = chooser.getFileSystemView();
                    JList list = (JList) e.getSource();

                    if (chooser.isMultiSelectionEnabled()) {
                        File[] files = null;
                        Object[] objects = list.getSelectedValues();
                        if (objects != null) {
                            if (objects.length == 1
                                && ((File)objects[0]).isDirectory()
                                && chooser.isTraversable(((File)objects[0]))
                                && (chooser.getFileSelectionMode() == chooser.FILES_ONLY
                                    || !fsv.isFileSystem(((File)objects[0])))) {
                                setDirectorySelected(true);
                                setDirectory(((File)objects[0]));
                            } else {
                                files = new File[objects.length];
                                int j = 0;
                                for (int i = 0; i < objects.length; i++) {
                                    File f = (File)objects[i];
                                    boolean isDir = f.isDirectory();
                                    boolean isFile = ShellFolder.disableFileChooserSpeedFix() ? f.isFile() : !isDir;
                                    if ((chooser.isFileSelectionEnabled() && isFile)
                                        || (chooser.isDirectorySelectionEnabled()
                                            && fsv.isFileSystem(f)
                                            && isDir)) {
                                        files[j++] = f;
                                    }
                                }
                                if (j == 0) {
                                    files = null;
                                } else if (j < objects.length) {
                                    File[] tmpFiles = new File[j];
                                    System.arraycopy(files, 0, tmpFiles, 0, j);
                                    files = tmpFiles;
                                }
                                setDirectorySelected(false);
                            }
                        }
                        chooser.setSelectedFiles(files);
                    } else {
                        File file = (File)list.getSelectedValue();
                        if (file != null
                            && file.isDirectory()
                            && chooser.isTraversable(file)
                            && (chooser.getFileSelectionMode() == chooser.FILES_ONLY
                                || !fsv.isFileSystem(file))) {

                            setDirectorySelected(true);
                            setDirectory(file);
                            chooser.setSelectedFile(null);
                        } else {
                            setDirectorySelected(false);

                            if (file != null) {
                               chooser.setSelectedFile(file);
                            }
                        }
                    }
                }
            }
        };
    }

    private MouseListener createSingleClickListener(JFileChooser fc, JList list) {
        return new SingleClickListener(list);
    }

    int lastIndex = -1;
    File editFile = null;
    int editX = 20;

    private int getEditIndex() {
        return lastIndex;
    }

    private void setEditIndex(int i) {
        lastIndex = i;
    }

    private void resetEditIndex() {
        lastIndex = -1;
    }

    private void cancelEdit() {
        if (editFile != null) {
            editFile = null;
            list.remove(editCell);
            centerPanel.repaint();
        } else if (detailsTable != null && detailsTable.isEditing()) {
            detailsTable.getCellEditor().cancelCellEditing();
        }
    }

    JTextField editCell = null;

    private void editFileName(int index) {
        ensureIndexIsVisible(index);
        if (listViewPanel.isVisible()) {
            editFile = (File)getModel().getElementAt(index);
            Rectangle r = list.getCellBounds(index, index);
            if (editCell == null) {
                editCell = new JTextField();
                editCell.addActionListener(new EditActionListener());
                editCell.addFocusListener(editorFocusListener);
                editCell.setNextFocusableComponent(list);
            }
            list.add(editCell);
            editCell.setText(getFileChooser().getName(editFile));
            if (list.getComponentOrientation().isLeftToRight()) {
                editCell.setBounds(editX + r.x, r.y, r.width - editX, r.height);
            } else {
                editCell.setBounds(r.x, r.y, r.width - editX, r.height);
            }
            editCell.requestFocus();
            editCell.selectAll();
        } else if (detailsViewPanel.isVisible()) {
            detailsTable.editCellAt(index, COLUMN_FILENAME);
        }
    }


    protected class SingleClickListener extends MouseAdapter {
        JList list;

        public  SingleClickListener(JList list) {
            this.list = list;
        }

        public void mouseClicked(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                if (e.getClickCount() == 1) {
                    JFileChooser fc = getFileChooser();
                    int index = list.locationToIndex(e.getPoint());
                    if ((!fc.isMultiSelectionEnabled() || fc.getSelectedFiles().length <= 1)
                        && index >= 0 && list.isSelectedIndex(index)
                        && getEditIndex() == index && editFile == null) {

                        editFileName(index);
                    } else {
                        if (index >= 0) {
                            setEditIndex(index);
                        } else {
                            resetEditIndex();
                        }
                    }
                } else {
                    // on double click (open or drill down one directory) be
                    // sure to clear the edit index
                    resetEditIndex();
                }
            }
        }
    }

    public Action getNewFolderAction() {
        return newFolderAction;
    }

    /**
     * Creates a new folder.
     */
    protected class WindowsNewFolderAction extends NewFolderAction {
        public void actionPerformed(ActionEvent e) {
            JFileChooser fc = getFileChooser();
            File oldFile = fc.getSelectedFile();
            super.actionPerformed(e);
            File newFile = fc.getSelectedFile();
            if (newFile != null && !newFile.equals(oldFile) && newFile.isDirectory()) {
                newFolderFile = newFile;
            }
        }
    }

    class EditActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            applyEdit();
        }
    }

    private void applyEdit() {
        if (editFile != null && editFile.exists()) {
            JFileChooser chooser = getFileChooser();
            String oldDisplayName = chooser.getName(editFile);
            String oldFileName = editFile.getName();
            String newDisplayName = editCell.getText().trim();
            String newFileName;

            if (!newDisplayName.equals(oldDisplayName)) {
                newFileName = newDisplayName;
                //Check if extension is hidden from user
                int i1 = oldFileName.length();
                int i2 = oldDisplayName.length();
                if (i1 > i2 && oldFileName.charAt(i2) == '.') {
                    newFileName = newDisplayName + oldFileName.substring(i2);
                }

                // rename
                FileSystemView fsv = chooser.getFileSystemView();
                File f2 = fsv.createFileObject(editFile.getParentFile(), newFileName);
                if (!f2.exists() && getModel().renameFile(editFile, f2)) {
                    if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
                        if (chooser.isMultiSelectionEnabled()) {
                            chooser.setSelectedFiles(new File[] { f2 });
                        } else {
                            chooser.setSelectedFile(f2);
                        }
                    } else {
                        //Could be because of delay in updating Desktop folder
                        //chooser.setSelectedFile(null);
                    }
                } else {
                    // PENDING(jeff) - show a dialog indicating failure
                }
            }
        }
        if (detailsTable != null && detailsTable.isEditing()) {
            detailsTable.getCellEditor().stopCellEditing();
        }
        cancelEdit();
    }

    protected class FileRenderer extends DefaultListCellRenderer  {

        public void setBounds(int x, int y, int width, int height) {
            super.setBounds(x, y, Math.min(width, this.getPreferredSize().width+4), height);
        }

        public Component getListCellRendererComponent(JList list, Object value,
                                                      int index, boolean isSelected,
                                                      boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            File file = (File) value;
            String fileName = getFileChooser().getName(file);
            setText(fileName);

            Icon icon = getFileChooser().getIcon(file);
            setIcon(icon);

            if(isSelected) {
                // PENDING(jeff) - grab padding (4) below from defaults table.
                editX = icon.getIconWidth() + 4;
            }

            return this;
        }
    }

    public void uninstallUI(JComponent c) {
        // Remove listeners
        c.removePropertyChangeListener(filterComboBoxModel);
        cancelButton.removeActionListener(getCancelSelectionAction());
        approveButton.removeActionListener(getApproveSelectionAction());
        filenameTextField.removeActionListener(getApproveSelectionAction());

        super.uninstallUI(c);
    }

    /**
     * Returns the preferred size of the specified
     * <code>JFileChooser</code>.
     * The preferred size is at least as large,
     * in both height and width,
     * as the preferred size recommended
     * by the file chooser's layout manager.
     *
     * @param c  a <code>JFileChooser</code>
     * @return   a <code>Dimension</code> specifying the preferred
     *           width and height of the file chooser
     */
    public Dimension getPreferredSize(JComponent c) {
        int prefWidth = PREF_SIZE.width;
        Dimension d = c.getLayout().preferredLayoutSize(c);
        if (d != null) {
            return new Dimension(d.width < prefWidth ? prefWidth : d.width,
                                 d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height);
        } else {
            return new Dimension(prefWidth, PREF_SIZE.height);
        }
    }

    /**
     * Returns the minimum size of the <code>JFileChooser</code>.
     *
     * @param c  a <code>JFileChooser</code>
     * @return   a <code>Dimension</code> specifying the minimum
     *           width and height of the file chooser
     */
    public Dimension getMinimumSize(JComponent c) {
        return MIN_SIZE;
    }

    /**
     * Returns the maximum size of the <code>JFileChooser</code>.
     *
     * @param c  a <code>JFileChooser</code>
     * @return   a <code>Dimension</code> specifying the maximum
     *           width and height of the file chooser
     */
    public Dimension getMaximumSize(JComponent c) {
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    void setFileSelected() {
        if (getFileChooser().isMultiSelectionEnabled() && !isDirectorySelected()) {
            File[] files = getFileChooser().getSelectedFiles(); // Should be selected
            Object[] selectedObjects = list.getSelectedValues(); // Are actually selected

            if (ShellFolder.disableFileChooserSpeedFix()) {
                // Remove files that shouldn't be selected
                for (int j = 0; j < selectedObjects.length; j++) {
                    boolean found = false;
                    for (int i = 0; i < files.length; i++) {
                        if (files[i].equals(selectedObjects[j])) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        int index = getModel().indexOf(selectedObjects[j]);
                        if (index >= 0) {
                            listSelectionModel.removeSelectionInterval(index, index);
                        }
                    }
                }
                // Add files that should be selected
                for (int i = 0; i < files.length; i++) {
                    boolean found = false;
                    for (int j = 0; j < selectedObjects.length; j++) {
                        if (files[i].equals(selectedObjects[j])) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        int index = getModel().indexOf(files[i]);
                        if (index >= 0) {
                            listSelectionModel.addSelectionInterval(index, index);
                        }
                    }
                }
            } else {
                listSelectionModel.setValueIsAdjusting(true);
                try {
                    Arrays.sort(files);
                    Arrays.sort(selectedObjects);

                    int shouldIndex = 0;
                    int actuallyIndex = 0;

                    // Remove files that shouldn't be selected and add files which should be selected
                    // Note: Assume files are already sorted in compareTo order.
                    while (shouldIndex < files.length &&
                           actuallyIndex < selectedObjects.length) {
                        int comparison = files[shouldIndex].compareTo(selectedObjects[actuallyIndex]);
                        if (comparison < 0) {
                            int index = getModel().indexOf(files[shouldIndex]);
                            listSelectionModel.addSelectionInterval(index, index);
                            shouldIndex++;
                        } else if (comparison > 0) {
                            int index = getModel().indexOf(selectedObjects[actuallyIndex]);
                            listSelectionModel.removeSelectionInterval(index, index);
                            actuallyIndex++;
                        } else {
                            // Do nothing
                            shouldIndex++;
                            actuallyIndex++;
                        }

                    }

                    while (shouldIndex < files.length) {
                        int index = getModel().indexOf(files[shouldIndex]);
                        listSelectionModel.addSelectionInterval(index, index);
                        shouldIndex++;
                    }

                    while (actuallyIndex < selectedObjects.length) {
                        int index = getModel().indexOf(selectedObjects[actuallyIndex]);
                        listSelectionModel.removeSelectionInterval(index, index);
                        actuallyIndex++;
                    }
                } finally {
                    listSelectionModel.setValueIsAdjusting(false);
                }
            }
        } else {
            JFileChooser chooser = getFileChooser();
            File f = null;
            if (isDirectorySelected()) {
                f = getDirectory();
            } else {
                f = chooser.getSelectedFile();
            }
            int i;
            if (f != null && (i = getModel().indexOf(f)) >= 0) {
                listSelectionModel.setSelectionInterval(i, i);
                ensureIndexIsVisible(i);
            } else {
                listSelectionModel.clearSelection();
            }
        }
    }


    private String fileNameString(File file) {
        if (file == null) {
            return null;
        } else {
            JFileChooser fc = getFileChooser();
            if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
                return file.getPath();
            } else {
                return file.getName();
            }
        }
    }

    private String fileNameString(File[] files) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; files != null && i < files.length; i++) {
            if (i > 0) {
                buf.append(" ");
            }
            if (files.length > 1) {
                buf.append("\"");
            }
            buf.append(fileNameString(files[i]));
            if (files.length > 1) {
                buf.append("\"");
            }
        }
        return buf.toString();
    }

    /* The following methods are used by the PropertyChange Listener */

    private void doSelectedFileChanged(PropertyChangeEvent e) {
        applyEdit();
        File f = (File) e.getNewValue();
        JFileChooser fc = getFileChooser();
        if (f != null
            && ((fc.isFileSelectionEnabled() && !f.isDirectory())
                || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {

            setFileName(fileNameString(f));
            setFileSelected();
        }
    }

    private void doSelectedFilesChanged(PropertyChangeEvent e) {
        applyEdit();
        File[] files = (File[]) e.getNewValue();
        JFileChooser fc = getFileChooser();
        if (files != null
            && files.length > 0
            && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {
            setFileName(fileNameString(files));
            setFileSelected();
        }
    }

    private void doDirectoryChanged(PropertyChangeEvent e) {
        JFileChooser fc = getFileChooser();
        FileSystemView fsv = fc.getFileSystemView();

        applyEdit();
        resetEditIndex();
        clearIconCache();
        listSelectionModel.clearSelection();
        ensureIndexIsVisible(0);
        File currentDirectory = fc.getCurrentDirectory();
        if (shortCutPanel != null) {
            shortCutPanel.doDirectoryChanged(currentDirectory);
        }
        if(currentDirectory != null) {
            directoryComboBoxModel.addItem(currentDirectory);
            getNewFolderAction().setEnabled(currentDirectory.canWrite());
            getChangeToParentDirectoryAction().setEnabled(!fsv.isRoot(currentDirectory));

            if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
                if (fsv.isFileSystem(currentDirectory)) {
                    setFileName(currentDirectory.getPath());
                } else {
                    setFileName(null);
                }
            }
        }
    }

    private void doFilterChanged(PropertyChangeEvent e) {
        applyEdit();
        resetEditIndex();
        clearIconCache();
        listSelectionModel.clearSelection();
    }

    private void doFileSelectionModeChanged(PropertyChangeEvent e) {
        applyEdit();
        resetEditIndex();
        clearIconCache();
        listSelectionModel.clearSelection();

        JFileChooser fc = getFileChooser();
        File currentDirectory = fc.getCurrentDirectory();
        if (currentDirectory != null
            && fc.isDirectorySelectionEnabled()
            && !fc.isFileSelectionEnabled()
            && fc.getFileSystemView().isFileSystem(currentDirectory)) {

            setFileName(currentDirectory.getPath());
        } else {
            setFileName(null);
        }
    }

    private void doMultiSelectionChanged(PropertyChangeEvent e) {
        if (getFileChooser().isMultiSelectionEnabled()) {
            listSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        } else {
            listSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            listSelectionModel.clearSelection();
            getFileChooser().setSelectedFiles(null);
        }
    }

    private void doAccessoryChanged(PropertyChangeEvent e) {
        if(getAccessoryPanel() != null) {
            if(e.getOldValue() != null) {
                getAccessoryPanel().remove((JComponent) e.getOldValue());
            }
            JComponent accessory = (JComponent) e.getNewValue();
            if(accessory != null) {
                getAccessoryPanel().add(accessory, BorderLayout.CENTER);
            }
        }
    }

    private void doApproveButtonTextChanged(PropertyChangeEvent e) {
        JFileChooser chooser = getFileChooser();
        approveButton.setText(getApproveButtonText(chooser));
        approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
        approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
    }

    private void doDialogTypeChanged(PropertyChangeEvent e) {
        JFileChooser chooser = getFileChooser();
        approveButton.setText(getApproveButtonText(chooser));
        approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
        approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
        if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
            lookInLabel.setText(saveInLabelText);
        } else {
            lookInLabel.setText(lookInLabelText);
        }
    }

    private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {
        approveButton.setMnemonic(getApproveButtonMnemonic(getFileChooser()));
    }

    private void doControlButtonsChanged(PropertyChangeEvent e) {
        if(getFileChooser().getControlButtonsAreShown()) {
            addControlButtons();
        } else {
            removeControlButtons();
        }
    }

    /*
     * Listen for filechooser property changes, such as
     * the selected file changing, or the type of the dialog changing.
     */
    public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
        return new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String s = e.getPropertyName();
                if(s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
                    doSelectedFileChanged(e);
                } else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
                    doSelectedFilesChanged(e);
                } else if(s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
                    doDirectoryChanged(e);
                } else if(s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
                    doFilterChanged(e);
                } else if(s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
                    doFileSelectionModeChanged(e);
                } else if(s.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
                    doMultiSelectionChanged(e);
                } else if(s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
                    doAccessoryChanged(e);
                } else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
                           s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
                    doApproveButtonTextChanged(e);
                } else if(s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
                    doDialogTypeChanged(e);
                } else if(s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
                    doApproveButtonMnemonicChanged(e);
                } else if(s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
                    doControlButtonsChanged(e);
                } else if (s.equals("componentOrientation")) {
                    ComponentOrientation o = (ComponentOrientation)e.getNewValue();
                    JFileChooser cc = (JFileChooser)e.getSource();
                    if (o != (ComponentOrientation)e.getOldValue()) {
                        cc.applyComponentOrientation(o);
                    }
                    if (detailsTable != null) {
                        detailsTable.setComponentOrientation(o);
                        detailsTable.getParent().getParent().setComponentOrientation(o);
                    }
                } else if (s == "FileChooser.useShellFolder") {
                    updateUseShellFolder();
                    doDirectoryChanged(e);
                } else if (s.equals("ancestor")) {
                    if (e.getOldValue() == null && e.getNewValue() != null) {
                        // Ancestor was added, set initial focus
                        filenameTextField.selectAll();
                        filenameTextField.requestFocus();
                    }
                }
            }
        };
    }


    protected void removeControlButtons() {
        getBottomPanel().remove(getButtonPanel());
    }

    protected void addControlButtons() {
        getBottomPanel().add(getButtonPanel());
    }

    private void ensureIndexIsVisible(int i) {
        if (i >= 0) {
            list.ensureIndexIsVisible(i);
            if (detailsTable != null) {
                detailsTable.scrollRectToVisible(detailsTable.getCellRect(i, COLUMN_FILENAME, true));
            }
        }
    }

    public void ensureFileIsVisible(JFileChooser fc, File f) {
        ensureIndexIsVisible(getModel().indexOf(f));
    }

    public void rescanCurrentDirectory(JFileChooser fc) {
        getModel().validateFileCache();
    }

    public String getFileName() {
        if(filenameTextField != null) {
            return filenameTextField.getText();
        } else {
            return null;
        }
    }

    public void setFileName(String filename) {
        if(filenameTextField != null) {
            filenameTextField.setText(filename);
        }
    }

    /**
     * Property to remember whether a directory is currently selected in the UI.
     * This is normally called by the UI on a selection event.
     *
     * @param directorySelected if a directory is currently selected.
     * @since 1.4
     */
    protected void setDirectorySelected(boolean directorySelected) {
        super.setDirectorySelected(directorySelected);
        JFileChooser chooser = getFileChooser();
        if(directorySelected) {
            approveButton.setText(directoryOpenButtonText);
            approveButton.setToolTipText(directoryOpenButtonToolTipText);
            approveButton.setMnemonic(directoryOpenButtonMnemonic);
        } else {
            approveButton.setText(getApproveButtonText(chooser));
            approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
            approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
        }
    }

    public String getDirectoryName() {
        // PENDING(jeff) - get the name from the directory combobox
        return null;
    }

    public void setDirectoryName(String dirname) {
        // PENDING(jeff) - set the name in the directory combobox
    }

    protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
        return new DirectoryComboBoxRenderer();
    }

    //
    // Renderer for DirectoryComboBox
    //
    class DirectoryComboBoxRenderer extends DefaultListCellRenderer  {
        IndentIcon ii = new IndentIcon();
        public Component getListCellRendererComponent(JList list, Object value,
                                                      int index, boolean isSelected,
                                                      boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            if (value == null) {
                setText("");
                return this;
            }
            File directory = (File)value;
            setText(getFileChooser().getName(directory));
            Icon icon = getFileChooser().getIcon(directory);
            ii.icon = icon;
            ii.depth = directoryComboBoxModel.getDepth(index);
            setIcon(ii);

            return this;
        }
    }

    final static int space = 10;
    class IndentIcon implements Icon {

        Icon icon = null;
        int depth = 0;

        public void paintIcon(Component c, Graphics g, int x, int y) {
            if (c.getComponentOrientation().isLeftToRight()) {
                icon.paintIcon(c, g, x+depth*space, y);
            } else {
                icon.paintIcon(c, g, x, y);
            }
        }

        public int getIconWidth() {
            return icon.getIconWidth() + depth*space;
        }

        public int getIconHeight() {
            return icon.getIconHeight();
        }

    }

    //
    // DataModel for DirectoryComboxbox
    //
    protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
        return new DirectoryComboBoxModel();
    }

    /**
     * Data model for a type-face selection combo-box.
     */
    protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
        Vector directories = new Vector();
        int[] depths = null;
        File selectedDirectory = null;
        JFileChooser chooser = getFileChooser();
        FileSystemView fsv = chooser.getFileSystemView();

        public DirectoryComboBoxModel() {
            // Add the current directory to the model, and make it the
            // selectedDirectory
            File dir = getFileChooser().getCurrentDirectory();
            if(dir != null) {
                addItem(dir);
            }
        }

        /**
         * Adds the directory to the model and sets it to be selected,
         * additionally clears out the previous selected directory and
         * the paths leading up to it, if any.
         */
        private void addItem(File directory) {

            if(directory == null) {
                return;
            }

            directories.clear();

            File[] baseFolders;
            if (useShellFolder) {
                baseFolders = (File[])AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        return ShellFolder.get("fileChooserComboBoxFolders");
                    }
                });
            } else {
                baseFolders = fsv.getRoots();
            }
            directories.addAll(Arrays.asList(baseFolders));

            // Get the canonical (full) path. This has the side
            // benefit of removing extraneous chars from the path,
            // for example /foo/bar/ becomes /foo/bar
            File canonical = null;
            try {
                canonical = directory.getCanonicalFile();
            } catch (IOException e) {
                // Maybe drive is not ready. Can't abort here.
                canonical = directory;
            }

            // create File instances of each directory leading up to the top
            try {
                File sf = useShellFolder ? ShellFolder.getShellFolder(canonical)
                                         : canonical;
                File f = sf;
                Vector path = new Vector(10);
                do {
                    path.addElement(f);
                } while ((f = f.getParentFile()) != null);

                int pathCount = path.size();
                // Insert chain at appropriate place in vector
                for (int i = 0; i < pathCount; i++) {
                    f = (File)path.get(i);
                    if (directories.contains(f)) {
                        int topIndex = directories.indexOf(f);
                        for (int j = i-1; j >= 0; j--) {
                            directories.insertElementAt(path.get(j), topIndex+i-j);
                        }
                        break;
                    }
                }
                calculateDepths();
                setSelectedItem(sf);
            } catch (FileNotFoundException ex) {
                calculateDepths();
            }
        }

        private void calculateDepths() {
            depths = new int[directories.size()];
            for (int i = 0; i < depths.length; i++) {
                File dir = (File)directories.get(i);
                File parent = dir.getParentFile();
                depths[i] = 0;
                if (parent != null) {
                    for (int j = i-1; j >= 0; j--) {
                        if (parent.equals((File)directories.get(j))) {
                            depths[i] = depths[j] + 1;
                            break;
                        }
                    }
                }
            }
        }

        public int getDepth(int i) {
            return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;
        }

        public void setSelectedItem(Object selectedDirectory) {
            this.selectedDirectory = (File)selectedDirectory;
            fireContentsChanged(this, -1, -1);
        }

        public Object getSelectedItem() {
            return selectedDirectory;
        }

        public int getSize() {
            return directories.size();
        }

        public Object getElementAt(int index) {
            return directories.elementAt(index);
        }
    }

    //
    // Renderer for Types ComboBox
    //
    protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
        return new FilterComboBoxRenderer();
    }

    /**
     * Render different type sizes and styles.
     */
    public class FilterComboBoxRenderer extends DefaultListCellRenderer {
        public Component getListCellRendererComponent(JList list,
            Object value, int index, boolean isSelected,
            boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            if (value != null && value instanceof FileFilter) {
                setText(((FileFilter)value).getDescription());
            }

            return this;
        }
    }

    //
    // DataModel for Types Comboxbox
    //
    protected FilterComboBoxModel createFilterComboBoxModel() {
        return new FilterComboBoxModel();
    }

    /**
     * Data model for a type-face selection combo-box.
     */
    protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
        protected FileFilter[] filters;
        protected FilterComboBoxModel() {
            super();
            filters = getFileChooser().getChoosableFileFilters();
        }

        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
            if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
                filters = (FileFilter[]) e.getNewValue();
                fireContentsChanged(this, -1, -1);
            } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
                fireContentsChanged(this, -1, -1);
            }
        }

        public void setSelectedItem(Object filter) {
            if(filter != null) {
                getFileChooser().setFileFilter((FileFilter) filter);
                setFileName(null);
                fireContentsChanged(this, -1, -1);
            }
        }

        public Object getSelectedItem() {
            // Ensure that the current filter is in the list.
            // NOTE: we shouldnt' have to do this, since JFileChooser adds
            // the filter to the choosable filters list when the filter
            // is set. Lets be paranoid just in case someone overrides
            // setFileFilter in JFileChooser.
            FileFilter currentFilter = getFileChooser().getFileFilter();
            boolean found = false;
            if(currentFilter != null) {
                for(int i=0; i < filters.length; i++) {
                    if(filters[i] == currentFilter) {
                        found = true;
                    }
                }
                if(found == false) {
                    getFileChooser().addChoosableFileFilter(currentFilter);
                }
            }
            return getFileChooser().getFileFilter();
        }

        public int getSize() {
            if(filters != null) {
                return filters.length;
            } else {
                return 0;
            }
        }

        public Object getElementAt(int index) {
            if(index > getSize() - 1) {
                // This shouldn't happen. Try to recover gracefully.
                return getFileChooser().getFileFilter();
            }
            if(filters != null) {
                return filters[index];
            } else {
                return null;
            }
        }
    }

    public void valueChanged(ListSelectionEvent e) {
        JFileChooser fc = getFileChooser();
        File f = fc.getSelectedFile();
        if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) {
            setFileName(fileNameString(f));
        }
    }

    /**
     * Acts when DirectoryComboBox has changed the selected item.
     */
    protected class DirectoryComboBoxAction implements ActionListener {




        public void actionPerformed(ActionEvent e) {
            File f = (File)directoryComboBox.getSelectedItem();
            getFileChooser().setCurrentDirectory(f);
        }
    }

    protected JButton getApproveButton(JFileChooser fc) {
        return approveButton;
    }

    public FileView getFileView(JFileChooser fc) {
        return fileView;
    }

    // ***********************
    // * FileView operations *
    // ***********************
    protected class WindowsFileView extends BasicFileView {
        /* FileView type descriptions */

        public Icon getIcon(File f) {
            Icon icon = getCachedIcon(f);
            if (icon != null) {
                return icon;
            }
            if (f != null) {
                icon = getFileChooser().getFileSystemView().getSystemIcon(f);
            }
            if (icon == null) {
                icon = super.getIcon(f);
            }
            cacheIcon(f, icon);
            return icon;
        }
    }
}
TOP

Related Classes of com.sun.java.swing.plaf.windows.WindowsFileChooserUI$WindowsFileView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.