Logo Search packages:      
Sourcecode: kaffe version File versions  Download package

MetalFileChooserUI.java

/* MetalFileChooserUI.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.plaf.metal;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.NumberFormat;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JViewport;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicFileChooserUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

import java.sql.Date;

import java.text.DateFormat;

import java.util.List;


/**
 * A UI delegate for the {@link JFileChooser} component.  This class is only
 * partially implemented and is not usable yet.
 */
00108 public class MetalFileChooserUI 
  extends BasicFileChooserUI
{
  
  /**
   * A renderer for the files and directories in the file chooser table.
   */
00115   class TableFileRenderer
    extends DefaultTableCellRenderer
  {
    
    /**
     * Creates a new renderer.
     */
00122     public TableFileRenderer()
    {
      super();
    }
    
    /**
     * Returns a component that can render the specified value.
     * 
     * @param table  the table
     * @param value  the string value of the cell
     * @param isSelected  is the item selected?
     * @param hasFocus  does the item have the focus?
     * @param row  the row
     * @param column  the column
     * 
     * @return The renderer.
     */
00139     public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
    {
      if (column == 0)
        {
          FileView v = getFileView(getFileChooser());
          ListModel lm = fileList.getModel();
          if (row < lm.getSize())
            setIcon(v.getIcon((File) lm.getElementAt(row)));
        }
      else
        setIcon(null);
      
      setText(value.toString());
      setOpaque(true);
      setEnabled(table.isEnabled());
      setFont(fileList.getFont());
      
      if (startEditing && column == 0 || !isSelected)
        {
          setBackground(table.getBackground());
          setForeground(table.getForeground());
        }
      else
        {
          setBackground(table.getSelectionBackground());
          setForeground(table.getSelectionForeground());
        }

      if (hasFocus)
        setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      else
        setBorder(noFocusBorder);
      
      return this;
    }
  }
  
  /**
   * ActionListener for the list view.
   */
00180   class ListViewActionListener implements ActionListener
  {
    
    /**
     * This method is invoked when an action occurs.
     * 
     * @param e -
     *          the <code>ActionEvent</code> that occurred
     */
00189     public void actionPerformed(ActionEvent e)
    {
      if (!listView)
        {
          int[] index = fileTable.getSelectedRows();
          listView = true;
          JFileChooser fc = getFileChooser();
          fc.remove(fileTablePanel);
          createList(fc);

          fileList.getSelectionModel().clearSelection();
          if (index.length > 0)
              for (int i = 0; i < index.length; i++)
                fileList.getSelectionModel().addSelectionInterval(index[i], index[i]);
          
          fc.add(fileListPanel, BorderLayout.CENTER);
          fc.revalidate();
          fc.repaint();
        }
    }
  }
  
  /**
   * ActionListener for the details view.
   */
00214   class DetailViewActionListener implements ActionListener
  {
    
    /**
     * This method is invoked when an action occurs.
     * 
     * @param e -
     *          the <code>ActionEvent</code> that occurred
     */
00223     public void actionPerformed(ActionEvent e)
    {
      if (listView)
        {
          int[] index = fileList.getSelectedIndices();
          JFileChooser fc = getFileChooser();
          listView = false;
          fc.remove(fileListPanel);
          
          if (fileTable == null)
            createDetailsView(fc);
          else
            updateTable();

          fileTable.getSelectionModel().clearSelection();
          if (index.length > 0)
            {
              for (int i = 0; i < index.length; i++)
                fileTable.getSelectionModel().addSelectionInterval(index[i], index[i]);
            }
          
          fc.add(fileTablePanel, BorderLayout.CENTER);
          fc.revalidate();
          fc.repaint();
        }
    }
  }
  
  /**
   * A property change listener.
   */
00254   class MetalFileChooserPropertyChangeListener 
    implements PropertyChangeListener
  {
    /**
     * Default constructor.
     */
00260     public MetalFileChooserPropertyChangeListener()
    {
    }
    
    /**
     * Handles a property change event.
     * 
     * @param e  the event.
     */
00269     public void propertyChange(PropertyChangeEvent e)
    {
      JFileChooser filechooser = getFileChooser();
      
      String n = e.getPropertyName();
      if (n.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY))
        {
          int mode = -1; 
          if (filechooser.isMultiSelectionEnabled())
            mode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
          else
            mode = ListSelectionModel.SINGLE_SELECTION;
          
          if (listView)
            fileList.setSelectionMode(mode);
          else
            fileTable.setSelectionMode(mode);
        }
      else if (n.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
        {
          File file = filechooser.getSelectedFile();
          
          if (file != null
              && filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
            {
              if (file.isDirectory() && filechooser.isTraversable(file))
                {
                  directoryLabel = look;
                  dirLabel.setText(directoryLabel);
                  filechooser.setApproveButtonText(openButtonText);
                  filechooser.setApproveButtonToolTipText(openButtonToolTipText);
                }
              else if (file.isFile())
                {
                  directoryLabel = save;
                  dirLabel.setText(directoryLabel);
                  filechooser.setApproveButtonText(saveButtonText);
                  filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
                }
            }
            
          if (file == null)
            setFileName(null);
          else
            setFileName(file.getName());
          int index = -1;
          index = getModel().indexOf(file);
          if (index >= 0)
            {
              if (listView)
                {
                  fileList.setSelectedIndex(index);
                  fileList.ensureIndexIsVisible(index);
                  fileList.revalidate();
                  fileList.repaint();
                }
              else
                {
                  fileTable.getSelectionModel().addSelectionInterval(index, index);
                  fileTable.scrollRectToVisible(fileTable.getCellRect(index, 0, true));
                  fileTable.revalidate();
                  fileTable.repaint();
                }
            }
        }
      
      else if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY))
        {
          if (listView)
            {
              fileList.clearSelection();
              fileList.revalidate();
              fileList.repaint();
            }
          else
            {
              fileTable.clearSelection();
              fileTable.revalidate();
              fileTable.repaint();
            }

          setDirectorySelected(false);
          File currentDirectory = filechooser.getCurrentDirectory();
          setDirectory(currentDirectory);
          boolean hasParent = (currentDirectory.getParentFile() != null);
          getChangeToParentDirectoryAction().setEnabled(hasParent);
        }
      
      else if (n.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
        {
          filterModel.propertyChange(e);
        }
      else if (n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
        {
          filterModel.propertyChange(e);
        }
      else if (n.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
                 || n.equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
        {
          Window owner = SwingUtilities.windowForComponent(filechooser);
          if (owner instanceof JDialog)
            ((JDialog) owner).setTitle(getDialogTitle(filechooser));
          approveButton.setText(getApproveButtonText(filechooser));
          approveButton.setToolTipText(
                  getApproveButtonToolTipText(filechooser));
          approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));
        }
      
      else if (n.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
        approveButton.setText(getApproveButtonText(filechooser));
      
      else if (n.equals(
              JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
        approveButton.setToolTipText(getApproveButtonToolTipText(filechooser));
      
      else if (n.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
        approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));

      else if (n.equals(
              JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
        {
          if (filechooser.getControlButtonsAreShown())
            {
              topPanel.add(controls, BorderLayout.EAST);
            }
          else
            topPanel.remove(controls);
          topPanel.revalidate();
          topPanel.repaint();
          topPanel.doLayout();
        }
      
      else if (n.equals(
              JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
        {
          if (filechooser.isAcceptAllFileFilterUsed())
            filechooser.addChoosableFileFilter(
                    getAcceptAllFileFilter(filechooser));
          else
            filechooser.removeChoosableFileFilter(
                    getAcceptAllFileFilter(filechooser));
        }
      
      else if (n.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY))
        {
          JComponent old = (JComponent) e.getOldValue();
          if (old != null)
            getAccessoryPanel().remove(old);
          JComponent newval = (JComponent) e.getNewValue();
          if (newval != null)
            getAccessoryPanel().add(newval);
        }
      
      if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
          || n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
          || n.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
        {
          // Remove editing component
          if (fileTable != null)
            fileTable.removeAll();
          if (fileList != null)
            fileList.removeAll();
          startEditing = false;
          
          // Set text on button back to original.
          if (filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
            {
              directoryLabel = save;
              dirLabel.setText(directoryLabel);
              filechooser.setApproveButtonText(saveButtonText);
              filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
            }
          
          rescanCurrentDirectory(filechooser);
        }
      
      filechooser.revalidate();
      filechooser.repaint();
    }
  };
  
  /** 
   * A combo box model containing the selected directory and all its parent
   * directories.
   */
00454   protected class DirectoryComboBoxModel
    extends AbstractListModel
    implements ComboBoxModel
  {
    /** Storage for the items in the model. */
00459     private List items;
    
    /** The index of the selected item. */
00462     private int selectedIndex;
    
    /**
     * Creates a new model.
     */
00467     public DirectoryComboBoxModel() 
    {
      items = new java.util.ArrayList();
      selectedIndex = -1;
    }
    
    /**
     * Returns the number of items in the model.
     * 
     * @return The number of items in the model.
     */
00478     public int getSize()
    {
      return items.size();
    }
    
    /**
     * Returns the item at the specified index.
     * 
     * @param index  the item index.
     * 
     * @return The item.
     */
00490     public Object getElementAt(int index)
    {
      return items.get(index);
    }
    
    /**
     * Returns the depth of the item at the given <code>index</code>.
     * 
     * @param index  the item index.
     * 
     * @return The depth.
     */
00502     public int getDepth(int index)
    {
      return Math.max(index, 0);
    }

    /**
     * Returns the selected item, or <code>null</code> if no item is selected.
     * 
     * @return The selected item, or <code>null</code>.
     */
00512     public Object getSelectedItem()
    {
      if (selectedIndex >= 0) 
        return items.get(selectedIndex);
      else
        return null;
    }
    
    /**
     * Sets the selected item.  This clears all the directories from the
     * existing list, and repopulates it with the new selected directory
     * and all its parent directories.
     * 
     * @param selectedDirectory  the selected directory.
     */
00527     public void setSelectedItem(Object selectedDirectory)
    {
      items.clear();
      FileSystemView fsv = getFileChooser().getFileSystemView();
      File parent = (File) selectedDirectory;
      while (parent != null)
        {
          items.add(0, parent);
          parent = fsv.getParentDirectory(parent);
        }
      selectedIndex = items.indexOf(selectedDirectory);
      fireContentsChanged(this, 0, items.size() - 1);
    }
    
  }

  /**
   * Handles changes to the selection in the directory combo box.
   */
00546   protected class DirectoryComboBoxAction
    extends AbstractAction
  {
    /**
     * Creates a new action.
     */
00552     protected DirectoryComboBoxAction()
    {
      // Nothing to do here.
    }
    
    /**
     * Handles the action event.
     * 
     * @param e  the event.
     */
00562     public void actionPerformed(ActionEvent e)
    {
      JFileChooser fc = getFileChooser();
      fc.setCurrentDirectory((File) directoryModel.getSelectedItem());
    }
  }

  /**
   * A renderer for the items in the directory combo box.
   */
00572   class DirectoryComboBoxRenderer
    extends DefaultListCellRenderer
  {
    /**
     * Creates a new renderer.
     */
00578     public DirectoryComboBoxRenderer(JFileChooser fc)
    { 
    }
    
    /**
     * Returns a component that can be used to paint the given value within 
     * the list.
     * 
     * @param list  the list.
     * @param value  the value (a {@link File}).
     * @param index  the item index.
     * @param isSelected  is the item selected?
     * @param cellHasFocus  does the list cell have focus?
     * 
     * @return The list cell renderer.
     */
00594     public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus)
    {
      FileView fileView = getFileView(getFileChooser());
      File file = (File) value;
      setIcon(fileView.getIcon(file));
      setText(fileView.getName(file));
      
      if (isSelected)
        {
          setBackground(list.getSelectionBackground());
          setForeground(list.getSelectionForeground());
        }
      else
        {
          setBackground(list.getBackground());
          setForeground(list.getForeground());
        }

      setEnabled(list.isEnabled());
      setFont(list.getFont());
      return this;
    }
  }

  /**
   * A renderer for the files and directories in the file chooser.
   */
00622   protected class FileRenderer
    extends DefaultListCellRenderer
  {
    
    /**
     * Creates a new renderer.
     */
00629     protected FileRenderer()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns a component that can render the specified value.
     * 
     * @param list  the list.
     * @param value  the value (a {@link File}).
     * @param index  the index.
     * @param isSelected  is the item selected?
     * @param cellHasFocus  does the item have the focus?
     * 
     * @return The renderer.
     */
00645     public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus)
    {
      FileView v = getFileView(getFileChooser());
      File f = (File) value;
      if (f != null)
      {
        setText(v.getName(f));
        setIcon(v.getIcon(f));
      }
      else
      {
        setText("");
        setIcon(null);
      }
      setOpaque(true);
      if (isSelected)
        {
          setBackground(list.getSelectionBackground());
          setForeground(list.getSelectionForeground());
        }
      else
        {
          setBackground(list.getBackground());
          setForeground(list.getForeground());
        }

      setEnabled(list.isEnabled());
      setFont(list.getFont());

      if (cellHasFocus)
        setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
      else
        setBorder(noFocusBorder);
      return this;
    }
  }

  /**
   * A combo box model for the file selection filters.
   */
00686   protected class FilterComboBoxModel
    extends AbstractListModel
    implements ComboBoxModel, PropertyChangeListener
  {

    /** Storage for the filters in the model. */
00692     protected FileFilter[] filters;

    /** The index of the selected file filter. */
00695     private Object selected;
    
    /**
     * Creates a new model.
     */
00700     protected FilterComboBoxModel()
    {
      filters = new FileFilter[1];
      filters[0] = getAcceptAllFileFilter(getFileChooser());
      selected = filters[0];
    }
    
    /**
     * Handles property changes.
     * 
     * @param e  the property change event.
     */
00712     public void propertyChange(PropertyChangeEvent e)
    {
      if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
        {
          JFileChooser fc = getFileChooser();
          FileFilter[] choosableFilters = fc.getChoosableFileFilters();
          filters = choosableFilters;
          fireContentsChanged(this, 0, filters.length);
          selected = e.getNewValue();
          fireContentsChanged(this, -1, -1);
        }
      else if (e.getPropertyName().equals(
              JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
        {
          // repopulate list
          JFileChooser fc = getFileChooser();
          FileFilter[] choosableFilters = fc.getChoosableFileFilters();
          filters = choosableFilters;
          fireContentsChanged(this, 0, filters.length);
        }
    }
    
    /**
     * Sets the selected filter.
     * 
     * @param filter  the filter (<code>null</code> ignored).
     */
00739     public void setSelectedItem(Object filter)
    {
      if (filter != null)
      {
          selected = filter;
          fireContentsChanged(this, -1, -1);
      }
    }
    
    /**
     * Returns the selected file filter.
     * 
     * @return The selected file filter.
     */
00753     public Object getSelectedItem()
    {
      return selected;
    }
    
    /**
     * Returns the number of items in the model.
     * 
     * @return The number of items in the model.
     */
00763     public int getSize()
    {
      return filters.length;
    }
    
    /**
     * Returns the item at the specified index.
     * 
     * @param index  the item index.
     * 
     * @return The item at the specified index.
     */
00775     public Object getElementAt(int index)
    {
      return filters[index];
    }
    
  }

  /**
   * A renderer for the items in the file filter combo box.
   */
00785   public class FilterComboBoxRenderer
    extends DefaultListCellRenderer
  {
    /**
     * Creates a new renderer.
     */
00791     public FilterComboBoxRenderer()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns a component that can be used to paint the given value within 
     * the list.
     * 
     * @param list  the list.
     * @param value  the value (a {@link FileFilter}).
     * @param index  the item index.
     * @param isSelected  is the item selected?
     * @param cellHasFocus  does the list cell have focus?
     * 
     * @return This component as the renderer.
     */
00808     public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus)
    {
      super.getListCellRendererComponent(list, value, index, isSelected, 
                                         cellHasFocus);
      FileFilter filter = (FileFilter) value;
      setText(filter.getDescription());
      return this;
    }
  }

  /**
   * A listener for selection events in the file list.
   * 
   * @see #createListSelectionListener(JFileChooser)
   */
00824   class MetalFileChooserSelectionListener 
    implements ListSelectionListener
  {
    /**
     * Creates a new <code>SelectionListener</code> object.
     */
00830     protected MetalFileChooserSelectionListener()
    {
      // Do nothing here.
    }

    /**
     * Makes changes to different properties when
     * a value has changed in the filechooser's selection.
     *
     * @param e - the list selection event that occured.
     */
00841     public void valueChanged(ListSelectionEvent e)
    {
      File f = (File) fileList.getSelectedValue();
      if (f == null)
        return;
      JFileChooser filechooser = getFileChooser();
      if (! filechooser.isTraversable(f))
        filechooser.setSelectedFile(f);
      else
        filechooser.setSelectedFile(null);
    }
  }

  /**
   * A mouse listener for the {@link JFileChooser}.
   * This listener is used for editing filenames.
   */
00858   protected class SingleClickListener
    extends MouseAdapter
  {
    
    /** Stores instance of the list */
00863     JList list;
    
    /** 
     * Stores the current file that is being edited.
     * It is null if nothing is currently being edited.
     */
00869     File editFile;
    
    /** The current file chooser. */
00872     JFileChooser fc;
    
    /** The last file selected. */
00875     Object lastSelected;
    
    /** The textfield used for editing. */
00878     JTextField editField;
    
    /**
     * Creates a new listener.
     * 
     * @param list  the directory/file list.
     */
00885     public SingleClickListener(JList list)
    {
      this.list = list;
      editFile = null;
      fc = getFileChooser();
      lastSelected = null;
      startEditing = false;
    }
    
    /**
     * Receives notification of a mouse click event.
     * 
     * @param e  the event.
     */
00899     public void mouseClicked(MouseEvent e)
    {
      if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1)
        {
          int index = list.locationToIndex(e.getPoint());
          File[] sf = fc.getSelectedFiles();
          if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
              && index >= 0 && !startEditing && list.isSelectedIndex(index))
            {
              Object tmp = list.getModel().getElementAt(index);
              if (lastSelected != null && lastSelected.equals(tmp))
                editFile(index);
              lastSelected = tmp;
            }
          else
              completeEditing();
        }
      else
        completeEditing();
    }
    
    /**
     * Sets up the text editor for the current file.
     * 
     * @param index -
     *          the current index of the item in the list to be edited.
     */
00926     void editFile(int index)
    {
      Rectangle bounds = list.getCellBounds(index, index);
      list.scrollRectToVisible(bounds);
      editFile = (File) list.getModel().getElementAt(index);
      if (editFile.canWrite())
        {
          startEditing = true;
          editField = new JTextField(editFile.getName());
          editField.addActionListener(new EditingActionListener());
          
          Icon icon = getFileView(fc).getIcon(editFile);
          if (icon != null)
            {
              int padding = icon.getIconWidth() + 4;
              bounds.x += padding;
              bounds.width -= padding;
            }
          editField.setBounds(bounds);
          
          list.add(editField);
          
          editField.requestFocus();
          editField.selectAll();
        }
      else
        completeEditing();
      list.repaint();
    }
    
    /** 
     * Completes the editing.
     */
00959     void completeEditing()
    {
      if (editField != null && editFile != null)
        {
          String text = editField.getText();
          if (text != null && text != "" && !text.equals(fc.getName(editFile)))
              if (editFile.renameTo
                  (fc.getFileSystemView().createFileObject
                   (fc.getCurrentDirectory(), text)))
                  rescanCurrentDirectory(fc);
          list.remove(editField);
        }
      startEditing = false;
      editFile = null;
      lastSelected = null;
      editField = null;
      list.repaint();
    }
    
    /**
     * ActionListener for the editing text field.
     */
00981     class EditingActionListener implements ActionListener
    {
      
      /**
       * This method is invoked when an action occurs.
       * 
       * @param e -
       *          the <code>ActionEvent</code> that occurred
       */
00990       public void actionPerformed(ActionEvent e)
      {
        if (e.getActionCommand().equals("notify-field-accept"))
          completeEditing();
        else if (editField != null)
          {
            list.remove(editField);
            startEditing = false;
            editFile = null;
            lastSelected = null;
            editField = null;
            list.repaint();
          }
      }
    }
  }

  /**
   * A mouse listener for the {@link JFileChooser}.
   * This listener is used for the table
   */
01011   private class TableClickListener extends MouseAdapter
  {

    /** Stores instance of the table */
01015     JTable table;

    /** Stores instance of the file chooser */
01018     JFileChooser fc;

    /** The last selected file. */
01021     Object lastSelected = null;
    
    /** 
     * Stores the current file that is being edited.
     * It is null if nothing is currently being edited.
     */
01027     File editFile;
    
    /** The textfield used for editing. */
01030     JTextField editField;

    /**
     * Creates a new listener.
     * 
     * @param table
     *          the directory/file table
     * @param fc
     *          the JFileChooser
     */
01040     public TableClickListener(JTable table, JFileChooser fc)
    {
      this.table = table;
      this.fc = fc;
      lastSelected = fileList.getSelectedValue();
      setDirectorySelected(false);
      startEditing = false;
      editFile = null;
      editField = null;
    }

    /**
     * Receives notification of a mouse click event.
     * 
     * @param e
     *          the event.
     */
01057     public void mouseClicked(MouseEvent e)
    {
      int row = table.getSelectedRow();
      Object selVal = fileList.getModel().getElementAt(row);
      if (selVal == null)
        return;
      FileSystemView fsv = fc.getFileSystemView();
      if (e.getClickCount() == 1 &&
          selVal.equals(lastSelected) &&
          e.getButton() == MouseEvent.BUTTON1)
        {
          File[] sf = fc.getSelectedFiles();
          if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
              && !startEditing)
            {
              editFile = (File) selVal;
              editFile(row);
            }
        }
      else if (e.getClickCount() >= 2 &&
          selVal.equals(lastSelected))
        {
          if (startEditing)
            completeEditing();
          File f = fsv.createFileObject(lastSelected.toString());
          if (fc.isTraversable(f))
            {
              fc.setCurrentDirectory(f);
              fc.rescanCurrentDirectory();
            }
          else
            {
              fc.setSelectedFile(f);
              fc.approveSelection();
              closeDialog();
            }
        }
      else
        {
          if (startEditing)
            completeEditing();
          String path = selVal.toString();
          File f = fsv.createFileObject(path);
          fc.setSelectedFile(f);
          if (fc.isTraversable(f))
            {
              setDirectorySelected(true);
              setDirectory(f);
            }
          else
            {
              setDirectorySelected(false);
              setDirectory(null);
            }
          lastSelected = selVal;
          if (f.isFile())
            setFileName(path.substring(path.lastIndexOf("/") + 1));
          else if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY)
            setFileName(path);
        }
      fileTable.repaint();
    }

    /**
     * Sets up the text editor for the current file.
     * 
     * @param row -
     *          the current row of the item in the list to be edited.
     */
01126     void editFile(int row)
    {
      Rectangle bounds = table.getCellRect(row, 0, true);
      table.scrollRectToVisible(bounds);
      if (editFile.canWrite())
        {
          startEditing = true;
          editField = new JTextField(editFile.getName());
          editField.addActionListener(new EditingActionListener());

          // Need to adjust y pos
          bounds.y = row * table.getRowHeight();
          editField.setBounds(bounds);
          
          table.add(editField);
          
          editField.requestFocus();
          editField.selectAll();
        }
      else
        completeEditing();
      table.repaint();
    }
    
    /** 
     * Completes the editing.
     */
01153     void completeEditing()
    {
      if (editField != null && editFile != null)
        {
          String text = editField.getText();
          if (text != null && text != "" && !text.equals(fc.getName(editFile)))
              if (editFile.renameTo
                  (fc.getFileSystemView().createFileObject
                   (fc.getCurrentDirectory(), text)))
                  rescanCurrentDirectory(fc);
          table.remove(editField);
        }
      startEditing = false;
      editFile = null;
      editField = null;
      table.repaint();
    }
    
    /**
     * ActionListener for the editing text field.
     */
01174     class EditingActionListener implements ActionListener
    {
      
      /**
       * This method is invoked when an action occurs.
       * 
       * @param e -
       *          the <code>ActionEvent</code> that occurred
       */
01183       public void actionPerformed(ActionEvent e)
      {
        if (e.getActionCommand().equals("notify-field-accept"))
          completeEditing();
        else if (editField != null)
          {
            table.remove(editField);
            startEditing = false;
            editFile = null;
            editField = null;
            table.repaint();
          }
      }
    }
    
    /**
     * Closes the dialog.
     */
01201     public void closeDialog()
    {
      Window owner = SwingUtilities.windowForComponent(fc);
      if (owner instanceof JDialog)
        ((JDialog) owner).dispose();
    }
  } 
  
  /** The text for a label describing the directory combo box. */
01210   private String directoryLabel;
  
  private JComboBox directoryComboBox;
  
  /** The model for the directory combo box. */
01215   DirectoryComboBoxModel directoryModel;
  
  /** The text for a label describing the file text field. */
01218   private String fileLabel;
  
  /** The file name text field. */
01221   private JTextField fileTextField;
  
  /** The text for a label describing the filter combo box. */
01224   private String filterLabel;

  /** 
   * The top panel (contains the directory combo box and the control buttons). 
   */
01229   private JPanel topPanel;
  
  /** A panel containing the control buttons ('up', 'home' etc.). */
01232   private JPanel controls;

  /** 
   * The panel that contains the filename field and the filter combobox. 
   */
01237   private JPanel bottomPanel;

  /** 
   * The panel that contains the 'Open' (or 'Save') and 'Cancel' buttons. 
   */
01242   private JPanel buttonPanel;
  
  private JButton approveButton;
  
  /** The file list. */
01247   JList fileList;
  
  /** The file table. */
01250   JTable fileTable;
  
  /** The panel containing the file list. */
01253   JPanel fileListPanel;
  
  /** The panel containing the file table. */
01256   JPanel fileTablePanel;
  
  /** The filter combo box model. */
01259   private FilterComboBoxModel filterModel;

  /** The action map. */
01262   private ActionMap actionMap;
  
  /** True if currently in list view. */
01265   boolean listView;
  
  /** True if we can or have started editing a cell. */
01268   boolean startEditing;
  
  /** The scrollpane used for the table and list. */
01271   JScrollPane scrollPane;
  
  /** The text for the label when saving. */
01274   String save;
  
  /** The text for the label when opening a directory. */
01277   String look;
  
  /** The label for the file combo box. */
01280   JLabel dirLabel;
  
  /** Listeners. */
01283   ListSelectionListener listSelList;
  MouseListener doubleClickList;
  SingleClickListener singleClickList;
  TableClickListener tableClickList;
  
  /**
   * A factory method that returns a UI delegate for the specified
   * component.
   * 
   * @param c  the component (which should be a {@link JFileChooser}).
   */
01294   public static ComponentUI createUI(JComponent c)
  {
    JFileChooser chooser = (JFileChooser) c;
    return new MetalFileChooserUI(chooser);
  }

  /**
   * Creates a new instance of this UI delegate.
   * 
   * @param filechooser  the file chooser component.
   */
01305   public MetalFileChooserUI(JFileChooser filechooser)
  {
    super(filechooser);
    bottomPanel = new JPanel(new GridLayout(3, 2));
    buttonPanel = new JPanel();
  }

01312   public void installUI(JComponent c)
  {
    super.installUI(c);
    actionMap = createActionMap();
  }
  
01318   public void uninstallUI(JComponent c)
  {
    super.uninstallUI(c);
    actionMap = null;
  }
  
  /**
   * Installs the sub-components of the file chooser.
   * 
   * @param fc  the file chooser component.
   */
01329   public void installComponents(JFileChooser fc)
  {
    fc.setLayout(new BorderLayout());
    topPanel = new JPanel(new BorderLayout());
    dirLabel = new JLabel(directoryLabel);
    topPanel.add(dirLabel, BorderLayout.WEST);
    this.controls = new JPanel();
    addControlButtons();
    
    JPanel dirPanel = new JPanel(new VerticalMidLayout());
    directoryModel = createDirectoryComboBoxModel(fc);
    directoryComboBox = new JComboBox(directoryModel);
    directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
    dirPanel.add(directoryComboBox);
    topPanel.add(dirPanel);
    topPanel.add(controls, BorderLayout.EAST);
    topPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8));
    fc.add(topPanel, BorderLayout.NORTH);
    
    JPanel list = createList(fc);
    list.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
    fc.add(list, BorderLayout.CENTER);
    
    JPanel bottomPanel = getBottomPanel();
    filterModel = createFilterComboBoxModel();
    JComboBox fileFilterCombo = new JComboBox(filterModel);
    fileFilterCombo.setRenderer(createFilterComboBoxRenderer());
    
    fileTextField = new JTextField();
    JPanel fileNamePanel = new JPanel(new VerticalMidLayout());
    fileNamePanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 5));
    fileNamePanel.add(fileTextField);
    JPanel row1 = new JPanel(new BorderLayout());
    row1.add(new JLabel(this.fileLabel), BorderLayout.WEST);
    row1.add(fileNamePanel);
    bottomPanel.add(row1);
    
    JPanel row2 = new JPanel(new BorderLayout());
    row2.add(new JLabel(this.filterLabel), BorderLayout.WEST);
    row2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
    row2.add(fileFilterCombo);
    bottomPanel.add(row2);
    JPanel buttonPanel = new JPanel(new ButtonLayout());
    
    approveButton = new JButton(getApproveSelectionAction());
    approveButton.setText(getApproveButtonText(fc));
    approveButton.setToolTipText(getApproveButtonToolTipText(fc));
    approveButton.setMnemonic(getApproveButtonMnemonic(fc));
    buttonPanel.add(approveButton);
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
    
    JButton cancelButton = new JButton(getCancelSelectionAction());
    cancelButton.setText(cancelButtonText);
    cancelButton.setToolTipText(cancelButtonToolTipText);
    cancelButton.setMnemonic(cancelButtonMnemonic);
    buttonPanel.add(cancelButton);
    bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
    bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 8));
    fc.add(bottomPanel, BorderLayout.SOUTH);
    
    fc.add(getAccessoryPanel(), BorderLayout.EAST);
  }
  
  /**
   * Uninstalls the components added by 
   * {@link #installComponents(JFileChooser)}.
   * 
   * @param fc  the file chooser.
   */
