/*
 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.apple.laf;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.beans.*;
import java.io.File;
import java.net.URI;
import java.text.DateFormat;
import java.util.*;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.plaf.*;
import javax.swing.table.*;

import sun.swing.SwingUtilities2;

public class AquaFileChooserUI extends FileChooserUI {
    /* FileView icons */
    protected Icon directoryIcon = null;
    protected Icon fileIcon = null;
    protected Icon computerIcon = null;
    protected Icon hardDriveIcon = null;
    protected Icon floppyDriveIcon = null;

    protected Icon upFolderIcon = null;
    protected Icon homeFolderIcon = null;
    protected Icon listViewIcon = null;
    protected Icon detailsViewIcon = null;

    protected int saveButtonMnemonic = 0;
    protected int openButtonMnemonic = 0;
    protected int cancelButtonMnemonic = 0;
    protected int updateButtonMnemonic = 0;
    protected int helpButtonMnemonic = 0;
    protected int chooseButtonMnemonic = 0;

    private String saveTitleText = null;
    private String openTitleText = null;
    String newFolderTitleText = null;

    protected String saveButtonText = null;
    protected String openButtonText = null;
    protected String cancelButtonText = null;
    protected String updateButtonText = null;
    protected String helpButtonText = null;
    protected String newFolderButtonText = null;
    protected String chooseButtonText = null;

    //private String newFolderErrorSeparator = null;
    String newFolderErrorText = null;
    String newFolderExistsErrorText = null;
    protected String fileDescriptionText = null;
    protected String directoryDescriptionText = null;

    protected String saveButtonToolTipText = null;
    protected String openButtonToolTipText = null;
    protected String cancelButtonToolTipText = null;
    protected String updateButtonToolTipText = null;
    protected String helpButtonToolTipText = null;
    protected String chooseItemButtonToolTipText = null; // Choose anything
    protected String chooseFolderButtonToolTipText = null; // Choose folder
    protected String directoryComboBoxToolTipText = null;
    protected String filenameTextFieldToolTipText = null;
    protected String filterComboBoxToolTipText = null;
    protected String openDirectoryButtonToolTipText = null;

    protected String cancelOpenButtonToolTipText = null;
    protected String cancelSaveButtonToolTipText = null;
    protected String cancelChooseButtonToolTipText = null;
    protected String cancelNewFolderButtonToolTipText = null;

    protected String desktopName = null;
    String newFolderDialogPrompt = null;
    String newFolderDefaultName = null;
    private String newFileDefaultName = null;
    String createButtonText = null;

    JFileChooser filechooser = null;

    private MouseListener doubleClickListener = null;
    private PropertyChangeListener propertyChangeListener = null;
    private AncestorListener ancestorListener = null;
    private DropTarget dragAndDropTarget = null;

    private final AcceptAllFileFilter acceptAllFileFilter = new AcceptAllFileFilter();

    private AquaFileSystemModel model;

    final AquaFileView fileView = new AquaFileView(this);

    boolean selectionInProgress = false;

    // The accessoryPanel is a container to place the JFileChooser accessory component
    private JPanel accessoryPanel = null;

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

    public AquaFileChooserUI(final JFileChooser filechooser) {
        super();
    }

    public void installUI(final JComponent c) {
        accessoryPanel = new JPanel(new BorderLayout());
        filechooser = (JFileChooser)c;

        createModel();

        installDefaults(filechooser);
        installComponents(filechooser);
        installListeners(filechooser);

        AquaUtils.enforceComponentOrientation(filechooser, ComponentOrientation.getOrientation(Locale.getDefault()));
    }

    public void uninstallUI(final JComponent c) {
        uninstallListeners(filechooser);
        uninstallComponents(filechooser);
        uninstallDefaults(filechooser);

        if (accessoryPanel != null) {
            accessoryPanel.removeAll();
        }

        accessoryPanel = null;
        getFileChooser().removeAll();
    }

    protected void installListeners(final JFileChooser fc) {
        doubleClickListener = createDoubleClickListener(fc, fFileList);
        fFileList.addMouseListener(doubleClickListener);

        propertyChangeListener = createPropertyChangeListener(fc);
        if (propertyChangeListener != null) {
            fc.addPropertyChangeListener(propertyChangeListener);
        }
        if (model != null) fc.addPropertyChangeListener(model);

        ancestorListener = new AncestorListener(){
            public void ancestorAdded(final AncestorEvent e) {
                // Request defaultness for the appropriate button based on mode
                setFocusForMode(getFileChooser());
                // Request defaultness for the appropriate button based on mode
                setDefaultButtonForMode(getFileChooser());
            }

            public void ancestorRemoved(final AncestorEvent e) {
            }

            public void ancestorMoved(final AncestorEvent e) {
            }
        };
        fc.addAncestorListener(ancestorListener);

        fc.registerKeyboardAction(new CancelSelectionAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        dragAndDropTarget = new DropTarget(fc, DnDConstants.ACTION_COPY, new DnDHandler(), true);
        fc.setDropTarget(dragAndDropTarget);
    }

    protected void uninstallListeners(final JFileChooser fc) {
        if (propertyChangeListener != null) {
            fc.removePropertyChangeListener(propertyChangeListener);
        }
        fFileList.removeMouseListener(doubleClickListener);
        fc.removePropertyChangeListener(model);
        fc.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
        fc.removeAncestorListener(ancestorListener);
        fc.setDropTarget(null);
        ancestorListener = null;
    }

    protected void installDefaults(final JFileChooser fc) {
        installIcons(fc);
        installStrings(fc);
        setPackageIsTraversable(fc.getClientProperty(PACKAGE_TRAVERSABLE_PROPERTY));
        setApplicationIsTraversable(fc.getClientProperty(APPLICATION_TRAVERSABLE_PROPERTY));
    }

    protected void installIcons(final JFileChooser fc) {
        directoryIcon = UIManager.getIcon("FileView.directoryIcon");
        fileIcon = UIManager.getIcon("FileView.fileIcon");
        computerIcon = UIManager.getIcon("FileView.computerIcon");
        hardDriveIcon = UIManager.getIcon("FileView.hardDriveIcon");
    }

    String getString(final String uiKey, final String fallback) {
        final String result = UIManager.getString(uiKey);
        return (result == null ? fallback : result);
    }

    protected void installStrings(final JFileChooser fc) {
        // Exist in basic.properties (though we might want to override)
        fileDescriptionText = UIManager.getString("FileChooser.fileDescriptionText");
        directoryDescriptionText = UIManager.getString("FileChooser.directoryDescriptionText");
        newFolderErrorText = getString("FileChooser.newFolderErrorText", "Error occurred during folder creation");

        saveButtonText = UIManager.getString("FileChooser.saveButtonText");
        openButtonText = UIManager.getString("FileChooser.openButtonText");
        cancelButtonText = UIManager.getString("FileChooser.cancelButtonText");
        updateButtonText = UIManager.getString("FileChooser.updateButtonText");
        helpButtonText = UIManager.getString("FileChooser.helpButtonText");

        saveButtonMnemonic = UIManager.getInt("FileChooser.saveButtonMnemonic");
        openButtonMnemonic = UIManager.getInt("FileChooser.openButtonMnemonic");
        cancelButtonMnemonic = UIManager.getInt("FileChooser.cancelButtonMnemonic");
        updateButtonMnemonic = UIManager.getInt("FileChooser.updateButtonMnemonic");
        helpButtonMnemonic = UIManager.getInt("FileChooser.helpButtonMnemonic");
        chooseButtonMnemonic = UIManager.getInt("FileChooser.chooseButtonMnemonic");

        saveButtonToolTipText = UIManager.getString("FileChooser.saveButtonToolTipText");
        openButtonToolTipText = UIManager.getString("FileChooser.openButtonToolTipText");
        cancelButtonToolTipText = UIManager.getString("FileChooser.cancelButtonToolTipText");
        updateButtonToolTipText = UIManager.getString("FileChooser.updateButtonToolTipText");
        helpButtonToolTipText = UIManager.getString("FileChooser.helpButtonToolTipText");

        // Mac-specific, but fallback to basic if it's missing
        saveTitleText = getString("FileChooser.saveTitleText", saveButtonText);
        openTitleText = getString("FileChooser.openTitleText", openButtonText);

        // Mac-specific, required
        newFolderExistsErrorText = getString("FileChooser.newFolderExistsErrorText", "That name is already taken");
        chooseButtonText = getString("FileChooser.chooseButtonText", "Choose");
        newFolderButtonText = getString("FileChooser.newFolderButtonText", "New");
        newFolderTitleText = getString("FileChooser.newFolderTitleText", "New Folder");

        if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
            fileNameLabelText = getString("FileChooser.saveDialogFileNameLabelText", "Save As:");
        } else {
            fileNameLabelText = getString("FileChooser.fileNameLabelText", "Name:");
        }

        filesOfTypeLabelText = getString("FileChooser.filesOfTypeLabelText", "Format:");

        desktopName = getString("FileChooser.desktopName", "Desktop");
        newFolderDialogPrompt = getString("FileChooser.newFolderPromptText", "Name of new folder:");
        newFolderDefaultName = getString("FileChooser.untitledFolderName", "untitled folder");
        newFileDefaultName = getString("FileChooser.untitledFileName", "untitled");
        createButtonText = getString("FileChooser.createButtonText", "Create");

        fColumnNames[1] = getString("FileChooser.byDateText", "Date Modified");
        fColumnNames[0] = getString("FileChooser.byNameText", "Name");

        // Mac-specific, optional
        chooseItemButtonToolTipText = UIManager.getString("FileChooser.chooseItemButtonToolTipText");
        chooseFolderButtonToolTipText = UIManager.getString("FileChooser.chooseFolderButtonToolTipText");
        openDirectoryButtonToolTipText = UIManager.getString("FileChooser.openDirectoryButtonToolTipText");

        directoryComboBoxToolTipText = UIManager.getString("FileChooser.directoryComboBoxToolTipText");
        filenameTextFieldToolTipText = UIManager.getString("FileChooser.filenameTextFieldToolTipText");
        filterComboBoxToolTipText = UIManager.getString("FileChooser.filterComboBoxToolTipText");

        cancelOpenButtonToolTipText = UIManager.getString("FileChooser.cancelOpenButtonToolTipText");
        cancelSaveButtonToolTipText = UIManager.getString("FileChooser.cancelSaveButtonToolTipText");
        cancelChooseButtonToolTipText = UIManager.getString("FileChooser.cancelChooseButtonToolTipText");
        cancelNewFolderButtonToolTipText = UIManager.getString("FileChooser.cancelNewFolderButtonToolTipText");

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

    protected void uninstallDefaults(final JFileChooser fc) {
        uninstallIcons(fc);
        uninstallStrings(fc);
    }

    protected void uninstallIcons(final JFileChooser fc) {
        directoryIcon = null;
        fileIcon = null;
        computerIcon = null;
        hardDriveIcon = null;
        floppyDriveIcon = null;

        upFolderIcon = null;
        homeFolderIcon = null;
        detailsViewIcon = null;
        listViewIcon = null;
    }

    protected void uninstallStrings(final JFileChooser fc) {
        saveTitleText = null;
        openTitleText = null;
        newFolderTitleText = null;

        saveButtonText = null;
        openButtonText = null;
        cancelButtonText = null;
        updateButtonText = null;
        helpButtonText = null;
        newFolderButtonText = null;
        chooseButtonText = null;

        cancelOpenButtonToolTipText = null;
        cancelSaveButtonToolTipText = null;
        cancelChooseButtonToolTipText = null;
        cancelNewFolderButtonToolTipText = null;

        saveButtonToolTipText = null;
        openButtonToolTipText = null;
        cancelButtonToolTipText = null;
        updateButtonToolTipText = null;
        helpButtonToolTipText = null;
        chooseItemButtonToolTipText = null;
        chooseFolderButtonToolTipText = null;
        openDirectoryButtonToolTipText = null;
        directoryComboBoxToolTipText = null;
        filenameTextFieldToolTipText = null;
        filterComboBoxToolTipText = null;

        newFolderDefaultName = null;
        newFileDefaultName = null;

        desktopName = null;
    }

    protected void createModel() {
    }

    AquaFileSystemModel getModel() {
        return model;
    }

    /*
     * Listen for filechooser property changes, such as
     * the selected file changing, or the type of the dialog changing.
     */
    // Taken almost verbatim from Metal
    protected PropertyChangeListener createPropertyChangeListener(final JFileChooser fc) {
        return new PropertyChangeListener(){
            public void propertyChange(final PropertyChangeEvent e) {
                final String prop = e.getPropertyName();
                if (prop.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
                    final File f = (File)e.getNewValue();
                    if (f != null) {
                        // Select the file in the list if the selected file didn't change as
                        // a result of a list click.
                        if (!selectionInProgress && getModel().contains(f)) {
                            fFileList.setSelectedIndex(getModel().indexOf(f));
                        }

                        // [3643835] Need to populate the text field here.  No-op on Open dialogs
                        // Note that this was removed for 3514735, but should not have been.
                        if (!f.isDirectory()) {
                            setFileName(getFileChooser().getName(f));
                        }
                    }
                    updateButtonState(getFileChooser());
                } else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
                    JFileChooser fileChooser = getFileChooser();
                    if (!fileChooser.isDirectorySelectionEnabled()) {
                        final File[] files = (File[]) e.getNewValue();
                        if (files != null) {
                            for (int selectedRow : fFileList.getSelectedRows()) {
                                File file = (File) fFileList.getValueAt(selectedRow, 0);
                                if (fileChooser.isTraversable(file)) {
                                    fFileList.removeSelectedIndex(selectedRow);
                                }
                            }
                        }
                    }
                } else if (prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
                    fFileList.clearSelection();
                    final File currentDirectory = getFileChooser().getCurrentDirectory();
                    if (currentDirectory != null) {
                        fDirectoryComboBoxModel.addItem(currentDirectory);
                        // Enable the newFolder action if the current directory
                        // is writable.
                        // PENDING(jeff) - broken - fix
                        getAction(kNewFolder).setEnabled(currentDirectory.canWrite());
                    }
                    updateButtonState(getFileChooser());
                } else if (prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
                    fFileList.clearSelection();
                    setBottomPanelForMode(getFileChooser()); // Also updates approve button
                } else if (prop == JFileChooser.ACCESSORY_CHANGED_PROPERTY) {
                    if (getAccessoryPanel() != null) {
                        if (e.getOldValue() != null) {
                            getAccessoryPanel().remove((JComponent)e.getOldValue());
                        }
                        final JComponent accessory = (JComponent)e.getNewValue();
                        if (accessory != null) {
                            getAccessoryPanel().add(accessory, BorderLayout.CENTER);
                        }
                    }
                } else if (prop == JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) {
                    updateApproveButton(getFileChooser());
                    getFileChooser().invalidate();
                } else if (prop == JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) {
                    if (getFileChooser().getDialogType() == JFileChooser.SAVE_DIALOG) {
                        fileNameLabelText = getString("FileChooser.saveDialogFileNameLabelText", "Save As:");
                    } else {
                        fileNameLabelText = getString("FileChooser.fileNameLabelText", "Name:");
                    }
                    fTextFieldLabel.setText(fileNameLabelText);

                    // Mac doesn't show the text field or "new folder" button in 'Open' dialogs
                    setBottomPanelForMode(getFileChooser()); // Also updates approve button
                } else if (prop.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
                    getApproveButton(getFileChooser()).setMnemonic(getApproveButtonMnemonic(getFileChooser()));
                } else if (prop.equals(PACKAGE_TRAVERSABLE_PROPERTY)) {
                    setPackageIsTraversable(e.getNewValue());
                } else if (prop.equals(APPLICATION_TRAVERSABLE_PROPERTY)) {
                    setApplicationIsTraversable(e.getNewValue());
                } else if (prop.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
                    if (getFileChooser().isMultiSelectionEnabled()) {
                        fFileList.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
                    } else {
                        fFileList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                    }
                } else if (prop.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
                    doControlButtonsChanged(e);
                }
            }
        };
    }

    void setPackageIsTraversable(final Object o) {
        int newProp = -1;
        if (o != null && o instanceof String) newProp = parseTraversableProperty((String)o);
        if (newProp != -1) fPackageIsTraversable = newProp;
        else fPackageIsTraversable = sGlobalPackageIsTraversable;
    }

    void setApplicationIsTraversable(final Object o) {
        int newProp = -1;
        if (o != null && o instanceof String) newProp = parseTraversableProperty((String)o);
        if (newProp != -1) fApplicationIsTraversable = newProp;
        else fApplicationIsTraversable = sGlobalApplicationIsTraversable;
    }

    void doControlButtonsChanged(final PropertyChangeEvent e) {
        if (getFileChooser().getControlButtonsAreShown()) {
            fBottomPanel.add(fDirectoryPanelSpacer);
            fBottomPanel.add(fDirectoryPanel);
        } else {
            fBottomPanel.remove(fDirectoryPanelSpacer);
            fBottomPanel.remove(fDirectoryPanel);
        }
    }

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

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

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

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

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

    public void ensureFileIsVisible(final JFileChooser fc, final File f) {
        if (f == null) {
            fFileList.requestFocusInWindow();
            fFileList.ensureIndexIsVisible(-1);
            return;
        }

        getModel().runWhenDone(new Runnable() {
            public void run() {
                fFileList.requestFocusInWindow();
                fFileList.ensureIndexIsVisible(getModel().indexOf(f));
            }
        });
    }

    public JFileChooser getFileChooser() {
        return filechooser;
    }

    public JPanel getAccessoryPanel() {
        return accessoryPanel;
    }

    protected JButton getApproveButton(final JFileChooser fc) {
        return fApproveButton;
    }

    public int getApproveButtonMnemonic(final JFileChooser fc) {
        return fSubPanel.getApproveButtonMnemonic(fc);
    }

    public String getApproveButtonToolTipText(final JFileChooser fc) {
        return fSubPanel.getApproveButtonToolTipText(fc);
    }

    public String getApproveButtonText(final JFileChooser fc) {
        return fSubPanel.getApproveButtonText(fc);
    }

    protected String getCancelButtonToolTipText(final JFileChooser fc) {
        return fSubPanel.getCancelButtonToolTipText(fc);
    }

    // If the item's not selectable, it'll be visible but disabled in the list
    boolean isSelectableInList(final File f) {
        return fSubPanel.isSelectableInList(getFileChooser(), f);
    }

    // Is this a file that the JFileChooser wants?
    // Directories can be selected in the list regardless of mode
    boolean isSelectableForMode(final JFileChooser fc, final File f) {
        if (f == null) return false;
        final int mode = fc.getFileSelectionMode();
        if (mode == JFileChooser.FILES_AND_DIRECTORIES) return true;
        boolean traversable = fc.isTraversable(f);
        if (mode == JFileChooser.DIRECTORIES_ONLY) return traversable;
        return !traversable;
    }

    // ********************************************
    // ************ Create Listeners **************
    // ********************************************

    // From Basic
    public ListSelectionListener createListSelectionListener(final JFileChooser fc) {
        return new SelectionListener();
    }

    protected class SelectionListener implements ListSelectionListener {
        public void valueChanged(final ListSelectionEvent e) {
            if (e.getValueIsAdjusting()) return;

            File f = null;
            final int selectedRow = fFileList.getSelectedRow();
            final JFileChooser chooser = getFileChooser();
            boolean isSave = (chooser.getDialogType() == JFileChooser.SAVE_DIALOG);
            if (selectedRow >= 0) {
                f = (File)fFileList.getValueAt(selectedRow, 0);
            }

            // Save dialog lists can't be multi select, because all we're selecting is the next folder to open
            selectionInProgress = true;
            if (!isSave && chooser.isMultiSelectionEnabled()) {
                final int[] rows = fFileList.getSelectedRows();
                int selectableCount = 0;
                // Double-check that all the list selections are valid for this mode
                // Directories can be selected in the list regardless of mode
                if (rows.length > 0) {
                    for (final int element : rows) {
                        if (isSelectableForMode(chooser, (File)fFileList.getValueAt(element, 0))) selectableCount++;
                    }
                }
                if (selectableCount > 0) {
                    final File[] files = new File[selectableCount];
                    for (int i = 0, si = 0; i < rows.length; i++) {
                        f = (File)fFileList.getValueAt(rows[i], 0);
                        if (isSelectableForMode(chooser, f)) {
                            if (fileView.isAlias(f)) {
                                f = fileView.resolveAlias(f);
                            }
                            files[si++] = f;
                        }
                    }
                    chooser.setSelectedFiles(files);
                } else {
                    chooser.setSelectedFiles(null);
                }
            } else {
                chooser.setSelectedFiles(null);
                chooser.setSelectedFile(f);
            }
            selectionInProgress = false;
        }
    }

    // When the Save textfield has the focus, the button should say "Save"
    // Otherwise, it depends on the list selection
    protected class SaveTextFocusListener implements FocusListener {
        public void focusGained(final FocusEvent e) {
            updateButtonState(getFileChooser());
        }

        // Do nothing, we might be losing focus due to window deactivation
        public void focusLost(final FocusEvent e) {

        }
    }

    // When the Save textfield is empty and the button says "Save", it should be disabled
    // Otherwise, it depends on the list selection
    protected class SaveTextDocumentListener implements DocumentListener {
        public void insertUpdate(final DocumentEvent e) {
            textChanged();
        }

        public void removeUpdate(final DocumentEvent e) {
            textChanged();
        }

        public void changedUpdate(final DocumentEvent e) {

        }

        void textChanged() {
            updateButtonState(getFileChooser());
        }
    }

    // Opens the File object if it's a traversable directory
    protected boolean openDirectory(final File f) {
        if (getFileChooser().isTraversable(f)) {
            fFileList.clearSelection();
            // Resolve any aliases
            final File original = fileView.resolveAlias(f);
            getFileChooser().setCurrentDirectory(original);
            updateButtonState(getFileChooser());
            return true;
        }
        return false;
    }

    // From Basic
    protected class DoubleClickListener extends MouseAdapter {
        JTableExtension list;

        public DoubleClickListener(final JTableExtension list) {
            this.list = list;
        }

        public void mouseClicked(final MouseEvent e) {
            if (e.getClickCount() != 2) return;

            final int index = list.locationToIndex(e.getPoint());
            if (index < 0) return;

            final File f = (File)((AquaFileSystemModel)list.getModel()).getElementAt(index);
            if (openDirectory(f)) return;

            if (!isSelectableInList(f)) return;
            getFileChooser().approveSelection();
        }
    }

    protected MouseListener createDoubleClickListener(final JFileChooser fc, final JTableExtension list) {
        return new DoubleClickListener(list);
    }

    // listens for drag events onto the JFileChooser and sets the selected file or directory
    class DnDHandler extends DropTargetAdapter {
        public void dragEnter(final DropTargetDragEvent dtde) {
            tryToAcceptDrag(dtde);
        }

        public void dragOver(final DropTargetDragEvent dtde) {
            tryToAcceptDrag(dtde);
        }

        public void dropActionChanged(final DropTargetDragEvent dtde) {
            tryToAcceptDrag(dtde);
        }

        public void drop(final DropTargetDropEvent dtde) {
            if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                handleFileDropEvent(dtde);
                return;
            }

            if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                handleStringDropEvent(dtde);
                return;
            }
        }

        protected void tryToAcceptDrag(final DropTargetDragEvent dtde) {
            if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor) || dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                dtde.acceptDrag(DnDConstants.ACTION_COPY);
                return;
            }

            dtde.rejectDrag();
        }

        protected void handleFileDropEvent(final DropTargetDropEvent dtde) {
            dtde.acceptDrop(dtde.getDropAction());
            final Transferable transferable = dtde.getTransferable();

            try {
                final java.util.List<File> fileList = (java.util.List<File>)transferable.getTransferData(DataFlavor.javaFileListFlavor);
                dropFiles(fileList.toArray(new File[fileList.size()]));
                dtde.dropComplete(true);
            } catch (final Exception e) {
                dtde.dropComplete(false);
            }
        }

        protected void handleStringDropEvent(final DropTargetDropEvent dtde) {
            dtde.acceptDrop(dtde.getDropAction());
            final Transferable transferable = dtde.getTransferable();

            final String stringData;
            try {
                stringData = (String)transferable.getTransferData(DataFlavor.stringFlavor);
            } catch (final Exception e) {
                dtde.dropComplete(false);
                return;
            }

            try {
                final File fileAsPath = new File(stringData);
                if (fileAsPath.exists()) {
                    dropFiles(new File[] {fileAsPath});
                    dtde.dropComplete(true);
                    return;
                }
            } catch (final Exception e) {
                // try again
            }

            try {
                final File fileAsURI = new File(new URI(stringData));
                if (fileAsURI.exists()) {
                    dropFiles(new File[] {fileAsURI});
                    dtde.dropComplete(true);
                    return;
                }
            } catch (final Exception e) {
                // nothing more to do
            }

            dtde.dropComplete(false);
        }

        protected void dropFiles(final File[] files) {
            final JFileChooser jfc = getFileChooser();

            if (files.length == 1) {
                if (files[0].isDirectory()) {
                    jfc.setCurrentDirectory(files[0]);
                    return;
                }

                if (!isSelectableForMode(jfc, files[0])) {
                    return;
                }
            }

            jfc.setSelectedFiles(files);
            for (final File file : files) {
                jfc.ensureFileIsVisible(file);
            }
            getModel().runWhenDone(new Runnable() {
                public void run() {
                    final AquaFileSystemModel fileSystemModel = getModel();
                    for (final File element : files) {
                        final int index = fileSystemModel.indexOf(element);
                        if (index >= 0) fFileList.addRowSelectionInterval(index, index);
                    }
                }
            });
        }
    }

    // FileChooser UI PLAF methods

    /**
     * Returns the default accept all file filter
     */
    public FileFilter getAcceptAllFileFilter(final JFileChooser fc) {
        return acceptAllFileFilter;
    }

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

    /**
     * Returns the title of this dialog
     */
    public String getDialogTitle(final JFileChooser fc) {
        if (fc.getDialogTitle() == null) {
            if (getFileChooser().getDialogType() == JFileChooser.OPEN_DIALOG) {
                return openTitleText;
            } else if (getFileChooser().getDialogType() == JFileChooser.SAVE_DIALOG) { return saveTitleText; }
        }
        return fc.getDialogTitle();
    }

    // Utility to get the first selected item regardless of whether we're single or multi select
    File getFirstSelectedItem() {
        // Get the selected item
        File selectedFile = null;
        final int index = fFileList.getSelectedRow();
        if (index >= 0) {
            selectedFile = (File)((AquaFileSystemModel)fFileList.getModel()).getElementAt(index);
        }
        return selectedFile;
    }

    // Make a file from the filename
    File makeFile(final JFileChooser fc, final String filename) {
        File selectedFile = null;
        // whitespace is legal on Macs, even on beginning and end of filename
        if (filename != null && !filename.equals("")) {
            final FileSystemView fs = fc.getFileSystemView();
            selectedFile = fs.createFileObject(filename);
            if (!selectedFile.isAbsolute()) {
                selectedFile = fs.createFileObject(fc.getCurrentDirectory(), filename);
            }
        }
        return selectedFile;
    }

    // Utility to tell if the textfield has anything in it
    boolean textfieldIsValid() {
        final String s = getFileName();
        return (s != null && !s.equals(""));
    }

    // Action to attach to the file list so we can override the default action
    // of the table for the return key, which is to select the next line.
    protected class DefaultButtonAction extends AbstractAction {
        public void actionPerformed(final ActionEvent e) {
            final JRootPane root = AquaFileChooserUI.this.getFileChooser().getRootPane();
            final JFileChooser fc = AquaFileChooserUI.this.getFileChooser();
            final JButton owner = root.getDefaultButton();
            if (owner != null && SwingUtilities.getRootPane(owner) == root && owner.isEnabled()) {
                owner.doClick(20);
            } else if (!fc.getControlButtonsAreShown()) {
                final JButton defaultButton = AquaFileChooserUI.this.fSubPanel.getDefaultButton(fc);

                if (defaultButton != null) {
                    defaultButton.doClick(20);
                }
            } else {
                Toolkit.getDefaultToolkit().beep();
            }
        }

        public boolean isEnabled() {
            return true;
        }
    }

    /**
     * Creates a new folder.
     */
    protected class NewFolderAction extends AbstractAction {
        protected NewFolderAction() {
            super(newFolderAccessibleName);
        }

        // Muchlike showInputDialog, but we give it options instead of selectionValues
        private Object showNewFolderDialog(final Component parentComponent, final Object message, final String title, final int messageType, final Icon icon, final Object[] options, final Object initialSelectionValue) {
            final JOptionPane pane = new JOptionPane(message, messageType, JOptionPane.OK_CANCEL_OPTION, icon, options, null);

            pane.setWantsInput(true);
            pane.setInitialSelectionValue(initialSelectionValue);

            final JDialog dialog = pane.createDialog(parentComponent, title);

            pane.selectInitialValue();
            dialog.setVisible(true);
            dialog.dispose();

            final Object value = pane.getValue();

            if (value == null || value.equals(cancelButtonText)) {
                return null;
            }
            return pane.getInputValue();
        }

        public void actionPerformed(final ActionEvent e) {
            final JFileChooser fc = getFileChooser();
            final File currentDirectory = fc.getCurrentDirectory();
            File newFolder = null;
            final String[] options = {createButtonText, cancelButtonText};
            final String filename = (String)showNewFolderDialog(fc, //parentComponent
                    newFolderDialogPrompt, // message
                    newFolderTitleText, // title
                    JOptionPane.PLAIN_MESSAGE, // messageType
                    null, // icon
                    options, // selectionValues
                    newFolderDefaultName); // initialSelectionValue

            if (filename != null) {
                try {
                    newFolder = fc.getFileSystemView().createFileObject(currentDirectory, filename);
                    if (newFolder.exists()) {
                        JOptionPane.showMessageDialog(fc, newFolderExistsErrorText, "", JOptionPane.ERROR_MESSAGE);
                        return;
                    }

                    newFolder.mkdirs();
                } catch(final Exception exc) {
                    JOptionPane.showMessageDialog(fc, newFolderErrorText, "", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                openDirectory(newFolder);
            }
        }
    }

    /**
     * Responds to an Open, Save, or Choose request
     */
    protected class ApproveSelectionAction extends AbstractAction {
        public void actionPerformed(final ActionEvent e) {
            fSubPanel.approveSelection(getFileChooser());
        }
    }

    /**
     * Responds to an OpenDirectory request
     */
    protected class OpenSelectionAction extends AbstractAction {
        public void actionPerformed(final ActionEvent e) {
            final int index = fFileList.getSelectedRow();
            if (index >= 0) {
                final File selectedFile = (File)((AquaFileSystemModel)fFileList.getModel()).getElementAt(index);
                if (selectedFile != null) openDirectory(selectedFile);
            }
        }
    }

    /**
     * Responds to a cancel request.
     */
    protected class CancelSelectionAction extends AbstractAction {
        public void actionPerformed(final ActionEvent e) {
            getFileChooser().cancelSelection();
        }

        public boolean isEnabled() {
            return getFileChooser().isEnabled();
        }
    }

    /**
     * Rescans the files in the current directory
     */
    protected class UpdateAction extends AbstractAction {
        public void actionPerformed(final ActionEvent e) {
            final JFileChooser fc = getFileChooser();
            fc.setCurrentDirectory(fc.getFileSystemView().createFileObject(getDirectoryName()));
            fc.rescanCurrentDirectory();
        }
    }

    // *****************************************
    // ***** default AcceptAll file filter *****
    // *****************************************
    protected class AcceptAllFileFilter extends FileFilter {
        public AcceptAllFileFilter() {
        }

        public boolean accept(final File f) {
            return true;
        }

        public String getDescription() {
            return UIManager.getString("FileChooser.acceptAllFileFilterText");
        }
    }

    // Penultimate superclass is JLabel
    protected class MacFCTableCellRenderer extends DefaultTableCellRenderer {
        boolean fIsSelected = false;

        public MacFCTableCellRenderer(final Font f) {
            super();
            setFont(f);
            setIconTextGap(10);
        }

        public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, final boolean cellHasFocus, final int index, final int col) {
            super.getTableCellRendererComponent(list, value, isSelected, false, index, col); // No focus border, thanks
            fIsSelected = isSelected;
            return this;
        }

        public boolean isSelected() {
            return fIsSelected && isEnabled();
        }

        protected String layoutCL(final JLabel label, final FontMetrics fontMetrics, final String text, final Icon icon, final Rectangle viewR, final Rectangle iconR, final Rectangle textR) {
            return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon, label.getVerticalAlignment(), label.getHorizontalAlignment(), label.getVerticalTextPosition(), label.getHorizontalTextPosition(), viewR, iconR, textR, label.getIconTextGap());
        }

        protected void paintComponent(final Graphics g) {
            final String text = getText();
            Icon icon = getIcon();
            if (icon != null && !isEnabled()) {
                final Icon disabledIcon = getDisabledIcon();
                if (disabledIcon != null) icon = disabledIcon;
            }

            if ((icon == null) && (text == null)) { return; }

            // from ComponentUI update
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth(), getHeight());

            // from BasicLabelUI paint
            final FontMetrics fm = g.getFontMetrics();
            Insets paintViewInsets = getInsets(null);
            paintViewInsets.left += 10;

            Rectangle paintViewR = new Rectangle(paintViewInsets.left, paintViewInsets.top, getWidth() - (paintViewInsets.left + paintViewInsets.right), getHeight() - (paintViewInsets.top + paintViewInsets.bottom));

            Rectangle paintIconR = new Rectangle();
            Rectangle paintTextR = new Rectangle();

            final String clippedText = layoutCL(this, fm, text, icon, paintViewR, paintIconR, paintTextR);

            if (icon != null) {
                icon.paintIcon(this, g, paintIconR.x + 5, paintIconR.y);
            }

            if (text != null) {
                final int textX = paintTextR.x;
                final int textY = paintTextR.y + fm.getAscent() + 1;
                if (isEnabled()) {
                    // Color background = fIsSelected ? getForeground() : getBackground();
                    final Color background = getBackground();

                    g.setColor(background);
                    g.fillRect(textX - 1, paintTextR.y, paintTextR.width + 2, fm.getAscent() + 2);

                    g.setColor(getForeground());
                    SwingUtilities2.drawString(filechooser, g, clippedText, textX, textY);
                } else {
                    final Color background = getBackground();
                    g.setColor(background);
                    g.fillRect(textX - 1, paintTextR.y, paintTextR.width + 2, fm.getAscent() + 2);

                    g.setColor(background.brighter());
                    SwingUtilities2.drawString(filechooser, g, clippedText, textX, textY);
                    g.setColor(background.darker());
                    SwingUtilities2.drawString(filechooser, g, clippedText, textX + 1, textY + 1);
                }
            }
        }

    }

    protected class FileRenderer extends MacFCTableCellRenderer {
        public FileRenderer(final Font f) {
            super(f);
        }

        public Component getTableCellRendererComponent(final JTable list,
                                                       final Object value,
                                                       final boolean isSelected,
                                                       final boolean cellHasFocus,
                                                       final int index,
                                                       final int col) {
            super.getTableCellRendererComponent(list, value, isSelected, false,
                                                index,
                                                col); // No focus border, thanks
            final File file = (File)value;
            final JFileChooser fc = getFileChooser();
            setText(fc.getName(file));
            setIcon(fc.getIcon(file));
            setEnabled(isSelectableInList(file));
            return this;
        }
    }

    protected class DateRenderer extends MacFCTableCellRenderer {
        public DateRenderer(final Font f) {
            super(f);
        }

        public Component getTableCellRendererComponent(final JTable list,
                                                       final Object value,
                                                       final boolean isSelected,
                                                       final boolean cellHasFocus,
                                                       final int index,
                                                       final int col) {
            super.getTableCellRendererComponent(list, value, isSelected, false,
                                                index, col);
            final File file = (File)fFileList.getValueAt(index, 0);
            setEnabled(isSelectableInList(file));
            final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT);
            final Date date = (Date)value;

            if (date != null) {
                setText(formatter.format(date));
            } else {
                setText("");
            }

            return this;
        }
    }

    @Override
    public Dimension getPreferredSize(final JComponent c) {
        return new Dimension(PREF_WIDTH, PREF_HEIGHT);
    }

    @Override
    public Dimension getMinimumSize(final JComponent c) {
        return new Dimension(MIN_WIDTH, MIN_HEIGHT);
    }

    @Override
    public Dimension getMaximumSize(final JComponent c) {
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    protected ListCellRenderer createDirectoryComboBoxRenderer(final JFileChooser fc) {
        return new AquaComboBoxRendererInternal(directoryComboBox) {
            public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                final File directory = (File)value;
                if (directory == null) {
                    setText("");
                    return this;
                }

                final JFileChooser chooser = getFileChooser();
                setText(chooser.getName(directory));
                setIcon(chooser.getIcon(directory));
                return this;
            }
        };
    }

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

    /**
     * Data model for a type-face selection combo-box.
     */
    protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
        Vector<File> fDirectories = new Vector<File>();
        int topIndex = -1;
        int fPathCount = 0;

        File fSelectedDirectory = null;

        public DirectoryComboBoxModel() {
            super();
            // Add the current directory to the model, and make it the
            // selectedDirectory
            addItem(getFileChooser().getCurrentDirectory());
        }

        /**
         * Removes the selected directory, and clears out the
         * path file entries leading up to that directory.
         */
        private void removeSelectedDirectory() {
            fDirectories.removeAllElements();
            fPathCount = 0;
            fSelectedDirectory = null;
            // dump();
        }

        /**
         * 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.
         */
        void addItem(final File directory) {
            if (directory == null) { return; }
            if (fSelectedDirectory != null) {
                removeSelectedDirectory();
            }

            // create File instances of each directory leading up to the top
            File f = directory.getAbsoluteFile();
            final Vector<File> path = new Vector<File>(10);
            while (f.getParent() != null) {
                path.addElement(f);
                f = getFileChooser().getFileSystemView().createFileObject(f.getParent());
            };

            // Add root file (the desktop) to the model
            final File[] roots = getFileChooser().getFileSystemView().getRoots();
            for (final File element : roots) {
                path.addElement(element);
            }
            fPathCount = path.size();

            // insert all the path fDirectories leading up to the
            // selected directory in reverse order (current directory at top)
            for (int i = 0; i < path.size(); i++) {
                fDirectories.addElement(path.elementAt(i));
            }

            setSelectedItem(fDirectories.elementAt(0));

            // dump();
        }

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

        public Object getSelectedItem() {
            return fSelectedDirectory;
        }

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

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

    //
    // Renderer for Types ComboBox
    //
    protected ListCellRenderer createFilterComboBoxRenderer() {
        return new AquaComboBoxRendererInternal(filterComboBox) {
            public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                final FileFilter filter = (FileFilter)value;
                if (filter != null) setText(filter.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<FileFilter> implements ComboBoxModel<FileFilter>,
            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) {
                setSelectedItem(e.getNewValue());
            }
        }

        public void setSelectedItem(Object filter) {
            if (filter != null && !containsFileFilter(filter)) {
                getFileChooser().setFileFilter((FileFilter) filter);
                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 (FileFilter filter : filters) {
                    if (filter == 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 FileFilter 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;
            }
        }
    }

    private boolean containsFileFilter(Object fileFilter) {
        return Objects.equals(fileFilter, getFileChooser().getFileFilter());
    }

    /**
     * Acts when FilterComboBox has changed the selected item.
     */
    protected class FilterComboBoxAction extends AbstractAction {
        protected FilterComboBoxAction() {
            super("FilterComboBoxAction");
        }

        public void actionPerformed(final ActionEvent e) {
            Object selectedFilter = filterComboBox.getSelectedItem();
            if (!containsFileFilter(selectedFilter)) {
                getFileChooser().setFileFilter((FileFilter) selectedFilter);
            }
        }
    }

    /**
     * Acts when DirectoryComboBox has changed the selected item.
     */
    protected class DirectoryComboBoxAction extends AbstractAction {
        protected DirectoryComboBoxAction() {
            super("DirectoryComboBoxAction");
        }

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

    // Sorting Table operations
    class JSortingTableHeader extends JTableHeader {
        public JSortingTableHeader(final TableColumnModel cm) {
            super(cm);
            setReorderingAllowed(true); // This causes mousePress to call setDraggedColumn
        }

        // One sort state for each column.  Both are ascending by default
        final boolean fSortAscending[] = {true, true};

        // Instead of dragging, it selects which one to sort by
        public void setDraggedColumn(final TableColumn aColumn) {
            if (aColumn != null) {
                final int colIndex = aColumn.getModelIndex();
                if (colIndex != fSortColumn) {
                    filechooser.firePropertyChange(AquaFileSystemModel.SORT_BY_CHANGED, fSortColumn, colIndex);
                    fSortColumn = colIndex;
                } else {
                    fSortAscending[colIndex] = !fSortAscending[colIndex];
                    filechooser.firePropertyChange(AquaFileSystemModel.SORT_ASCENDING_CHANGED, !fSortAscending[colIndex], fSortAscending[colIndex]);
                }
                // Need to repaint the highlighted column.
                repaint();
            }
        }

        // This stops mouseDrags from moving the column
        public TableColumn getDraggedColumn() {
            return null;
        }

        protected TableCellRenderer createDefaultRenderer() {
            final DefaultTableCellRenderer label = new AquaTableCellRenderer();
            label.setHorizontalAlignment(SwingConstants.LEFT);
            return label;
        }

        class AquaTableCellRenderer extends DefaultTableCellRenderer implements UIResource {
            public Component getTableCellRendererComponent(final JTable localTable, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
                if (localTable != null) {
                    final JTableHeader header = localTable.getTableHeader();
                    if (header != null) {
                        setForeground(header.getForeground());
                        setBackground(header.getBackground());
                        setFont(UIManager.getFont("TableHeader.font"));
                    }
                }

                setText((value == null) ? "" : value.toString());

                // Modify the table "border" to draw smaller, and with the titles in the right position
                // and sort indicators, just like an NSSave/Open panel.
                final AquaTableHeaderBorder cellBorder = AquaTableHeaderBorder.getListHeaderBorder();
                cellBorder.setSelected(column == fSortColumn);
                final int horizontalShift = (column == 0 ? 35 : 10);
                cellBorder.setHorizontalShift(horizontalShift);

                if (column == fSortColumn) {
                    cellBorder.setSortOrder(fSortAscending[column] ? AquaTableHeaderBorder.SORT_ASCENDING : AquaTableHeaderBorder.SORT_DECENDING);
                } else {
                    cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE);
                }
                setBorder(cellBorder);
                return this;
            }
        }
    }

    public void installComponents(final JFileChooser fc) {
        JPanel tPanel; // temp panel
        // set to a Y BoxLayout. The chooser will be laid out top to bottom.
        fc.setLayout(new BoxLayout(fc, BoxLayout.Y_AXIS));
        fc.add(Box.createRigidArea(vstrut10));

        // construct the top panel

        final JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
        fc.add(topPanel);
        fc.add(Box.createRigidArea(vstrut10));

        // Add the textfield pane

        fTextfieldPanel = new JPanel();
        fTextfieldPanel.setLayout(new BorderLayout());
        // setBottomPanelForMode will make this visible if we need it
        fTextfieldPanel.setVisible(false);
        topPanel.add(fTextfieldPanel);

        tPanel = new JPanel();
        tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.Y_AXIS));
        final JPanel labelArea = new JPanel();
        labelArea.setLayout(new FlowLayout(FlowLayout.CENTER));
        fTextFieldLabel = new JLabel(fileNameLabelText);
        labelArea.add(fTextFieldLabel);

        // text field
        filenameTextField = new JTextField();
        fTextFieldLabel.setLabelFor(filenameTextField);
        filenameTextField.addActionListener(getAction(kOpen));
        filenameTextField.addFocusListener(new SaveTextFocusListener());
        final Dimension minSize = filenameTextField.getMinimumSize();
        Dimension d = new Dimension(250, (int)minSize.getHeight());
        filenameTextField.setPreferredSize(d);
        filenameTextField.setMaximumSize(d);
        labelArea.add(filenameTextField);
        final File f = fc.getSelectedFile();
        if (f != null) {
            setFileName(fc.getName(f));
        } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
            setFileName(newFileDefaultName);
        }

        tPanel.add(labelArea);
        // separator line
        final JSeparator sep = new JSeparator(){
            public Dimension getPreferredSize() {
                return new Dimension(((JComponent)getParent()).getWidth(), 3);
            }
        };
        tPanel.add(Box.createRigidArea(new Dimension(1, 8)));
        tPanel.add(sep);
        tPanel.add(Box.createRigidArea(new Dimension(1, 7)));
        fTextfieldPanel.add(tPanel, BorderLayout.CENTER);

        // DirectoryComboBox, left-justified, 200x20 not including drop shadow
        directoryComboBox = new JComboBox();
        directoryComboBox.putClientProperty("JComboBox.lightweightKeyboardNavigation", "Lightweight");
        fDirectoryComboBoxModel = createDirectoryComboBoxModel(fc);
        directoryComboBox.setModel(fDirectoryComboBoxModel);
        directoryComboBox.addActionListener(directoryComboBoxAction);
        directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
        directoryComboBox.setToolTipText(directoryComboBoxToolTipText);
        d = new Dimension(250, (int)directoryComboBox.getMinimumSize().getHeight());
        directoryComboBox.setPreferredSize(d);
        directoryComboBox.setMaximumSize(d);
        topPanel.add(directoryComboBox);

        // ************************************** //
        // ** Add the directory/Accessory pane ** //
        // ************************************** //
        final JPanel centerPanel = new JPanel(new BorderLayout());
        fc.add(centerPanel);

        // Accessory pane (equiv to Preview pane in NavServices)
        final JComponent accessory = fc.getAccessory();
        if (accessory != null) {
            getAccessoryPanel().add(accessory);
        }
        centerPanel.add(getAccessoryPanel(), BorderLayout.LINE_START);

        // Directory list(table), right-justified, resizable
        final JPanel p = createList(fc);
        p.setMinimumSize(LIST_MIN_SIZE);
        centerPanel.add(p, BorderLayout.CENTER);

        // ********************************** //
        // **** Construct the bottom panel ** //
        // ********************************** //
        fBottomPanel = new JPanel();
        fBottomPanel.setLayout(new BoxLayout(fBottomPanel, BoxLayout.Y_AXIS));
        fc.add(fBottomPanel);

        // Filter label and combobox.
        // I know it's unMaclike, but the filter goes on Directory_only too.
        tPanel = new JPanel();
        tPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
        tPanel.setBorder(AquaGroupBorder.getTitlelessBorder());
        final JLabel formatLabel = new JLabel(filesOfTypeLabelText);
        tPanel.add(formatLabel);

        // Combobox
        filterComboBoxModel = createFilterComboBoxModel();
        fc.addPropertyChangeListener(filterComboBoxModel);
        filterComboBox = new JComboBox(filterComboBoxModel);
        formatLabel.setLabelFor(filterComboBox);
        filterComboBox.setRenderer(createFilterComboBoxRenderer());
        d = new Dimension(220, (int)filterComboBox.getMinimumSize().getHeight());
        filterComboBox.setPreferredSize(d);
        filterComboBox.setMaximumSize(d);
        filterComboBox.addActionListener(filterComboBoxAction);
        filterComboBox.setOpaque(false);
        tPanel.add(filterComboBox);

        fBottomPanel.add(tPanel);

        // fDirectoryPanel: New, Open, Cancel, Approve buttons, right-justified, 82x22
        // (sometimes the NewFolder and OpenFolder buttons are invisible)
        fDirectoryPanel = new JPanel();
        fDirectoryPanel.setLayout(new BoxLayout(fDirectoryPanel, BoxLayout.PAGE_AXIS));
        JPanel directoryPanel = new JPanel(new BorderLayout());
        JPanel newFolderButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        newFolderButtonPanel.add(Box.createHorizontalStrut(20));
        fNewFolderButton = createNewFolderButton(); // Because we hide it depending on style
        newFolderButtonPanel.add(fNewFolderButton);
        directoryPanel.add(newFolderButtonPanel, BorderLayout.LINE_START);
        JPanel approveCancelButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 0, 0));
        fOpenButton = createButton(kOpenDirectory, openButtonText);
        approveCancelButtonPanel.add(fOpenButton);
        approveCancelButtonPanel.add(Box.createHorizontalStrut(8));
        fCancelButton = createButton(kCancel, null);
        approveCancelButtonPanel.add(fCancelButton);
        approveCancelButtonPanel.add(Box.createHorizontalStrut(8));
        // The ApproveSelection button
        fApproveButton = new JButton();
        fApproveButton.addActionListener(fApproveSelectionAction);
        approveCancelButtonPanel.add(fApproveButton);
        approveCancelButtonPanel.add(Box.createHorizontalStrut(20));
        directoryPanel.add(approveCancelButtonPanel, BorderLayout.LINE_END);
        fDirectoryPanel.add(Box.createVerticalStrut(5));
        fDirectoryPanel.add(directoryPanel);
        fDirectoryPanel.add(Box.createVerticalStrut(12));
        fDirectoryPanelSpacer = Box.createRigidArea(hstrut10);

        if (fc.getControlButtonsAreShown()) {
            fBottomPanel.add(fDirectoryPanelSpacer);
            fBottomPanel.add(fDirectoryPanel);
        }

        setBottomPanelForMode(fc); // updates ApproveButtonText etc

        // don't create til after the FCSubpanel and buttons are made
        filenameTextField.getDocument().addDocumentListener(new SaveTextDocumentListener());
    }

    void setDefaultButtonForMode(final JFileChooser fc) {
        final JButton defaultButton = fSubPanel.getDefaultButton(fc);
        final JRootPane root = defaultButton.getRootPane();
        if (root != null) {
            root.setDefaultButton(defaultButton);
        }
    }

    // Macs start with their focus in text areas if they have them,
    // lists otherwise (the other plafs start with the focus on approveButton)
    void setFocusForMode(final JFileChooser fc) {
        final JComponent focusComponent = fSubPanel.getFocusComponent(fc);
        if (focusComponent != null) {
            focusComponent.requestFocus();
        }
    }

    // Enable/disable buttons as needed for the current selection/focus state
    void updateButtonState(final JFileChooser fc) {
        fSubPanel.updateButtonState(fc, getFirstSelectedItem());
        updateApproveButton(fc);
    }

    void updateApproveButton(final JFileChooser chooser) {
        fApproveButton.setText(getApproveButtonText(chooser));
        fApproveButton.setToolTipText(getApproveButtonToolTipText(chooser));
        fApproveButton.setMnemonic(getApproveButtonMnemonic(chooser));
        fCancelButton.setToolTipText(getCancelButtonToolTipText(chooser));
    }

    // Lazy-init the subpanels
    synchronized FCSubpanel getSaveFilePanel() {
        if (fSaveFilePanel == null) fSaveFilePanel = new SaveFilePanel();
        return fSaveFilePanel;
    }

    synchronized FCSubpanel getOpenFilePanel() {
        if (fOpenFilePanel == null) fOpenFilePanel = new OpenFilePanel();
        return fOpenFilePanel;
    }

    synchronized FCSubpanel getOpenDirOrAnyPanel() {
        if (fOpenDirOrAnyPanel == null) fOpenDirOrAnyPanel = new OpenDirOrAnyPanel();
        return fOpenDirOrAnyPanel;
    }

    synchronized FCSubpanel getCustomFilePanel() {
        if (fCustomFilePanel == null) fCustomFilePanel = new CustomFilePanel();
        return fCustomFilePanel;
    }

    synchronized FCSubpanel getCustomDirOrAnyPanel() {
        if (fCustomDirOrAnyPanel == null) fCustomDirOrAnyPanel = new CustomDirOrAnyPanel();
        return fCustomDirOrAnyPanel;
    }

    void setBottomPanelForMode(final JFileChooser fc) {
        if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) fSubPanel = getSaveFilePanel();
        else if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
            if (fc.getFileSelectionMode() == JFileChooser.FILES_ONLY) fSubPanel = getOpenFilePanel();
            else fSubPanel = getOpenDirOrAnyPanel();
        } else if (fc.getDialogType() == JFileChooser.CUSTOM_DIALOG) {
            if (fc.getFileSelectionMode() == JFileChooser.FILES_ONLY) fSubPanel = getCustomFilePanel();
            else fSubPanel = getCustomDirOrAnyPanel();
        }

        fSubPanel.installPanel(fc, true);
        updateApproveButton(fc);
        updateButtonState(fc);
        setDefaultButtonForMode(fc);
        setFocusForMode(fc);
        fc.invalidate();
    }

    // fTextfieldPanel and fDirectoryPanel both have NewFolder buttons; only one should be visible at a time
    JButton createNewFolderButton() {
        final JButton b = new JButton(newFolderButtonText);
        b.setToolTipText(newFolderToolTipText);
        b.getAccessibleContext().setAccessibleName(newFolderAccessibleName);
        b.setHorizontalTextPosition(SwingConstants.LEFT);
        b.setAlignmentX(Component.LEFT_ALIGNMENT);
        b.setAlignmentY(Component.CENTER_ALIGNMENT);
        b.addActionListener(getAction(kNewFolder));
        return b;
    }

    JButton createButton(final int which, String label) {
        if (label == null) label = UIManager.getString(sDataPrefix + sButtonKinds[which] + sButtonData[0]);
        final int mnemonic = UIManager.getInt(sDataPrefix + sButtonKinds[which] + sButtonData[1]);
        final String tipText = UIManager.getString(sDataPrefix + sButtonKinds[which] + sButtonData[2]);
        final JButton b = new JButton(label);
        b.setMnemonic(mnemonic);
        b.setToolTipText(tipText);
        b.addActionListener(getAction(which));
        return b;
    }

    AbstractAction getAction(final int which) {
        return fButtonActions[which];
    }

    public void uninstallComponents(final JFileChooser fc) { //$ Metal (on which this is based) doesn't uninstall its components.
    }

    // Consistent with the AppKit NSSavePanel, clicks on a file (not a directory) should populate the text field
    // with that file's display name.
    protected class FileListMouseListener extends MouseAdapter {
        public void mouseClicked(final MouseEvent e) {
            final Point p = e.getPoint();
            final int row = fFileList.rowAtPoint(p);
            final int column = fFileList.columnAtPoint(p);

            // The autoscroller can generate drag events outside the Table's range.
            if ((column == -1) || (row == -1)) { return; }

            final File clickedFile = (File)(fFileList.getValueAt(row, 0));

            // rdar://problem/3734130 -- don't populate the text field if this file isn't selectable in this mode.
            if (isSelectableForMode(getFileChooser(), clickedFile)) {
                // [3188387] Populate the file name field with the selected file name
                // [3484163] It should also use the display name, not the actual name.
                setFileName(fileView.getName(clickedFile));
            }
        }
    }

    protected JPanel createList(final JFileChooser fc) {
        // The first part is similar to MetalFileChooserUI.createList - same kind of listeners
        final JPanel p = new JPanel(new BorderLayout());
        fFileList = new JTableExtension();
        fFileList.setToolTipText(null); // Workaround for 2487689
        fFileList.addMouseListener(new FileListMouseListener());
        model = new AquaFileSystemModel(fc, fFileList, fColumnNames);
        final MacListSelectionModel listSelectionModel = new MacListSelectionModel(model);

        if (getFileChooser().isMultiSelectionEnabled()) {
            listSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        } else {
            listSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        }

        fFileList.setModel(model);
        fFileList.setSelectionModel(listSelectionModel);
        fFileList.getSelectionModel().addListSelectionListener(createListSelectionListener(fc));

        // Now we're different, because we're a table, not a list
        fc.addPropertyChangeListener(model);
        fFileList.addFocusListener(new SaveTextFocusListener());
        final JTableHeader th = new JSortingTableHeader(fFileList.getColumnModel());
        fFileList.setTableHeader(th);
        fFileList.setRowMargin(0);
        fFileList.setIntercellSpacing(new Dimension(0, 1));
        fFileList.setShowVerticalLines(false);
        fFileList.setShowHorizontalLines(false);
        final Font f = fFileList.getFont(); //ThemeFont.GetThemeFont(AppearanceConstants.kThemeViewsFont);
        //fc.setFont(f);
        //fFileList.setFont(f);
        fFileList.setDefaultRenderer(File.class, new FileRenderer(f));
        fFileList.setDefaultRenderer(Date.class, new DateRenderer(f));
        final FontMetrics fm = fFileList.getFontMetrics(f);

        // Row height isn't based on the renderers.  It defaults to 16 so we have to set it
        fFileList.setRowHeight(Math.max(fm.getHeight(), fileIcon.getIconHeight() + 2));

        // Add a binding for the file list that triggers return and escape
        fFileList.registerKeyboardAction(new CancelSelectionAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED);
        // Add a binding for the file list that triggers the default button (see DefaultButtonAction)
        fFileList.registerKeyboardAction(new DefaultButtonAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_FOCUSED);
        fFileList.setDropTarget(dragAndDropTarget);

        final JScrollPane scrollpane = new JScrollPane(fFileList, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollpane.setComponentOrientation(ComponentOrientation.getOrientation(Locale.getDefault()));
        scrollpane.setCorner(ScrollPaneConstants.UPPER_TRAILING_CORNER, new ScrollPaneCornerPanel());
        p.add(scrollpane, BorderLayout.CENTER);
        return p;
    }

    protected class ScrollPaneCornerPanel extends JPanel {
        final Border border = UIManager.getBorder("TableHeader.cellBorder");

        protected void paintComponent(final Graphics g) {
            border.paintBorder(this, g, 0, 0, getWidth() + 1, getHeight());
        }
    }

    JComboBox directoryComboBox;
    DirectoryComboBoxModel fDirectoryComboBoxModel;
    private final Action directoryComboBoxAction = new DirectoryComboBoxAction();

    JTextField filenameTextField;

    JTableExtension fFileList;

    private FilterComboBoxModel filterComboBoxModel;
    JComboBox filterComboBox;
    private final Action filterComboBoxAction = new FilterComboBoxAction();

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

    private static final int PREF_WIDTH = 550;
    private static final int PREF_HEIGHT = 400;
    private static final int MIN_WIDTH = 400;
    private static final int MIN_HEIGHT = 250;
    private static final int LIST_MIN_WIDTH = 400;
    private static final int LIST_MIN_HEIGHT = 100;
    private static final Dimension LIST_MIN_SIZE = new Dimension(LIST_MIN_WIDTH, LIST_MIN_HEIGHT);

    static String fileNameLabelText = null;
    JLabel fTextFieldLabel = null;

    private static String filesOfTypeLabelText = null;

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

    private static final String[] fColumnNames = new String[2];

    JPanel fTextfieldPanel; // Filename textfield for Save or Custom
    private JPanel fDirectoryPanel; // NewFolder/OpenFolder/Cancel/Approve buttons
    private Component fDirectoryPanelSpacer;
    private JPanel fBottomPanel; // The panel that holds fDirectoryPanel and filterComboBox

    private FCSubpanel fSaveFilePanel = null;
    private FCSubpanel fOpenFilePanel = null;
    private FCSubpanel fOpenDirOrAnyPanel = null;
    private FCSubpanel fCustomFilePanel = null;
    private FCSubpanel fCustomDirOrAnyPanel = null;

    FCSubpanel fSubPanel = null; // Current FCSubpanel

    JButton fApproveButton; // mode-specific behavior is managed by FCSubpanel.approveSelection
    JButton fOpenButton; // for Directories
    JButton fNewFolderButton; // for fDirectoryPanel

    // ToolTip text varies with type of dialog
    private JButton fCancelButton;

    private final ApproveSelectionAction fApproveSelectionAction = new ApproveSelectionAction();
    protected int fSortColumn = 0;
    protected int fPackageIsTraversable = -1;
    protected int fApplicationIsTraversable = -1;

    protected static final int sGlobalPackageIsTraversable;
    protected static final int sGlobalApplicationIsTraversable;

    protected static final String PACKAGE_TRAVERSABLE_PROPERTY = "JFileChooser.packageIsTraversable";
    protected static final String APPLICATION_TRAVERSABLE_PROPERTY = "JFileChooser.appBundleIsTraversable";
    protected static final String[] sTraversableProperties = {"always", // Bundle is always traversable
            "never", // Bundle is never traversable
            "conditional"}; // Bundle is traversable on command click
    protected static final int kOpenAlways = 0, kOpenNever = 1, kOpenConditional = 2;

    AbstractAction[] fButtonActions = {fApproveSelectionAction, fApproveSelectionAction, new CancelSelectionAction(), new OpenSelectionAction(), null, new NewFolderAction()};

    static int parseTraversableProperty(final String s) {
        if (s == null) return -1;
        for (int i = 0; i < sTraversableProperties.length; i++) {
            if (s.equals(sTraversableProperties[i])) return i;
        }
        return -1;
    }

    static {
        Object o = UIManager.get(PACKAGE_TRAVERSABLE_PROPERTY);
        if (o != null && o instanceof String) sGlobalPackageIsTraversable = parseTraversableProperty((String)o);
        else sGlobalPackageIsTraversable = kOpenConditional;

        o = UIManager.get(APPLICATION_TRAVERSABLE_PROPERTY);
        if (o != null && o instanceof String) sGlobalApplicationIsTraversable = parseTraversableProperty((String)o);
        else sGlobalApplicationIsTraversable = kOpenConditional;
    }
    static final String sDataPrefix = "FileChooser.";
    static final String[] sButtonKinds = {"openButton", "saveButton", "cancelButton", "openDirectoryButton", "helpButton", "newFolderButton"};
    static final String[] sButtonData = {"Text", "Mnemonic", "ToolTipText"};
    static final int kOpen = 0, kSave = 1, kCancel = 2, kOpenDirectory = 3, kHelp = 4, kNewFolder = 5;

    /*-------

     Possible states: Save, {Open, Custom}x{Files, File and Directory, Directory}
     --------- */

    // This class returns the values for the Custom type, to avoid duplicating code in the two Custom subclasses
    abstract class FCSubpanel {
        // Install the appropriate panels for this mode
        abstract void installPanel(JFileChooser fc, boolean controlButtonsAreShown);

        abstract void updateButtonState(JFileChooser fc, File f);

        // Can this item be selected?
        // if not, it's disabled in the list
        boolean isSelectableInList(final JFileChooser fc, final File f) {
            if (f == null) return false;
            if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) return fc.isTraversable(f);
            return fc.accept(f);
        }

        void approveSelection(final JFileChooser fc) {
            fc.approveSelection();
        }

        JButton getDefaultButton(final JFileChooser fc) {
            return fApproveButton;
        }

        // Default to the textfield, panels without one should subclass
        JComponent getFocusComponent(final JFileChooser fc) {
            return filenameTextField;
        }

        String getApproveButtonText(final JFileChooser fc) {
            // Fallback to "choose"
            return this.getApproveButtonText(fc, chooseButtonText);
        }

        // Try to get the custom text.  If none, use the fallback
        String getApproveButtonText(final JFileChooser fc, final String fallbackText) {
            final String buttonText = fc.getApproveButtonText();
            if (buttonText != null) {
                buttonText.trim();
                if (!buttonText.equals("")) return buttonText;
            }
            return fallbackText;
        }

        int getApproveButtonMnemonic(final JFileChooser fc) {
            // Don't use a default
            return fc.getApproveButtonMnemonic();
        }

        // No fallback
        String getApproveButtonToolTipText(final JFileChooser fc) {
            return getApproveButtonToolTipText(fc, null);
        }

        String getApproveButtonToolTipText(final JFileChooser fc, final String fallbackText) {
            final String tooltipText = fc.getApproveButtonToolTipText();
            if (tooltipText != null) {
                tooltipText.trim();
                if (!tooltipText.equals("")) return tooltipText;
            }
            return fallbackText;
        }

        String getCancelButtonToolTipText(final JFileChooser fc) {
            return cancelChooseButtonToolTipText;
        }
    }

    // Custom FILES_ONLY dialog
    /*
     NavServices Save appearance with Open behavior
     Approve button label = Open when list has focus and a directory is selected, Custom otherwise
     No OpenDirectory button - Approve button is overloaded
     Default button / double click = Approve
     Has text field
     List - everything is enabled
     */
    class CustomFilePanel extends FCSubpanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            fTextfieldPanel.setVisible(true); // do we really want one in multi-select?  It's confusing
            fOpenButton.setVisible(false);
            fNewFolderButton.setVisible(true);
        }

        // If the list has focus, the mode depends on the selection
        // - directory = open, file = approve
        // If something else has focus and we have text, it's approve
        // otherwise, it depends on selection again.
        boolean inOpenDirectoryMode(final JFileChooser fc, final File f) {
            final boolean selectionIsDirectory = (f != null && fc.isTraversable(f));
            if (fFileList.hasFocus()) return selectionIsDirectory;
            else if (textfieldIsValid()) return false;
            return selectionIsDirectory;
        }

        // The approve button is overloaded to mean OpenDirectory or Save
        void approveSelection(final JFileChooser fc) {
            File f = getFirstSelectedItem();
            if (inOpenDirectoryMode(fc, f)) {
                openDirectory(f);
            } else {
                f = makeFile(fc, getFileName());
                if (f != null) {
                    selectionInProgress = true;
                    getFileChooser().setSelectedFile(f);
                    selectionInProgress = false;
                }
                getFileChooser().approveSelection();
            }
        }

        // The approve button should be enabled
        // - if something in the list can be opened
        // - if the textfield has something in it
        void updateButtonState(final JFileChooser fc, final File f) {
            boolean enabled = true;
            if (!inOpenDirectoryMode(fc, f)) {
                enabled = (f != null) || textfieldIsValid();
            }
            getApproveButton(fc).setEnabled(enabled);

            // The OpenDirectory button should be disabled if there's no directory selected
            fOpenButton.setEnabled(f != null && fc.isTraversable(f));

            // Update the default button, since we may have disabled the current default.
            setDefaultButtonForMode(fc);
        }

        // everything's enabled, because we don't know what they're doing with them
        boolean isSelectableInList(final JFileChooser fc, final File f) {
            if (f == null) return false;
            return fc.accept(f);
        }

        String getApproveButtonToolTipText(final JFileChooser fc) {
            // The approve Button should have openDirectoryButtonToolTipText when the selection is a folder...
            if (inOpenDirectoryMode(fc, getFirstSelectedItem())) return openDirectoryButtonToolTipText;
            return super.getApproveButtonToolTipText(fc);
        }
    }

    // All Save dialogs
    /*
     NavServices Save
     Approve button label = Open when list has focus and a directory is selected, Save otherwise
     No OpenDirectory button - Approve button is overloaded
     Default button / double click = Approve
     Has text field
     Has NewFolder button (by text field)
     List - only traversables are enabled
     List is always SINGLE_SELECT
     */
    // Subclasses CustomFilePanel because they look alike and have some common behavior
    class SaveFilePanel extends CustomFilePanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            fTextfieldPanel.setVisible(true);
            fOpenButton.setVisible(false);
            fNewFolderButton.setVisible(true);
        }

        // only traversables are enabled, regardless of mode
        // because all you can do is select the next folder to open
        boolean isSelectableInList(final JFileChooser fc, final File f) {
            return fc.accept(f) && fc.isTraversable(f);
        }

        // The approve button means 'approve the file name in the text field.'
        void approveSelection(final JFileChooser fc) {
            final File f = makeFile(fc, getFileName());
            if (f != null) {
                selectionInProgress = true;
                getFileChooser().setSelectedFile(f);
                selectionInProgress = false;
                getFileChooser().approveSelection();
            }
        }

        // The approve button should be enabled if the textfield has something in it
        void updateButtonState(final JFileChooser fc, final File f) {
            final boolean enabled = textfieldIsValid();
            getApproveButton(fc).setEnabled(enabled);
        }

        String getApproveButtonText(final JFileChooser fc) {
            // Get the custom text, or fallback to "Save"
            return this.getApproveButtonText(fc, saveButtonText);
        }

        int getApproveButtonMnemonic(final JFileChooser fc) {
            return saveButtonMnemonic;
        }

        String getApproveButtonToolTipText(final JFileChooser fc) {
            // The approve Button should have openDirectoryButtonToolTipText when the selection is a folder...
            if (inOpenDirectoryMode(fc, getFirstSelectedItem())) return openDirectoryButtonToolTipText;
            return this.getApproveButtonToolTipText(fc, saveButtonToolTipText);
        }

        String getCancelButtonToolTipText(final JFileChooser fc) {
            return cancelSaveButtonToolTipText;
        }
    }

    // Open FILES_ONLY
    /*
     NSOpenPanel-style
     Approve button label = Open
     Default button / double click = Approve
     No text field
     No NewFolder button
     List - all items are enabled
     */
    class OpenFilePanel extends FCSubpanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            fTextfieldPanel.setVisible(false);
            fOpenButton.setVisible(false);
            fNewFolderButton.setVisible(false);
            setDefaultButtonForMode(fc);
        }

        boolean inOpenDirectoryMode(final JFileChooser fc, final File f) {
            return (f != null && fc.isTraversable(f));
        }

        // Default to the list
        JComponent getFocusComponent(final JFileChooser fc) {
            return fFileList;
        }

        void updateButtonState(final JFileChooser fc, final File f) {
            // Button is disabled if there's nothing selected
            final boolean enabled = (f != null) && !fc.isTraversable(f);
            getApproveButton(fc).setEnabled(enabled);
        }

        // all items are enabled
        boolean isSelectableInList(final JFileChooser fc, final File f) {
            return f != null && fc.accept(f);
        }

        String getApproveButtonText(final JFileChooser fc) {
            // Get the custom text, or fallback to "Open"
            return this.getApproveButtonText(fc, openButtonText);
        }

        int getApproveButtonMnemonic(final JFileChooser fc) {
            return openButtonMnemonic;
        }

        String getApproveButtonToolTipText(final JFileChooser fc) {
            return this.getApproveButtonToolTipText(fc, openButtonToolTipText);
        }

        String getCancelButtonToolTipText(final JFileChooser fc) {
            return cancelOpenButtonToolTipText;
        }
    }

    // used by open and custom panels for Directory only or files and directories
    abstract class DirOrAnyPanel extends FCSubpanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            fOpenButton.setVisible(false);
        }

        JButton getDefaultButton(final JFileChooser fc) {
            return getApproveButton(fc);
        }

        void updateButtonState(final JFileChooser fc, final File f) {
            // Button is disabled if there's nothing selected
            // Approve button is handled by the subclasses
            // getApproveButton(fc).setEnabled(f != null);

            // The OpenDirectory button should be disabled if there's no directory selected
            // - we only check the first item

            fOpenButton.setEnabled(false);
            setDefaultButtonForMode(fc);
        }
    }

    // Open FILES_AND_DIRECTORIES or DIRECTORIES_ONLY
    /*
     NavServices Choose
     Approve button label = Choose/Custom
     Has OpenDirectory button
     Default button / double click = OpenDirectory
     No text field
     List - files are disabled in DIRECTORIES_ONLY
     */
    class OpenDirOrAnyPanel extends DirOrAnyPanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            super.installPanel(fc, controlButtonsAreShown);
            fTextfieldPanel.setVisible(false);
            fNewFolderButton.setVisible(false);
        }

        // Default to the list
        JComponent getFocusComponent(final JFileChooser fc) {
            return fFileList;
        }

        int getApproveButtonMnemonic(final JFileChooser fc) {
            return chooseButtonMnemonic;
        }

        String getApproveButtonToolTipText(final JFileChooser fc) {
            String fallbackText;
            if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) fallbackText = chooseFolderButtonToolTipText;
            else fallbackText = chooseItemButtonToolTipText;
            return this.getApproveButtonToolTipText(fc, fallbackText);
        }

        void updateButtonState(final JFileChooser fc, final File f) {
            // Button is disabled if there's nothing selected
            getApproveButton(fc).setEnabled(f != null);
            super.updateButtonState(fc, f);
        }
    }

    // Custom FILES_AND_DIRECTORIES or DIRECTORIES_ONLY
    /*
     No NavServices equivalent
     Approve button label = user defined or Choose
     Has OpenDirectory button
     Default button / double click = OpenDirectory
     Has text field
     Has NewFolder button (by text field)
     List - files are disabled in DIRECTORIES_ONLY
     */
    class CustomDirOrAnyPanel extends DirOrAnyPanel {
        void installPanel(final JFileChooser fc, final boolean controlButtonsAreShown) {
            super.installPanel(fc, controlButtonsAreShown);
            fTextfieldPanel.setVisible(true);
            fNewFolderButton.setVisible(true);
        }

        // If there's text, make a file and select it
        void approveSelection(final JFileChooser fc) {
            final File f = makeFile(fc, getFileName());
            if (f != null) {
                selectionInProgress = true;
                getFileChooser().setSelectedFile(f);
                selectionInProgress = false;
            }
            getFileChooser().approveSelection();
        }

        void updateButtonState(final JFileChooser fc, final File f) {
            // Button is disabled if there's nothing selected
            getApproveButton(fc).setEnabled(f != null || textfieldIsValid());
            super.updateButtonState(fc, f);
        }
    }

    // See FileRenderer - documents in Save dialogs draw disabled, so they shouldn't be selected
    class MacListSelectionModel extends DefaultListSelectionModel {
        AquaFileSystemModel fModel;

        MacListSelectionModel(final AquaFileSystemModel model) {
            fModel = model;
        }

        // Can the file be selected in this mode?
        // (files are visible even if they can't be selected)
        boolean isSelectableInListIndex(final int index) {
            final File file = (File)fModel.getValueAt(index, 0);
            return (file != null && isSelectableInList(file));
        }

        // Make sure everything in the selection interval is valid
        void verifySelectionInterval(int index0, int index1, boolean isSetSelection) {
            if (index0 > index1) {
                final int tmp = index1;
                index1 = index0;
                index0 = tmp;
            }
            int start = index0;
            int end;
            do {
                // Find the first selectable file in the range
                for (; start <= index1; start++) {
                    if (isSelectableInListIndex(start)) break;
                }
                end = -1;
                // Find the last selectable file in the range
                for (int i = start; i <= index1; i++) {
                    if (!isSelectableInListIndex(i)) {
                        break;
                    }
                    end = i;
                }
                // Select the range
                if (end >= 0) {
                    // If setting the selection, do "set" the first time to clear the old one
                    // after that do "add" to extend it
                    if (isSetSelection) {
                        super.setSelectionInterval(start, end);
                        isSetSelection = false;
                    } else {
                        super.addSelectionInterval(start, end);
                    }
                    start = end + 1;
                } else {
                    break;
                }
            } while (start <= index1);
        }

        public void setAnchorSelectionIndex(final int anchorIndex) {
            if (isSelectableInListIndex(anchorIndex)) super.setAnchorSelectionIndex(anchorIndex);
        }

        public void setLeadSelectionIndex(final int leadIndex) {
            if (isSelectableInListIndex(leadIndex)) super.setLeadSelectionIndex(leadIndex);
        }

        public void setSelectionInterval(final int index0, final int index1) {
            if (index0 == -1 || index1 == -1) { return; }

            if ((getSelectionMode() == SINGLE_SELECTION) || (index0 == index1)) {
                if (isSelectableInListIndex(index1)) super.setSelectionInterval(index1, index1);
            } else {
                verifySelectionInterval(index0, index1, true);
            }
        }

        public void addSelectionInterval(final int index0, final int index1) {
            if (index0 == -1 || index1 == -1) { return; }

            if (index0 == index1) {
                if (isSelectableInListIndex(index1)) super.addSelectionInterval(index1, index1);
                return;
            }

            if (getSelectionMode() != MULTIPLE_INTERVAL_SELECTION) {
                setSelectionInterval(index0, index1);
                return;
            }

            verifySelectionInterval(index0, index1, false);
        }
    }

    // Convenience, to translate from the JList directory view to the Mac-style JTable
    //   & minimize diffs between this and BasicFileChooserUI
    class JTableExtension extends JTable {
        public void setSelectedIndex(final int index) {
            getSelectionModel().setSelectionInterval(index, index);
        }

        public void removeSelectedIndex(final int index) {
            getSelectionModel().removeSelectionInterval(index, index);
        }

        public void ensureIndexIsVisible(final int index) {
            final Rectangle cellBounds = getCellRect(index, 0, false);
            if (cellBounds != null) {
                scrollRectToVisible(cellBounds);
            }
        }

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