[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cp-patches] RFC: MetalFileChooserUI implementation
From: |
David Gilbert |
Subject: |
[cp-patches] RFC: MetalFileChooserUI implementation |
Date: |
Fri, 25 Nov 2005 11:39:42 +0000 |
User-agent: |
Mozilla Thunderbird 1.0.7 (X11/20051026) |
Hi all,
In recent weeks I have done some work on a MetalFileChooserUI implementation, but
don't have enough time lately to fix the last few problems. Lillian mentioned that
she has just started looking at this also, so I thought I would send in my current
patch (which is unfortunately somewhat large) for others to look at and/or work on.
Some notes:
- the patch destroys the current file chooser UI in the BasicLookAndFeel (the one in
the reference implementation doesn't function on its own either);
- I already committed a FileChooserDemo to the GNU Classpath Swing demo, and this is
useful for testing ('open' and 'save' work for me, selecting a directory doesn't,
multiple selection doesn't);
- a recent regression in the JComboBox implementation makes the directory selection
somewhat flakey;
- there is a bug in the JList implementation that prevents the correct layout of the
files and directories from being used, it was working previously (for now, I've used
the standard list layout);
- this patch fixes most (but not all) of the Mauve tests that I've written for
JFileChooser/BasicFileChooserUI/MetalFileChooserUI.
If there any questions, please ask. Perhaps if the patch works well enough for
others, I can just commit it to CVS and then anyone else can jump in to help with fixes.
Here is a ChangeLog entry (with some TODOs marked):
2005-11-25 David Gilbert <address@hidden>
* javax/swing/JFileChooser.java
(selectedFiles): Initialise,
(JFileChooser(String)): Delegate to another constructor,
(JFileChooser(String, FileSystemView)): Convert directory to file,
(setSelectedFile): Check for current selection == null,
(getSelectedFiles): Updated API docs,
(setSelectedFiles): Changed order of event generation,
(changeToParentDirectory): Don't check for null parent (reference
implementation doesn't),
(addChoosableFileFilter): Change handling of null filter,
(removeChoosableFileFilter): Handle case where removed filter is also
the current selection,
(setAcceptAllFileFilterUsed): Add or remove accept all filter as
appropriate,
(setFileFilter): Add new filter to choosable filters if necessary,
(accept): Reimplemented,
* javax/swing/plaf/basic/BasicFileChooserUI.java
(ApproveSelectionAction.ApproveSelectionAction): Set action name,
(ApproveSelectionAction.actionPerformed): Call getFileName() rather
than accessing JTextField directly,
(CancelSelectionAction.CancelSelectionAction): Set action name,
(ChangeToParentDirectoryAction.ChangeToParentDirectoryAction): Set
action name,
(DoubleClickListener.mouseClicked): Call setFileName rather than
accessing JTextField directly,
(GoHomeAction.GoHomeAction): Set action name,
(NewFolderAction.NewFolderAction): Set action name,
(SelectionListener.valueChanged): Get list from event,
(UpdateAction.UpdateAction): Set action name to null,
(computerIcon): Removed initialization,
(detailsViewIcon): Likewise,
(directoryIcon): Likewise,
(fileIcon): Likewise,
(floppyDriveIcon): Likewise,
(hardDriveIcon): Likewise,
(homeFolderIcon): Likewise,
(listViewIcon): Likewise,
(upFolderIcon): Likewise,
(fileList): Removed,
(filters): Removed,
(ICON_SIZE): Removed,
(parents): Removed,
(filename): Removed,
(cancel): Removed,
(upFolderButton): Removed,
(newFolderButton): Removed,
(homeFolderButton): Removed,
(approveSelectionAction): New field,
(cancelSelectionAction): New field,
(goHomeAction): New field,
(changeToParentDirectoryAction): New field,
(newFolderAction): New field,
(updateAction): New field,
(BasicFileChooserUI): Do nothing here,
(installUI): Initialise filechooser field,
(createBoxListener): Removed,
(createFilterListener): Removed,
(filterEntries): Removed,
(installComponents): Do nothing here,
(uninstallComponents): Do nothing here,
(installListeners): Removed component specific listeners,
(installIcons): Use Metal icons,
(unintallIcons): Clear icons,
(installStrings): Use fixed strings for text items that aren't defined
in the UI defaults - should implement localised strings later,
(uninstallStrings): Clear text items,
(createPropertyChangeListener): Return blank listener,
(getFileName): TODO,
(setFileName): TODO,
(rescanCurrentDirectory): Remove call on deleted filelist,
(getApproveButton): Just return field,
(getFileView): Updated API docs,
(getDialogTitle): Reimplemented,
(getApproveButtonText): Reimplemented,
(getNewFolderAction): Create new instance if required,
(getGoHomeAction): Likewise,
(getChangeToParentDirectoryAction): Likewise,
(getApproveSelectionAction): Likewise,
(getCancelSelectionAction): Likewise,
(getUpdateAction): Likewise,
* javax/swing/plaf/metal/MetalFileChooserUI.java
(MetalFileChooserPropertyChangeListener): New class,
(DirectoryComboBoxRenderer): New class,
(FilterComboBoxModel.selectedIndex): Removed field,
(FilterComboBoxModel.selected): New field,
(FilterComboBoxModel.FilterComboBoxModel): Initialise selected field,
(FilterComboBoxModel.propertyChange): Update filter list,
(FilterComboBoxModel.setSelectedItem): Reimplemented,
(FilterComboBoxModel.getSelectedItem): Return selected field,
(FilterComboBoxRenderer.getListCellRendererComponent): Call super,
(MetalFileChooserSelectionListener): New class,
(SingleClickListener): New class TODO,
(directoryLabel): New field,
(directoryComboBox): New field,
(fileLabel): New field,
(fileTextField): New field,
(filterLabel): New field,
(topPanel): New field,
(controls): New field,
(bottomPanel): New field,
(buttonPanel): New field,
(approveButton): New field,
(fileList): New field,
(fileListPanel): New field,
(filterModel): New field,
(MetalFileChooserUI): Initialise panels,
(installUI): TODO,
(uninstallUI): TODO,
(installComponents): Implemented,
(uninstallComponents): Implemented,
(getButtonPanel): Implemented,
(getBottomPanel): Implemented,
(installStrings): Implemented,
(installListeners): Implemented,
(uninstallListeners): Implemented,
(getActionMap): TODO,
(createActionMap): Implemented,
(createList): Implemented,
(createDetailsView): Implemented,
(createListSelectionListener): Implemented,
(getPreferredSize): Implemented badly,
(getMinimumSize): Likewise,
(getMaximumSize): Implemented,
(createPropertyChangeListener): Implemented,
(createDirectoryComboBoxRenderer): Implemented,
(addControlButtons): Implemented,
(removeControlButtons): TODO,
(ensureFileIsVisible): TODO,
(rescanCurrentDirectory): Implemented,
(getFileName): Implemented,
(setFileName): Implemented,
(setDirectorySelected): TODO,
(getDirectoryName): TODO,
(setDirectoryName): TODO,
(valueChanged): TODO,
(getApproveButton): Implemented,
(VerticalMidLayout): New support class,
(ButtonLayout): New support class,
* javax/swing/plaf/metal/MetalLookAndFeel.java
(initClassDefaults): Add 'FileChooserUI' default,
(initComponentDefaults): Added FileChooser icons.
Regards,
Dave
Index: javax/swing/JFileChooser.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JFileChooser.java,v
retrieving revision 1.22
diff -u -r1.22 JFileChooser.java
--- javax/swing/JFileChooser.java 1 Nov 2005 18:02:30 -0000 1.22
+++ javax/swing/JFileChooser.java 25 Nov 2005 10:21:07 -0000
@@ -381,7 +381,7 @@
* An array of selected files.
* @see #setSelectedFiles(File[])
*/
- private File[] selectedFiles;
+ private File[] selectedFiles = new File[0];
/**
* The selected file.
@@ -407,8 +407,7 @@
*/
public JFileChooser(String currentDirectoryPath)
{
- setup(null);
- setCurrentDirectory(fsv.createFileObject(currentDirectoryPath));
+ this(currentDirectoryPath, null);
}
/**
@@ -424,7 +423,10 @@
public JFileChooser(String currentDirectoryPath, FileSystemView fsv)
{
setup(fsv);
- setCurrentDirectory(fsv.createFileObject(currentDirectoryPath));
+ File dir = null;
+ if (currentDirectoryPath != null)
+ dir = getFileSystemView().createFileObject(currentDirectoryPath);
+ setCurrentDirectory(dir);
}
/**
@@ -525,7 +527,7 @@
*/
public void setSelectedFile(File file)
{
- if (selectedFile != file)
+ if (selectedFile == null || !selectedFile.equals(file))
{
File old = selectedFile;
selectedFile = file;
@@ -534,10 +536,10 @@
}
/**
- * Returns the selected file or files.
+ * Returns the selected file or files in an array. If no files are selected,
+ * an empty array is returned.
*
- * @return An array of the selected files, or <code>null</code> if there are
- * no selected files.
+ * @return An array of the selected files (possibly empty).
*/
public File[] getSelectedFiles()
{
@@ -557,6 +559,12 @@
*/
public void setSelectedFiles(File[] selectedFiles)
{
+ if (selectedFiles == null)
+ selectedFiles = new File[0];
+ if (selectedFiles.length > 0)
+ setSelectedFile(selectedFiles[0]);
+ else
+ setSelectedFile(null);
if (this.selectedFiles != selectedFiles)
{
File[] old = this.selectedFiles;
@@ -564,8 +572,6 @@
firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, old, selectedFiles);
}
- if (selectedFiles != null)
- setSelectedFile(selectedFiles[0]);
}
/**
@@ -607,8 +613,7 @@
*/
public void changeToParentDirectory()
{
- if (fsv.getParentDirectory(currentDir) != null)
- setCurrentDirectory(fsv.getParentDirectory(currentDir));
+ setCurrentDirectory(fsv.getParentDirectory(currentDir));
}
/**
@@ -958,14 +963,19 @@
* address@hidden #CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY}) to all
registered
* listeners.
*
- * @param filter the filter.
+ * @param filter the filter (<code>null</code> permitted).
*/
public void addChoosableFileFilter(FileFilter filter)
{
- FileFilter[] old = getChoosableFileFilters();
- choosableFilters.add(filter);
- FileFilter[] newFilters = getChoosableFileFilters();
- firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old,
newFilters);
+ if (filter != null)
+ {
+ FileFilter[] old = getChoosableFileFilters();
+ choosableFilters.add(filter);
+ FileFilter[] newFilters = getChoosableFileFilters();
+ firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old,
+ newFilters);
+ }
+ setFileFilter(filter);
}
/**
@@ -981,6 +991,8 @@
*/
public boolean removeChoosableFileFilter(FileFilter f)
{
+ if (f == currentFilter)
+ setFileFilter(null);
FileFilter[] old = getChoosableFileFilters();
if (! choosableFilters.remove(f))
return false;
@@ -1037,6 +1049,10 @@
if (isAcceptAll != b)
{
isAcceptAll = b;
+ if (b)
+ addChoosableFileFilter(getAcceptAllFileFilter());
+ else
+ removeChoosableFileFilter(getAcceptAllFileFilter());
firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY,
! isAcceptAll, isAcceptAll);
}
@@ -1208,15 +1224,17 @@
* property name address@hidden #FILE_FILTER_CHANGED_PROPERTY}) to all
registered
* listeners.
*
- * @param filter the filter.
+ * @param filter the filter (<code>null</code> permitted).
*/
public void setFileFilter(FileFilter filter)
{
if (currentFilter != filter)
{
- FileFilter old = currentFilter;
- currentFilter = filter;
- firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, old, currentFilter);
+ if (filter != null && !choosableFilters.contains(filter))
+ addChoosableFileFilter(filter);
+ FileFilter old = currentFilter;
+ currentFilter = filter;
+ firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, old, currentFilter);
}
}
@@ -1356,8 +1374,12 @@
public boolean accept(File f)
{
if (f == null)
- return false;
- return getFileFilter().accept(f);
+ return true;
+ FileFilter ff = getFileFilter();
+ if (ff != null)
+ return ff.accept(f);
+ else
+ return true;
}
/**
Index: javax/swing/plaf/basic/BasicFileChooserUI.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java,v
retrieving revision 1.17
diff -u -r1.17 BasicFileChooserUI.java
--- javax/swing/plaf/basic/BasicFileChooserUI.java 15 Nov 2005 20:32:46
-0000 1.17
+++ javax/swing/plaf/basic/BasicFileChooserUI.java 25 Nov 2005 10:21:09
-0000
@@ -37,19 +37,10 @@
package javax.swing.plaf.basic;
-import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Point;
-import java.awt.Polygon;
import java.awt.Window;
import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
@@ -62,23 +53,20 @@
import javax.swing.AbstractAction;
import javax.swing.Action;
-import javax.swing.ButtonGroup;
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.JTextField;
-import javax.swing.JToggleButton;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
+import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -87,6 +75,7 @@
import javax.swing.filechooser.FileView;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.FileChooserUI;
+import javax.swing.plaf.metal.MetalIconFactory;
/**
@@ -144,7 +133,7 @@
*/
protected ApproveSelectionAction()
{
- // Nothing to do here.
+ super("approveSelection");
}
/**
@@ -154,7 +143,7 @@
*/
public void actionPerformed(ActionEvent e)
{
- Object obj = new String(parentPath + entry.getText());
+ Object obj = new String(parentPath + getFileName());
if (obj != null)
{
File f = filechooser.getFileSystemView().createFileObject(
@@ -307,7 +296,7 @@
*/
protected CancelSelectionAction()
{
- // Nothing to do here.
+ super(null);
}
/**
@@ -335,7 +324,7 @@
*/
protected ChangeToParentDirectoryAction()
{
- // Nothing to do here.
+ super("Go Up");
}
/**
@@ -424,7 +413,7 @@
}
lastSelected = path;
parentPath = path.substring(0, path.lastIndexOf("/") + 1);
- entry.setText(path.substring(path.lastIndexOf("/") + 1));
+ setFileName(path.substring(path.lastIndexOf("/") + 1));
timer.restart();
}
}
@@ -453,7 +442,7 @@
*/
protected GoHomeAction()
{
- // Nothing to do here.
+ super("Go Home");
}
/**
@@ -483,7 +472,7 @@
*/
protected NewFolderAction()
{
- // Nothing to do here.
+ super("New Folder");
}
/**
@@ -529,7 +518,8 @@
*/
public void valueChanged(ListSelectionEvent e)
{
- Object f = filelist.getSelectedValue();
+ JList list = (JList) e.getSource();
+ Object f = list.getSelectedValue();
if (f == null)
return;
File file =
filechooser.getFileSystemView().createFileObject(f.toString());
@@ -552,7 +542,7 @@
*/
protected UpdateAction()
{
- // Nothing to do here.
+ super(null);
}
/**
@@ -576,91 +566,13 @@
protected String cancelButtonToolTipText;
/** An icon representing a computer. */
- protected Icon computerIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- // FIXME: is this not implemented, or is the icon intentionally blank?
- }
- };
+ protected Icon computerIcon;
/** An icon for the "details view" button. */
- protected Icon detailsViewIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- g.setColor(Color.GRAY);
- g.drawRect(1, 1, 15, 20);
- g.drawLine(17, 6, 23, 6);
- g.drawLine(17, 12, 23, 12);
- g.drawLine(17, 18, 23, 18);
-
- g.setColor(saved);
- g.translate(-x, -y);
- }
- };
+ protected Icon detailsViewIcon;
/** An icon representing a directory. */
- protected Icon directoryIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- Point ap = new Point(3, 7);
- Point bp = new Point(3, 21);
- Point cp = new Point(21, 21);
- Point dp = new Point(21, 12);
- Point ep = new Point(16, 12);
- Point fp = new Point(13, 7);
-
- Polygon dir = new Polygon(new int[] { ap.x, bp.x, cp.x, dp.x, ep.x,
fp.x },
- new int[] { ap.y, bp.y, cp.y, dp.y, ep.y,
fp.y },
- 6);
-
- g.setColor(new Color(153, 204, 255));
- g.fillPolygon(dir);
- g.setColor(Color.BLACK);
- g.drawPolygon(dir);
-
- g.translate(-x, -y);
- g.setColor(saved);
- }
- };
+ protected Icon directoryIcon;
/** The localised Mnemonic for the open button. */
protected int directoryOpenButtonMnemonic;
@@ -672,82 +584,13 @@
protected String directoryOpenButtonToolTipText;
/** An icon representing a file. */
- protected Icon fileIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- Point a = new Point(5, 4);
- Point b = new Point(5, 20);
- Point d = new Point(19, 20);
- Point e = new Point(19, 7);
- Point f = new Point(16, 4);
-
- Polygon p = new Polygon(new int[] { a.x, b.x, d.x, e.x, f.x, },
- new int[] { a.y, b.y, d.y, e.y, f.y }, 5);
-
- g.setColor(Color.WHITE);
- g.fillPolygon(p);
- g.setColor(Color.BLACK);
- g.drawPolygon(p);
-
- g.drawLine(16, 4, 14, 6);
- g.drawLine(14, 6, 19, 7);
-
- g.setColor(saved);
- g.translate(-x, -y);
- }
- };
+ protected Icon fileIcon;
/** An icon representing a floppy drive. */
- protected Icon floppyDriveIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- // FIXME: is this not implemented, or is the icon intentionally blank?
- }
- };
+ protected Icon floppyDriveIcon;
/** An icon representing a hard drive. */
- protected Icon hardDriveIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- // FIXME: is this not implemented, or is the icon intentionally blank?
- }
- };
+ protected Icon hardDriveIcon;
/** The localised mnemonic for the "help" button. */
protected int helpButtonMnemonic;
@@ -759,86 +602,10 @@
protected String helpButtonToolTipText;
/** An icon representing the user's home folder. */
- protected Icon homeFolderIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- Point a = new Point(12, 3);
- Point b = new Point(4, 10);
- Point d = new Point(20, 10);
-
- Polygon p = new Polygon(new int[] { a.x, b.x, d.x },
- new int[] { a.y, b.y, d.y }, 3);
-
- g.setColor(new Color(104, 51, 0));
- g.fillPolygon(p);
- g.setColor(Color.BLACK);
- g.drawPolygon(p);
-
- g.setColor(Color.WHITE);
- g.fillRect(8, 10, 8, 10);
- g.setColor(Color.BLACK);
- g.drawRect(8, 10, 8, 10);
-
- g.setColor(saved);
- g.translate(-x, -y);
- }
- };
+ protected Icon homeFolderIcon;
/** An icon for the "list view" button. */
- protected Icon listViewIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- // Not needed. Only simplifies things until we get real icons.
- private void paintPartial(Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- g.setColor(Color.GRAY);
- g.drawRect(1, 1, 7, 10);
- g.drawLine(8, 6, 11, 6);
-
- g.setColor(saved);
- g.translate(-x, -y);
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- paintPartial(g, 0, 0);
- paintPartial(g, 12, 0);
- paintPartial(g, 0, 12);
- paintPartial(g, 12, 12);
-
- g.setColor(saved);
- g.translate(-x, -y);
- }
- };
+ protected Icon listViewIcon;
/** An icon for the "new folder" button. */
protected Icon newFolderIcon = directoryIcon;
@@ -871,65 +638,13 @@
protected String updateButtonToolTipText;
/** An icon for the "up folder" button. */
- protected Icon upFolderIcon = new Icon()
- {
- public int getIconHeight()
- {
- return ICON_SIZE;
- }
-
- public int getIconWidth()
- {
- return ICON_SIZE;
- }
-
- public void paintIcon(Component comp, Graphics g, int x, int y)
- {
- Color saved = g.getColor();
- g.translate(x, y);
-
- Point a = new Point(3, 7);
- Point b = new Point(3, 21);
- Point c = new Point(21, 21);
- Point d = new Point(21, 12);
- Point e = new Point(16, 12);
- Point f = new Point(13, 7);
-
- Polygon dir = new Polygon(new int[] { a.x, b.x, c.x, d.x, e.x, f.x },
- new int[] { a.y, b.y, c.y, d.y, e.y, f.y },
6);
-
- g.setColor(new Color(153, 204, 255));
- g.fillPolygon(dir);
- g.setColor(Color.BLACK);
- g.drawPolygon(dir);
-
- a = new Point(12, 15);
- b = new Point(9, 18);
- c = new Point(15, 18);
-
- Polygon arrow = new Polygon(new int[] { a.x, b.x, c.x },
- new int[] { a.y, b.y, c.y }, 3);
-
- g.fillPolygon(arrow);
-
- g.drawLine(12, 15, 12, 22);
-
- g.translate(-x, -y);
- g.setColor(saved);
- }
- };
+ protected Icon upFolderIcon;
// -- begin private, but package local since used in inner classes --
/** The file chooser component represented by this UI delegate. */
JFileChooser filechooser;
- /** The file list. */
- JList filelist;
-
- /** The combo box used to display/select file filters. */
- JComboBox filters;
-
/** The model for the directory list. */
BasicDirectoryModel model;
@@ -939,30 +654,9 @@
/** The default file view. */
FileView fv = new BasicFileView();
- /** The icon size. */
- static final int ICON_SIZE = 24;
-
- /** A combo box for display/selection of parent directories. */
- JComboBox parents;
-
- /** The current file name. */
- String filename;
-
/** The accept (open/save) button. */
JButton accept;
- /** The cancel button. */
- JButton cancel;
-
- /** The button to move up to the parent directory. */
- JButton upFolderButton;
-
- /** The button to create a new directory. */
- JButton newFolderButton;
-
- /** The button to move to the user's home directory. */
- JButton homeFolderButton;
-
/** An optional accessory panel. */
JPanel accessoryPanel;
@@ -997,6 +691,42 @@
/** Current parent path */
String parentPath;
+ /**
+ * The action for the 'approve' button.
+ * @see #getApproveSelectionAction()
+ */
+ private ApproveSelectionAction approveSelectionAction;
+
+ /**
+ * The action for the 'cancel' button.
+ * @see #getCancelSelectionAction()
+ */
+ private CancelSelectionAction cancelSelectionAction;
+
+ /**
+ * The action for the 'go home' control button.
+ * @see #getGoHomeAction()
+ */
+ private GoHomeAction goHomeAction;
+
+ /**
+ * The action for the 'up folder' control button.
+ * @see #getChangeToParentDirectoryAction()
+ */
+ private ChangeToParentDirectoryAction changeToParentDirectoryAction;
+
+ /**
+ * The action for the 'new folder' control button.
+ * @see #getNewFolderAction()
+ */
+ private NewFolderAction newFolderAction;
+
+ /**
+ * The action for ???. // FIXME: what is this?
+ * @see #getUpdateAction()
+ */
+ private UpdateAction updateAction;
+
// -- end private --
private class ListLabelRenderer extends JLabel implements ListCellRenderer
{
@@ -1056,7 +786,6 @@
*/
public BasicFileChooserUI(JFileChooser b)
{
- this.filechooser = b;
}
/**
@@ -1081,6 +810,7 @@
if (c instanceof JFileChooser)
{
JFileChooser fc = (JFileChooser) c;
+ this.filechooser = fc;
fc.resetChoosableFileFilters();
createModel();
clearIconCache();
@@ -1130,78 +860,7 @@
if (parentFiles.size() == 0)
return;
- if (parents.getItemCount() > 0)
- parents.removeAllItems();
- for (int i = parentFiles.size() - 1; i >= 0; i--)
- parents.addItem(parentFiles.get(i));
- parents.setSelectedIndex(parentFiles.size() - 1);
- parents.revalidate();
- parents.repaint();
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- private ItemListener createBoxListener()
- {
- return new ItemListener()
- {
- public void itemStateChanged(ItemEvent e)
- {
- if (parents.getItemCount() - 1 == parents.getSelectedIndex())
- return;
- StringBuffer dir = new StringBuffer();
- for (int i = 0; i <= parents.getSelectedIndex(); i++)
- {
- dir.append(parents.getItemAt(i));
- dir.append(File.separatorChar);
- }
- filechooser.setCurrentDirectory(filechooser.getFileSystemView()
- .createFileObject(dir
-
.toString()));
- }
- };
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- private ItemListener createFilterListener()
- {
- return new ItemListener()
- {
- public void itemStateChanged(ItemEvent e)
- {
- int index = filters.getSelectedIndex();
- if (index == -1)
- return;
-
filechooser.setFileFilter(filechooser.getChoosableFileFilters()[index]);
- }
- };
- }
-
- void filterEntries()
- {
- FileFilter[] list = filechooser.getChoosableFileFilters();
- if (filters.getItemCount() > 0)
- filters.removeAllItems();
-
- int index = -1;
- String selected = filechooser.getFileFilter().getDescription();
- for (int i = 0; i < list.length; i++)
- {
- if (selected.equals(list[i].getDescription()))
- index = i;
- filters.addItem(list[i].getDescription());
- }
- filters.setSelectedIndex(index);
- filters.revalidate();
- filters.repaint();
- }
+ }
/**
* Creates and install the subcomponents for the file chooser.
@@ -1210,121 +869,6 @@
*/
public void installComponents(JFileChooser fc)
{
- JLabel look = new JLabel("Look In:");
-
- parents = new JComboBox();
- parents.setRenderer(new BasicComboBoxRenderer());
- boxEntries();
- look.setLabelFor(parents);
- JPanel parentsPanel = new JPanel();
- parentsPanel.add(look);
- parentsPanel.add(parents);
- JPanel buttonPanel = new JPanel();
-
- upFolderButton = new JButton();
- upFolderButton.setIcon(upFolderIcon);
- buttonPanel.add(upFolderButton);
-
- homeFolderButton = new JButton();
- homeFolderButton = new JButton(homeFolderIcon);
- buttonPanel.add(homeFolderButton);
-
- newFolderButton = new JButton();
- newFolderButton.setIcon(newFolderIcon);
- buttonPanel.add(newFolderButton);
-
- ButtonGroup toggles = new ButtonGroup();
- JToggleButton listViewButton = new JToggleButton();
- listViewButton.setIcon(listViewIcon);
- toggles.add(listViewButton);
- buttonPanel.add(listViewButton);
-
- JToggleButton detailsViewButton = new JToggleButton();
- detailsViewButton.setIcon(detailsViewIcon);
- toggles.add(detailsViewButton);
- buttonPanel.add(detailsViewButton);
-
- JPanel topPanel = new JPanel();
- parentsPanel.add(buttonPanel);
- topPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0,
0));
- topPanel.add(parentsPanel);
-
- accessoryPanel = new JPanel();
- if (filechooser.getAccessory() != null)
- accessoryPanel.add(filechooser.getAccessory(), BorderLayout.CENTER);
-
- filelist = new JList(model);
- filelist.setVisibleRowCount(6);
- JScrollPane scrollp = new JScrollPane(filelist);
- scrollp.setPreferredSize(new Dimension(400, 175));
- filelist.setBackground(Color.WHITE);
-
- filelist.setLayoutOrientation(JList.VERTICAL_WRAP);
- filelist.setCellRenderer(new ListLabelRenderer());
-
- GridBagConstraints c = new GridBagConstraints();
- c.gridx = 0;
- c.gridy = 0;
- c.fill = GridBagConstraints.BOTH;
- c.weightx = 1;
- c.weighty = 1;
-
- JPanel centrePanel = new JPanel();
- centrePanel.setLayout(new GridBagLayout());
- centrePanel.add(scrollp, c);
-
- c.gridx = 1;
- centrePanel.add(accessoryPanel, c);
-
- JLabel fileNameLabel = new JLabel("File Name:");
- JLabel fileTypesLabel = new JLabel("Files of Type:");
-
- entry = new JTextField();
- filters = new JComboBox();
- filterEntries();
-
- fileNameLabel.setLabelFor(entry);
- fileNameLabel.setHorizontalTextPosition(SwingConstants.LEFT);
- fileTypesLabel.setLabelFor(filters);
- fileTypesLabel.setHorizontalTextPosition(SwingConstants.LEFT);
-
- closePanel = new JPanel();
- accept = getApproveButton(filechooser);
- cancel = new JButton(cancelButtonText);
- cancel.setMnemonic(cancelButtonMnemonic);
- cancel.setToolTipText(cancelButtonToolTipText);
- closePanel.add(accept);
- closePanel.add(cancel);
-
- c.anchor = GridBagConstraints.WEST;
- c.weighty = 0;
- c.weightx = 0;
- c.gridx = 0;
-
- bottomPanel = new JPanel();
- bottomPanel.setLayout(new GridBagLayout());
- bottomPanel.add(fileNameLabel, c);
-
- c.gridy = 1;
- bottomPanel.add(fileTypesLabel, c);
- c.gridx = 1;
- c.gridy = 0;
- c.weightx = 1;
- c.weighty = 1;
- bottomPanel.add(entry, c);
-
- c.gridy = 1;
- bottomPanel.add(filters, c);
-
- c.fill = GridBagConstraints.NONE;
- c.gridy = 2;
- c.anchor = GridBagConstraints.EAST;
- bottomPanel.add(closePanel, c);
-
- filechooser.setLayout(new BorderLayout());
- filechooser.add(topPanel, BorderLayout.NORTH);
- filechooser.add(centrePanel, BorderLayout.CENTER);
- filechooser.add(bottomPanel, BorderLayout.SOUTH);
}
/**
@@ -1334,15 +878,6 @@
*/
public void uninstallComponents(JFileChooser fc)
{
- parents = null;
-
- accept = null;
- cancel = null;
- upFolderButton = null;
- homeFolderButton = null;
- newFolderButton = null;
-
- filelist = null;
}
/**
@@ -1354,17 +889,6 @@
{
propertyChangeListener = createPropertyChangeListener(filechooser);
filechooser.addPropertyChangeListener(propertyChangeListener);
-
- //parents.addItemListener(createBoxListener());
- accept.addActionListener(getApproveSelectionAction());
- cancel.addActionListener(getCancelSelectionAction());
- upFolderButton.addActionListener(getChangeToParentDirectoryAction());
- homeFolderButton.addActionListener(getGoHomeAction());
- newFolderButton.addActionListener(getNewFolderAction());
- filters.addItemListener(createFilterListener());
-
- filelist.addMouseListener(createDoubleClickListener(filechooser,
filelist));
-
filelist.addListSelectionListener(createListSelectionListener(filechooser));
}
/**
@@ -1401,24 +925,42 @@
}
/**
- * Installs the icons for this UI delegate (NOT YET IMPLEMENTED).
+ * Installs the icons for this UI delegate.
*
- * @param fc the file chooser.
+ * @param fc the file chooser (ignored).
*/
protected void installIcons(JFileChooser fc)
{
- // FIXME: Implement.
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ computerIcon = MetalIconFactory.getTreeComputerIcon();
+ detailsViewIcon = defaults.getIcon("FileChooser.detailsViewIcon");
+ directoryIcon = new MetalIconFactory.TreeFolderIcon();
+ fileIcon = new MetalIconFactory.TreeLeafIcon();
+ floppyDriveIcon = MetalIconFactory.getTreeFloppyDriveIcon();
+ hardDriveIcon = MetalIconFactory.getTreeHardDriveIcon();
+ homeFolderIcon = defaults.getIcon("FileChooser.homeFolderIcon");
+ listViewIcon = defaults.getIcon("FileChooser.listViewIcon");
+ newFolderIcon = defaults.getIcon("FileChooser.newFolderIcon");
+ upFolderIcon = defaults.getIcon("FileChooser.upFolderIcon");
}
/**
- * Uninstalls the icons previously added by this UI delegate (NOT YET
- * IMPLEMENTED).
+ * Uninstalls the icons previously added by this UI delegate.
*
* @param fc the file chooser.
*/
protected void uninstallIcons(JFileChooser fc)
{
- // FIXME: Implement.
+ computerIcon = null;
+ detailsViewIcon = null;
+ directoryIcon = null;
+ fileIcon = null;
+ floppyDriveIcon = null;
+ hardDriveIcon = null;
+ homeFolderIcon = null;
+ listViewIcon = null;
+ newFolderIcon = null;
+ upFolderIcon = null;
}
/**
@@ -1428,25 +970,36 @@
*/
protected void installStrings(JFileChooser fc)
{
- acceptAllFileFilterText =
UIManager.getString("FileChooser.acceptAllFileFilterText");
- cancelButtonMnemonic =
UIManager.getInt("FileChooser.cancelButtonMnemonic");
- cancelButtonText = UIManager.getString("FileChooser.cancelButtonText");
- cancelButtonToolTipText =
UIManager.getString("FileChooser.cancelButtonToolTipText");
-
- dirDescText = UIManager.getString("FileChooser.directoryDescriptionText");
- fileDescText = UIManager.getString("FileChooser.fileDescriptionText");
-
- helpButtonMnemonic = UIManager.getInt("FileChooser.helpButtonMnemonic");
- helpButtonText = UIManager.getString("FileChooser.helpButtonText");
- helpButtonToolTipText =
UIManager.getString("FileChooser.helpButtonToolTipText");
-
- openButtonMnemonic = UIManager.getInt("FileChooser.openButtonMnemonic");
- openButtonText = UIManager.getString("FileChooser.openButtonText");
- openButtonToolTipText =
UIManager.getString("FileChooser.openButtonToolTipText");
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ dirDescText = defaults.getString("FileChooser.directoryDescriptionText");
+ fileDescText = defaults.getString("FileChooser.fileDescriptionText");
+
+ acceptAllFileFilterText =
defaults.getString("FileChooser.acceptAllFileFilterText");
+ cancelButtonText = "Cancel";
+ cancelButtonToolTipText = "Abort file chooser dialog";
+ cancelButtonMnemonic = defaults.getInt("FileChooser.cancelButtonMnemonic");
+
+ directoryOpenButtonText = "Open";
+ directoryOpenButtonToolTipText = "Open selected directory";
+ directoryOpenButtonMnemonic
+ = defaults.getInt("FileChooser.directoryOpenButtonMnemonic");
+
+ helpButtonText = "Help";
+ helpButtonToolTipText = "FileChooser help";
+ helpButtonMnemonic = defaults.getInt("FileChooser.helpButtonMnemonic");
+
+ openButtonText = "Open";
+ openButtonToolTipText = "Open selected file";
+ openButtonMnemonic = defaults.getInt("FileChooser.openButtonMnemonic");
+ saveButtonText = "Save";
+ saveButtonToolTipText = "Save selected file";
saveButtonMnemonic = UIManager.getInt("FileChooser.saveButtonMnemonic");
- saveButtonText = UIManager.getString("FileChooser.saveButtonText");
- saveButtonToolTipText =
UIManager.getString("FileChooser.saveButtonToolTipText");
+
+ updateButtonText = "Update";
+ updateButtonToolTipText = "Update directory listing";
+ updateButtonMnemonic = defaults.getInt("FileChooser.updateButtonMnemonic");
}
/**
@@ -1457,24 +1010,26 @@
protected void uninstallStrings(JFileChooser fc)
{
acceptAllFileFilterText = null;
- cancelButtonMnemonic = 0;
+ dirDescText = null;
+ fileDescText = null;
+
cancelButtonText = null;
cancelButtonToolTipText = null;
- dirDescText = null;
- fileDescText = null;
+ directoryOpenButtonText = null;
+ directoryOpenButtonToolTipText = null;
- helpButtonMnemonic = 0;
helpButtonText = null;
helpButtonToolTipText = null;
- openButtonMnemonic = 0;
openButtonText = null;
openButtonToolTipText = null;
- saveButtonMnemonic = 0;
saveButtonText = null;
saveButtonToolTipText = null;
+
+ updateButtonText = null;
+ updateButtonToolTipText = null;
}
/**
@@ -1509,110 +1064,6 @@
{
public void propertyChange(PropertyChangeEvent e)
{
- // FIXME: Multiple file selection waiting on JList multiple selection
- // bug.
- if (e.getPropertyName().equals(
-
JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
- {
- if (filechooser.getSelectedFile() == null)
- setFileName(null);
- else
- setFileName(filechooser.getSelectedFile().toString());
- int index = -1;
- File file = filechooser.getSelectedFile();
- for (index = 0; index < model.getSize(); index++)
- if (((File) model.getElementAt(index)).equals(file))
- break;
- if (index == -1)
- return;
- filelist.setSelectedIndex(index);
- filelist.ensureIndexIsVisible(index);
- filelist.revalidate();
- filelist.repaint();
- }
- else if (e.getPropertyName().equals(
-
JFileChooser.DIRECTORY_CHANGED_PROPERTY))
- {
- filelist.clearSelection();
- filelist.revalidate();
- filelist.repaint();
- setDirectorySelected(false);
- setDirectory(filechooser.getCurrentDirectory());
- boxEntries();
- }
- else if (e.getPropertyName().equals(
-
JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)
- || e.getPropertyName().equals(
-
JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
- filterEntries();
- else if (e.getPropertyName().equals(
-
JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
- || e.getPropertyName().equals(
-
JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
- {
- Window owner = SwingUtilities.windowForComponent(filechooser);
- if (owner instanceof JDialog)
- ((JDialog) owner).setTitle(getDialogTitle(filechooser));
- accept.setText(getApproveButtonText(filechooser));
- accept.setToolTipText(getApproveButtonToolTipText(filechooser));
- accept.setMnemonic(getApproveButtonMnemonic(filechooser));
- }
- else if (e.getPropertyName().equals(
-
JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
- accept.setText(getApproveButtonText(filechooser));
- else if (e.getPropertyName().equals(
-
JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
- accept.setToolTipText(getApproveButtonToolTipText(filechooser));
- else if (e.getPropertyName().equals(
-
JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
- accept.setMnemonic(getApproveButtonMnemonic(filechooser));
- else if (e.getPropertyName().equals(
-
JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
- {
- if (filechooser.getControlButtonsAreShown())
- {
- GridBagConstraints c = new GridBagConstraints();
- c.gridy = 1;
- bottomPanel.add(filters, c);
-
- c.fill = GridBagConstraints.BOTH;
- c.gridy = 2;
- c.anchor = GridBagConstraints.EAST;
- bottomPanel.add(closePanel, c);
- bottomPanel.revalidate();
- bottomPanel.repaint();
- bottomPanel.doLayout();
- }
- else
- bottomPanel.remove(closePanel);
- }
- else if (e.getPropertyName().equals(
-
JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
- {
- if (filechooser.isAcceptAllFileFilterUsed())
-
filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser));
- else
-
filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser));
- }
- else if (e.getPropertyName().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 (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
- || e.getPropertyName().equals(
-
JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
- || e.getPropertyName().equals(
-
JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
- rescanCurrentDirectory(filechooser);
-
- filechooser.revalidate();
- filechooser.repaint();
}
};
}
@@ -1624,7 +1075,9 @@
*/
public String getFileName()
{
- return filename;
+ // FIXME: I'm thinking that this method just provides access to the
+ // text value in the JTextField component...but not sure yet
+ return null; //filename;
}
/**
@@ -1649,7 +1102,9 @@
*/
public void setFileName(String filename)
{
- this.filename = filename;
+ // FIXME: it might be the case that this method provides an access
+ // point for the JTextField (or whatever) a subclass is using...
+ //this.filename = filename;
}
/**
@@ -1672,7 +1127,6 @@
public void rescanCurrentDirectory(JFileChooser fc)
{
getModel().validateFileCache();
- filelist.revalidate();
}
/**
@@ -1708,17 +1162,14 @@
}
/**
- * Creates and returns an approve (open or save) button for the dialog.
+ * Returns the approve (open or save) button for the dialog.
*
* @param fc the file chooser.
*
* @return The button.
*/
- public JButton getApproveButton(JFileChooser fc)
+ protected JButton getApproveButton(JFileChooser fc)
{
- accept = new JButton(getApproveButtonText(fc));
- accept.setMnemonic(getApproveButtonMnemonic(fc));
- accept.setToolTipText(getApproveButtonToolTipText(fc));
return accept;
}
@@ -1830,9 +1281,8 @@
}
/**
- * Returns the file view for the file chooser. This returns either the
- * file view that has been explicitly set for the address@hidden
JFileChooser}, or
- * a default file view.
+ * Returns the default file view (NOT the file view from the file chooser,
+ * if there is one).
*
* @param fc the file chooser component.
*
@@ -1856,24 +1306,10 @@
*/
public String getDialogTitle(JFileChooser fc)
{
- String ret = fc.getDialogTitle();
- if (ret != null)
- return ret;
- switch (fc.getDialogType())
- {
- case JFileChooser.OPEN_DIALOG:
- ret = openButtonText;
- break;
- case JFileChooser.SAVE_DIALOG:
- ret = saveButtonText;
- break;
- default:
- ret = fc.getApproveButtonText();
- break;
- }
- if (ret == null)
- ret = openButtonText;
- return ret;
+ String result = fc.getDialogTitle();
+ if (result == null)
+ result = getApproveButtonText(fc);
+ return result;
}
/**
@@ -1906,23 +1342,28 @@
*/
public String getApproveButtonText(JFileChooser fc)
{
- if (fc.getApproveButtonText() != null)
- return fc.getApproveButtonText();
- else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
- return saveButtonText;
- else
- return openButtonText;
+ String result = fc.getApproveButtonText();
+ if (result == null)
+ {
+ if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
+ result = saveButtonText;
+ else
+ result = openButtonText;
+ }
+ return result;
}
/**
* Creates and returns a new action that will be used with the "new folder"
* button.
*
- * @return A new instance of address@hidden GoHomeAction}.
+ * @return A new instance of address@hidden NewFolderAction}.
*/
public Action getNewFolderAction()
{
- return new NewFolderAction();
+ if (newFolderAction == null)
+ newFolderAction = new NewFolderAction();
+ return newFolderAction;
}
/**
@@ -1933,49 +1374,56 @@
*/
public Action getGoHomeAction()
{
- return new GoHomeAction();
+ if (goHomeAction == null)
+ goHomeAction = new GoHomeAction();
+ return goHomeAction;
}
/**
- * Creates and returns a new action that will be used with the "up folder"
- * button.
+ * Returns the action that handles events for the "up folder" control button.
*
- * @return A new instance of address@hidden ChangeToParentDirectoryAction}.
+ * @return An instance of address@hidden ChangeToParentDirectoryAction}.
*/
public Action getChangeToParentDirectoryAction()
{
- return new ChangeToParentDirectoryAction();
+ if (changeToParentDirectoryAction == null)
+ changeToParentDirectoryAction = new ChangeToParentDirectoryAction();
+ return changeToParentDirectoryAction;
}
/**
- * Creates and returns a new action that will be used with the "approve"
- * button.
+ * Returns the action that handles events for the "approve" button.
*
- * @return A new instance of address@hidden ApproveSelectionAction}.
+ * @return An instance of address@hidden ApproveSelectionAction}.
*/
public Action getApproveSelectionAction()
{
- return new ApproveSelectionAction();
+ if (approveSelectionAction == null)
+ approveSelectionAction = new ApproveSelectionAction();
+ return approveSelectionAction;
}
/**
- * Creates and returns a new action that will be used with the "cancel"
- * button.
+ * Returns the action that handles events for the "cancel" button.
*
- * @return A new instance of address@hidden CancelSelectionAction}.
+ * @return An instance of address@hidden CancelSelectionAction}.
*/
public Action getCancelSelectionAction()
{
- return new CancelSelectionAction();
+ if (cancelSelectionAction == null)
+ cancelSelectionAction = new CancelSelectionAction();
+ return cancelSelectionAction;
}
/**
- * Creates and returns a new instance of address@hidden UpdateAction}.
+ * Returns the update action (an instance of address@hidden UpdateAction}).
*
* @return An action.
*/
public Action getUpdateAction()
{
- return new UpdateAction();
+ if (updateAction == null)
+ updateAction = new UpdateAction();
+ return updateAction;
}
}
Index: javax/swing/plaf/metal/MetalFileChooserUI.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java,v
retrieving revision 1.3
diff -u -r1.3 MetalFileChooserUI.java
--- javax/swing/plaf/metal/MetalFileChooserUI.java 19 Oct 2005 13:46:02
-0000 1.3
+++ javax/swing/plaf/metal/MetalFileChooserUI.java 25 Nov 2005 10:21:11
-0000
@@ -38,8 +38,17 @@
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.Window;
import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
@@ -47,12 +56,26 @@
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.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.JTextField;
+import javax.swing.JToggleButton;
+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;
@@ -64,13 +87,147 @@
* A UI delegate for the address@hidden JFileChooser} component. This class
is only
* partially implemented and is not usable yet.
*/
-public class MetalFileChooserUI extends BasicFileChooserUI
+public class MetalFileChooserUI
+ extends BasicFileChooserUI
{
+
+ /**
+ * A property change listener.
+ */
+ class MetalFileChooserPropertyChangeListener
+ implements PropertyChangeListener
+ {
+ /**
+ * Default constructor.
+ */
+ public MetalFileChooserPropertyChangeListener()
+ {
+ }
+
+ /**
+ * Handles a property change event.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ JFileChooser filechooser = getFileChooser();
+ // FIXME: Multiple file selection waiting on JList multiple selection
+ // bug.
+ String n = e.getPropertyName();
+
+ if (n.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
+ {
+ File file = filechooser.getSelectedFile();
+ if (file == null)
+ setFileName(null);
+ else
+ setFileName(file.getName());
+ int index = -1;
+ index = getModel().indexOf(file);
+ if (index >= 0)
+ {
+ fileList.setSelectedIndex(index);
+ fileList.ensureIndexIsVisible(index);
+ fileList.revalidate();
+ fileList.repaint();
+ }
+ }
+
+ else if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY))
+ {
+ fileList.clearSelection();
+ fileList.revalidate();
+ fileList.repaint();
+ setDirectorySelected(false);
+ File currentDirectory = filechooser.getCurrentDirectory();
+ setDirectory(currentDirectory);
+ boolean hasParent = (currentDirectory.getParentFile() != null);
+ getChangeToParentDirectoryAction().setEnabled(hasParent);
+ //boxEntries();
+ }
+
+ 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))
+ rescanCurrentDirectory(filechooser);
+
+ filechooser.revalidate();
+ filechooser.repaint();
+ }
+ };
+
/**
* A combo box model containing the selected directory and all its parent
* directories.
*/
- protected class DirectoryComboBoxModel extends AbstractListModel
+ protected class DirectoryComboBoxModel
+ extends AbstractListModel
implements ComboBoxModel
{
/** Storage for the items in the model. */
@@ -161,7 +318,8 @@
/**
* Handles changes to the selection in the directory combo box.
*/
- protected class DirectoryComboBoxAction extends AbstractAction
+ protected class DirectoryComboBoxAction
+ extends AbstractAction
{
/**
* Creates a new action.
@@ -184,9 +342,62 @@
}
/**
+ * A renderer for the items in the directory combo box.
+ */
+ class DirectoryComboBoxRenderer
+ extends DefaultListCellRenderer
+ {
+ /**
+ * Creates a new renderer.
+ */
+ 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 address@hidden 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.
+ */
+ 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));
+
+ // FIXME: we can't go creating a new border here every time...
+ //setBorder(BorderFactory.createEmptyBorder(0, index * 8, 0, 0));
+ 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.
*/
- protected class FileRenderer extends DefaultListCellRenderer
+ protected class FileRenderer
+ extends DefaultListCellRenderer
{
/**
@@ -249,7 +460,7 @@
protected FileFilter[] filters;
/** The index of the selected file filter. */
- private int selectedIndex;
+ private Object selected;
/**
* Creates a new model.
@@ -258,7 +469,7 @@
{
filters = new FileFilter[1];
filters[0] = getAcceptAllFileFilter(getFileChooser());
- selectedIndex = 0;
+ selected = filters[0];
}
/**
@@ -270,11 +481,11 @@
{
if
(e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
{
- selectedIndex = -1;
- FileFilter selected = (FileFilter) e.getNewValue();
- for (int i = 0; i < filters.length; i++)
- if (filters[i].equals(selected))
- selectedIndex = i;
+ 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(
@@ -291,13 +502,15 @@
/**
* Sets the selected filter.
*
- * @param filter the filter.
+ * @param filter the filter (<code>null</code> ignored).
*/
public void setSelectedItem(Object filter)
{
- // change the filter in the file chooser and let the property change
- // event trigger the change to the selected item
- getFileChooser().setFileFilter((FileFilter) filter);
+ if (filter != null)
+ {
+ selected = filter;
+ fireContentsChanged(this, -1, -1);
+ }
}
/**
@@ -307,9 +520,7 @@
*/
public Object getSelectedItem()
{
- if (selectedIndex >= 0)
- return filters[selectedIndex];
- return null;
+ return selected;
}
/**
@@ -339,7 +550,8 @@
/**
* A renderer for the items in the file filter combo box.
*/
- public class FilterComboBoxRenderer extends DefaultListCellRenderer
+ public class FilterComboBoxRenderer
+ extends DefaultListCellRenderer
{
/**
* Creates a new renderer.
@@ -359,20 +571,126 @@
* @param isSelected is the item selected?
* @param cellHasFocus does the list cell have focus?
*
- * @return A component.
+ * @return This component as the renderer.
*/
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus)
{
+ super.getListCellRendererComponent(list, value, index, isSelected,
+ cellHasFocus);
FileFilter filter = (FileFilter) value;
- return super.getListCellRendererComponent(list, filter.getDescription(),
- index, isSelected, cellHasFocus);
+ setText(filter.getDescription());
+ return this;
}
}
+ /**
+ * A listener for selection events in the file list.
+ *
+ * @see #createListSelectionListener(JFileChooser)
+ */
+ class MetalFileChooserSelectionListener
+ implements ListSelectionListener
+ {
+ /**
+ * Creates a new <code>SelectionListener</code> object.
+ */
+ protected MetalFileChooserSelectionListener()
+ {
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param e DOCUMENT ME!
+ */
+ 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 address@hidden JFileChooser}. This class is not
yet
+ * implemented.
+ */
+ protected class SingleClickListener
+ extends MouseAdapter
+ {
+ /**
+ * Creates a new listener.
+ *
+ * @param list the directory/file list.
+ */
+ public SingleClickListener(JList list)
+ {
+ // FIXME: implement
+ }
+
+ /**
+ * Receives notification of a mouse click event.
+ *
+ * @param e the event.
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ // FIXME: implement
+ }
+ }
+
+ /** The text for a label describing the directory combo box. */
+ private String directoryLabel;
+
+ private JComboBox directoryComboBox;
+
/** The model for the directory combo box. */
DirectoryComboBoxModel directoryModel;
+ /** The text for a label describing the file text field. */
+ private String fileLabel;
+
+ /** The file name text field. */
+ private JTextField fileTextField;
+
+ /** The text for a label describing the filter combo box. */
+ private String filterLabel;
+
+ /**
+ * The top panel (contains the directory combo box and the control buttons).
+ */
+ private JPanel topPanel;
+
+ /** A panel containing the control buttons ('up', 'home' etc.). */
+ private JPanel controls;
+
+ /**
+ * The panel that contains the filename field and the filter combobox.
+ */
+ private JPanel bottomPanel;
+
+ /**
+ * The panel that contains the 'Open' (or 'Save') and 'Cancel' buttons.
+ */
+ private JPanel buttonPanel;
+
+ private JButton approveButton;
+
+ /** The file list. */
+ private JList fileList;
+
+ /** The panel containing the file list. */
+ private JPanel fileListPanel;
+
+ /** The filter combo box model. */
+ private FilterComboBoxModel filterModel;
+
/**
* A factory method that returns a UI delegate for the specified
* component.
@@ -393,9 +711,304 @@
public MetalFileChooserUI(JFileChooser filechooser)
{
super(filechooser);
+ bottomPanel = new JPanel(new GridLayout(3, 2));
+ buttonPanel = new JPanel();
+ }
+
+ public void installUI(JComponent c)
+ {
+ // FIXME: do something here
+ super.installUI(c);
+ }
+
+ public void uninstallUI(JComponent c)
+ {
+ // FIXME: do something here
+ super.uninstallUI(c);
+ }
+
+ /**
+ * Installs the sub-components of the file chooser.
+ *
+ * @param fc the file chooser component.
+ */
+ public void installComponents(JFileChooser fc)
+ {
+ fc.setLayout(new BorderLayout());
+ topPanel = new JPanel(new BorderLayout());
+ topPanel.add(new JLabel(directoryLabel), BorderLayout.WEST);
+ this.controls = new JPanel();
+ addControlButtons();
+
+ JPanel dirPanel = new JPanel(new VerticalMidLayout());
+ dirPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
+ directoryModel = createDirectoryComboBoxModel(fc);
+ directoryComboBox = new JComboBox(directoryModel);
+ directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
+ dirPanel.add(directoryComboBox);
+ topPanel.add(dirPanel);
+ topPanel.add(controls, BorderLayout.EAST);
+ fc.add(topPanel, BorderLayout.NORTH);
+ fileListPanel = createList(fc);
+ fc.add(fileListPanel);
+ JPanel bottomPanel = getBottomPanel();
+ filterModel = createFilterComboBoxModel();
+ JComboBox fileFilterCombo = new JComboBox(filterModel);
+ fileFilterCombo.setRenderer(createFilterComboBoxRenderer());
+
+ fileTextField = new JTextField();
+ JPanel fileNamePanel = new JPanel(new VerticalMidLayout());
+ fileNamePanel.add(fileTextField);
+ JPanel row1 = new JPanel(new BorderLayout());
+ row1.add(new JLabel(this.fileLabel), BorderLayout.WEST);
+ row1.add(fileNamePanel);
+ bottomPanel.add(row1);
+
+ JPanel filterPanel = new JPanel(new VerticalMidLayout());
+ filterPanel.add(fileFilterCombo);
+ JPanel row2 = new JPanel(new BorderLayout());
+ row2.add(new JLabel(this.filterLabel), BorderLayout.WEST);
+ row2.add(filterPanel);
+ bottomPanel.add(row2);
+ JPanel buttonPanel = new JPanel(new ButtonLayout());
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 0));
+
+ approveButton = new JButton(getApproveSelectionAction());
+ approveButton.setText(getApproveButtonText(fc));
+ approveButton.setToolTipText(getApproveButtonToolTipText(fc));
+ approveButton.setMnemonic(getApproveButtonMnemonic(fc));
+ buttonPanel.add(approveButton);
+
+ JButton cancelButton = new JButton(getCancelSelectionAction());
+ cancelButton.setText(cancelButtonText);
+ cancelButton.setToolTipText(cancelButtonToolTipText);
+ cancelButton.setMnemonic(cancelButtonMnemonic);
+ buttonPanel.add(cancelButton);
+ bottomPanel.add(buttonPanel);
+ fc.add(bottomPanel, BorderLayout.SOUTH);
+ }
+
+ /**
+ * Uninstalls the components added by
+ * address@hidden #installComponents(JFileChooser)}.
+ *
+ * @param fc the file chooser.
+ */
+ public void uninstallComponents(JFileChooser fc)
+ {
+ fc.remove(bottomPanel);
+ bottomPanel = null;
+ fc.remove(fileListPanel);
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ protected void installStrings(JFileChooser fc)
+ {
+ super.installStrings(fc);
+ directoryLabel = "Look In: "; // FIXME: localise
+ fileLabel = "File Name: "; // FIXME: localise
+ filterLabel = "Files of Type: "; // FIXME: localise
+
+ this.cancelButtonMnemonic = 0;
+ this.cancelButtonText = "Cancel";
+ this.cancelButtonToolTipText = "Cancel ToolTip Text";
+
+ this.directoryOpenButtonMnemonic = 0;
+ this.directoryOpenButtonText = "Open";
+ this.directoryOpenButtonToolTipText = "Open ToolTip Text";
+
+ this.helpButtonMnemonic = 0;
+ this.helpButtonText = "Help";
+ this.helpButtonToolTipText = "Help";
+
+ this.openButtonMnemonic = 0;
+ this.openButtonText = "Open";
+ this.openButtonToolTipText = "Open ToolTip Text";
+
+ this.saveButtonMnemonic = 0;
+ this.saveButtonText = "Save";
+ this.saveButtonToolTipText = "Save ToolTip Text";
+
+ this.updateButtonMnemonic = 0;
+ this.updateButtonText = "Update";
+ this.updateButtonToolTipText = "Update ToolTip Text";
+ }
+
+ /**
+ * Installs the listeners required.
+ *
+ * @param fc the file chooser.
+ */
+ protected void installListeners(JFileChooser fc)
+ {
+ directoryComboBox.setAction(new DirectoryComboBoxAction());
+ fileList.addListSelectionListener(createListSelectionListener(fc));
+ fileList.addMouseListener(this.createDoubleClickListener(fc, fileList));
+ fileList.addMouseListener(new SingleClickListener(fileList));
+ fc.addPropertyChangeListener(filterModel);
+ super.installListeners(fc);
+ }
+
+ protected void uninstallListeners(JFileChooser fc)
+ {
+ super.uninstallListeners(fc);
+ fc.removePropertyChangeListener(filterModel);
+ }
+
+ protected ActionMap getActionMap()
+ {
+ // FIXME: implement this
+ return null;
+ }
+
+ /**
+ * Creates and returns an action map.
+ *
+ * @return The action map.
+ */
+ protected ActionMap createActionMap()
+ {
+ ActionMap map = new ActionMap();
+ map.put("approveSelection", getApproveSelectionAction());
+ map.put("cancelSelection", null); // FIXME: implement this one
+ map.put("Go Up", getChangeToParentDirectoryAction());
+ return map;
+ }
+
+ /**
+ * Creates a panel containing a list of files.
+ *
+ * @param fc the file chooser.
+ *
+ * @return A panel.
+ */
+ protected JPanel createList(JFileChooser fc)
+ {
+ JPanel panel = new JPanel(new BorderLayout());
+ fileList = new JList(getModel());
+ // a bug is preventing the vertical wrap from working right now,
+ // uncomment the next line once that is fixed...
+ //fileList.setLayoutOrientation(JList.VERTICAL_WRAP);
+ fileList.setVisibleRowCount(0);
+ fileList.setCellRenderer(new FileRenderer());
+ panel.add(new JScrollPane(fileList));
+ return panel;
+ }
+
+ /**
+ * Creates a panel containing a table within a scroll pane.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The details view.
+ */
+ protected JPanel createDetailsView(JFileChooser fc)
+ {
+ // FIXME: implement this. The details view is a panel containing a table
+ // inside a JScrollPane - it gets displayed when the user clicks on the
+ // "details" button.
+ return new JPanel();
+ }
+
+ /**
+ * Creates a listener that monitors selections in the directory/file list
+ * and keeps the address@hidden JFileChooser} component up to date.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The listener.
+ *
+ * @see #installListeners(JFileChooser)
+ */
+ public ListSelectionListener createListSelectionListener(JFileChooser fc)
+ {
+ return new MetalFileChooserSelectionListener();
+ }
+
+ /**
+ * Returns the preferred size for the file chooser component.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ // FIXME: not likely to be a fixed value
+ return new Dimension(500, 326);
+ }
+
+ /**
+ * Returns the minimum size for the file chooser component.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ // FIXME: not likely to be a fixed value
+ return new Dimension(506, 326);
+ }
+
+ /**
+ * Returns the maximum size for the file chooser component.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a property change listener that monitors the address@hidden
JFileChooser}
+ * for property change events and updates the component display accordingly.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The property change listener.
+ *
+ * @see #installListeners(JFileChooser)
+ */
+ public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
+ {
+ return new MetalFileChooserPropertyChangeListener();
+ }
+
+ /**
* Creates and returns a new instance of address@hidden
DirectoryComboBoxModel}.
*
* @return A new instance of address@hidden DirectoryComboBoxModel}.
@@ -407,6 +1020,20 @@
}
/**
+ * Creates a new instance of the renderer used in the directory
+ * combo box.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The renderer.
+ */
+ protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
+ JFileChooser fc)
+ {
+ return new DirectoryComboBoxRenderer(fc);
+ }
+
+ /**
* Creates and returns a new instance of address@hidden FilterComboBoxModel}.
*
* @return A new instance of address@hidden FilterComboBoxModel}.
@@ -425,6 +1052,307 @@
createFilterComboBoxRenderer()
{
return new FilterComboBoxRenderer();
+ }
+
+ /**
+ * Adds the control buttons ('up', 'home' etc.) to the panel.
+ */
+ 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();
+ listButton.setIcon(this.listViewIcon);
+ listButton.setMargin(new Insets(0, 0, 0, 0));
+ // FIXME: this button needs an action that handles a click
+ controls.add(listButton);
+
+ JToggleButton detailButton = new JToggleButton(this.detailsViewIcon);
+ detailButton.setMargin(new Insets(0, 0, 0, 0));
+ // FIXME: this button needs an action that handles a click
+ controls.add(detailButton);
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(listButton);
+ buttonGroup.add(detailButton);
+ }
+
+ protected void removeControlButtons()
+ {
+ // FIXME: implement this
+ }
+
+ public void ensureFileIsVisible(JFileChooser fc, File f)
+ {
+ // FIXME: do something here - probably this figures out whether the
+ // list or table view is current, and forwards the request to the
+ // appropriate one...
+ super.ensureFileIsVisible(fc, f);
+ }
+
+ public void rescanCurrentDirectory(JFileChooser fc)
+ {
+ // FIXME: this will need to take into account whether the list view or
+ // the table view is current
+ directoryModel.setSelectedItem(fc.getCurrentDirectory());
+ getModel().validateFileCache();
+ fileList.revalidate();
+ }
+
+ /**
+ * Returns the file name in the text field.
+ *
+ * @return The file name.
+ */
+ 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.
+ */
+ public void setFileName(String filename)
+ {
+ fileTextField.setText(filename);
+ }
+
+ protected void setDirectorySelected(boolean directorySelected)
+ {
+ // FIXME: do something here
+ super.setDirectorySelected(directorySelected);
+ }
+
+ public String getDirectoryName()
+ {
+ // FIXME: do something here
+ return super.getDirectoryName();
+ }
+
+ public void setDirectoryName(String dirname)
+ {
+ // FIXME: do something here
+ super.setDirectoryName(dirname);
+ }
+
+ public void valueChanged(ListSelectionEvent e)
+ {
+ // FIXME: implement
+ }
+
+ /**
+ * Returns the approve button.
+ *
+ * @return The approve button.
+ */
+ protected JButton getApproveButton(JFileChooser fc)
+ {
+ return approveButton;
+ }
+
+ /**
+ * A layout manager that is used to arrange the subcomponents of the
+ * address@hidden JFileChooser}.
+ */
+ class VerticalMidLayout implements LayoutManager
+ {
+ /**
+ * Performs the layout.
+ *
+ * @param parent the container.
+ */
+ 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.
+ */
+ public Dimension minimumLayoutSize(Container parent)
+ {
+ return preferredLayoutSize(parent);
+ }
+
+ /**
+ * Returns the preferred layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The preferred layout size.
+ */
+ 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.
+ */
+ 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.
+ */
+ public void removeLayoutComponent(Component component) {
+ // do nothing
+ }
+ }
+
+ /**
+ * A layout manager that is used to arrange buttons for the
+ * address@hidden JFileChooser}.
+ */
+ class ButtonLayout implements LayoutManager
+ {
+ static final int GAP = 4;
+
+ /**
+ * Performs the layout.
+ *
+ * @param parent the container.
+ */
+ 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.
+ */
+ public Dimension minimumLayoutSize(Container parent)
+ {
+ return preferredLayoutSize(parent);
+ }
+
+ /**
+ * Returns the preferred layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The preferred layout size.
+ */
+ 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.
+ */
+ 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.
+ */
+ public void removeLayoutComponent(Component component) {
+ // do nothing
+ }
}
}
Index: javax/swing/plaf/metal/MetalLookAndFeel.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java,v
retrieving revision 1.72
diff -u -r1.72 MetalLookAndFeel.java
--- javax/swing/plaf/metal/MetalLookAndFeel.java 23 Nov 2005 19:45:43
-0000 1.72
+++ javax/swing/plaf/metal/MetalLookAndFeel.java 25 Nov 2005 10:21:12
-0000
@@ -54,7 +54,17 @@
/**
* A custom look and feel that is designed to look similar across different
- * operating systems.
+ * operating systems. To install this look and feel, add the following code
+ * (or something similar) near the start of your application:</p>
+ * <pre>
+ * try
+ * {
+ * UIManager.setLookAndFeel(new MetalLookAndFeel());
+ * }
+ * catch (UnsupportedLookAndFeelException e)
+ * {
+ * e.printStackTrace();
+ * }</pre>
*/
public class MetalLookAndFeel extends BasicLookAndFeel
{
@@ -690,6 +700,7 @@
"CheckBoxUI", "javax.swing.plaf.metal.MetalCheckBoxUI",
"ComboBoxUI", "javax.swing.plaf.metal.MetalComboBoxUI",
"DesktopIconUI", "javax.swing.plaf.metal.MetalDesktopIconUI",
+ "FileChooserUI", "javax.swing.plaf.metal.MetalFileChooserUI",
"InternalFrameUI", "javax.swing.plaf.metal.MetalInternalFrameUI",
"LabelUI", "javax.swing.plaf.metal.MetalLabelUI",
"MenuBarUI", "javax.swing.plaf.metal.MetalMenuBarUI",
@@ -856,6 +867,17 @@
"FormattedTextField.inactiveForeground", getInactiveSystemTextColor(),
"FormattedTextField.selectionBackground", getTextHighlightColor(),
"FormattedTextField.selectionForeground", getHighlightedTextColor(),
+
+ "FileChooser.upFolderIcon",
+ MetalIconFactory.getFileChooserUpFolderIcon(),
+ "FileChooser.listViewIcon",
+ MetalIconFactory.getFileChooserListViewIcon(),
+ "FileChooser.newFolderIcon",
+ MetalIconFactory.getFileChooserNewFolderIcon(),
+ "FileChooser.homeFolderIcon",
+ MetalIconFactory.getFileChooserHomeFolderIcon(),
+ "FileChooser.detailsViewIcon",
+ MetalIconFactory.getFileChooserDetailViewIcon(),
"FileView.computerIcon", MetalIconFactory.getTreeComputerIcon(),
"FileView.directoryIcon", MetalIconFactory.getTreeFolderIcon(),
- [cp-patches] RFC: MetalFileChooserUI implementation,
David Gilbert <=