01398   public void uninstallComponents(JFileChooser fc)
  {
    fc.remove(bottomPanel);
    bottomPanel = null;
    fc.remove(fileListPanel);
    fc.remove(fileTablePanel);
    fileTablePanel = null;
    fileListPanel = null;
    fc.remove(topPanel);
    topPanel = null;
    
    directoryModel = null;
    fileTextField = null;
    directoryComboBox = null;
  }
  
  /**
   * Returns the panel that contains the 'Open' (or 'Save') and 'Cancel' 
   * buttons.
   * 
   * @return The panel.
   */
01420   protected JPanel getButtonPanel()
  {
    return buttonPanel;    
  }
  
  /**
   * Creates and returns a new panel that will be used for the controls at
   * the bottom of the file chooser.
   * 
   * @return A new panel.
   */
01431   protected JPanel getBottomPanel()
  {
    if (bottomPanel == null)
      bottomPanel = new JPanel(new GridLayout(3, 2));
    return bottomPanel;
  }
  
  /**
   * Fetches localised strings for use by the labels and buttons on the
   * file chooser.
   * 
   * @param fc  the file chooser.
   */
01444   protected void installStrings(JFileChooser fc)
  { 
     super.installStrings(fc);
     look = "Look In: ";
     save = "Save In: ";
     if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
       directoryLabel = save;
     else
       directoryLabel = look;
     
     fileLabel = "File Name: ";
     filterLabel = "Files of Type: ";
     
     this.cancelButtonMnemonic = 0;
     this.cancelButtonText = "Cancel";
     this.cancelButtonToolTipText = "Abort file chooser dialog";
     
     this.directoryOpenButtonMnemonic = 0;
     this.directoryOpenButtonText = "Open";
     this.directoryOpenButtonToolTipText = "Open selected directory";
     
     this.helpButtonMnemonic = 0;
     this.helpButtonText = "Help";
     this.helpButtonToolTipText = "Filechooser help";
     
     this.openButtonMnemonic = 0;
     this.openButtonText = "Open";
     this.openButtonToolTipText = "Open selected file";
     
     this.saveButtonMnemonic = 0;
     this.saveButtonText = "Save";
     this.saveButtonToolTipText = "Save selected file";
     
     this.updateButtonMnemonic = 0;
     this.updateButtonText = "Update";
     this.updateButtonToolTipText = "Update directory listing";   
  }
  
  /**
   * Installs the listeners required.
   * 
   * @param fc  the file chooser.
   */
