/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.java.swing.plaf.windows;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.beans.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.awt.shell.ShellFolder;
import sun.swing.*;
import javax.accessibility.*;
/**
* Windows L&F implementation of a FileChooser.
*
* @author Jeff Dinkins
*/
public class WindowsFileChooserUI extends BasicFileChooserUI {
// The following are private because the implementation of the
// Windows FileChooser L&F is not complete yet.
private JPanel centerPanel;
private JLabel lookInLabel;
private JComboBox directoryComboBox;
private DirectoryComboBoxModel directoryComboBoxModel;
private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();
private FilterComboBoxModel filterComboBoxModel;
private JTextField filenameTextField;
private FilePane filePane;
private WindowsPlacesBar placesBar;
private JButton approveButton;
private JButton cancelButton;
private JPanel buttonPanel;
private JPanel bottomPanel;
private JComboBox filterComboBox;
private static final Dimension hstrut10 = new Dimension(10, 1);
private static final Dimension vstrut4 = new Dimension(1, 4);
private static final Dimension vstrut6 = new Dimension(1, 6);
private static final Dimension vstrut8 = new Dimension(1, 8);
private static final Insets shrinkwrap = new Insets(0,0,0,0);
// Preferred and Minimum sizes for the dialog box
private static int PREF_WIDTH = 425;
private static int PREF_HEIGHT = 245;
private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);
private static int MIN_WIDTH = 425;
private static int MIN_HEIGHT = 245;
private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);
private static int LIST_PREF_WIDTH = 444;
private static int LIST_PREF_HEIGHT = 138;
private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);
// 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 newFolderToolTipText = null;
private String newFolderAccessibleName = null;
private String viewMenuButtonToolTipText = null;
private String viewMenuButtonAccessibleName = null;
private BasicFileView fileView = new WindowsFileView();
private JLabel fileNameLabel;
private void populateFileNameLabel() {
if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
fileNameLabel.setText(folderNameLabelText);
fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic);
} else {
fileNameLabel.setText(fileNameLabelText);
fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);
}
}
//
// ComponentUI Interface Implementation methods
//
public static ComponentUI createUI(JComponent c) {
return new WindowsFileChooserUI((JFileChooser) c);
}
public WindowsFileChooserUI(JFileChooser filechooser) {
super(filechooser);
}
public void installUI(JComponent c) {
super.installUI(c);
}
public void uninstallComponents(JFileChooser fc) {
fc.removeAll();
}
private class WindowsFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {
public JFileChooser getFileChooser() {
return WindowsFileChooserUI.this.getFileChooser();
}
public BasicDirectoryModel getModel() {
return WindowsFileChooserUI.this.getModel();
}
public JPanel createList() {
return WindowsFileChooserUI.this.createList(getFileChooser());
}
public JPanel createDetailsView() {
return WindowsFileChooserUI.this.createDetailsView(getFileChooser());
}
public boolean isDirectorySelected() {
return WindowsFileChooserUI.this.isDirectorySelected();
}
public File getDirectory() {
return WindowsFileChooserUI.this.getDirectory();
}
public Action getChangeToParentDirectoryAction() {
return WindowsFileChooserUI.this.getChangeToParentDirectoryAction();
}
public Action getApproveSelectionAction() {
return WindowsFileChooserUI.this.getApproveSelectionAction();
}
public Action getNewFolderAction() {
return WindowsFileChooserUI.this.getNewFolderAction();
}
public MouseListener createDoubleClickListener(JList list) {
return WindowsFileChooserUI.this.createDoubleClickListener(getFileChooser(),
list);
}
public ListSelectionListener createListSelectionListener() {
return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser());
}
}
public void installComponents(JFileChooser fc) {
filePane = new FilePane(new WindowsFileChooserUIAccessor());
fc.addPropertyChangeListener(filePane);
FileSystemView fsv = fc.getFileSystemView();
fc.setBorder(new EmptyBorder(4, 10, 10, 10));
fc.setLayout(new BorderLayout(8, 8));
updateUseShellFolder();
// ********************************* //
// **** Construct the top panel **** //
// ********************************* //
// Directory manipulation buttons
JToolBar topPanel = new JToolBar();
topPanel.setFloatable(false);
topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
// Add the top panel to the fileChooser
fc.add(topPanel, BorderLayout.NORTH);
// ComboBox Label
lookInLabel = new JLabel(lookInLabelText, JLabel.TRAILING) {
public Dimension getPreferredSize() {
return getMinimumSize();
}
public Dimension getMinimumSize() {
Dimension d = super.getPreferredSize();
if (placesBar != null) {
d.width = Math.max(d.width, placesBar.getWidth());
}
return d;
}
};
lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
lookInLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
lookInLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT);
topPanel.add(lookInLabel);
topPanel.add(Box.createRigidArea(new Dimension(8,0)));
// CurrentDir ComboBox
directoryComboBox = new JComboBox() {
public Dimension getMinimumSize() {
Dimension d = super.getMinimumSize();
d.width = 60;
return d;
}
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
// Must be small enough to not affect total width.
d.width = 150;
return d;
}
};
directoryComboBox.putClientProperty( "JComboBox.lightweightKeyboardNavigation", "Lightweight" );
lookInLabel.setLabelFor(directoryComboBox);
directoryComboBoxModel = createDirectoryComboBoxModel(fc);
directoryComboBox.setModel(directoryComboBoxModel);
directoryComboBox.addActionListener(directoryComboBoxAction);
directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
directoryComboBox.setAlignmentY(JComponent.CENTER_ALIGNMENT);
directoryComboBox.setMaximumRowCount(8);
topPanel.add(directoryComboBox);
topPanel.add(Box.createRigidArea(hstrut10));
// Up Button
JButton upFolderButton = createToolButton(getChangeToParentDirectoryAction(), upFolderIcon,
upFolderToolTipText, upFolderAccessibleName);
topPanel.add(upFolderButton);
// New Directory Button
if (!UIManager.getBoolean("FileChooser.readOnly")) {
JButton newFolderButton = createToolButton(filePane.getNewFolderAction(), newFolderIcon,
newFolderToolTipText, newFolderAccessibleName);
topPanel.add(newFolderButton);
}
// View button group
ButtonGroup viewButtonGroup = new ButtonGroup();
// Popup Menu
final JPopupMenu viewTypePopupMenu = new JPopupMenu();
final JRadioButtonMenuItem listViewMenuItem = new JRadioButtonMenuItem(
filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));
listViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_LIST);
viewTypePopupMenu.add(listViewMenuItem);
viewButtonGroup.add(listViewMenuItem);
final JRadioButtonMenuItem detailsViewMenuItem = new JRadioButtonMenuItem(
filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));
detailsViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_DETAILS);
viewTypePopupMenu.add(detailsViewMenuItem);
viewButtonGroup.add(detailsViewMenuItem);
// Create icon for viewMenuButton
BufferedImage image = new BufferedImage(viewMenuIcon.getIconWidth() + 7, viewMenuIcon.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics graphics = image.getGraphics();
viewMenuIcon.paintIcon(filePane, graphics, 0, 0);
int x = image.getWidth() - 5;
int y = image.getHeight() / 2 - 1;
graphics.setColor(Color.BLACK);
graphics.fillPolygon(new int[]{x, x + 5, x + 2}, new int[]{y, y, y + 3}, 3);
// Details Button
final JButton viewMenuButton = createToolButton(null, new ImageIcon(image), viewMenuButtonToolTipText,
viewMenuButtonAccessibleName);
viewMenuButton.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && !viewMenuButton.isSelected()) {
viewMenuButton.setSelected(true);
viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight());
}
}
});
viewMenuButton.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
// Forbid keyboard actions if the button is not in rollover state
if (e.getKeyCode() == KeyEvent.VK_SPACE && viewMenuButton.getModel().isRollover()) {
viewMenuButton.setSelected(true);
viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight());
}
}
});
viewTypePopupMenu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
viewMenuButton.setSelected(false);
}
});
}
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
topPanel.add(viewMenuButton);
topPanel.add(Box.createRigidArea(new Dimension(80, 0)));
filePane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if ("viewType".equals(e.getPropertyName())) {
switch (filePane.getViewType()) {
case FilePane.VIEWTYPE_LIST:
listViewMenuItem.setSelected(true);
break;
case FilePane.VIEWTYPE_DETAILS:
detailsViewMenuItem.setSelected(true);
break;
}
}
}
});
// ************************************** //
// ******* Add the directory pane ******* //
// ************************************** //
centerPanel = new JPanel(new BorderLayout());
centerPanel.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
JComponent accessory = fc.getAccessory();
if(accessory != null) {
getAccessoryPanel().add(accessory);
}
filePane.setPreferredSize(LIST_PREF_SIZE);
centerPanel.add(filePane, BorderLayout.CENTER);
fc.add(centerPanel, BorderLayout.CENTER);
// ********************************** //
// **** Construct the bottom panel ** //
// ********************************** //
getBottomPanel().setLayout(new BoxLayout(getBottomPanel(), BoxLayout.LINE_AXIS));
// Add the bottom panel to file chooser
centerPanel.add(getBottomPanel(), BorderLayout.SOUTH);
// labels
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
labelPanel.add(Box.createRigidArea(vstrut4));
fileNameLabel = new JLabel();
populateFileNameLabel();
fileNameLabel.setAlignmentY(0);
labelPanel.add(fileNameLabel);
labelPanel.add(Box.createRigidArea(new Dimension(1,12)));
JLabel ftl = new JLabel(filesOfTypeLabelText);
ftl.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
labelPanel.add(ftl);
getBottomPanel().add(labelPanel);
getBottomPanel().add(Box.createRigidArea(new Dimension(15, 0)));
// file entry and filters
JPanel fileAndFilterPanel = new JPanel();
fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel, BoxLayout.Y_AXIS));
filenameTextField = new JTextField(35) {
public Dimension getMaximumSize() {
return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
}
};
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()));
}
fileAndFilterPanel.add(filenameTextField);
fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
filterComboBoxModel = createFilterComboBoxModel();
fc.addPropertyChangeListener(filterComboBoxModel);
filterComboBox = new JComboBox(filterComboBoxModel);
ftl.setLabelFor(filterComboBox);
filterComboBox.setRenderer(createFilterComboBoxRenderer());
fileAndFilterPanel.add(filterComboBox);
getBottomPanel().add(fileAndFilterPanel);
getBottomPanel().add(Box.createRigidArea(new Dimension(30, 0)));
// buttons
getButtonPanel().setLayout(new BoxLayout(getButtonPanel(), BoxLayout.Y_AXIS));
approveButton = new JButton(getApproveButtonText(fc)) {
public Dimension getMaximumSize() {
return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
approveButton.getPreferredSize() : cancelButton.getPreferredSize();
}
};
Insets buttonMargin = approveButton.getMargin();
buttonMargin = new InsetsUIResource(buttonMargin.top, buttonMargin.left + 5,
buttonMargin.bottom, buttonMargin.right + 5);
approveButton.setMargin(buttonMargin);
approveButton.setMnemonic(getApproveButtonMnemonic(fc));
approveButton.addActionListener(getApproveSelectionAction());
approveButton.setToolTipText(getApproveButtonToolTipText(fc));
getButtonPanel().add(Box.createRigidArea(vstrut6));
getButtonPanel().add(approveButton);
getButtonPanel().add(Box.createRigidArea(vstrut4));
cancelButton = new JButton(cancelButtonText) {
public Dimension getMaximumSize() {
return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
approveButton.getPreferredSize() : cancelButton.getPreferredSize();
}
};
cancelButton.setMargin(buttonMargin);
cancelButton.setToolTipText(cancelButtonToolTipText);
cancelButton.addActionListener(getCancelSelectionAction());
getButtonPanel().add(cancelButton);
if(fc.getControlButtonsAreShown()) {
addControlButtons();
}
}
private void updateUseShellFolder() {
// Decide whether to use the ShellFolder class to populate shortcut
// panel and combobox.
JFileChooser fc = getFileChooser();
if (FilePane.usesShellFolder(fc)) {
if (placesBar == null && !UIManager.getBoolean("FileChooser.noPlacesBar")) {
placesBar = new WindowsPlacesBar(fc, XPStyle.getXP() != null);
fc.add(placesBar, BorderLayout.BEFORE_LINE_BEGINS);
fc.addPropertyChangeListener(placesBar);
}
} else {
if (placesBar != null) {
fc.remove(placesBar);
fc.removePropertyChangeListener(placesBar);
placesBar = null;
}
}
}
protected JPanel getButtonPanel() {
if(buttonPanel == null) {
buttonPanel = new JPanel();
}
return buttonPanel;
}
protected JPanel getBottomPanel() {
if(bottomPanel == null) {
bottomPanel = new JPanel();
}
return bottomPanel;
}
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);
newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);
newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);
viewMenuButtonToolTipText = UIManager.getString("FileChooser.viewMenuButtonToolTipText",l);
viewMenuButtonAccessibleName = UIManager.getString("FileChooser.viewMenuButtonAccessibleName",l);
}
private Integer getMnemonic(String key, Locale l) {
return SwingUtilities2.getUIDefaultsInt(key, l);
}
protected void installListeners(JFileChooser fc) {
super.installListeners(fc);
ActionMap actionMap = getActionMap();
SwingUtilities.replaceUIActionMap(fc, actionMap);
}
protected ActionMap getActionMap() {
return createActionMap();
}
protected ActionMap createActionMap() {
ActionMap map = new ActionMapUIResource();
FilePane.addActionsToMap(map, filePane.getActions());
return map;
}
protected JPanel createList(JFileChooser fc) {
return filePane.createList();
}
protected JPanel createDetailsView(JFileChooser fc) {
return filePane.createDetailsView();
}
/**
* Creates a selection listener for the list of files and directories.
*
* @param fc a JFileChooser
* @return a ListSelectionListener
*/
public ListSelectionListener createListSelectionListener(JFileChooser fc) {
return super.createListSelectionListener(fc);
}
// Obsolete class, not used in this version.
protected class WindowsNewFolderAction extends NewFolderAction {
}
// Obsolete class, not used in this version.
protected class SingleClickListener extends MouseAdapter {
}
// Obsolete class, not used in this version.
protected class FileRenderer extends DefaultListCellRenderer {
}
public void uninstallUI(JComponent c) {
// Remove listeners
c.removePropertyChangeListener(filterComboBoxModel);
c.removePropertyChangeListener(filePane);
if (placesBar != null) {
c.removePropertyChangeListener(placesBar);
}
cancelButton.removeActionListener(getCancelSelectionAction());
approveButton.removeActionListener(getApproveSelectionAction());
filenameTextField.removeActionListener(getApproveSelectionAction());
if (filePane != null) {
filePane.uninstallUI();
filePane = null;
}
super.uninstallUI(c);
}
/**
* Returns the preferred size of the specified
* JFileChooser
.
* The preferred size is at least as large,
* in both height and width,
* as the preferred size recommended
* by the file chooser's layout manager.
*
* @param c a JFileChooser
* @return a Dimension
specifying the preferred
* width and height of the file chooser
*/
public Dimension getPreferredSize(JComponent c) {
int prefWidth = PREF_SIZE.width;
Dimension d = c.getLayout().preferredLayoutSize(c);
if (d != null) {
return new Dimension(d.width < prefWidth ? prefWidth : d.width,
d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height);
} else {
return new Dimension(prefWidth, PREF_SIZE.height);
}
}
/**
* Returns the minimum size of the JFileChooser
.
*
* @param c a JFileChooser
* @return a Dimension
specifying the minimum
* width and height of the file chooser
*/
public Dimension getMinimumSize(JComponent c) {
return MIN_SIZE;
}
/**
* Returns the maximum size of the JFileChooser
.
*
* @param c a JFileChooser
* @return a Dimension
specifying the maximum
* width and height of the file chooser
*/
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
private String fileNameString(File file) {
if (file == null) {
return null;
} else {
JFileChooser fc = getFileChooser();
if ((fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) ||
(fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystemRoot(file))){
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();
}
/* The following methods are used by the PropertyChange Listener */
private void doSelectedFileChanged(PropertyChangeEvent e) {
File f = (File) e.getNewValue();
JFileChooser fc = getFileChooser();
if (f != null
&& ((fc.isFileSelectionEnabled() && !f.isDirectory())
|| (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {
setFileName(fileNameString(f));
}
}
private void doSelectedFilesChanged(PropertyChangeEvent 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));
}
}
private void doDirectoryChanged(PropertyChangeEvent e) {
JFileChooser fc = getFileChooser();
FileSystemView fsv = fc.getFileSystemView();
clearIconCache();
File currentDirectory = fc.getCurrentDirectory();
if(currentDirectory != null) {
directoryComboBoxModel.addItem(currentDirectory);
if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
if (fsv.isFileSystem(currentDirectory)) {
setFileName(currentDirectory.getPath());
} else {
setFileName(null);
}
}
}
}
private void doFilterChanged(PropertyChangeEvent e) {
clearIconCache();
}
private void doFileSelectionModeChanged(PropertyChangeEvent e) {
if (fileNameLabel != null) {
populateFileNameLabel();
}
clearIconCache();
JFileChooser fc = getFileChooser();
File currentDirectory = fc.getCurrentDirectory();
if (currentDirectory != null
&& fc.isDirectorySelectionEnabled()
&& !fc.isFileSelectionEnabled()
&& fc.getFileSystemView().isFileSystem(currentDirectory)) {
setFileName(currentDirectory.getPath());
} else {
setFileName(null);
}
}
private 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);
}
}
}
private void doApproveButtonTextChanged(PropertyChangeEvent e) {
JFileChooser chooser = getFileChooser();
approveButton.setText(getApproveButtonText(chooser));
approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
}
private void doDialogTypeChanged(PropertyChangeEvent e) {
JFileChooser chooser = getFileChooser();
approveButton.setText(getApproveButtonText(chooser));
approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
lookInLabel.setText(saveInLabelText);
} else {
lookInLabel.setText(lookInLabelText);
}
}
private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {
approveButton.setMnemonic(getApproveButtonMnemonic(getFileChooser()));
}
private void doControlButtonsChanged(PropertyChangeEvent e) {
if(getFileChooser().getControlButtonsAreShown()) {
addControlButtons();
} else {
removeControlButtons();
}
}
/*
* Listen for filechooser property changes, such as
* the selected file changing, or the type of the dialog changing.
*/
public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String s = e.getPropertyName();
if(s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
doSelectedFileChanged(e);
} else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
doSelectedFilesChanged(e);
} else if(s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
doDirectoryChanged(e);
} else if(s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
doFilterChanged(e);
} else if(s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
doFileSelectionModeChanged(e);
} else if(s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
doAccessoryChanged(e);
} else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
doApproveButtonTextChanged(e);
} else if(s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
doDialogTypeChanged(e);
} else if(s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
doApproveButtonMnemonicChanged(e);
} else if(s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
doControlButtonsChanged(e);
} else if (s == "FileChooser.useShellFolder") {
updateUseShellFolder();
doDirectoryChanged(e);
} else if (s.equals("componentOrientation")) {
ComponentOrientation o = (ComponentOrientation)e.getNewValue();
JFileChooser cc = (JFileChooser)e.getSource();
if (o != e.getOldValue()) {
cc.applyComponentOrientation(o);
}
} else if (s.equals("ancestor")) {
if (e.getOldValue() == null && e.getNewValue() != null) {
// Ancestor was added, set initial focus
filenameTextField.selectAll();
filenameTextField.requestFocus();
}
}
}
};
}
protected void removeControlButtons() {
getBottomPanel().remove(getButtonPanel());
}
protected void addControlButtons() {
getBottomPanel().add(getButtonPanel());
}
public void ensureFileIsVisible(JFileChooser fc, File f) {
filePane.ensureFileIsVisible(fc, f);
}
public void rescanCurrentDirectory(JFileChooser fc) {
filePane.rescanCurrentDirectory();
}
public String getFileName() {
if(filenameTextField != null) {
return filenameTextField.getText();
} else {
return null;
}
}
public void setFileName(String filename) {
if(filenameTextField != null) {
filenameTextField.setText(filename);
}
}
/**
* Property to remember whether a directory is currently selected in the UI.
* This is normally called by the UI on a selection event.
*
* @param directorySelected if a directory is currently selected.
* @since 1.4
*/
protected void setDirectorySelected(boolean directorySelected) {
super.setDirectorySelected(directorySelected);
JFileChooser chooser = getFileChooser();
if(directorySelected) {
approveButton.setText(directoryOpenButtonText);
approveButton.setToolTipText(directoryOpenButtonToolTipText);
approveButton.setMnemonic(directoryOpenButtonMnemonic);
} else {
approveButton.setText(getApproveButtonText(chooser));
approveButton.setToolTipText(getApproveButtonToolTipText(chooser));
approveButton.setMnemonic(getApproveButtonMnemonic(chooser));
}
}
public String getDirectoryName() {
// PENDING(jeff) - get the name from the directory combobox
return null;
}
public void setDirectoryName(String dirname) {
// PENDING(jeff) - set the name in the directory combobox
}
protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
return new DirectoryComboBoxRenderer();
}
private static JButton createToolButton(Action a, Icon defaultIcon, String toolTipText, String accessibleName) {
final JButton result = new JButton(a);
result.setText(null);
result.setIcon(defaultIcon);
result.setToolTipText(toolTipText);
result.setRequestFocusEnabled(false);
result.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, accessibleName);
result.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, Boolean.TRUE);
result.setAlignmentX(JComponent.LEFT_ALIGNMENT);
result.setAlignmentY(JComponent.CENTER_ALIGNMENT);
result.setMargin(shrinkwrap);
result.setFocusPainted(false);
result.setModel(new DefaultButtonModel() {
public void setPressed(boolean b) {
// Forbid keyboard actions if the button is not in rollover state
if (!b || isRollover()) {
super.setPressed(b);
}
}
public void setRollover(boolean b) {
if (b && !isRollover()) {
// Reset other buttons
for (Component component : result.getParent().getComponents()) {
if (component instanceof JButton && component != result) {
((JButton) component).getModel().setRollover(false);
}
}
}
super.setRollover(b);
}
public void setSelected(boolean b) {
super.setSelected(b);
if (b) {
stateMask |= PRESSED | ARMED;
} else {
stateMask &= ~(PRESSED | ARMED);
}
}
});
result.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
result.getModel().setRollover(true);
}
public void focusLost(FocusEvent e) {
result.getModel().setRollover(false);
}
});
return result;
}
//
// 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 (c.getComponentOrientation().isLeftToRight()) {
icon.paintIcon(c, g, x+depth*space, y);
} else {
icon.paintIcon(c, g, x, y);
}
}
public int getIconWidth() {
return icon.getIconWidth() + depth*space;
}
public int getIconHeight() {
return icon.getIconHeight();
}
}
//
// 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.
*/
private void addItem(File directory) {
if(directory == null) {
return;
}
boolean useShellFolder = FilePane.usesShellFolder(chooser);
directories.clear();
File[] baseFolders;
if (useShellFolder) {
baseFolders = AccessController.doPrivileged(new PrivilegedAction() {
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;
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 = 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 = directories.get(i);
File parent = dir.getParentFile();
depths[i] = 0;
if (parent != null) {
for (int j = i-1; j >= 0; j--) {
if (parent.equals(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);
}
}
//
// 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 (FileFilter filter : filters) {
if (filter == 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;
}
}
}
public void valueChanged(ListSelectionEvent e) {
JFileChooser fc = getFileChooser();
File f = fc.getSelectedFile();
if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) {
setFileName(fileNameString(f));
}
}
/**
* Acts when DirectoryComboBox has changed the selected item.
*/
protected class DirectoryComboBoxAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
File f = (File)directoryComboBox.getSelectedItem();
getFileChooser().setCurrentDirectory(f);
}
}
protected JButton getApproveButton(JFileChooser fc) {
return approveButton;
}
public FileView getFileView(JFileChooser fc) {
return fileView;
}
// ***********************
// * FileView operations *
// ***********************
protected class WindowsFileView extends BasicFileView {
/* FileView type descriptions */
public Icon getIcon(File f) {
Icon icon = getCachedIcon(f);
if (icon != null) {
return icon;
}
if (f != null) {
icon = getFileChooser().getFileSystemView().getSystemIcon(f);
}
if (icon == null) {
icon = super.getIcon(f);
}
cacheIcon(f, icon);
return icon;
}
}
}