/* * 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 java.security.AccessController; import java.security.PrivilegedAction; 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. * <p> * 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 = AccessController.doPrivileged(new PrivilegedAction<File[]>() { public File[] run() { return (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; } } } /** * <code>ButtonAreaLayout</code> behaves in a similar manner to * <code>FlowLayout</code>. 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; } } }