/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

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

import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import sun.awt.shell.ShellFolder;
import sun.swing.SwingUtilities2;

/**
 * Motif FileChooserUI.
 *
 * @author Jeff Dinkins
 */
public class MotifFileChooserUI extends BasicFileChooserUI {

    private FilterComboBoxModel filterComboBoxModel;

    protected JList directoryList = null;
    protected JList fileList = null;

    protected JTextField pathField = null;
    protected JComboBox filterComboBox = null;
    protected JTextField filenameTextField = null;

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

    private static final Insets insets = new Insets(10, 10, 10, 10);

    private static Dimension prefListSize = new Dimension(75, 150);

    private static Dimension WITH_ACCELERATOR_PREF_SIZE = new Dimension(650, 450);
    private static Dimension PREF_SIZE = new Dimension(350, 450);
    private static Dimension MIN_SIZE = new Dimension(200, 300);

    private static Dimension PREF_ACC_SIZE = new Dimension(10, 10);
    private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1);

    private static Dimension MAX_SIZE = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);

    private static final Insets buttonMargin = new Insets(3, 3, 3, 3);

    private JPanel bottomPanel;

    protected JButton approveButton;

    private String enterFolderNameLabelText = null;
    private int enterFolderNameLabelMnemonic = 0;
    private String enterFileNameLabelText = null;
    private int enterFileNameLabelMnemonic = 0;

    private String filesLabelText = null;
    private int filesLabelMnemonic = 0;

    private String foldersLabelText = null;
    private int foldersLabelMnemonic = 0;

    private String pathLabelText = null;
    private int pathLabelMnemonic = 0;

    private String filterLabelText = null;
    private int filterLabelMnemonic = 0;

    private JLabel fileNameLabel;

    private void populateFileNameLabel() {
        if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
            fileNameLabel.setText(enterFolderNameLabelText);
            fileNameLabel.setDisplayedMnemonic(enterFolderNameLabelMnemonic);
        } else {
            fileNameLabel.setText(enterFileNameLabelText);
            fileNameLabel.setDisplayedMnemonic(enterFileNameLabelMnemonic);
        }
    }

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

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

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

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

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

    public String getDirectoryName() {
        return pathField.getText();
    }

    public void setDirectoryName(String dirname) {
        pathField.setText(dirname);
    }

    public void ensureFileIsVisible(JFileChooser fc, File f) {
        // PENDING(jeff)
    }

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

    public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
        return new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String prop = e.getPropertyName();
                if(prop.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
                    File f = (File) e.getNewValue();
                    if(f != null) {
                        setFileName(getFileChooser().getName(f));
                    }
                } else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
                    File[] files = (File[]) e.getNewValue();
                    JFileChooser fc = getFileChooser();
                    if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled()
                            || !files[0].isDirectory())) {
                        setFileName(fileNameString(files));
                    }
                } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
                    fileList.clearSelection();
                } else if(prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
                    directoryList.clearSelection();
                    ListSelectionModel sm = directoryList.getSelectionModel();
                    if (sm instanceof DefaultListSelectionModel) {
                        ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
                        sm.setAnchorSelectionIndex(0);
                    }
                    fileList.clearSelection();
                    sm = fileList.getSelectionModel();
                    if (sm instanceof DefaultListSelectionModel) {
                        ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
                        sm.setAnchorSelectionIndex(0);
                    }
                    File currentDirectory = getFileChooser().getCurrentDirectory();
                    if(currentDirectory != null) {
                        try {
                            setDirectoryName(ShellFolder.getNormalizedFile((File)e.getNewValue()).getPath());
                        } catch (IOException ioe) {
                            setDirectoryName(((File)e.getNewValue()).getAbsolutePath());
                        }
                        if ((getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) && !getFileChooser().isMultiSelectionEnabled()) {
                            setFileName(getDirectoryName());
                        }
                    }
                } else if(prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
                    if (fileNameLabel != null) {
                        populateFileNameLabel();
                    }
                    directoryList.clearSelection();
                } else if (prop.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
                    if(getFileChooser().isMultiSelectionEnabled()) {
                        fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
                    } else {
                        fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                        fileList.clearSelection();
                        getFileChooser().setSelectedFiles(null);
                    }
                } else if (prop.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
                    if(getAccessoryPanel() != null) {
                        if(e.getOldValue() != null) {
                            getAccessoryPanel().remove((JComponent) e.getOldValue());
                        }
                        JComponent accessory = (JComponent) e.getNewValue();
                        if(accessory != null) {
                            getAccessoryPanel().add(accessory, BorderLayout.CENTER);
                            getAccessoryPanel().setPreferredSize(PREF_ACC_SIZE);
                            getAccessoryPanel().setMaximumSize(MAX_SIZE);
                        } else {
                            getAccessoryPanel().setPreferredSize(ZERO_ACC_SIZE);
                            getAccessoryPanel().setMaximumSize(ZERO_ACC_SIZE);
                        }
                    }
                } else if (prop.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
                        prop.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY) ||
                        prop.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
                    approveButton.setText(getApproveButtonText(getFileChooser()));
                    approveButton.setToolTipText(getApproveButtonToolTipText(getFileChooser()));
                } else if (prop.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
                    doControlButtonsChanged(e);
                } else if (prop.equals("componentOrientation")) {
                    ComponentOrientation o = (ComponentOrientation)e.getNewValue();
                    JFileChooser cc = (JFileChooser)e.getSource();
                    if (o != (ComponentOrientation)e.getOldValue()) {
                        cc.applyComponentOrientation(o);
                    }
                }
            }
        };
    }

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

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

    public void uninstallUI(JComponent c) {
        getFileChooser().removeAll();
        super.uninstallUI(c);
    }

    public void installComponents(JFileChooser fc) {
        fc.setLayout(new BorderLayout(10, 10));
        fc.setAlignmentX(JComponent.CENTER_ALIGNMENT);

        JPanel interior = new JPanel() {
            public Insets getInsets() {
                return insets;
            }
        };
        interior.setInheritsPopupMenu(true);
        align(interior);
        interior.setLayout(new BoxLayout(interior, BoxLayout.PAGE_AXIS));

        fc.add(interior, BorderLayout.CENTER);

        // PENDING(jeff) - I18N
        JLabel l = new JLabel(pathLabelText);
        l.setDisplayedMnemonic(pathLabelMnemonic);
        align(l);
        interior.add(l);

        File currentDirectory = fc.getCurrentDirectory();
        String curDirName = null;
        if(currentDirectory != null) {
            curDirName = currentDirectory.getPath();
        }
        pathField = new JTextField(curDirName) {
            public Dimension getMaximumSize() {
                Dimension d = super.getMaximumSize();
                d.height = getPreferredSize().height;
                return d;
            }
        };
        pathField.setInheritsPopupMenu(true);
        l.setLabelFor(pathField);
        align(pathField);

        // Change to folder on return
        pathField.addActionListener(getUpdateAction());
        interior.add(pathField);

        interior.add(Box.createRigidArea(vstrut10));


        // CENTER: left, right accessory
        JPanel centerPanel = new JPanel();
        centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS));
        align(centerPanel);

        // left panel - Filter & folderList
        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
        align(leftPanel);

        // add the filter PENDING(jeff) - I18N
        l = new JLabel(filterLabelText);
        l.setDisplayedMnemonic(filterLabelMnemonic);
        align(l);
        leftPanel.add(l);

        filterComboBox = new JComboBox() {
            public Dimension getMaximumSize() {
                Dimension d = super.getMaximumSize();
                d.height = getPreferredSize().height;
                return d;
            }
        };
        filterComboBox.setInheritsPopupMenu(true);
        l.setLabelFor(filterComboBox);
        filterComboBoxModel = createFilterComboBoxModel();
        filterComboBox.setModel(filterComboBoxModel);
        filterComboBox.setRenderer(createFilterComboBoxRenderer());
        fc.addPropertyChangeListener(filterComboBoxModel);
        align(filterComboBox);
        leftPanel.add(filterComboBox);

        // leftPanel.add(Box.createRigidArea(vstrut10));

        // Add the Folder List PENDING(jeff) - I18N
        l = new JLabel(foldersLabelText);
        l.setDisplayedMnemonic(foldersLabelMnemonic);
        align(l);
        leftPanel.add(l);
        JScrollPane sp = createDirectoryList();
        sp.getVerticalScrollBar().setFocusable(false);
        sp.getHorizontalScrollBar().setFocusable(false);
        sp.setInheritsPopupMenu(true);
        l.setLabelFor(sp.getViewport().getView());
        leftPanel.add(sp);
        leftPanel.setInheritsPopupMenu(true);


        // create files list
        JPanel rightPanel = new JPanel();
        align(rightPanel);
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));
        rightPanel.setInheritsPopupMenu(true);

        l = new JLabel(filesLabelText);
        l.setDisplayedMnemonic(filesLabelMnemonic);
        align(l);
        rightPanel.add(l);
        sp = createFilesList();
        l.setLabelFor(sp.getViewport().getView());
        rightPanel.add(sp);
        sp.setInheritsPopupMenu(true);

        centerPanel.add(leftPanel);
        centerPanel.add(Box.createRigidArea(hstrut10));
        centerPanel.add(rightPanel);
        centerPanel.setInheritsPopupMenu(true);

        JComponent accessoryPanel = getAccessoryPanel();
        JComponent accessory = fc.getAccessory();
        if(accessoryPanel != null) {
            if(accessory == null) {
                accessoryPanel.setPreferredSize(ZERO_ACC_SIZE);
                accessoryPanel.setMaximumSize(ZERO_ACC_SIZE);
            } else {
                getAccessoryPanel().add(accessory, BorderLayout.CENTER);
                accessoryPanel.setPreferredSize(PREF_ACC_SIZE);
                accessoryPanel.setMaximumSize(MAX_SIZE);
            }
            align(accessoryPanel);
            centerPanel.add(accessoryPanel);
            accessoryPanel.setInheritsPopupMenu(true);
        }
        interior.add(centerPanel);
        interior.add(Box.createRigidArea(vstrut10));

        // add the filename field PENDING(jeff) - I18N
        fileNameLabel = new JLabel();
        populateFileNameLabel();
        align(fileNameLabel);
        interior.add(fileNameLabel);

        filenameTextField = new JTextField() {
            public Dimension getMaximumSize() {
                Dimension d = super.getMaximumSize();
                d.height = getPreferredSize().height;
                return d;
            }
        };
        filenameTextField.setInheritsPopupMenu(true);
        fileNameLabel.setLabelFor(filenameTextField);
        filenameTextField.addActionListener(getApproveSelectionAction());
        align(filenameTextField);
        filenameTextField.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        interior.add(filenameTextField);

        bottomPanel = getBottomPanel();
        bottomPanel.add(new JSeparator(), BorderLayout.NORTH);

        // Add buttons
        JPanel buttonPanel = new JPanel();
        align(buttonPanel);
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
        buttonPanel.add(Box.createGlue());

        approveButton = new JButton(getApproveButtonText(fc)) {
            public Dimension getMaximumSize() {
                return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
            }
        };
        approveButton.setMnemonic(getApproveButtonMnemonic(fc));
        approveButton.setToolTipText(getApproveButtonToolTipText(fc));
        approveButton.setInheritsPopupMenu(true);
        align(approveButton);
        approveButton.setMargin(buttonMargin);
        approveButton.addActionListener(getApproveSelectionAction());
        buttonPanel.add(approveButton);
        buttonPanel.add(Box.createGlue());

        JButton updateButton = new JButton(updateButtonText) {
            public Dimension getMaximumSize() {
                return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
            }
        };
        updateButton.setMnemonic(updateButtonMnemonic);
        updateButton.setToolTipText(updateButtonToolTipText);
        updateButton.setInheritsPopupMenu(true);
        align(updateButton);
        updateButton.setMargin(buttonMargin);
        updateButton.addActionListener(getUpdateAction());
        buttonPanel.add(updateButton);
        buttonPanel.add(Box.createGlue());

        JButton cancelButton = new JButton(cancelButtonText) {
            public Dimension getMaximumSize() {
                return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
            }
        };
        cancelButton.setMnemonic(cancelButtonMnemonic);
        cancelButton.setToolTipText(cancelButtonToolTipText);
        cancelButton.setInheritsPopupMenu(true);
        align(cancelButton);
        cancelButton.setMargin(buttonMargin);
        cancelButton.addActionListener(getCancelSelectionAction());
        buttonPanel.add(cancelButton);
        buttonPanel.add(Box.createGlue());

        JButton helpButton = new JButton(helpButtonText) {
            public Dimension getMaximumSize() {
                return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
            }
        };
        helpButton.setMnemonic(helpButtonMnemonic);
        helpButton.setToolTipText(helpButtonToolTipText);
        align(helpButton);
        helpButton.setMargin(buttonMargin);
        helpButton.setEnabled(false);
        helpButton.setInheritsPopupMenu(true);
        buttonPanel.add(helpButton);
        buttonPanel.add(Box.createGlue());
        buttonPanel.setInheritsPopupMenu(true);

        bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
        bottomPanel.setInheritsPopupMenu(true);
        if (fc.getControlButtonsAreShown()) {
           fc.add(bottomPanel, BorderLayout.SOUTH);
        }
    }

    protected JPanel getBottomPanel() {
        if (bottomPanel == null) {
            bottomPanel = new JPanel(new BorderLayout(0, 4));
        }
        return bottomPanel;
    }

    private void doControlButtonsChanged(PropertyChangeEvent e) {
        if (getFileChooser().getControlButtonsAreShown()) {
            getFileChooser().add(bottomPanel,BorderLayout.SOUTH);
        } else {
            getFileChooser().remove(getBottomPanel());
        }
    }

    public void uninstallComponents(JFileChooser fc) {
        fc.removeAll();
        if (filterComboBoxModel != null) {
            fc.removePropertyChangeListener(filterComboBoxModel);
        }
    }

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

        Locale l = fc.getLocale();

        enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l);
        enterFolderNameLabelMnemonic = UIManager.getInt("FileChooser.enterFolderNameLabelMnemonic");
        enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l);
        enterFileNameLabelMnemonic = UIManager.getInt("FileChooser.enterFileNameLabelMnemonic");

        filesLabelText = UIManager.getString("FileChooser.filesLabelText",l);
        filesLabelMnemonic = UIManager.getInt("FileChooser.filesLabelMnemonic");

        foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l);
        foldersLabelMnemonic = UIManager.getInt("FileChooser.foldersLabelMnemonic");

        pathLabelText = UIManager.getString("FileChooser.pathLabelText",l);
        pathLabelMnemonic = UIManager.getInt("FileChooser.pathLabelMnemonic");

        filterLabelText = UIManager.getString("FileChooser.filterLabelText",l);
        filterLabelMnemonic = UIManager.getInt("FileChooser.filterLabelMnemonic");
    }

    protected void installIcons(JFileChooser fc) {
        // Since motif doesn't have button icons, leave this empty
        // which overrides the supertype icon loading
    }

    protected void uninstallIcons(JFileChooser fc) {
        // Since motif doesn't have button icons, leave this empty
        // which overrides the supertype icon loading
    }

    protected JScrollPane createFilesList() {
        fileList = new JList();

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

        fileList.setModel(new MotifFileListModel());
        fileList.getSelectionModel().removeSelectionInterval(0, 0);
        fileList.setCellRenderer(new FileCellRenderer());
        fileList.addListSelectionListener(createListSelectionListener(getFileChooser()));
        fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList));
        fileList.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                JFileChooser chooser = getFileChooser();
                if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) {
                    int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint());
                    if (index >= 0) {
                        File file = (File) fileList.getModel().getElementAt(index);
                        setFileName(chooser.getName(file));
                    }
                }
            }
        });
        align(fileList);
        JScrollPane scrollpane = new JScrollPane(fileList);
        scrollpane.setPreferredSize(prefListSize);
        scrollpane.setMaximumSize(MAX_SIZE);
        align(scrollpane);
        fileList.setInheritsPopupMenu(true);
        scrollpane.setInheritsPopupMenu(true);
        return scrollpane;
    }

    protected JScrollPane createDirectoryList() {
        directoryList = new JList();
        align(directoryList);

        directoryList.setCellRenderer(new DirectoryCellRenderer());
        directoryList.setModel(new MotifDirectoryListModel());
        directoryList.getSelectionModel().removeSelectionInterval(0, 0);
        directoryList.addMouseListener(createDoubleClickListener(getFileChooser(), directoryList));
        directoryList.addListSelectionListener(createListSelectionListener(getFileChooser()));
        directoryList.setInheritsPopupMenu(true);

        JScrollPane scrollpane = new JScrollPane(directoryList);
        scrollpane.setMaximumSize(MAX_SIZE);
        scrollpane.setPreferredSize(prefListSize);
        scrollpane.setInheritsPopupMenu(true);
        align(scrollpane);
        return scrollpane;
    }

    public Dimension getPreferredSize(JComponent c) {
        Dimension prefSize =
            (getFileChooser().getAccessory() != null) ? WITH_ACCELERATOR_PREF_SIZE : PREF_SIZE;
        Dimension d = c.getLayout().preferredLayoutSize(c);
        if (d != null) {
            return new Dimension(d.width < prefSize.width ? prefSize.width : d.width,
                                 d.height < prefSize.height ? prefSize.height : d.height);
        } else {
            return prefSize;
        }
    }

    public Dimension getMinimumSize(JComponent x)  {
        return MIN_SIZE;
    }

    public Dimension getMaximumSize(JComponent x) {
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    protected void align(JComponent c) {
        c.setAlignmentX(JComponent.LEFT_ALIGNMENT);
        c.setAlignmentY(JComponent.TOP_ALIGNMENT);
    }

    protected class FileCellRenderer extends DefaultListCellRenderer  {
        public Component getListCellRendererComponent(JList list, Object value, int index,
                                                      boolean isSelected, boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            setText(getFileChooser().getName((File) value));
            setInheritsPopupMenu(true);
            return this;
        }
    }

    protected class DirectoryCellRenderer extends DefaultListCellRenderer  {
        public Component getListCellRendererComponent(JList list, Object value, int index,
                                                      boolean isSelected, boolean cellHasFocus) {

            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            setText(getFileChooser().getName((File) value));
            setInheritsPopupMenu(true);
            return this;
        }
    }

    protected class MotifDirectoryListModel extends AbstractListModel implements ListDataListener {
        public MotifDirectoryListModel() {
            getModel().addListDataListener(this);
        }

        public int getSize() {
            return getModel().getDirectories().size();
        }

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

        public void intervalAdded(ListDataEvent e) {
            fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
        }

        public void intervalRemoved(ListDataEvent e) {
            fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
        }

        // PENDING(jeff) - this is inefficient - should sent out
        // incremental adjustment values instead of saying that the
        // whole list has changed.
        public void fireContentsChanged() {
            fireContentsChanged(this, 0, getModel().getDirectories().size()-1);
        }

        // PENDING(jeff) - fire the correct interval changed - currently sending
        // out that everything has changed
        public void contentsChanged(ListDataEvent e) {
            fireContentsChanged();
        }

    }

    protected class MotifFileListModel extends AbstractListModel implements ListDataListener {
        public MotifFileListModel() {
            getModel().addListDataListener(this);
        }

        public int getSize() {
            return getModel().getFiles().size();
        }

        public boolean contains(Object o) {
            return getModel().getFiles().contains(o);
        }

        public int indexOf(Object o) {
            return getModel().getFiles().indexOf(o);
        }

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

        public void intervalAdded(ListDataEvent e) {
            fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
        }

        public void intervalRemoved(ListDataEvent e) {
            fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
        }

        // PENDING(jeff) - this is inefficient - should sent out
        // incremental adjustment values instead of saying that the
        // whole list has changed.
        public void fireContentsChanged() {
            fireContentsChanged(this, 0, getModel().getFiles().size()-1);
        }

        // PENDING(jeff) - fire the interval changed
        public void contentsChanged(ListDataEvent e) {
            fireContentsChanged();
        }

    }

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

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


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

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

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

            return this;
        }
    }

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

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

        public void setSelectedItem(Object filter) {
            if(filter != null) {
                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) {
                    getFileChooser().addChoosableFileFilter(currentFilter);
                }
            }
            return getFileChooser().getFileFilter();
        }

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

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

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

}