01487   protected void installListeners(JFileChooser fc)
  {
    directoryComboBox.setAction(new DirectoryComboBoxAction());
    fc.addPropertyChangeListener(filterModel);
    listSelList = createListSelectionListener(fc);
    doubleClickList = this.createDoubleClickListener(fc, fileList);
    singleClickList = new SingleClickListener(fileList);
    fileList.addListSelectionListener(listSelList);
    fileList.addMouseListener(doubleClickList);
    fileList.addMouseListener(singleClickList);
    super.installListeners(fc);
  }
  
01500   protected void uninstallListeners(JFileChooser fc) 
  {
    super.uninstallListeners(fc);
    fc.removePropertyChangeListener(filterModel);
    directoryComboBox.setAction(null);
    fileList.removeListSelectionListener(listSelList);
    fileList.removeMouseListener(doubleClickList);
    fileList.removeMouseListener(singleClickList);
    
    if (fileTable != null)
      fileTable.removeMouseListener(tableClickList);
  }
  
  protected ActionMap getActionMap()
  {
    if (actionMap == null)
      actionMap = createActionMap();
    return actionMap;
  }
  
  /**
   * Creates and returns an action map.
   * 
   * @return The action map.
   */
01525   protected ActionMap createActionMap()
  {
    ActionMap map = new ActionMap();
    map.put("approveSelection", getApproveSelectionAction());
    map.put("cancelSelection", getCancelSelectionAction());
    map.put("Go Up", getChangeToParentDirectoryAction());
    return map;
  }

  /**
   * Creates a panel containing a list of files.
   * 
   * @param fc  the file chooser.
   * 
   * @return A panel.
   */
