EMMA Coverage Report (generated Wed Aug 16 18:51:55 GMT 2006)
[all classes][javax.swing.plaf.metal]

COVERAGE SUMMARY FOR SOURCE FILE [MetalFileChooserUI.java]

nameclass, %method, %block, %line, %
MetalFileChooserUI.java79%  (15/19)54%  (51/94)46%  (1492/3249)48%  (352/731)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MetalFileChooserUI100% (1/1)76%  (25/33)69%  (847/1231)72%  (189/261)
MetalFileChooserUI (JFileChooser): void 100% (1/1)100% (19/19)100% (4/4)
addControlButtons (): void 100% (1/1)100% (153/153)100% (30/30)
createActionMap (): ActionMap 100% (1/1)100% (21/21)100% (5/5)
createDetailsView (JFileChooser): JPanel 0%   (0/1)0%   (0/99)0%   (0/13)
createDirectoryComboBoxModel (JFileChooser): MetalFileChooserUI$DirectoryComb... 100% (1/1)100% (5/5)100% (1/1)
createDirectoryComboBoxRenderer (JFileChooser): MetalFileChooserUI$DirectoryC... 100% (1/1)100% (6/6)100% (1/1)
createFilterComboBoxModel (): MetalFileChooserUI$FilterComboBoxModel 100% (1/1)100% (5/5)100% (1/1)
createFilterComboBoxRenderer (): MetalFileChooserUI$FilterComboBoxRenderer 100% (1/1)100% (5/5)100% (1/1)
createList (JFileChooser): JPanel 100% (1/1)100% (68/68)100% (12/12)
createListSelectionListener (JFileChooser): ListSelectionListener 100% (1/1)100% (5/5)100% (1/1)
createPropertyChangeListener (JFileChooser): PropertyChangeListener 100% (1/1)100% (5/5)100% (1/1)
createUI (JComponent): ComponentUI 100% (1/1)100% (8/8)100% (2/2)
formatSize (long): String 0%   (0/1)0%   (0/84)0%   (0/18)
getActionMap (): ActionMap 0%   (0/1)0%   (0/10)0%   (0/3)
getApproveButton (JFileChooser): JButton 100% (1/1)100% (3/3)100% (1/1)
getBottomPanel (): JPanel 100% (1/1)38%  (6/16)67%  (2/3)
getButtonPanel (): JPanel 100% (1/1)100% (3/3)100% (1/1)
getFileName (): String 100% (1/1)100% (11/11)100% (4/4)
getMaximumSize (JComponent): Dimension 100% (1/1)100% (6/6)100% (1/1)
getMinimumSize (JComponent): Dimension 0%   (0/1)0%   (0/26)0%   (0/4)
getPreferredSize (JComponent): Dimension 0%   (0/1)0%   (0/26)0%   (0/4)
installComponents (JFileChooser): void 100% (1/1)100% (286/286)100% (52/52)
installListeners (JFileChooser): void 100% (1/1)100% (50/50)100% (10/10)
installStrings (JFileChooser): void 100% (1/1)94%  (78/83)96%  (26/27)
installUI (JComponent): void 100% (1/1)100% (8/8)100% (3/3)
removeControlButtons (): void 0%   (0/1)0%   (0/10)0%   (0/4)
rescanCurrentDirectory (JFileChooser): void 100% (1/1)80%  (16/20)83%  (5/6)
setFileName (String): void 100% (1/1)100% (5/5)100% (2/2)
uninstallComponents (JFileChooser): void 100% (1/1)100% (38/38)100% (12/12)
uninstallListeners (JFileChooser): void 100% (1/1)86%  (30/35)89%  (8/9)
uninstallUI (JComponent): void 100% (1/1)100% (7/7)100% (3/3)
updateTable (): JPanel 0%   (0/1)0%   (0/104)0%   (0/21)
valueChanged (ListSelectionEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
     
class MetalFileChooserUI$ButtonLayout100% (1/1)33%  (2/6)4%   (7/164)6%   (2/35)
MetalFileChooserUI$ButtonLayout (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (1/1)
addLayoutComponent (String, Component): void 100% (1/1)100% (1/1)100% (1/1)
layoutContainer (Container): void 0%   (0/1)0%   (0/90)0%   (0/19)
minimumLayoutSize (Container): Dimension 0%   (0/1)0%   (0/4)0%   (0/1)
preferredLayoutSize (Container): Dimension 0%   (0/1)0%   (0/62)0%   (0/12)
removeLayoutComponent (Component): void 0%   (0/1)0%   (0/1)0%   (0/1)
     
class MetalFileChooserUI$DetailViewActionListener100% (1/1)50%  (1/2)8%   (6/80)6%   (1/17)
MetalFileChooserUI$DetailViewActionListener (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (1/1)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/74)0%   (0/16)
     
class MetalFileChooserUI$DirectoryComboBoxAction100% (1/1)50%  (1/2)33%  (6/18)40%  (2/5)
MetalFileChooserUI$DirectoryComboBoxAction (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (2/2)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/12)0%   (0/3)
     
class MetalFileChooserUI$DirectoryComboBoxModel100% (1/1)67%  (4/6)88%  (68/77)89%  (17/19)
MetalFileChooserUI$DirectoryComboBoxModel (MetalFileChooserUI): void 100% (1/1)100% (14/14)100% (4/4)
getDepth (int): int 0%   (0/1)0%   (0/4)0%   (0/1)
getElementAt (int): Object 0%   (0/1)0%   (0/5)0%   (0/1)
getSelectedItem (): Object 100% (1/1)100% (11/11)100% (3/3)
getSize (): int 100% (1/1)100% (4/4)100% (1/1)
setSelectedItem (Object): void 100% (1/1)100% (39/39)100% (9/9)
     
class MetalFileChooserUI$DirectoryComboBoxRenderer100% (1/1)50%  (1/2)21%  (12/56)23%  (3/13)
MetalFileChooserUI$DirectoryComboBoxRenderer (MetalFileChooserUI, JFileChoose... 100% (1/1)100% (12/12)100% (3/3)
getListCellRendererComponent (JList, Object, int, boolean, boolean): Component 0%   (0/1)0%   (0/44)0%   (0/10)
     
class MetalFileChooserUI$FileRenderer100% (1/1)100% (2/2)82%  (63/77)86%  (18/21)
MetalFileChooserUI$FileRenderer (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (2/2)
getListCellRendererComponent (JList, Object, int, boolean, boolean): Component 100% (1/1)80%  (57/71)84%  (16/19)
     
class MetalFileChooserUI$FilterComboBoxModel100% (1/1)83%  (5/6)89%  (91/102)85%  (22/26)
MetalFileChooserUI$FilterComboBoxModel (MetalFileChooserUI): void 100% (1/1)100% (24/24)100% (5/5)
getElementAt (int): Object 100% (1/1)100% (5/5)100% (1/1)
getSelectedItem (): Object 100% (1/1)100% (3/3)100% (1/1)
getSize (): int 100% (1/1)100% (4/4)100% (1/1)
propertyChange (PropertyChangeEvent): void 100% (1/1)100% (55/55)100% (14/14)
setSelectedItem (Object): void 0%   (0/1)0%   (0/11)0%   (0/4)
     
class MetalFileChooserUI$FilterComboBoxRenderer100% (1/1)100% (2/2)100% (23/23)100% (7/7)
MetalFileChooserUI$FilterComboBoxRenderer (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (2/2)
getListCellRendererComponent (JList, Object, int, boolean, boolean): Component 100% (1/1)100% (17/17)100% (5/5)
     
class MetalFileChooserUI$IndentIcon100% (1/1)17%  (1/6)15%  (6/40)11%  (1/9)
MetalFileChooserUI$IndentIcon (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (1/1)
getIconHeight (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getIconWidth (): int 0%   (0/1)0%   (0/9)0%   (0/1)
paintIcon (Component, Graphics, int, int): void 0%   (0/1)0%   (0/13)0%   (0/2)
setDepth (int): void 0%   (0/1)0%   (0/4)0%   (0/2)
setIcon (Icon): void 0%   (0/1)0%   (0/4)0%   (0/2)
     
class MetalFileChooserUI$ListViewActionListener100% (1/1)50%  (1/2)8%   (6/71)7%   (1/15)
MetalFileChooserUI$ListViewActionListener (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (1/1)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/65)0%   (0/14)
     
class MetalFileChooserUI$MetalFileChooserPropertyChangeListener100% (1/1)100% (2/2)64%  (322/506)68%  (78/114)
MetalFileChooserUI$MetalFileChooserPropertyChangeListener (MetalFileChooserUI... 100% (1/1)100% (6/6)100% (2/2)
propertyChange (PropertyChangeEvent): void 100% (1/1)63%  (316/500)68%  (76/112)
     
class MetalFileChooserUI$MetalFileChooserSelectionListener100% (1/1)50%  (1/2)19%  (6/31)20%  (2/10)
MetalFileChooserUI$MetalFileChooserSelectionListener (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (2/2)
valueChanged (ListSelectionEvent): void 0%   (0/1)0%   (0/25)0%   (0/8)
     
class MetalFileChooserUI$SingleClickListener100% (1/1)25%  (1/4)9%   (22/244)13%  (7/52)
MetalFileChooserUI$SingleClickListener (MetalFileChooserUI, JList): void 100% (1/1)100% (22/22)100% (7/7)
completeEditing (): void 0%   (0/1)0%   (0/64)0%   (0/14)
editFile (int): void 0%   (0/1)0%   (0/92)0%   (0/19)
mouseClicked (MouseEvent): void 0%   (0/1)0%   (0/66)0%   (0/12)
     
class MetalFileChooserUI$SingleClickListener$EditingActionListener0%   (0/1)0%   (0/2)0%   (0/14)0%   (0/4)
MetalFileChooserUI$SingleClickListener$EditingActionListener (MetalFileChoose... 0%   (0/1)0%   (0/6)0%   (0/1)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/8)0%   (0/3)
     
class MetalFileChooserUI$TableClickListener0%   (0/1)0%   (0/5)0%   (0/333)0%   (0/80)
MetalFileChooserUI$TableClickListener (MetalFileChooserUI, JTable, JFileChoos... 0%   (0/1)0%   (0/29)0%   (0/9)
closeDialog (): void 0%   (0/1)0%   (0/11)0%   (0/4)
completeEditing (): void 0%   (0/1)0%   (0/59)0%   (0/12)
editFile (int): void 0%   (0/1)0%   (0/64)0%   (0/14)
mouseClicked (MouseEvent): void 0%   (0/1)0%   (0/170)0%   (0/41)
     
class MetalFileChooserUI$TableClickListener$EditingActionListener0%   (0/1)0%   (0/2)0%   (0/14)0%   (0/4)
MetalFileChooserUI$TableClickListener$EditingActionListener (MetalFileChooser... 0%   (0/1)0%   (0/6)0%   (0/1)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/8)0%   (0/3)
     
class MetalFileChooserUI$TableFileRenderer0%   (0/1)0%   (0/2)0%   (0/90)0%   (0/21)
MetalFileChooserUI$TableFileRenderer (MetalFileChooserUI): void 0%   (0/1)0%   (0/6)0%   (0/2)
getTableCellRendererComponent (JTable, Object, boolean, boolean, int, int): C... 0%   (0/1)0%   (0/84)0%   (0/19)
     
class MetalFileChooserUI$VerticalMidLayout100% (1/1)33%  (2/6)9%   (7/78)11%  (2/18)
MetalFileChooserUI$VerticalMidLayout (MetalFileChooserUI): void 100% (1/1)100% (6/6)100% (1/1)
addLayoutComponent (String, Component): void 100% (1/1)100% (1/1)100% (1/1)
layoutContainer (Container): void 0%   (0/1)0%   (0/56)0%   (0/11)
minimumLayoutSize (Container): Dimension 0%   (0/1)0%   (0/4)0%   (0/1)
preferredLayoutSize (Container): Dimension 0%   (0/1)0%   (0/10)0%   (0/3)
removeLayoutComponent (Component): void 0%   (0/1)0%   (0/1)0%   (0/1)

1/* MetalFileChooserUI.java --
2   Copyright (C) 2005 Free Software Foundation, Inc.
3 
4This file is part of GNU Classpath.
5 
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10 
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14General Public License for more details.
15 
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING.  If not, write to the
18Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1902110-1301 USA.
20 
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library.  Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25 
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module.  An independent module is a module which is not derived from
33or based on this library.  If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so.  If you do not wish to do so, delete this
36exception statement from your version. */
37 
38 
39package javax.swing.plaf.metal;
40 
41import java.awt.BorderLayout;
42import java.awt.Component;
43import java.awt.Container;
44import java.awt.Dimension;
45import java.awt.Graphics;
46import java.awt.GridLayout;
47import java.awt.Insets;
48import java.awt.LayoutManager;
49import java.awt.Rectangle;
50import java.awt.Window;
51import java.awt.event.ActionEvent;
52import java.awt.event.ActionListener;
53import java.awt.event.MouseAdapter;
54import java.awt.event.MouseEvent;
55import java.awt.event.MouseListener;
56import java.beans.PropertyChangeEvent;
57import java.beans.PropertyChangeListener;
58import java.io.File;
59import java.sql.Date;
60import java.text.DateFormat;
61import java.text.NumberFormat;
62import java.util.List;
63 
64import javax.swing.AbstractAction;
65import javax.swing.AbstractListModel;
66import javax.swing.ActionMap;
67import javax.swing.BorderFactory;
68import javax.swing.ButtonGroup;
69import javax.swing.ComboBoxModel;
70import javax.swing.DefaultListCellRenderer;
71import javax.swing.Icon;
72import javax.swing.JButton;
73import javax.swing.JComboBox;
74import javax.swing.JComponent;
75import javax.swing.JDialog;
76import javax.swing.JFileChooser;
77import javax.swing.JLabel;
78import javax.swing.JList;
79import javax.swing.JPanel;
80import javax.swing.JScrollPane;
81import javax.swing.JTable;
82import javax.swing.JTextField;
83import javax.swing.JToggleButton;
84import javax.swing.ListModel;
85import javax.swing.ListSelectionModel;
86import javax.swing.SwingUtilities;
87import javax.swing.UIManager;
88import javax.swing.event.ListSelectionEvent;
89import javax.swing.event.ListSelectionListener;
90import javax.swing.filechooser.FileFilter;
91import javax.swing.filechooser.FileSystemView;
92import javax.swing.filechooser.FileView;
93import javax.swing.plaf.ComponentUI;
94import javax.swing.plaf.basic.BasicFileChooserUI;
95import javax.swing.table.DefaultTableCellRenderer;
96import javax.swing.table.DefaultTableModel;
97 
98 
99/**
100 * A UI delegate for the {@link JFileChooser} component.  This class is only
101 * partially implemented and is not usable yet.
102 */
103public class MetalFileChooserUI 
104  extends BasicFileChooserUI
105{
106  
107  /**
108   * A renderer for the files and directories in the file chooser table.
109   */
110  class TableFileRenderer
111    extends DefaultTableCellRenderer
112  {
113    
114    /**
115     * Creates a new renderer.
116     */
117    public TableFileRenderer()
118    {
119      super();
120    }
121    
122    /**
123     * Returns a component that can render the specified value.
124     * 
125     * @param table  the table
126     * @param value  the string value of the cell
127     * @param isSelected  is the item selected?
128     * @param hasFocus  does the item have the focus?
129     * @param row  the row
130     * @param column  the column
131     * 
132     * @return The renderer.
133     */
134    public Component getTableCellRendererComponent(JTable table, Object value,
135        boolean isSelected, boolean hasFocus, int row, int column)
136    {
137      if (column == 0)
138        {
139          FileView v = getFileView(getFileChooser());
140          ListModel lm = fileList.getModel();
141          if (row < lm.getSize())
142            setIcon(v.getIcon((File) lm.getElementAt(row)));
143        }
144      else
145        setIcon(null);
146      
147      setText(value.toString());
148      setOpaque(true);
149      setEnabled(table.isEnabled());
150      setFont(fileList.getFont());
151      
152      if (startEditing && column == 0 || !isSelected)
153        {
154          setBackground(table.getBackground());
155          setForeground(table.getForeground());
156        }
157      else
158        {
159          setBackground(table.getSelectionBackground());
160          setForeground(table.getSelectionForeground());
161        }
162 
163      if (hasFocus)
164        setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
165      else
166        setBorder(noFocusBorder);
167      
168      return this;
169    }
170  }
171  
172  /**
173   * ActionListener for the list view.
174   */
175  class ListViewActionListener implements ActionListener
176  {
177    
178    /**
179     * This method is invoked when an action occurs.
180     * 
181     * @param e -
182     *          the <code>ActionEvent</code> that occurred
183     */
184    public void actionPerformed(ActionEvent e)
185    {
186      if (!listView)
187        {
188          int[] index = fileTable.getSelectedRows();
189          listView = true;
190          JFileChooser fc = getFileChooser();
191          fc.remove(fileTablePanel);
192          createList(fc);
193 
194          fileList.getSelectionModel().clearSelection();
195          if (index.length > 0)
196              for (int i = 0; i < index.length; i++)
197                fileList.getSelectionModel().addSelectionInterval(index[i], index[i]);
198          
199          fc.add(fileListPanel, BorderLayout.CENTER);
200          fc.revalidate();
201          fc.repaint();
202        }
203    }
204  }
205  
206  /**
207   * ActionListener for the details view.
208   */
209  class DetailViewActionListener implements ActionListener
210  {
211    
212    /**
213     * This method is invoked when an action occurs.
214     * 
215     * @param e -
216     *          the <code>ActionEvent</code> that occurred
217     */
218    public void actionPerformed(ActionEvent e)
219    {
220      if (listView)
221        {
222          int[] index = fileList.getSelectedIndices();
223          JFileChooser fc = getFileChooser();
224          listView = false;
225          fc.remove(fileListPanel);
226          
227          if (fileTable == null)
228            createDetailsView(fc);
229          else
230            updateTable();
231 
232          fileTable.getSelectionModel().clearSelection();
233          if (index.length > 0)
234            {
235              for (int i = 0; i < index.length; i++)
236                fileTable.getSelectionModel().addSelectionInterval(index[i], index[i]);
237            }
238          
239          fc.add(fileTablePanel, BorderLayout.CENTER);
240          fc.revalidate();
241          fc.repaint();
242        }
243    }
244  }
245  
246  /**
247   * A property change listener.
248   */
249  class MetalFileChooserPropertyChangeListener 
250    implements PropertyChangeListener
251  {
252    /**
253     * Default constructor.
254     */
255    public MetalFileChooserPropertyChangeListener()
256    {
257    }
258    
259    /**
260     * Handles a property change event.
261     * 
262     * @param e  the event.
263     */
264    public void propertyChange(PropertyChangeEvent e)
265    {
266      JFileChooser filechooser = getFileChooser();
267      
268      String n = e.getPropertyName();
269      if (n.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY))
270        {
271          int mode = -1; 
272          if (filechooser.isMultiSelectionEnabled())
273            mode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
274          else
275            mode = ListSelectionModel.SINGLE_SELECTION;
276          
277          if (listView)
278            fileList.setSelectionMode(mode);
279          else
280            fileTable.setSelectionMode(mode);
281        }
282      else if (n.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
283        {
284          File file = filechooser.getSelectedFile();
285          
286          if (file != null
287              && filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
288            {
289              if (file.isDirectory() && filechooser.isTraversable(file))
290                {
291                  directoryLabel = look;
292                  dirLabel.setText(directoryLabel);
293                  filechooser.setApproveButtonText(openButtonText);
294                  filechooser.setApproveButtonToolTipText(openButtonToolTipText);
295                }
296              else if (file.isFile())
297                {
298                  directoryLabel = save;
299                  dirLabel.setText(directoryLabel);
300                  filechooser.setApproveButtonText(saveButtonText);
301                  filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
302                }
303            }
304            
305          if (file == null)
306            setFileName(null);
307          else if (file.isFile() || filechooser.getFileSelectionMode() 
308                   != JFileChooser.FILES_ONLY)
309            setFileName(file.getName());
310          int index = -1;
311          index = getModel().indexOf(file);
312          if (index >= 0)
313            {
314              if (listView)
315                {
316                  fileList.setSelectedIndex(index);
317                  fileList.ensureIndexIsVisible(index);
318                  fileList.revalidate();
319                  fileList.repaint();
320                }
321              else
322                {
323                  fileTable.getSelectionModel().addSelectionInterval(index, index);
324                  fileTable.scrollRectToVisible(fileTable.getCellRect(index, 0, true));
325                  fileTable.revalidate();
326                  fileTable.repaint();
327                }
328            }
329        }
330      
331      else if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY))
332        {
333          if (listView)
334            {
335              fileList.clearSelection();
336              fileList.revalidate();
337              fileList.repaint();
338            }
339          else
340            {
341              fileTable.clearSelection();
342              fileTable.revalidate();
343              fileTable.repaint();
344            }
345 
346          setDirectorySelected(false);
347          File currentDirectory = filechooser.getCurrentDirectory();
348          setDirectory(currentDirectory);
349          boolean hasParent = currentDirectory.getParentFile() != null;
350          getChangeToParentDirectoryAction().setEnabled(hasParent);
351        }
352      
353      else if (n.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
354        {
355          filterModel.propertyChange(e);
356        }
357      else if (n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
358        {
359          filterModel.propertyChange(e);
360        }
361      else if (n.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
362                 || n.equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
363        {
364          Window owner = SwingUtilities.windowForComponent(filechooser);
365          if (owner instanceof JDialog)
366            ((JDialog) owner).setTitle(getDialogTitle(filechooser));
367          approveButton.setText(getApproveButtonText(filechooser));
368          approveButton.setToolTipText(
369                  getApproveButtonToolTipText(filechooser));
370          approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));
371        }
372      
373      else if (n.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
374        approveButton.setText(getApproveButtonText(filechooser));
375      
376      else if (n.equals(
377              JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
378        approveButton.setToolTipText(getApproveButtonToolTipText(filechooser));
379      
380      else if (n.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
381        approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));
382 
383      else if (n.equals(
384              JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
385        {
386          if (filechooser.getControlButtonsAreShown())
387            {
388              topPanel.add(controls, BorderLayout.EAST);
389            }
390          else
391            topPanel.remove(controls);
392          topPanel.revalidate();
393          topPanel.repaint();
394          topPanel.doLayout();
395        }
396      
397      else if (n.equals(
398              JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
399        {
400          if (filechooser.isAcceptAllFileFilterUsed())
401            filechooser.addChoosableFileFilter(
402                    getAcceptAllFileFilter(filechooser));
403          else
404            filechooser.removeChoosableFileFilter(
405                    getAcceptAllFileFilter(filechooser));
406        }
407      
408      else if (n.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY))
409        {
410          JComponent old = (JComponent) e.getOldValue();
411          if (old != null)
412            getAccessoryPanel().remove(old);
413          JComponent newval = (JComponent) e.getNewValue();
414          if (newval != null)
415            getAccessoryPanel().add(newval);
416        }
417      
418      if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
419          || n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
420          || n.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
421        {
422          // Remove editing component
423          if (fileTable != null)
424            fileTable.removeAll();
425          if (fileList != null)
426            fileList.removeAll();
427          startEditing = false;
428          
429          // Set text on button back to original.
430          if (filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
431            {
432              directoryLabel = save;
433              dirLabel.setText(directoryLabel);
434              filechooser.setApproveButtonText(saveButtonText);
435              filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
436            }
437          
438          rescanCurrentDirectory(filechooser);
439        }
440      
441      filechooser.revalidate();
442      filechooser.repaint();
443    }
444  };
445  
446  /** 
447   * A combo box model containing the selected directory and all its parent
448   * directories.
449   */
450  protected class DirectoryComboBoxModel
451    extends AbstractListModel
452    implements ComboBoxModel
453  {
454    /** Storage for the items in the model. */
455    private List items;
456    
457    /** The index of the selected item. */
458    private int selectedIndex;
459    
460    /**
461     * Creates a new model.
462     */
463    public DirectoryComboBoxModel() 
464    {
465      items = new java.util.ArrayList();
466      selectedIndex = -1;
467    }
468    
469    /**
470     * Returns the number of items in the model.
471     * 
472     * @return The number of items in the model.
473     */
474    public int getSize()
475    {
476      return items.size();
477    }
478    
479    /**
480     * Returns the item at the specified index.
481     * 
482     * @param index  the item index.
483     * 
484     * @return The item.
485     */
486    public Object getElementAt(int index)
487    {
488      return items.get(index);
489    }
490    
491    /**
492     * Returns the depth of the item at the given <code>index</code>.
493     * 
494     * @param index  the item index.
495     * 
496     * @return The depth.
497     */
498    public int getDepth(int index)
499    {
500      return Math.max(index, 0);
501    }
502 
503    /**
504     * Returns the selected item, or <code>null</code> if no item is selected.
505     * 
506     * @return The selected item, or <code>null</code>.
507     */
508    public Object getSelectedItem()
509    {
510      if (selectedIndex >= 0) 
511        return items.get(selectedIndex);
512      else
513        return null;
514    }
515    
516    /**
517     * Sets the selected item.  This clears all the directories from the
518     * existing list, and repopulates it with the new selected directory
519     * and all its parent directories.
520     * 
521     * @param selectedDirectory  the selected directory.
522     */
523    public void setSelectedItem(Object selectedDirectory)
524    {
525      items.clear();
526      FileSystemView fsv = getFileChooser().getFileSystemView();
527      File parent = (File) selectedDirectory;
528      while (parent != null)
529        {
530          items.add(0, parent);
531          parent = fsv.getParentDirectory(parent);
532        }
533      selectedIndex = items.indexOf(selectedDirectory);
534      fireContentsChanged(this, 0, items.size() - 1);
535    }
536    
537  }
538 
539  /**
540   * Handles changes to the selection in the directory combo box.
541   */
542  protected class DirectoryComboBoxAction
543    extends AbstractAction
544  {
545    /**
546     * Creates a new action.
547     */
548    protected DirectoryComboBoxAction()
549    {
550      // Nothing to do here.
551    }
552    
553    /**
554     * Handles the action event.
555     * 
556     * @param e  the event.
557     */
558    public void actionPerformed(ActionEvent e)
559    {
560      JFileChooser fc = getFileChooser();
561      fc.setCurrentDirectory((File) directoryModel.getSelectedItem());
562    }
563  }
564 
565  /**
566   * A renderer for the items in the directory combo box.
567   */
568  class DirectoryComboBoxRenderer
569    extends DefaultListCellRenderer
570  {
571    /**
572     * This is the icon that is displayed in the combobox. This wraps
573     * the standard icon and adds indendation.
574     */
575    private IndentIcon indentIcon;
576 
577    /**
578     * Creates a new renderer.
579     */
580    public DirectoryComboBoxRenderer(JFileChooser fc)
581    {
582      indentIcon = new IndentIcon();
583    }
584    
585    /**
586     * Returns a component that can be used to paint the given value within 
587     * the list.
588     * 
589     * @param list  the list.
590     * @param value  the value (a {@link File}).
591     * @param index  the item index.
592     * @param isSelected  is the item selected?
593     * @param cellHasFocus  does the list cell have focus?
594     * 
595     * @return The list cell renderer.
596     */
597    public Component getListCellRendererComponent(JList list, Object value,
598                                                  int index,
599                                                  boolean isSelected,
600                                                  boolean cellHasFocus)
601    {
602      super.getListCellRendererComponent(list, value, index, isSelected,
603                                         cellHasFocus);
604      File file = (File) value;
605      setText(getFileChooser().getName(file));
606 
607      // Install indented icon.
608      Icon icon = getFileChooser().getIcon(file);
609      indentIcon.setIcon(icon);
610      int depth = directoryModel.getDepth(index);
611      indentIcon.setDepth(depth);
612      setIcon(indentIcon);
613 
614      return this;
615    }
616  }
617 
618  /**
619   * An icon that wraps another icon and adds indentation.
620   */
621  class IndentIcon
622    implements Icon
623  {
624 
625    /**
626     * The indentation level.
627     */
628    private static final int INDENT = 10;
629 
630    /**
631     * The wrapped icon.
632     */
633    private Icon icon;
634 
635    /**
636     * The current depth.
637     */
638    private int depth;
639 
640    /**
641     * Sets the icon to be wrapped.
642     *
643     * @param i the icon
644     */
645    void setIcon(Icon i)
646    {
647      icon = i;
648    }
649 
650    /**
651     * Sets the indentation depth.
652     *
653     * @param d the depth to set
654     */
655    void setDepth(int d)
656    {
657      depth = d;
658    }
659 
660    public int getIconHeight()
661    {
662      return icon.getIconHeight();
663    }
664 
665    public int getIconWidth()
666    {
667      return icon.getIconWidth() + depth * INDENT;
668    }
669 
670    public void paintIcon(Component c, Graphics g, int x, int y)
671    {
672      icon.paintIcon(c, g, x + depth * INDENT, y);
673    }
674      
675  }
676 
677  /**
678   * A renderer for the files and directories in the file chooser.
679   */
680  protected class FileRenderer
681    extends DefaultListCellRenderer
682  {
683    
684    /**
685     * Creates a new renderer.
686     */
687    protected FileRenderer()
688    {
689      // Nothing to do here.
690    }
691    
692    /**
693     * Returns a component that can render the specified value.
694     * 
695     * @param list  the list.
696     * @param value  the value (a {@link File}).
697     * @param index  the index.
698     * @param isSelected  is the item selected?
699     * @param cellHasFocus  does the item have the focus?
700     * 
701     * @return The renderer.
702     */
703    public Component getListCellRendererComponent(JList list, Object value,
704        int index, boolean isSelected, boolean cellHasFocus)
705    {
706      FileView v = getFileView(getFileChooser());
707      File f = (File) value;
708      if (f != null)
709        {
710          setText(v.getName(f));
711          setIcon(v.getIcon(f));
712        }
713      else
714        {
715          setText("");
716          setIcon(null);
717        }
718      setOpaque(true);
719      if (isSelected)
720        {
721          setBackground(list.getSelectionBackground());
722          setForeground(list.getSelectionForeground());
723        }
724      else
725        {
726          setBackground(list.getBackground());
727          setForeground(list.getForeground());
728        }
729 
730      setEnabled(list.isEnabled());
731      setFont(list.getFont());
732 
733      if (cellHasFocus)
734        setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
735      else
736        setBorder(noFocusBorder);
737      return this;
738    }
739  }
740 
741  /**
742   * A combo box model for the file selection filters.
743   */
744  protected class FilterComboBoxModel
745    extends AbstractListModel
746    implements ComboBoxModel, PropertyChangeListener
747  {
748 
749    /** Storage for the filters in the model. */
750    protected FileFilter[] filters;
751 
752    /** The index of the selected file filter. */
753    private Object selected;
754    
755    /**
756     * Creates a new model.
757     */
758    protected FilterComboBoxModel()
759    {
760      filters = new FileFilter[1];
761      filters[0] = getAcceptAllFileFilter(getFileChooser());
762      selected = filters[0];
763    }
764    
765    /**
766     * Handles property changes.
767     * 
768     * @param e  the property change event.
769     */
770    public void propertyChange(PropertyChangeEvent e)
771    {
772      if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
773        {
774          JFileChooser fc = getFileChooser();
775          FileFilter[] choosableFilters = fc.getChoosableFileFilters();
776          filters = choosableFilters;
777          fireContentsChanged(this, 0, filters.length);
778          selected = e.getNewValue();
779          fireContentsChanged(this, -1, -1);
780        }
781      else if (e.getPropertyName().equals(
782              JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
783        {
784          // repopulate list
785          JFileChooser fc = getFileChooser();
786          FileFilter[] choosableFilters = fc.getChoosableFileFilters();
787          filters = choosableFilters;
788          fireContentsChanged(this, 0, filters.length);
789        }
790    }
791    
792    /**
793     * Sets the selected filter.
794     * 
795     * @param filter  the filter (<code>null</code> ignored).
796     */
797    public void setSelectedItem(Object filter)
798    {
799      if (filter != null)
800      {
801          selected = filter;
802          fireContentsChanged(this, -1, -1);
803      }
804    }
805    
806    /**
807     * Returns the selected file filter.
808     * 
809     * @return The selected file filter.
810     */
811    public Object getSelectedItem()
812    {
813      return selected;
814    }
815    
816    /**
817     * Returns the number of items in the model.
818     * 
819     * @return The number of items in the model.
820     */
821    public int getSize()
822    {
823      return filters.length;
824    }
825    
826    /**
827     * Returns the item at the specified index.
828     * 
829     * @param index  the item index.
830     * 
831     * @return The item at the specified index.
832     */
833    public Object getElementAt(int index)
834    {
835      return filters[index];
836    }
837    
838  }
839 
840  /**
841   * A renderer for the items in the file filter combo box.
842   */
843  public class FilterComboBoxRenderer
844    extends DefaultListCellRenderer
845  {
846    /**
847     * Creates a new renderer.
848     */
849    public FilterComboBoxRenderer()
850    {
851      // Nothing to do here.
852    }
853    
854    /**
855     * Returns a component that can be used to paint the given value within 
856     * the list.
857     * 
858     * @param list  the list.
859     * @param value  the value (a {@link FileFilter}).
860     * @param index  the item index.
861     * @param isSelected  is the item selected?
862     * @param cellHasFocus  does the list cell have focus?
863     * 
864     * @return This component as the renderer.
865     */
866    public Component getListCellRendererComponent(JList list, Object value,
867        int index, boolean isSelected, boolean cellHasFocus)
868    {
869      super.getListCellRendererComponent(list, value, index, isSelected, 
870                                         cellHasFocus);
871      FileFilter filter = (FileFilter) value;
872      setText(filter.getDescription());
873      return this;
874    }
875  }
876 
877  /**
878   * A listener for selection events in the file list.
879   * 
880   * @see #createListSelectionListener(JFileChooser)
881   */
882  class MetalFileChooserSelectionListener 
883    implements ListSelectionListener
884  {
885    /**
886     * Creates a new <code>SelectionListener</code> object.
887     */
888    protected MetalFileChooserSelectionListener()
889    {
890      // Do nothing here.
891    }
892 
893    /**
894     * Makes changes to different properties when
895     * a value has changed in the filechooser's selection.
896     *
897     * @param e - the list selection event that occured.
898     */
899    public void valueChanged(ListSelectionEvent e)
900    {
901      File f = (File) fileList.getSelectedValue();
902      if (f == null)
903        return;
904      JFileChooser filechooser = getFileChooser();
905      if (! filechooser.isTraversable(f))
906        filechooser.setSelectedFile(f);
907      else
908        filechooser.setSelectedFile(null);
909    }
910  }
911 
912  /**
913   * A mouse listener for the {@link JFileChooser}.
914   * This listener is used for editing filenames.
915   */
916  protected class SingleClickListener
917    extends MouseAdapter
918  {
919    
920    /** Stores instance of the list */
921    JList list;
922    
923    /** 
924     * Stores the current file that is being edited.
925     * It is null if nothing is currently being edited.
926     */
927    File editFile;
928    
929    /** The current file chooser. */
930    JFileChooser fc;
931    
932    /** The last file selected. */
933    Object lastSelected;
934    
935    /** The textfield used for editing. */
936    JTextField editField;
937    
938    /**
939     * Creates a new listener.
940     * 
941     * @param list  the directory/file list.
942     */
943    public SingleClickListener(JList list)
944    {
945      this.list = list;
946      editFile = null;
947      fc = getFileChooser();
948      lastSelected = null;
949      startEditing = false;
950    }
951    
952    /**
953     * Receives notification of a mouse click event.
954     * 
955     * @param e  the event.
956     */
957    public void mouseClicked(MouseEvent e)
958    {
959      if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1)
960        {
961          int index = list.locationToIndex(e.getPoint());
962          File[] sf = fc.getSelectedFiles();
963          if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
964              && index >= 0 && !startEditing && list.isSelectedIndex(index))
965            {
966              Object tmp = list.getModel().getElementAt(index);
967              if (lastSelected != null && lastSelected.equals(tmp))
968                editFile(index);
969              lastSelected = tmp;
970            }
971          else
972              completeEditing();
973        }
974      else
975        completeEditing();
976    }
977    
978    /**
979     * Sets up the text editor for the current file.
980     * 
981     * @param index -
982     *          the current index of the item in the list to be edited.
983     */
984    void editFile(int index)
985    {
986      Rectangle bounds = list.getCellBounds(index, index);
987      list.scrollRectToVisible(bounds);
988      editFile = (File) list.getModel().getElementAt(index);
989      if (editFile.canWrite())
990        {
991          startEditing = true;
992          editField = new JTextField(editFile.getName());
993          editField.addActionListener(new EditingActionListener());
994          
995          Icon icon = getFileView(fc).getIcon(editFile);
996          if (icon != null)
997            {
998              int padding = icon.getIconWidth() + 4;
999              bounds.x += padding;
1000              bounds.width -= padding;
1001            }
1002          editField.setBounds(bounds);
1003          
1004          list.add(editField);
1005          
1006          editField.requestFocus();
1007          editField.selectAll();
1008        }
1009      else
1010        completeEditing();
1011      list.repaint();
1012    }
1013    
1014    /** 
1015     * Completes the editing.
1016     */
1017    void completeEditing()
1018    {
1019      if (editField != null && editFile != null)
1020        {
1021          String text = editField.getText();
1022          if (text != null && text != "" && !text.equals(fc.getName(editFile)))
1023            {
1024              File f = fc.getFileSystemView().
1025                createFileObject(fc.getCurrentDirectory(), text);
1026              if ( editFile.renameTo(f) )
1027                rescanCurrentDirectory(fc);
1028            }
1029          list.remove(editField);
1030        }
1031      startEditing = false;
1032      editFile = null;
1033      lastSelected = null;
1034      editField = null;
1035      list.repaint();
1036    }
1037    
1038    /**
1039     * ActionListener for the editing text field.
1040     */
1041    class EditingActionListener implements ActionListener
1042    {
1043      
1044      /**
1045       * This method is invoked when an action occurs.
1046       * 
1047       * @param e -
1048       *          the <code>ActionEvent</code> that occurred
1049       */
1050      public void actionPerformed(ActionEvent e)
1051      {
1052        if (editField != null)
1053          completeEditing();
1054      }
1055    }
1056  }
1057 
1058  /**
1059   * A mouse listener for the {@link JFileChooser}.
1060   * This listener is used for the table
1061   */
1062  private class TableClickListener extends MouseAdapter
1063  {
1064 
1065    /** Stores instance of the table */
1066    JTable table;
1067 
1068    /** Stores instance of the file chooser */
1069    JFileChooser fc;
1070 
1071    /** The last selected file. */
1072    Object lastSelected;
1073    
1074    /** 
1075     * Stores the current file that is being edited.
1076     * It is null if nothing is currently being edited.
1077     */
1078    File editFile;
1079    
1080    /** The textfield used for editing. */
1081    JTextField editField;
1082 
1083    /**
1084     * Creates a new listener.
1085     * 
1086     * @param table the directory/file table
1087     * @param fc the JFileChooser
1088     */
1089    public TableClickListener(JTable table, JFileChooser fc)
1090    {
1091      this.table = table;
1092      this.fc = fc;
1093      lastSelected = fileList.getSelectedValue();
1094      setDirectorySelected(false);
1095      startEditing = false;
1096      editFile = null;
1097      editField = null;
1098    }
1099 
1100    /**
1101     * Receives notification of a mouse click event.
1102     * 
1103     * @param e the event.
1104     */
1105    public void mouseClicked(MouseEvent e)
1106    {
1107      int row = table.getSelectedRow();
1108      Object selVal = fileList.getModel().getElementAt(row);
1109      if (selVal == null)
1110        return;
1111      FileSystemView fsv = fc.getFileSystemView();
1112      if (e.getClickCount() == 1 &&
1113          selVal.equals(lastSelected) &&
1114          e.getButton() == MouseEvent.BUTTON1)
1115        {
1116          File[] sf = fc.getSelectedFiles();
1117          if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
1118              && !startEditing)
1119            {
1120              editFile = (File) selVal;
1121              editFile(row);
1122            }
1123        }
1124      else if (e.getClickCount() >= 2 &&
1125          selVal.equals(lastSelected))
1126        {
1127          if (startEditing)
1128            completeEditing();
1129          File f = fsv.createFileObject(lastSelected.toString());
1130          if (fc.isTraversable(f))
1131            {
1132              fc.setCurrentDirectory(f);
1133              fc.rescanCurrentDirectory();
1134            }
1135          else
1136            {
1137              fc.setSelectedFile(f);
1138              fc.approveSelection();
1139              closeDialog();
1140            }
1141        }
1142      else
1143        {
1144          if (startEditing)
1145            completeEditing();
1146          String path = selVal.toString();
1147          File f = fsv.createFileObject(path);
1148          fc.setSelectedFile(f);
1149          if (fc.isTraversable(f))
1150            {
1151              setDirectorySelected(true);
1152              setDirectory(f);
1153            }
1154          else
1155            {
1156              setDirectorySelected(false);
1157              setDirectory(null);
1158            }
1159          lastSelected = selVal;
1160          if (f.isFile())
1161            setFileName(path.substring(path.lastIndexOf("/") + 1));
1162          else if (fc.getFileSelectionMode() != JFileChooser.FILES_ONLY)
1163            setFileName(path);
1164        }
1165      fileTable.repaint();
1166    }
1167 
1168    /**
1169     * Sets up the text editor for the current file.
1170     * 
1171     * @param row -
1172     *          the current row of the item in the list to be edited.
1173     */
1174    void editFile(int row)
1175    {
1176      Rectangle bounds = table.getCellRect(row, 0, true);
1177      table.scrollRectToVisible(bounds);
1178      if (editFile.canWrite())
1179        {
1180          startEditing = true;
1181          editField = new JTextField(editFile.getName());
1182          editField.addActionListener(new EditingActionListener());
1183 
1184          // Need to adjust y pos
1185          bounds.y = row * table.getRowHeight();
1186          editField.setBounds(bounds);
1187          
1188          table.add(editField);
1189          
1190          editField.requestFocus();
1191          editField.selectAll();
1192        }
1193      else
1194        completeEditing();
1195      table.repaint();
1196    }
1197    
1198    /** 
1199     * Completes the editing.
1200     */
1201    void completeEditing()
1202    {
1203      if (editField != null && editFile != null)
1204        {
1205          String text = editField.getText();
1206          if (text != null && text != "" && !text.equals(fc.getName(editFile)))
1207              if (editFile.renameTo(fc.getFileSystemView().createFileObject(
1208                  fc.getCurrentDirectory(), text)))
1209                rescanCurrentDirectory(fc);
1210          table.remove(editField);
1211        }
1212      startEditing = false;
1213      editFile = null;
1214      editField = null;
1215      table.repaint();
1216    }
1217    
1218    /**
1219     * ActionListener for the editing text field.
1220     */
1221    class EditingActionListener implements ActionListener
1222    {
1223      
1224      /**
1225       * This method is invoked when an action occurs.
1226       * 
1227       * @param e -
1228       *          the <code>ActionEvent</code> that occurred
1229       */
1230      public void actionPerformed(ActionEvent e)
1231      {
1232        if (editField != null)
1233          completeEditing();
1234      }
1235    }
1236    
1237    /**
1238     * Closes the dialog.
1239     */
1240    public void closeDialog()
1241    {
1242      Window owner = SwingUtilities.windowForComponent(fc);
1243      if (owner instanceof JDialog)
1244        ((JDialog) owner).dispose();
1245    }
1246  } 
1247  
1248  /** The text for a label describing the directory combo box. */
1249  private String directoryLabel;
1250  
1251  private JComboBox directoryComboBox;
1252  
1253  /** The model for the directory combo box. */
1254  DirectoryComboBoxModel directoryModel;
1255  
1256  /** The text for a label describing the file text field. */
1257  private String fileLabel;
1258  
1259  /** The file name text field. */
1260  private JTextField fileTextField;
1261  
1262  /** The text for a label describing the filter combo box. */
1263  private String filterLabel;
1264 
1265  /** 
1266   * The top panel (contains the directory combo box and the control buttons). 
1267   */
1268  private JPanel topPanel;
1269  
1270  /** A panel containing the control buttons ('up', 'home' etc.). */
1271  private JPanel controls;
1272 
1273  /** 
1274   * The panel that contains the filename field and the filter combobox. 
1275   */
1276  private JPanel bottomPanel;
1277 
1278  /** 
1279   * The panel that contains the 'Open' (or 'Save') and 'Cancel' buttons. 
1280   */
1281  private JPanel buttonPanel;
1282  
1283  private JButton approveButton;
1284  
1285  /** The file list. */
1286  JList fileList;
1287  
1288  /** The file table. */
1289  JTable fileTable;
1290  
1291  /** The panel containing the file list. */
1292  JPanel fileListPanel;
1293  
1294  /** The panel containing the file table. */
1295  JPanel fileTablePanel;
1296  
1297  /** The filter combo box model. */
1298  private FilterComboBoxModel filterModel;
1299 
1300  /** The action map. */
1301  private ActionMap actionMap;
1302  
1303  /** True if currently in list view. */
1304  boolean listView;
1305  
1306  /** True if we can or have started editing a cell. */
1307  boolean startEditing;
1308  
1309  /** The scrollpane used for the table and list. */
1310  JScrollPane scrollPane;
1311  
1312  /** The text for the label when saving. */
1313  String save;
1314  
1315  /** The text for the label when opening a directory. */
1316  String look;
1317  
1318  /** The label for the file combo box. */
1319  JLabel dirLabel;
1320  
1321  /** Listeners. */
1322  ListSelectionListener listSelList;
1323  MouseListener doubleClickList;
1324  SingleClickListener singleClickList;
1325  TableClickListener tableClickList;
1326  
1327  /**
1328   * A factory method that returns a UI delegate for the specified
1329   * component.
1330   * 
1331   * @param c  the component (which should be a {@link JFileChooser}).
1332   */
1333  public static ComponentUI createUI(JComponent c)
1334  {
1335    JFileChooser chooser = (JFileChooser) c;
1336    return new MetalFileChooserUI(chooser);
1337  }
1338 
1339  /**
1340   * Creates a new instance of this UI delegate.
1341   * 
1342   * @param filechooser  the file chooser component.
1343   */
1344  public MetalFileChooserUI(JFileChooser filechooser)
1345  {
1346    super(filechooser);
1347    bottomPanel = new JPanel(new GridLayout(3, 2));
1348    buttonPanel = new JPanel();
1349  }
1350 
1351  public void installUI(JComponent c)
1352  {
1353    super.installUI(c);
1354    actionMap = createActionMap();
1355  }
1356  
1357  public void uninstallUI(JComponent c)
1358  {
1359    super.uninstallUI(c);
1360    actionMap = null;
1361  }
1362  
1363  /**
1364   * Installs the sub-components of the file chooser.
1365   * 
1366   * @param fc  the file chooser component.
1367   */
1368  public void installComponents(JFileChooser fc)
1369  {
1370    fc.setLayout(new BorderLayout());
1371    topPanel = new JPanel(new BorderLayout());
1372    dirLabel = new JLabel(directoryLabel);
1373    topPanel.add(dirLabel, BorderLayout.WEST);
1374    this.controls = new JPanel();
1375    addControlButtons();
1376    
1377    JPanel dirPanel = new JPanel(new VerticalMidLayout());
1378    directoryModel = createDirectoryComboBoxModel(fc);
1379    directoryComboBox = new JComboBox(directoryModel);
1380    directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
1381    dirPanel.add(directoryComboBox);
1382    topPanel.add(dirPanel);
1383    topPanel.add(controls, BorderLayout.EAST);
1384    topPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8));
1385    fc.add(topPanel, BorderLayout.NORTH);
1386    
1387    JPanel list = createList(fc);
1388    list.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
1389    fc.add(list, BorderLayout.CENTER);
1390    
1391    JPanel bottomPanel = getBottomPanel();
1392    filterModel = createFilterComboBoxModel();
1393    JComboBox fileFilterCombo = new JComboBox(filterModel);
1394    fileFilterCombo.setRenderer(createFilterComboBoxRenderer());
1395    
1396    fileTextField = new JTextField();
1397    JPanel fileNamePanel = new JPanel(new VerticalMidLayout());
1398    fileNamePanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 5));
1399    fileNamePanel.add(fileTextField);
1400    JPanel row1 = new JPanel(new BorderLayout());
1401    row1.add(new JLabel(this.fileLabel), BorderLayout.WEST);
1402    row1.add(fileNamePanel);
1403    bottomPanel.add(row1);
1404    
1405    JPanel row2 = new JPanel(new BorderLayout());
1406    row2.add(new JLabel(this.filterLabel), BorderLayout.WEST);
1407    row2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
1408    row2.add(fileFilterCombo);
1409    bottomPanel.add(row2);
1410    JPanel buttonPanel = new JPanel(new ButtonLayout());
1411    
1412    approveButton = new JButton(getApproveSelectionAction());
1413    approveButton.setText(getApproveButtonText(fc));
1414    approveButton.setToolTipText(getApproveButtonToolTipText(fc));
1415    approveButton.setMnemonic(getApproveButtonMnemonic(fc));
1416    buttonPanel.add(approveButton);
1417    buttonPanel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
1418    
1419    JButton cancelButton = new JButton(getCancelSelectionAction());
1420    cancelButton.setText(cancelButtonText);
1421    cancelButton.setToolTipText(cancelButtonToolTipText);
1422    cancelButton.setMnemonic(cancelButtonMnemonic);
1423    buttonPanel.add(cancelButton);
1424    bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
1425    bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 8));
1426    fc.add(bottomPanel, BorderLayout.SOUTH);
1427    
1428    fc.add(getAccessoryPanel(), BorderLayout.EAST);
1429  }
1430  
1431  /**
1432   * Uninstalls the components added by 
1433   * {@link #installComponents(JFileChooser)}.
1434   * 
1435   * @param fc  the file chooser.
1436   */
1437  public void uninstallComponents(JFileChooser fc)
1438  {
1439    fc.remove(bottomPanel);
1440    bottomPanel = null;
1441    fc.remove(fileListPanel);
1442    fc.remove(fileTablePanel);
1443    fileTablePanel = null;
1444    fileListPanel = null;
1445    fc.remove(topPanel);
1446    topPanel = null;
1447    
1448    directoryModel = null;
1449    fileTextField = null;
1450    directoryComboBox = null;
1451  }
1452  
1453  /**
1454   * Returns the panel that contains the 'Open' (or 'Save') and 'Cancel' 
1455   * buttons.
1456   * 
1457   * @return The panel.
1458   */
1459  protected JPanel getButtonPanel()
1460  {
1461    return buttonPanel;    
1462  }
1463  
1464  /**
1465   * Creates and returns a new panel that will be used for the controls at
1466   * the bottom of the file chooser.
1467   * 
1468   * @return A new panel.
1469   */
1470  protected JPanel getBottomPanel()
1471  {
1472    if (bottomPanel == null)
1473      bottomPanel = new JPanel(new GridLayout(3, 2));
1474    return bottomPanel;
1475  }
1476  
1477  /**
1478   * Fetches localised strings for use by the labels and buttons on the
1479   * file chooser.
1480   * 
1481   * @param fc  the file chooser.
1482   */
1483  protected void installStrings(JFileChooser fc)
1484  { 
1485     super.installStrings(fc);
1486     look = "Look In: ";
1487     save = "Save In: ";
1488     if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1489       directoryLabel = save;
1490     else
1491       directoryLabel = look;
1492     
1493     fileLabel = "File Name: ";
1494     filterLabel = "Files of Type: ";
1495     
1496     this.cancelButtonMnemonic = 0;
1497     this.cancelButtonText = "Cancel";
1498     this.cancelButtonToolTipText = "Abort file chooser dialog";
1499     
1500     this.directoryOpenButtonMnemonic = 0;
1501     this.directoryOpenButtonText = "Open";
1502     this.directoryOpenButtonToolTipText = "Open selected directory";
1503     
1504     this.helpButtonMnemonic = 0;
1505     this.helpButtonText = "Help";
1506     this.helpButtonToolTipText = "Filechooser help";
1507     
1508     this.openButtonMnemonic = 0;
1509     this.openButtonText = "Open";
1510     this.openButtonToolTipText = "Open selected file";
1511     
1512     this.saveButtonMnemonic = 0;
1513     this.saveButtonText = "Save";
1514     this.saveButtonToolTipText = "Save selected file";
1515     
1516     this.updateButtonMnemonic = 0;
1517     this.updateButtonText = "Update";
1518     this.updateButtonToolTipText = "Update directory listing";   
1519  }
1520  
1521  /**
1522   * Installs the listeners required.
1523   * 
1524   * @param fc  the file chooser.
1525   */
1526  protected void installListeners(JFileChooser fc)
1527  {
1528    directoryComboBox.setAction(new DirectoryComboBoxAction());
1529    fc.addPropertyChangeListener(filterModel);
1530    listSelList = createListSelectionListener(fc);
1531    doubleClickList = this.createDoubleClickListener(fc, fileList);
1532    singleClickList = new SingleClickListener(fileList);
1533    fileList.addListSelectionListener(listSelList);
1534    fileList.addMouseListener(doubleClickList);
1535    fileList.addMouseListener(singleClickList);
1536    super.installListeners(fc);
1537  }
1538  
1539  protected void uninstallListeners(JFileChooser fc) 
1540  {
1541    super.uninstallListeners(fc);
1542    fc.removePropertyChangeListener(filterModel);
1543    directoryComboBox.setAction(null);
1544    fileList.removeListSelectionListener(listSelList);
1545    fileList.removeMouseListener(doubleClickList);
1546    fileList.removeMouseListener(singleClickList);
1547    
1548    if (fileTable != null)
1549      fileTable.removeMouseListener(tableClickList);
1550  }
1551  
1552  protected ActionMap getActionMap()
1553  {
1554    if (actionMap == null)
1555      actionMap = createActionMap();
1556    return actionMap;
1557  }
1558  
1559  /**
1560   * Creates and returns an action map.
1561   * 
1562   * @return The action map.
1563   */
1564  protected ActionMap createActionMap()
1565  {
1566    ActionMap map = new ActionMap();
1567    map.put("approveSelection", getApproveSelectionAction());
1568    map.put("cancelSelection", getCancelSelectionAction());
1569    map.put("Go Up", getChangeToParentDirectoryAction());
1570    return map;
1571  }
1572 
1573  /**
1574   * Creates a panel containing a list of files.
1575   * 
1576   * @param fc  the file chooser.
1577   * 
1578   * @return A panel.
1579   */
1580  protected JPanel createList(JFileChooser fc)
1581  {
1582    if (fileList == null)
1583      {
1584        fileListPanel = new JPanel(new BorderLayout());
1585        fileList = new JList(getModel());
1586        scrollPane = new JScrollPane(fileList);
1587        fileList.setLayoutOrientation(JList.VERTICAL_WRAP);
1588        fileList.setCellRenderer(new FileRenderer());
1589      }
1590    else
1591      {
1592        fileList.setModel(getModel());
1593        fileListPanel.removeAll();
1594        scrollPane.getViewport().setView(fileList);
1595      }
1596    fileListPanel.add(scrollPane);
1597    // This size was determined using BeanShell and dumping the JFileChooser
1598    // component hierarchy. Sun has an internal FilePane class in there, but
1599    // that probably doesn't matter atm.
1600    fileListPanel.setPreferredSize(new Dimension(405, 135));
1601    return fileListPanel;
1602  }
1603  
1604  /**
1605   * Creates a panel containing a table within a scroll pane.
1606   * 
1607   * @param fc  the file chooser.
1608   * 
1609   * @return The details view.
1610   */
1611  protected JPanel createDetailsView(JFileChooser fc)
1612  {
1613    fileTablePanel = new JPanel(new BorderLayout());
1614    
1615    Object[] cols = new Object[] {"Name", "Size", "Modified"};
1616    Object[][] rows = new Object[fileList.getModel().getSize()][3];
1617    
1618    fileTable = new JTable(new DefaultTableModel(rows, cols));
1619    
1620    if (fc.isMultiSelectionEnabled())
1621      fileTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
1622    else
1623      fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
1624    
1625    fileTable.setShowGrid(false);
1626    fileTable.setColumnSelectionAllowed(false);
1627    fileTable.setDefaultRenderer(Object.class, new TableFileRenderer());
1628 
1629    tableClickList = new TableClickListener(fileTable, fc);
1630    fileTable.addMouseListener(tableClickList);
1631    
1632    return updateTable();  
1633  }
1634  
1635  /**
1636   * Sets the values in the table, and puts it in the panel.
1637   * 
1638   * @return the panel containing the table.
1639   */
1640  JPanel updateTable()
1641  {
1642    DefaultTableModel mod = (DefaultTableModel) fileTable.getModel();
1643    ListModel lm = fileList.getModel();
1644    DateFormat dt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
1645                                                   DateFormat.SHORT);
1646    File curr = null;
1647    int size = lm.getSize();
1648    int rc = mod.getRowCount();
1649 
1650    // If there are not enough rows
1651    for (int x = rc; x < size; x++)
1652      mod.addRow(new Object[3]);
1653 
1654    for (int i = 0; i < size; i++)
1655      {
1656        curr = (File) lm.getElementAt(i);
1657        fileTable.setValueAt(curr.getName(), i, 0);
1658        fileTable.setValueAt(formatSize(curr.length()), i, 1);
1659        fileTable.setValueAt(dt.format(new Date(curr.lastModified())), i, 2);
1660      }
1661 
1662    // If there are too many rows
1663    while (rc > size)
1664      mod.removeRow(--rc);
1665 
1666    scrollPane.getViewport().setView(fileTable);
1667    scrollPane.setColumnHeaderView(fileTable.getTableHeader());
1668 
1669    fileTablePanel.removeAll();
1670    fileTablePanel.add(scrollPane);
1671 
1672    return fileTablePanel;
1673  }
1674  
1675  /**
1676   * Formats bytes into the appropriate size.
1677   * 
1678   * @param bytes the number of bytes to convert
1679   * @return a string representation of the size
1680   */
1681  private String formatSize(long bytes)
1682  {
1683    NumberFormat nf = NumberFormat.getNumberInstance();
1684    long mb = (long) Math.pow(2, 20);
1685    long kb = (long) Math.pow(2, 10);
1686    long gb = (long) Math.pow(2, 30);
1687    double size = 0;
1688    String id = "";
1689    
1690    if ((bytes / gb) >= 1)
1691      {
1692        size = (double) bytes / (double) gb;
1693        id = "GB";
1694      }
1695    else if ((bytes / mb) >= 1)
1696      {
1697        size = (double) bytes / (double) mb;
1698        id = "MB";
1699      }
1700    else if ((bytes / kb) >= 1)
1701      {
1702        size = (double) bytes / (double) kb;
1703        id = "KB";
1704      }
1705    else
1706      {
1707        size = bytes;
1708        id = "Bytes";
1709      }
1710    
1711    return nf.format(size) + " " + id;
1712  }
1713  /**
1714   * Creates a listener that monitors selections in the directory/file list
1715   * and keeps the {@link JFileChooser} component up to date.
1716   * 
1717   * @param fc  the file chooser.
1718   * 
1719   * @return The listener.
1720   * 
1721   * @see #installListeners(JFileChooser)
1722   */
1723  public ListSelectionListener createListSelectionListener(JFileChooser fc)
1724  {
1725    return new MetalFileChooserSelectionListener();
1726  }
1727  
1728  /**
1729   * Returns the preferred size for the file chooser component.
1730   * 
1731   * @return The preferred size.
1732   */
1733  public Dimension getPreferredSize(JComponent c)
1734  {
1735    Dimension tp = topPanel.getPreferredSize();
1736    Dimension bp = bottomPanel.getPreferredSize();
1737    Dimension fl = fileListPanel.getPreferredSize();
1738    return new Dimension(fl.width, tp.height + bp.height + fl.height);
1739  }
1740 
1741  /**
1742   * Returns the minimum size for the file chooser component.
1743   * 
1744   * @return The minimum size.
1745   */
1746  public Dimension getMinimumSize(JComponent c)
1747  {
1748    Dimension tp = topPanel.getMinimumSize();
1749    Dimension bp = bottomPanel.getMinimumSize();
1750    Dimension fl = fileListPanel.getMinimumSize();
1751    return new Dimension(fl.width, tp.height + bp.height + fl.height);
1752  }
1753  
1754  /**
1755   * Returns the maximum size for the file chooser component.
1756   * 
1757   * @return The maximum size.
1758   */
1759  public Dimension getMaximumSize(JComponent c)
1760  {
1761    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
1762  }
1763  
1764  /**
1765   * Creates a property change listener that monitors the {@link JFileChooser}
1766   * for property change events and updates the component display accordingly.
1767   * 
1768   * @param fc  the file chooser.
1769   * 
1770   * @return The property change listener.
1771   * 
1772   * @see #installListeners(JFileChooser)
1773   */
1774  public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
1775  {
1776    return new MetalFileChooserPropertyChangeListener();
1777  }
1778 
1779  /**
1780   * Creates and returns a new instance of {@link DirectoryComboBoxModel}.
1781   * 
1782   * @return A new instance of {@link DirectoryComboBoxModel}.
1783   */
1784  protected MetalFileChooserUI.DirectoryComboBoxModel 
1785      createDirectoryComboBoxModel(JFileChooser fc)
1786  {
1787    return new DirectoryComboBoxModel();
1788  }
1789 
1790  /**
1791   * Creates a new instance of the renderer used in the directory
1792   * combo box.
1793   * 
1794   * @param fc  the file chooser.
1795   * 
1796   * @return The renderer.
1797   */
1798  protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
1799          JFileChooser fc)
1800  {
1801    return new DirectoryComboBoxRenderer(fc);
1802  }
1803 
1804  /**
1805   * Creates and returns a new instance of {@link FilterComboBoxModel}.
1806   * 
1807   * @return A new instance of {@link FilterComboBoxModel}.
1808   */
1809  protected FilterComboBoxModel createFilterComboBoxModel()
1810  {
1811    return new FilterComboBoxModel();  
1812  }
1813 
1814  /**
1815   * Creates and returns a new instance of {@link FilterComboBoxRenderer}.
1816   * 
1817   * @return A new instance of {@link FilterComboBoxRenderer}.
1818   */
1819  protected MetalFileChooserUI.FilterComboBoxRenderer 
1820      createFilterComboBoxRenderer()
1821  {
1822    return new FilterComboBoxRenderer(); 
1823  }
1824 
1825  /**
1826   * Adds the control buttons ('up', 'home' etc.) to the panel.
1827   */
1828  protected void addControlButtons()
1829  {
1830    JButton upButton = new JButton(getChangeToParentDirectoryAction());
1831    upButton.setText(null);
1832    upButton.setIcon(this.upFolderIcon);
1833    upButton.setMargin(new Insets(0, 0, 0, 0));
1834    controls.add(upButton);
1835    
1836    JButton homeButton = new JButton(getGoHomeAction());
1837    homeButton.setText(null);
1838    homeButton.setIcon(this.homeFolderIcon);
1839    homeButton.setMargin(new Insets(0, 0, 0, 0));
1840    controls.add(homeButton);
1841    
1842    JButton newFolderButton = new JButton(getNewFolderAction());
1843    newFolderButton.setText(null);
1844    newFolderButton.setIcon(this.newFolderIcon);
1845    newFolderButton.setMargin(new Insets(0, 0, 0, 0));
1846    controls.add(newFolderButton);
1847    
1848    JToggleButton listButton = new JToggleButton(this.listViewIcon);
1849    listButton.setMargin(new Insets(0, 0, 0, 0));
1850    listButton.addActionListener(new ListViewActionListener());
1851    listButton.setSelected(true);
1852    listView = true; 
1853    controls.add(listButton);
1854    
1855    JToggleButton detailButton = new JToggleButton(this.detailsViewIcon);
1856    detailButton.setMargin(new Insets(0, 0, 0, 0));
1857    detailButton.addActionListener(new DetailViewActionListener());
1858    detailButton.setSelected(false);
1859    controls.add(detailButton);
1860 
1861    ButtonGroup buttonGroup = new ButtonGroup();
1862    buttonGroup.add(listButton);
1863    buttonGroup.add(detailButton);
1864  }
1865  
1866  /**
1867   * Removes all the buttons from the control panel.
1868   */
1869  protected void removeControlButtons()
1870  {
1871    controls.removeAll();
1872    controls.revalidate();
1873    controls.repaint();
1874  }
1875  
1876  /**
1877   * Updates the current directory.
1878   * 
1879   * @param fc  the file chooser to update.
1880   */
1881  public void rescanCurrentDirectory(JFileChooser fc)
1882  {
1883    directoryModel.setSelectedItem(fc.getCurrentDirectory());
1884    getModel().validateFileCache();
1885    if (!listView)
1886        updateTable();
1887    else
1888      createList(fc);
1889  }
1890  
1891  /**
1892   * Returns the file name in the text field.
1893   * 
1894   * @return The file name.
1895   */
1896  public String getFileName()
1897  {
1898    String result = null;
1899    if (fileTextField != null) 
1900      result = fileTextField.getText();
1901    return result;
1902  }
1903  
1904  /**
1905   * Sets the file name in the text field.
1906   * 
1907   * @param filename  the file name.
1908   */
1909  public void setFileName(String filename)
1910  {
1911    fileTextField.setText(filename);
1912  }
1913  
1914  /**
1915   * DOCUMENT ME!!
1916   * 
1917   * @param e - DOCUMENT ME!
1918   */
1919  public void valueChanged(ListSelectionEvent e)
1920  {
1921    // FIXME: Not sure what we should be doing here, if anything.
1922  }
1923  
1924  /**
1925   * Returns the approve button.
1926   * 
1927   * @return The approve button.
1928   */
1929  protected JButton getApproveButton(JFileChooser fc)
1930  {
1931    return approveButton;
1932  }
1933 
1934  /**
1935   * A layout manager that is used to arrange the subcomponents of the
1936   * {@link JFileChooser}.
1937   */
1938  class VerticalMidLayout implements LayoutManager
1939  {
1940    /**
1941     * Performs the layout.
1942     * 
1943     * @param parent  the container.
1944     */
1945    public void layoutContainer(Container parent) 
1946    {
1947      int count = parent.getComponentCount();
1948      if (count > 0)
1949        {
1950          Insets insets = parent.getInsets();
1951          Component c = parent.getComponent(0);
1952          Dimension prefSize = c.getPreferredSize();
1953          int h = parent.getHeight() - insets.top - insets.bottom;
1954          int adj = Math.max(0, (h - prefSize.height) / 2);
1955          c.setBounds(insets.left, insets.top + adj, parent.getWidth() 
1956              - insets.left - insets.right, 
1957              (int) Math.min(prefSize.getHeight(), h));
1958        }
1959    }
1960    
1961    /**
1962     * Returns the minimum layout size.
1963     * 
1964     * @param parent  the container.
1965     * 
1966     * @return The minimum layout size.
1967     */
1968    public Dimension minimumLayoutSize(Container parent) 
1969    {
1970      return preferredLayoutSize(parent);
1971    }
1972    
1973    /**
1974     * Returns the preferred layout size.
1975     * 
1976     * @param parent  the container.
1977     * 
1978     * @return The preferred layout size.
1979     */
1980    public Dimension preferredLayoutSize(Container parent) 
1981    {
1982      if (parent.getComponentCount() > 0)
1983        {
1984          return parent.getComponent(0).getPreferredSize();
1985        }
1986      else return null;
1987    }
1988    
1989    /**
1990     * This layout manager does not need to track components, so this 
1991     * method does nothing.
1992     * 
1993     * @param name  the name the component is associated with.
1994     * @param component  the component.
1995     */
1996    public void addLayoutComponent(String name, Component component) 
1997    {
1998      // do nothing
1999    }
2000    
2001    /**
2002     * This layout manager does not need to track components, so this 
2003     * method does nothing.
2004     * 
2005     * @param component  the component.
2006     */
2007    public void removeLayoutComponent(Component component) 
2008    {
2009      // do nothing
2010    }
2011  }
2012 
2013  /**
2014   * A layout manager that is used to arrange buttons for the
2015   * {@link JFileChooser}.
2016   */
2017  class ButtonLayout implements LayoutManager
2018  {
2019    static final int GAP = 4;
2020      
2021    /**
2022     * Performs the layout.
2023     * 
2024     * @param parent  the container.
2025     */
2026    public void layoutContainer(Container parent) 
2027    {
2028      int count = parent.getComponentCount();
2029      if (count > 0)
2030        {
2031          // first find the widest button
2032          int maxW = 0;
2033          for (int i = 0; i < count; i++)
2034            {
2035              Component c = parent.getComponent(i);
2036              Dimension prefSize = c.getPreferredSize();
2037              maxW = Math.max(prefSize.width, maxW);
2038            }
2039  
2040          // then position the buttons
2041          Insets insets = parent.getInsets();
2042          int availableH = parent.getHeight() - insets.top - insets.bottom;
2043          int currentX = parent.getWidth() - insets.right;
2044          for (int i = count - 1; i >= 0; i--)
2045            {
2046              Component c = parent.getComponent(i);
2047              Dimension prefSize = c.getPreferredSize();      
2048              int adj = Math.max(0, (availableH - prefSize.height) / 2);
2049              currentX = currentX - prefSize.width;
2050              c.setBounds(currentX, insets.top + adj, prefSize.width, 
2051                  (int) Math.min(prefSize.getHeight(), availableH));
2052              currentX = currentX - GAP;
2053            }
2054        }
2055    }
2056    
2057    /**
2058     * Returns the minimum layout size.
2059     * 
2060     * @param parent  the container.
2061     * 
2062     * @return The minimum layout size.
2063     */
2064    public Dimension minimumLayoutSize(Container parent) 
2065    {
2066      return preferredLayoutSize(parent);
2067    }
2068    
2069    /**
2070     * Returns the preferred layout size.
2071     * 
2072     * @param parent  the container.
2073     * 
2074     * @return The preferred layout size.
2075     */
2076    public Dimension preferredLayoutSize(Container parent) 
2077    {
2078      Insets insets = parent.getInsets();
2079      int maxW = 0;
2080      int maxH = 0;
2081      int count = parent.getComponentCount();
2082      if (count > 0) 
2083        {
2084          for (int i = 0; i < count; i++)
2085            {
2086              Component c = parent.getComponent(i);
2087              Dimension d = c.getPreferredSize();
2088              maxW = Math.max(d.width, maxW);
2089              maxH = Math.max(d.height, maxH);
2090            }
2091        }
2092      return new Dimension(maxW * count + GAP * (count - 1) + insets.left 
2093              + insets.right, maxH + insets.top + insets.bottom);
2094    }
2095    
2096    /**
2097     * This layout manager does not need to track components, so this 
2098     * method does nothing.
2099     * 
2100     * @param name  the name the component is associated with.
2101     * @param component  the component.
2102     */
2103    public void addLayoutComponent(String name, Component component) 
2104    {
2105      // do nothing
2106    }
2107    
2108    /**
2109     * This layout manager does not need to track components, so this 
2110     * method does nothing.
2111     * 
2112     * @param component  the component.
2113     */
2114    public void removeLayoutComponent(Component component) 
2115    {
2116      // do nothing
2117    }
2118  }
2119 
2120}

[all classes][javax.swing.plaf.metal]
EMMA 2.0.6427 (unsupported private build) (C) Vladimir Roubtsov