diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,1096 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.swing.plaf.synth; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import java.io.*; +import java.util.*; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.filechooser.*; +import javax.swing.filechooser.FileFilter; +import javax.swing.plaf.basic.*; +import javax.swing.plaf.synth.*; + +import sun.swing.SwingUtilities2; + +import sun.awt.shell.ShellFolder; +import sun.swing.*; + +/** + * Synth FileChooserUI implementation. + *

+ * Note that the classes in the com.sun.java.swing.plaf.synth + * package are not + * part of the core Java APIs. They are a part of Sun's JDK and JRE + * distributions. Although other licensees may choose to distribute + * these classes, developers cannot depend on their availability in + * non-Sun implementations. Additionally this API may change in + * incompatible ways between releases. While this class is public, it + * shoud be considered an implementation detail, and subject to change. + * + * @author Leif Samuelsson + * @author Jeff Dinkins + */ +public class SynthFileChooserUIImpl extends SynthFileChooserUI { + private JLabel lookInLabel; + private JComboBox directoryComboBox; + private DirectoryComboBoxModel directoryComboBoxModel; + private Action directoryComboBoxAction = new DirectoryComboBoxAction(); + + private FilterComboBoxModel filterComboBoxModel; + + private JTextField fileNameTextField; + + private FilePane filePane; + private JToggleButton listViewButton; + private JToggleButton detailsViewButton; + + private boolean useShellFolder; + + private boolean readOnly; + + private JPanel buttonPanel; + private JPanel bottomPanel; + + private JComboBox filterComboBox; + + private static final Dimension hstrut5 = new Dimension(5, 1); + private static final Dimension vstrut5 = new Dimension(1, 5); + + private static final Insets shrinkwrap = new Insets(0,0,0,0); + + // Preferred and Minimum sizes for the dialog box + private static Dimension LIST_PREF_SIZE = new Dimension(405, 135); + + // Labels, mnemonics, and tooltips (oh my!) + private int lookInLabelMnemonic = 0; + private String lookInLabelText = null; + private String saveInLabelText = null; + + private int fileNameLabelMnemonic = 0; + private String fileNameLabelText = null; + private int folderNameLabelMnemonic = 0; + private String folderNameLabelText = null; + + private int filesOfTypeLabelMnemonic = 0; + private String filesOfTypeLabelText = null; + + private String upFolderToolTipText = null; + private String upFolderAccessibleName = null; + + private String homeFolderToolTipText = null; + private String homeFolderAccessibleName = null; + + private String newFolderToolTipText = null; + private String newFolderAccessibleName = null; + + private String listViewButtonToolTipText = null; + private String listViewButtonAccessibleName = null; + + private String detailsViewButtonToolTipText = null; + private String detailsViewButtonAccessibleName = null; + + private AlignedLabel fileNameLabel; + private final PropertyChangeListener modeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fileNameLabel != null) { + populateFileNameLabel(); + } + } + }; + + private void populateFileNameLabel() { + if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { + fileNameLabel.setText(folderNameLabelText); + fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic); + } else { + fileNameLabel.setText(fileNameLabelText); + fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + } + } + + public SynthFileChooserUIImpl(JFileChooser b) { + super(b); + } + + + private class SynthFileChooserUIAccessor implements FilePane.FileChooserUIAccessor { + public JFileChooser getFileChooser() { + return SynthFileChooserUIImpl.this.getFileChooser(); + } + + public BasicDirectoryModel getModel() { + return SynthFileChooserUIImpl.this.getModel(); + } + + public JPanel createList() { + return null; + } + + public JPanel createDetailsView() { + return null; + } + + public boolean isDirectorySelected() { + return SynthFileChooserUIImpl.this.isDirectorySelected(); + } + + public File getDirectory() { + return SynthFileChooserUIImpl.this.getDirectory(); + } + + public Action getChangeToParentDirectoryAction() { + return SynthFileChooserUIImpl.this.getChangeToParentDirectoryAction(); + } + + public Action getApproveSelectionAction() { + return SynthFileChooserUIImpl.this.getApproveSelectionAction(); + } + + public Action getNewFolderAction() { + return SynthFileChooserUIImpl.this.getNewFolderAction(); + } + + public MouseListener createDoubleClickListener(JList list) { + return SynthFileChooserUIImpl.this.createDoubleClickListener(getFileChooser(), + list); + } + + public ListSelectionListener createListSelectionListener() { + return SynthFileChooserUIImpl.this.createListSelectionListener(getFileChooser()); + } + + public boolean usesShellFolder() { + return useShellFolder; + } + } + + protected void installDefaults(JFileChooser fc) { + super.installDefaults(fc); + readOnly = UIManager.getBoolean("FileChooser.readOnly"); + } + + public void installComponents(JFileChooser fc) { + super.installComponents(fc); + + SynthContext context = getContext(fc, ENABLED); + + updateUseShellFolder(); + + fc.setLayout(new BorderLayout(0, 11)); + + // ********************************* // + // **** Construct the top panel **** // + // ********************************* // + + // Directory manipulation buttons + JPanel topPanel = new JPanel(new BorderLayout(11, 0)); + JPanel topButtonPanel = new JPanel(); + topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.LINE_AXIS)); + topPanel.add(topButtonPanel, BorderLayout.AFTER_LINE_ENDS); + + // Add the top panel to the fileChooser + fc.add(topPanel, BorderLayout.NORTH); + + // ComboBox Label + lookInLabel = new JLabel(lookInLabelText); + lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic); + topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS); + + // CurrentDir ComboBox + directoryComboBox = new JComboBox(); + directoryComboBox.getAccessibleContext().setAccessibleDescription(lookInLabelText); + directoryComboBox.putClientProperty( "JComboBox.isTableCellEditor", Boolean.TRUE ); + lookInLabel.setLabelFor(directoryComboBox); + directoryComboBoxModel = createDirectoryComboBoxModel(fc); + directoryComboBox.setModel(directoryComboBoxModel); + directoryComboBox.addActionListener(directoryComboBoxAction); + directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc)); + directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT); + directoryComboBox.setAlignmentY(JComponent.TOP_ALIGNMENT); + directoryComboBox.setMaximumRowCount(8); + topPanel.add(directoryComboBox, BorderLayout.CENTER); + + filePane = new FilePane(new SynthFileChooserUIAccessor()); + fc.addPropertyChangeListener(filePane); + + // Add 'Go Up' to context menu, plus 'Go Home' if on Unix + JPopupMenu contextMenu = filePane.getComponentPopupMenu(); + if (contextMenu != null) { + contextMenu.insert(getChangeToParentDirectoryAction(), 0); + if (File.separatorChar == '/') { + contextMenu.insert(getGoHomeAction(), 1); + } + } + + FileSystemView fsv = fc.getFileSystemView(); + + // Up Button + JButton upFolderButton = new JButton(getChangeToParentDirectoryAction()); + upFolderButton.setText(null); + upFolderButton.setIcon(upFolderIcon); + upFolderButton.setToolTipText(upFolderToolTipText); + upFolderButton.getAccessibleContext().setAccessibleName(upFolderAccessibleName); + upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + upFolderButton.setMargin(shrinkwrap); + + topButtonPanel.add(upFolderButton); + topButtonPanel.add(Box.createRigidArea(hstrut5)); + + // Home Button + File homeDir = fsv.getHomeDirectory(); + String toolTipText = homeFolderToolTipText; + if (fsv.isRoot(homeDir)) { + toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop". + } + + JButton b = new JButton(homeFolderIcon); + b.setToolTipText(toolTipText); + b.getAccessibleContext().setAccessibleName(homeFolderAccessibleName); + b.setAlignmentX(JComponent.LEFT_ALIGNMENT); + b.setAlignmentY(JComponent.CENTER_ALIGNMENT); + b.setMargin(shrinkwrap); + + b.addActionListener(getGoHomeAction()); + topButtonPanel.add(b); + topButtonPanel.add(Box.createRigidArea(hstrut5)); + + // New Directory Button + if (!readOnly) { + b = new JButton(filePane.getNewFolderAction()); + b.setText(null); + b.setIcon(newFolderIcon); + b.setToolTipText(newFolderToolTipText); + b.getAccessibleContext().setAccessibleName(newFolderAccessibleName); + b.setAlignmentX(JComponent.LEFT_ALIGNMENT); + b.setAlignmentY(JComponent.CENTER_ALIGNMENT); + b.setMargin(shrinkwrap); + } + topButtonPanel.add(b); + topButtonPanel.add(Box.createRigidArea(hstrut5)); + + // View button group + ButtonGroup viewButtonGroup = new ButtonGroup(); + + // List Button + listViewButton = new JToggleButton(listViewIcon); + listViewButton.setToolTipText(listViewButtonToolTipText); + listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName); + listViewButton.setSelected(true); + listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + listViewButton.setMargin(shrinkwrap); + listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); + topButtonPanel.add(listViewButton); + viewButtonGroup.add(listViewButton); + + // Details Button + detailsViewButton = new JToggleButton(detailsViewIcon); + detailsViewButton.setToolTipText(detailsViewButtonToolTipText); + detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName); + detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + detailsViewButton.setMargin(shrinkwrap); + detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); + topButtonPanel.add(detailsViewButton); + viewButtonGroup.add(detailsViewButton); + + filePane.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if ("viewType".equals(e.getPropertyName())) { + int viewType = filePane.getViewType(); + switch (viewType) { + case FilePane.VIEWTYPE_LIST: + listViewButton.setSelected(true); + break; + case FilePane.VIEWTYPE_DETAILS: + detailsViewButton.setSelected(true); + break; + } + } + } + }); + + // ************************************** // + // ******* Add the directory pane ******* // + // ************************************** // + fc.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS); + JComponent accessory = fc.getAccessory(); + if (accessory != null) { + getAccessoryPanel().add(accessory); + } + filePane.setPreferredSize(LIST_PREF_SIZE); + fc.add(filePane, BorderLayout.CENTER); + + + // ********************************** // + // **** Construct the bottom panel ** // + // ********************************** // + bottomPanel = new JPanel(); + bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); + fc.add(bottomPanel, BorderLayout.SOUTH); + + // FileName label and textfield + JPanel fileNamePanel = new JPanel(); + fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS)); + bottomPanel.add(fileNamePanel); + bottomPanel.add(Box.createRigidArea(new Dimension(1, 5))); + + fileNameLabel = new AlignedLabel(); + populateFileNameLabel(); + fileNamePanel.add(fileNameLabel); + + fileNameTextField = new JTextField(35) { + public Dimension getMaximumSize() { + return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height); + } + }; + fileNamePanel.add(fileNameTextField); + fileNameLabel.setLabelFor(fileNameTextField); + fileNameTextField.addFocusListener( + new FocusAdapter() { + public void focusGained(FocusEvent e) { + if (!getFileChooser().isMultiSelectionEnabled()) { + filePane.clearSelection(); + } + } + } + ); + if (fc.isMultiSelectionEnabled()) { + setFileName(fileNameString(fc.getSelectedFiles())); + } else { + setFileName(fileNameString(fc.getSelectedFile())); + } + + + // Filetype label and combobox + JPanel filesOfTypePanel = new JPanel(); + filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS)); + bottomPanel.add(filesOfTypePanel); + + AlignedLabel filesOfTypeLabel = new AlignedLabel(filesOfTypeLabelText); + filesOfTypeLabel.setDisplayedMnemonic(filesOfTypeLabelMnemonic); + filesOfTypePanel.add(filesOfTypeLabel); + + filterComboBoxModel = createFilterComboBoxModel(); + fc.addPropertyChangeListener(filterComboBoxModel); + filterComboBox = new JComboBox(filterComboBoxModel); + filterComboBox.getAccessibleContext().setAccessibleDescription(filesOfTypeLabelText); + filesOfTypeLabel.setLabelFor(filterComboBox); + filterComboBox.setRenderer(createFilterComboBoxRenderer()); + filesOfTypePanel.add(filterComboBox); + + + // buttons + buttonPanel = new JPanel(); + buttonPanel.setLayout(new ButtonAreaLayout()); + + buttonPanel.add(getApproveButton(fc)); + buttonPanel.add(getCancelButton(fc)); + + if (fc.getControlButtonsAreShown()) { + addControlButtons(); + } + + groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel }); + } + + protected void installListeners(JFileChooser fc) { + super.installListeners(fc); + fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + } + + protected void uninstallListeners(JFileChooser fc) { + fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + super.uninstallListeners(fc); + } + + private void updateUseShellFolder() { + // Decide whether to use the ShellFolder class to populate shortcut + // panel and combobox. + JFileChooser fc = getFileChooser(); + Boolean prop = + (Boolean)fc.getClientProperty("FileChooser.useShellFolder"); + if (prop != null) { + useShellFolder = prop.booleanValue(); + } else { + useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView()); + } + } + + + private String fileNameString(File file) { + if (file == null) { + return null; + } else { + JFileChooser fc = getFileChooser(); + if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { + return file.getPath(); + } else { + return file.getName(); + } + } + } + + private String fileNameString(File[] files) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; files != null && i < files.length; i++) { + if (i > 0) { + buf.append(" "); + } + if (files.length > 1) { + buf.append("\""); + } + buf.append(fileNameString(files[i])); + if (files.length > 1) { + buf.append("\""); + } + } + return buf.toString(); + } + + public void uninstallUI(JComponent c) { + // Remove listeners + c.removePropertyChangeListener(filterComboBoxModel); + c.removePropertyChangeListener(filePane); + + if (filePane != null) { + filePane.uninstallUI(); + filePane = null; + } + + super.uninstallUI(c); + } + + protected void installStrings(JFileChooser fc) { + super.installStrings(fc); + + Locale l = fc.getLocale(); + + lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l); + lookInLabelText = UIManager.getString("FileChooser.lookInLabelText", l); + saveInLabelText = UIManager.getString("FileChooser.saveInLabelText", l); + + fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l); + fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l); + folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l); + folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText", l); + + filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l); + filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l); + + upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText",l); + upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l); + + homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText",l); + homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l); + + newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l); + newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l); + + listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l); + listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l); + + detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l); + detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l); + } + + private int getMnemonic(String key, Locale l) { + return SwingUtilities2.getUIDefaultsInt(key, l); + } + + + public String getFileName() { + if (fileNameTextField != null) { + return fileNameTextField.getText(); + } else { + return null; + } + } + + public void setFileName(String fileName) { + if (fileNameTextField != null) { + fileNameTextField.setText(fileName); + } + } + + + protected void doSelectedFileChanged(PropertyChangeEvent e) { + super.doSelectedFileChanged(e); + + File f = (File) e.getNewValue(); + JFileChooser fc = getFileChooser(); + if (f != null + && ((fc.isFileSelectionEnabled() && !f.isDirectory()) + || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) { + + setFileName(fileNameString(f)); + } + } + + protected void doSelectedFilesChanged(PropertyChangeEvent e) { + super.doSelectedFilesChanged(e); + + File[] files = (File[]) e.getNewValue(); + JFileChooser fc = getFileChooser(); + if (files != null + && files.length > 0 + && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) { + setFileName(fileNameString(files)); + } + } + + protected void doDirectoryChanged(PropertyChangeEvent e) { + super.doDirectoryChanged(e); + + JFileChooser fc = getFileChooser(); + FileSystemView fsv = fc.getFileSystemView(); + File currentDirectory = fc.getCurrentDirectory(); + + if (!readOnly && currentDirectory != null) { + getNewFolderAction().setEnabled(filePane.canWrite(currentDirectory)); + } + + if (currentDirectory != null) { + JComponent cb = getDirectoryComboBox(); + if (cb instanceof JComboBox) { + ComboBoxModel model = ((JComboBox)cb).getModel(); + if (model instanceof DirectoryComboBoxModel) { + ((DirectoryComboBoxModel)model).addItem(currentDirectory); + } + } + + if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { + if (fsv.isFileSystem(currentDirectory)) { + setFileName(currentDirectory.getPath()); + } else { + setFileName(null); + } + } + } + } + + + protected void doFileSelectionModeChanged(PropertyChangeEvent e) { + super.doFileSelectionModeChanged(e); + + JFileChooser fc = getFileChooser(); + File currentDirectory = fc.getCurrentDirectory(); + if (currentDirectory != null + && fc.isDirectorySelectionEnabled() + && !fc.isFileSelectionEnabled() + && fc.getFileSystemView().isFileSystem(currentDirectory)) { + + setFileName(currentDirectory.getPath()); + } else { + setFileName(null); + } + } + + protected void doAccessoryChanged(PropertyChangeEvent e) { + if (getAccessoryPanel() != null) { + if (e.getOldValue() != null) { + getAccessoryPanel().remove((JComponent)e.getOldValue()); + } + JComponent accessory = (JComponent)e.getNewValue(); + if (accessory != null) { + getAccessoryPanel().add(accessory, BorderLayout.CENTER); + } + } + } + + protected void doControlButtonsChanged(PropertyChangeEvent e) { + super.doControlButtonsChanged(e); + + if (getFileChooser().getControlButtonsAreShown()) { + addControlButtons(); + } else { + removeControlButtons(); + } + } + + protected void addControlButtons() { + if (bottomPanel != null) { + bottomPanel.add(buttonPanel); + } + } + + protected void removeControlButtons() { + if (bottomPanel != null) { + bottomPanel.remove(buttonPanel); + } + } + + + + + // ******************************************************* + // ************ FileChooser UI PLAF methods ************** + // ******************************************************* + + + // ***************************** + // ***** Directory Actions ***** + // ***************************** + + protected JComponent getDirectoryComboBox() { + return directoryComboBox; + } + + protected Action getDirectoryComboBoxAction() { + return directoryComboBoxAction; + } + + protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { + return new DirectoryComboBoxRenderer(); + } + + // + // Renderer for DirectoryComboBox + // + class DirectoryComboBoxRenderer extends DefaultListCellRenderer { + IndentIcon ii = new IndentIcon(); + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, + boolean cellHasFocus) { + + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value == null) { + setText(""); + return this; + } + File directory = (File)value; + setText(getFileChooser().getName(directory)); + Icon icon = getFileChooser().getIcon(directory); + ii.icon = icon; + ii.depth = directoryComboBoxModel.getDepth(index); + setIcon(ii); + + return this; + } + } + + final static int space = 10; + class IndentIcon implements Icon { + + Icon icon = null; + int depth = 0; + + public void paintIcon(Component c, Graphics g, int x, int y) { + if (icon != null) { + if (c.getComponentOrientation().isLeftToRight()) { + icon.paintIcon(c, g, x+depth*space, y); + } else { + icon.paintIcon(c, g, x, y); + } + } + } + + public int getIconWidth() { + return ((icon != null) ? icon.getIconWidth() : 0) + depth*space; + } + + public int getIconHeight() { + return (icon != null) ? icon.getIconHeight() : 0; + } + + } + + // + // DataModel for DirectoryComboxbox + // + protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) { + return new DirectoryComboBoxModel(); + } + + /** + * Data model for a type-face selection combo-box. + */ + protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { + Vector directories = new Vector(); + int[] depths = null; + File selectedDirectory = null; + JFileChooser chooser = getFileChooser(); + FileSystemView fsv = chooser.getFileSystemView(); + + public DirectoryComboBoxModel() { + // Add the current directory to the model, and make it the + // selectedDirectory + File dir = getFileChooser().getCurrentDirectory(); + if (dir != null) { + addItem(dir); + } + } + + /** + * Adds the directory to the model and sets it to be selected, + * additionally clears out the previous selected directory and + * the paths leading up to it, if any. + */ + public void addItem(File directory) { + + if (directory == null) { + return; + } + + int oldSize = directories.size(); + directories.clear(); + if (oldSize > 0) { + fireIntervalRemoved(this, 0, oldSize); + } + + File[] baseFolders; + if (useShellFolder) { + baseFolders = (File[])ShellFolder.get("fileChooserComboBoxFolders"); + } else { + baseFolders = fsv.getRoots(); + } + directories.addAll(Arrays.asList(baseFolders)); + + // Get the canonical (full) path. This has the side + // benefit of removing extraneous chars from the path, + // for example /foo/bar/ becomes /foo/bar + File canonical = null; + try { + canonical = directory.getCanonicalFile(); + } catch (IOException e) { + // Maybe drive is not ready. Can't abort here. + canonical = directory; + } + + // create File instances of each directory leading up to the top + try { + File sf = useShellFolder ? ShellFolder.getShellFolder(canonical) + : canonical; + File f = sf; + Vector path = new Vector(10); + do { + path.addElement(f); + } while ((f = f.getParentFile()) != null); + + int pathCount = path.size(); + // Insert chain at appropriate place in vector + for (int i = 0; i < pathCount; i++) { + f = (File)path.get(i); + if (directories.contains(f)) { + int topIndex = directories.indexOf(f); + for (int j = i-1; j >= 0; j--) { + directories.insertElementAt(path.get(j), topIndex+i-j); + } + break; + } + } + calculateDepths(); + setSelectedItem(sf); + } catch (FileNotFoundException ex) { + calculateDepths(); + } + } + + private void calculateDepths() { + depths = new int[directories.size()]; + for (int i = 0; i < depths.length; i++) { + File dir = (File)directories.get(i); + File parent = dir.getParentFile(); + depths[i] = 0; + if (parent != null) { + for (int j = i-1; j >= 0; j--) { + if (parent.equals((File)directories.get(j))) { + depths[i] = depths[j] + 1; + break; + } + } + } + } + } + + public int getDepth(int i) { + return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0; + } + + public void setSelectedItem(Object selectedDirectory) { + this.selectedDirectory = (File)selectedDirectory; + fireContentsChanged(this, -1, -1); + } + + public Object getSelectedItem() { + return selectedDirectory; + } + + public int getSize() { + return directories.size(); + } + + public Object getElementAt(int index) { + return directories.elementAt(index); + } + } + + /** + * Acts when DirectoryComboBox has changed the selected item. + */ + protected class DirectoryComboBoxAction extends AbstractAction { + protected DirectoryComboBoxAction() { + super("DirectoryComboBoxAction"); + } + + public void actionPerformed(ActionEvent e) { + directoryComboBox.hidePopup(); + JComponent cb = getDirectoryComboBox(); + if (cb instanceof JComboBox) { + File f = (File)((JComboBox)cb).getSelectedItem(); + getFileChooser().setCurrentDirectory(f); + } + } + } + + // + // Renderer for Types ComboBox + // + protected FilterComboBoxRenderer createFilterComboBoxRenderer() { + return new FilterComboBoxRenderer(); + } + + /** + * Render different type sizes and styles. + */ + public class FilterComboBoxRenderer extends DefaultListCellRenderer { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value != null && value instanceof FileFilter) { + setText(((FileFilter)value).getDescription()); + } + + return this; + } + } + + // + // DataModel for Types Comboxbox + // + protected FilterComboBoxModel createFilterComboBoxModel() { + return new FilterComboBoxModel(); + } + + /** + * Data model for a type-face selection combo-box. + */ + protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { + protected FileFilter[] filters; + protected FilterComboBoxModel() { + super(); + filters = getFileChooser().getChoosableFileFilters(); + } + + public void propertyChange(PropertyChangeEvent e) { + String prop = e.getPropertyName(); + if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { + filters = (FileFilter[]) e.getNewValue(); + fireContentsChanged(this, -1, -1); + } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { + fireContentsChanged(this, -1, -1); + } + } + + public void setSelectedItem(Object filter) { + if(filter != null) { + getFileChooser().setFileFilter((FileFilter) filter); + fireContentsChanged(this, -1, -1); + } + } + + public Object getSelectedItem() { + // Ensure that the current filter is in the list. + // NOTE: we shouldnt' have to do this, since JFileChooser adds + // the filter to the choosable filters list when the filter + // is set. Lets be paranoid just in case someone overrides + // setFileFilter in JFileChooser. + FileFilter currentFilter = getFileChooser().getFileFilter(); + boolean found = false; + if(currentFilter != null) { + for(int i=0; i < filters.length; i++) { + if(filters[i] == currentFilter) { + found = true; + } + } + if(found == false) { + getFileChooser().addChoosableFileFilter(currentFilter); + } + } + return getFileChooser().getFileFilter(); + } + + public int getSize() { + if(filters != null) { + return filters.length; + } else { + return 0; + } + } + + public Object getElementAt(int index) { + if(index > getSize() - 1) { + // This shouldn't happen. Try to recover gracefully. + return getFileChooser().getFileFilter(); + } + if(filters != null) { + return filters[index]; + } else { + return null; + } + } + } + + + + /** + * ButtonAreaLayout behaves in a similar manner to + * FlowLayout. It lays out all components from left to + * right, flushed right. The widths of all components will be set + * to the largest preferred size width. + */ + private static class ButtonAreaLayout implements LayoutManager { + private int hGap = 5; + private int topMargin = 17; + + public void addLayoutComponent(String string, Component comp) { + } + + public void layoutContainer(Container container) { + Component[] children = container.getComponents(); + + if (children != null && children.length > 0) { + int numChildren = children.length; + Dimension[] sizes = new Dimension[numChildren]; + Insets insets = container.getInsets(); + int yLocation = insets.top + topMargin; + int maxWidth = 0; + + for (int counter = 0; counter < numChildren; counter++) { + sizes[counter] = children[counter].getPreferredSize(); + maxWidth = Math.max(maxWidth, sizes[counter].width); + } + int xLocation, xOffset; + if (container.getComponentOrientation().isLeftToRight()) { + xLocation = container.getSize().width - insets.left - maxWidth; + xOffset = hGap + maxWidth; + } else { + xLocation = insets.left; + xOffset = -(hGap + maxWidth); + } + for (int counter = numChildren - 1; counter >= 0; counter--) { + children[counter].setBounds(xLocation, yLocation, + maxWidth, sizes[counter].height); + xLocation -= xOffset; + } + } + } + + public Dimension minimumLayoutSize(Container c) { + if (c != null) { + Component[] children = c.getComponents(); + + if (children != null && children.length > 0) { + int numChildren = children.length; + int height = 0; + Insets cInsets = c.getInsets(); + int extraHeight = topMargin + cInsets.top + cInsets.bottom; + int extraWidth = cInsets.left + cInsets.right; + int maxWidth = 0; + + for (int counter = 0; counter < numChildren; counter++) { + Dimension aSize = children[counter].getPreferredSize(); + height = Math.max(height, aSize.height); + maxWidth = Math.max(maxWidth, aSize.width); + } + return new Dimension(extraWidth + numChildren * maxWidth + + (numChildren - 1) * hGap, + extraHeight + height); + } + } + return new Dimension(0, 0); + } + + public Dimension preferredLayoutSize(Container c) { + return minimumLayoutSize(c); + } + + public void removeLayoutComponent(Component c) { } + } + + private static void groupLabels(AlignedLabel[] group) { + for (int i = 0; i < group.length; i++) { + group[i].group = group; + } + } + + private class AlignedLabel extends JLabel { + private AlignedLabel[] group; + private int maxWidth = 0; + + AlignedLabel() { + super(); + setAlignmentX(JComponent.LEFT_ALIGNMENT); + } + + AlignedLabel(String text) { + super(text); + setAlignmentX(JComponent.LEFT_ALIGNMENT); + } + + public Dimension getPreferredSize() { + Dimension d = super.getPreferredSize(); + // Align the width with all other labels in group. + return new Dimension(getMaxWidth() + 11, d.height); + } + + private int getMaxWidth() { + if (maxWidth == 0 && group != null) { + int max = 0; + for (int i = 0; i < group.length; i++) { + max = Math.max(group[i].getSuperPreferredWidth(), max); + } + for (int i = 0; i < group.length; i++) { + group[i].maxWidth = max; + } + } + return maxWidth; + } + + private int getSuperPreferredWidth() { + return super.getPreferredSize().width; + } + } +}