01541   protected JPanel createList(JFileChooser fc)
  {
    if (fileList == null)
      {
        fileListPanel = new JPanel(new BorderLayout());
        fileList = new JList(getModel());
        scrollPane = new JScrollPane(fileList);
        scrollPane.setVerticalScrollBarPolicy
                                        (JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        fileList.setLayoutOrientation(JList.VERTICAL_WRAP);
        fileList.setCellRenderer(new FileRenderer());
      }
    else
      {
        fileList.setModel(getModel());
        fileListPanel.removeAll();
        scrollPane.getViewport().setView(fileList);
      }
    fileListPanel.add(scrollPane);

    return fileListPanel;
  }
  
  /**
   * Creates a panel containing a table within a scroll pane.
   * 
   * @param fc  the file chooser.
   * 
   * @return The details view.
   */
01571   protected JPanel createDetailsView(JFileChooser fc)
  {
    fileTablePanel = new JPanel(new BorderLayout());
    
    Object[] cols = new Object[] {"Name", "Size", "Modified"};
    Object[][] rows = new Object[fileList.getModel().getSize()][3];
    
    fileTable = new JTable(new DefaultTableModel(rows, cols));
    
    if (fc.isMultiSelectionEnabled())
      fileTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    else
      fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    
    fileTable.setShowGrid(false);
    fileTable.setColumnSelectionAllowed(false);
    fileTable.setDefaultRenderer(Object.class, new TableFileRenderer());

    tableClickList = new TableClickListener(fileTable, fc);
    fileTable.addMouseListener(tableClickList);
    
    return updateTable();  
  }
  
  /**
   * Sets the values in the table, and puts it in the panel.
   * 
   * @return the panel containing the table.
   */
01600   JPanel updateTable()
  {
    DefaultTableModel mod = (DefaultTableModel) fileTable.getModel();
    ListModel lm = fileList.getModel();
    DateFormat dt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
                                                   DateFormat.SHORT);
    File curr = null;
    int size = lm.getSize();
    int rc = mod.getRowCount();

    // If there are not enough rows
    for (int x = rc; x < size; x++)
      mod.addRow(new Object[3]);

    for (int i = 0; i < size; i++)
      {
        curr = (File) lm.getElementAt(i);
        fileTable.setValueAt(curr.getName(), i, 0);
        fileTable.setValueAt(formatSize(curr.length()), i, 1);
        fileTable.setValueAt(dt.format(new Date(curr.lastModified())), i, 2);
      }

    // If there are too many rows
    while (rc > size)
      mod.removeRow(--rc);

    scrollPane.getViewport().setView(fileTable);
    scrollPane.setColumnHeaderView(fileTable.getTableHeader());

    fileTablePanel.removeAll();
    fileTablePanel.add(scrollPane);

    return fileTablePanel;
  }
  
  /**
   * Formats bytes into the appropriate size.
   * 
   * @param bytes -
   *          the number of bytes to convert
   * @return a string representation of the size
   */
01642   private String formatSize(long bytes)
  {
    NumberFormat nf = NumberFormat.getNumberInstance();
    long mb = (long) Math.pow(2, 20);
    long kb = (long) Math.pow(2, 10);
    long gb = (long) Math.pow(2, 30);
    double size = 0;
    String id = "";
    
    if ((bytes / gb) >= 1)
      {
        size = (double) bytes / (double) gb;
        id = "GB";
      }
    else if ((bytes / mb) >= 1)
      {
        size = (double) bytes / (double) mb;
        id = "MB";
      }
    else if ((bytes / kb) >= 1)
      {
        size = (double) bytes / (double) kb;
        id = "KB";
      }
    else
      {
        size = bytes;
        id = "Bytes";
      }
    
    return nf.format(size) + " " + id;
  }
  /**
   * Creates a listener that monitors selections in the directory/file list
   * and keeps the {@link JFileChooser} component up to date.
   * 
   * @param fc  the file chooser.
   * 
   * @return The listener.
   * 
   * @see #installListeners(JFileChooser)
   */
01684   public ListSelectionListener createListSelectionListener(JFileChooser fc)
  {
    return new MetalFileChooserSelectionListener();
  }
  
  /**
   * Returns the preferred size for the file chooser component.
   * 
   * @return The preferred size.
   */
01694   public Dimension getPreferredSize(JComponent c)
  {
    Dimension tp = topPanel.getPreferredSize();
    Dimension bp = bottomPanel.getPreferredSize();
    Dimension fl = fileListPanel.getPreferredSize();
    return new Dimension(fl.width, tp.height + bp.height + fl.height);
  }

  /**
   * Returns the minimum size for the file chooser component.
   * 
   * @return The minimum size.
   */
01707   public Dimension getMinimumSize(JComponent c)
  {
    Dimension tp = topPanel.getMinimumSize();
    Dimension bp = bottomPanel.getMinimumSize();
    Dimension fl = fileListPanel.getMinimumSize();
    return new Dimension(fl.width, tp.height + bp.height + fl.height);
  }
  
  /**
   * Returns the maximum size for the file chooser component.
   * 
   * @return The maximum size.
   */
01720   public Dimension getMaximumSize(JComponent c)
  {
    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  }
  
  /**
   * Creates a property change listener that monitors the {@link JFileChooser}
   * for property change events and updates the component display accordingly.
   * 
   * @param fc  the file chooser.
   * 
   * @return The property change listener.
   * 
   * @see #installListeners(JFileChooser)
   */
01735   public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
  {
    return new MetalFileChooserPropertyChangeListener();
  }

  /**
   * Creates and returns a new instance of {@link DirectoryComboBoxModel}.
   * 
   * @return A new instance of {@link DirectoryComboBoxModel}.
   */
  protected MetalFileChooserUI.DirectoryComboBoxModel 
01746       createDirectoryComboBoxModel(JFileChooser fc)
  {
    return new DirectoryComboBoxModel();
  }

  /**
   * Creates a new instance of the renderer used in the directory
   * combo box.
   * 
   * @param fc  the file chooser.
   * 
   * @return The renderer.
   */
01759   protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
          JFileChooser fc)
  {
    return new DirectoryComboBoxRenderer(fc);
  }

  /**
   * Creates and returns a new instance of {@link FilterComboBoxModel}.
   * 
   * @return A new instance of {@link FilterComboBoxModel}.
   */
01770   protected FilterComboBoxModel createFilterComboBoxModel()
  {
    return new FilterComboBoxModel();  
  }

  /**
   * Creates and returns a new instance of {@link FilterComboBoxRenderer}.
   * 
   * @return A new instance of {@link FilterComboBoxRenderer}.
   */
  protected MetalFileChooserUI.FilterComboBoxRenderer 
01781       createFilterComboBoxRenderer()
  {
    return new FilterComboBoxRenderer(); 
  }

  /**
   * Adds the control buttons ('up', 'home' etc.) to the panel.
   */
01789   protected void addControlButtons()
  {
    JButton upButton = new JButton(getChangeToParentDirectoryAction());
    upButton.setText(null);
    upButton.setIcon(this.upFolderIcon);
    upButton.setMargin(new Insets(0, 0, 0, 0));
    controls.add(upButton);
    
    JButton homeButton = new JButton(getGoHomeAction());
    homeButton.setText(null);
    homeButton.setIcon(this.homeFolderIcon);
    homeButton.setMargin(new Insets(0, 0, 0, 0));
    controls.add(homeButton);
    
    JButton newFolderButton = new JButton(getNewFolderAction());
    newFolderButton.setText(null);
    newFolderButton.setIcon(this.newFolderIcon);
    newFolderButton.setMargin(new Insets(0, 0, 0, 0));
    controls.add(newFolderButton);
    
    JToggleButton listButton = new JToggleButton(this.listViewIcon);
    listButton.setMargin(new Insets(0, 0, 0, 0));
    listButton.addActionListener(new ListViewActionListener());
    listButton.setSelected(true);
    listView = true; 
    controls.add(listButton);
    
    JToggleButton detailButton = new JToggleButton(this.detailsViewIcon);
    detailButton.setMargin(new Insets(0, 0, 0, 0));
    detailButton.addActionListener(new DetailViewActionListener());
    detailButton.setSelected(false);
    controls.add(detailButton);

    ButtonGroup buttonGroup = new ButtonGroup();
    buttonGroup.add(listButton);
    buttonGroup.add(detailButton);
  }
  
  /**
   * Removes all the buttons from the control panel.
   */
01830   protected void removeControlButtons()
  {
    controls.removeAll();
    controls.revalidate();
    controls.repaint();
  }
  
  /**
   * Updates the current directory.
   * 
   * @param the file chooser to update.
   */
01842   public void rescanCurrentDirectory(JFileChooser fc)
  {
    directoryModel.setSelectedItem(fc.getCurrentDirectory());
    getModel().validateFileCache();
    if (!listView)
        updateTable();
    else
      createList(fc);
  }
  
  /**
   * Returns the file name in the text field.
   * 
   * @return The file name.
   */
01857   public String getFileName()
  {
    String result = null;
    if (fileTextField != null) 
      result = fileTextField.getText();
    return result;
  }
  
  /**
   * Sets the file name in the text field.
   * 
   * @param filename  the file name.
   */
01870   public void setFileName(String filename)
  {
    fileTextField.setText(filename);
  }
  
  /**
   * DOCUMENT ME!!
   * 
   * @param e - DOCUMENT ME!
   */
01880   public void valueChanged(ListSelectionEvent e)
  {
    // FIXME: Not sure what we should be doing here, if anything.
  }
  
  /**
   * Returns the approve button.
   * 
   * @return The approve button.
   */
01890   protected JButton getApproveButton(JFileChooser fc)
  {
    return approveButton;
  }

  /**
   * A layout manager that is used to arrange the subcomponents of the
   * {@link JFileChooser}.
   */
01899   class VerticalMidLayout implements LayoutManager
  {
    /**
     * Performs the layout.
     * 
     * @param parent  the container.
     */
01906     public void layoutContainer(Container parent) 
    {
      int count = parent.getComponentCount();
      if (count > 0)
        {
          Insets insets = parent.getInsets();
          Component c = parent.getComponent(0);
          Dimension prefSize = c.getPreferredSize();
          int h = parent.getHeight() - insets.top - insets.bottom;
          int adj = Math.max(0, (h - prefSize.height) / 2);
          c.setBounds(insets.left, insets.top + adj, parent.getWidth() 
              - insets.left - insets.right, 
              (int) Math.min(prefSize.getHeight(), h));
        }
    }
    
    /**
     * Returns the minimum layout size.
     * 
     * @param parent  the container.
     * 
     * @return The minimum layout size.
     */
01929     public Dimension minimumLayoutSize(Container parent) 
    {
      return preferredLayoutSize(parent);
    }
    
    /**
     * Returns the preferred layout size.
     * 
     * @param parent  the container.
     * 
     * @return The preferred layout size.
     */
01941     public Dimension preferredLayoutSize(Container parent) 
    {
      if (parent.getComponentCount() > 0)
        {
          return parent.getComponent(0).getPreferredSize();
        }
      else return null;
    }
    
    /**
     * This layout manager does not need to track components, so this 
     * method does nothing.
     * 
     * @param name  the name the component is associated with.
     * @param component  the component.
     */
01957     public void addLayoutComponent(String name, Component component) 
    {
      // do nothing
    }
    
    /**
     * This layout manager does not need to track components, so this 
     * method does nothing.
     * 
     * @param component  the component.
     */
01968     public void removeLayoutComponent(Component component) {
      // do nothing
    }
  }

  /**
   * A layout manager that is used to arrange buttons for the
   * {@link JFileChooser}.
   */
01977   class ButtonLayout implements LayoutManager
  {
    static final int GAP = 4;
      
    /**
     * Performs the layout.
     * 
     * @param parent  the container.
     */
01986     public void layoutContainer(Container parent) 
    {
      int count = parent.getComponentCount();
      if (count > 0)
        {
          // first find the widest button
          int maxW = 0;
          for (int i = 0; i < count; i++)
            {
              Component c = parent.getComponent(i);
              Dimension prefSize = c.getPreferredSize();
              maxW = Math.max(prefSize.width, maxW);
            }
  
          // then position the buttons
          Insets insets = parent.getInsets();
          int availableH = parent.getHeight() - insets.top - insets.bottom;
          int currentX = parent.getWidth() - insets.right;
          for (int i = count - 1; i >= 0; i--)
            {
              Component c = parent.getComponent(i);
              Dimension prefSize = c.getPreferredSize();      
              int adj = Math.max(0, (availableH - prefSize.height) / 2);
              currentX = currentX - prefSize.width;
              c.setBounds(currentX, insets.top + adj, prefSize.width, 
                  (int) Math.min(prefSize.getHeight(), availableH));
              currentX = currentX - GAP;
            }
        }
    }
    
    /**
     * Returns the minimum layout size.
     * 
     * @param parent  the container.
     * 
     * @return The minimum layout size.
     */
02024     public Dimension minimumLayoutSize(Container parent) 
    {
      return preferredLayoutSize(parent);
    }
    
    /**
     * Returns the preferred layout size.
     * 
     * @param parent  the container.
     * 
     * @return The preferred layout size.
     */
02036     public Dimension preferredLayoutSize(Container parent) 
    {
      Insets insets = parent.getInsets();
      int maxW = 0;
      int maxH = 0;
      int count = parent.getComponentCount();
      if (count > 0) 
        {
          for (int i = 0; i < count; i++)
            {
              Component c = parent.getComponent(i);
              Dimension d = c.getPreferredSize();
              maxW = Math.max(d.width, maxW);
              maxH = Math.max(d.height, maxH);
            }
        }
      return new Dimension(maxW * count + GAP * (count - 1) + insets.left 
              + insets.right, maxH + insets.top + insets.bottom);
    }
    
    /**
     * This layout manager does not need to track components, so this 
     * method does nothing.
     * 
     * @param name  the name the component is associated with.
     * @param component  the component.
     */
02063     public void addLayoutComponent(String name, Component component) 
    {
      // do nothing
    }
    
    /**
     * This layout manager does not need to track components, so this 
     * method does nothing.
     * 
     * @param component  the component.
     */
02074     public void removeLayoutComponent(Component component) {
      // do nothing
    }
  }

}

Generated by  Doxygen 1.6.0   Back to index