/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
*/
/*
* @(#)WindowsFileChooserUI.java 1.82 08/09/23
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
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 javax.swing.table.*;
import javax.swing.text.Position;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.awt.shell.ShellFolder;
/**
* Windows L&F implementation of a FileChooser.
*
* @version 1.82 09/23/08
* @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 static final String[] OS_NAMES =
new String[] { "Windows 3.1", "Windows 95", "Windows NT",
"Windows 98", "Windows 2000", "Windows Me", "Windows XP" };
private static int WIN_31 = 0;
private static int WIN_95 = 1;
private static int WIN_NT = 2;
private static int WIN_98 = 3;
private static int WIN_2k = 4;
private static int WIN_Me = 5;
private static int WIN_XP = 6;
private static final int OS_LEVEL = getOsLevel();
private static int getOsLevel() {
String osName = System.getProperty("os.name");
if (osName.equals(OS_NAMES[WIN_98]) &&
System.getProperty("os.version").startsWith("4.9")) {
return WIN_Me;
}
int level = OS_NAMES.length;
while (level-- > 0)
if (osName.equals(OS_NAMES[level]))
return level;
return WIN_2k;
}
private JPanel centerPanel;
private JLabel lookInLabel;
private JComboBox directoryComboBox;
private DirectoryComboBoxModel directoryComboBoxModel;
private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();
private FilterComboBoxModel filterComboBoxModel;
private JTextField filenameTextField;
private ShortCutPanel shortCutPanel;
private JToggleButton listViewButton;
private JToggleButton detailsViewButton;
private JPanel listViewPanel;
private JPanel detailsViewPanel;
private JPanel currentViewPanel;
private FocusListener editorFocusListener = new FocusAdapter() {
public void focusLost(FocusEvent e) {
if (! e.isTemporary()) {
applyEdit();
}
}
};
private boolean smallIconsView = false;
private Border listViewBorder;
private boolean useShellFolder;
private ListSelectionModel listSelectionModel;
private JList list;
private JTable detailsTable;
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 hstrut25 = new Dimension(25, 1);
private static final Dimension vstrut1 = new Dimension(1, 1);
private static final Dimension vstrut4 = new Dimension(1, 4);
private static final Dimension vstrut5 = new Dimension(1, 5);
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);
private static final int COLUMN_FILENAME = 0;
private static final int COLUMN_FILESIZE = 1;
private static final int COLUMN_FILETYPE = 2;
private static final int COLUMN_FILEDATE = 3;
private static final int COLUMN_FILEATTR = 4;
private static final int COLUMN_COLCOUNT = 5;
private int[] COLUMN_WIDTHS = { 150, 75, 130, 130, 40 };
// 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 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 String fileNameHeaderText = null;
private String fileSizeHeaderText = null;
private String fileTypeHeaderText = null;
private String fileDateHeaderText = null;
private String fileAttrHeaderText = null;
private Action newFolderAction = new WindowsNewFolderAction();
private File newFolderFile;
private BasicFileView fileView = new WindowsFileView();
//
// 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();
}
public void installComponents(JFileChooser fc) {
FileSystemView fsv = fc.getFileSystemView();
XPStyle xp = XPStyle.getXP();
if (xp != null) {
listViewBorder = xp.getBorder("listview");
} else {
listViewBorder = new BevelBorder(BevelBorder.LOWERED,
UIManager.getColor("ToolBar.highlight"),
UIManager.getColor("ToolBar.background"),
UIManager.getColor("ToolBar.darkShadow"),
UIManager.getColor("ToolBar.shadow"));
}
fc.setBorder(new EmptyBorder(4, 10, 10, 10));
fc.setLayout(new BorderLayout(8, 8));
// ********************************* //
// **** Construct the top panel **** //
// ********************************* //
// Directory manipulation buttons
JToolBar topPanel = new JToolBar();
topPanel.setFloatable(false);
if (OS_LEVEL >= WIN_2k) {
topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
}
// Add the top panel to the fileChooser
fc.add(topPanel, BorderLayout.NORTH);
// ComboBox Label
lookInLabel = new JLabel(lookInLabelText);
lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
lookInLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
lookInLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT);
topPanel.add(Box.createRigidArea(new Dimension(14,0)));
topPanel.add(lookInLabel);
topPanel.add(Box.createRigidArea(new Dimension(29,0)));
// CurrentDir ComboBox
directoryComboBox = new JComboBox();
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 = 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);
upFolderButton.setFocusPainted(false);
topPanel.add(upFolderButton);
if (OS_LEVEL < WIN_2k) {
topPanel.add(Box.createRigidArea(hstrut10));
}
JButton b;
if (OS_LEVEL == WIN_98) {
// Desktop Button
File homeDir = fsv.getHomeDirectory();
String toolTipText = homeFolderToolTipText;
if (fsv.isRoot(homeDir)) {
toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop".
}
b = new JButton(getFileView(fc).getIcon(homeDir));
b.setToolTipText(toolTipText);
b.getAccessibleContext().setAccessibleName(toolTipText);
b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
b.setMargin(shrinkwrap);
b.setFocusPainted(false);
b.addActionListener(getGoHomeAction());
topPanel.add(b);
topPanel.add(Box.createRigidArea(hstrut10));
}
// New Directory Button
b = new JButton(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);
b.setFocusPainted(false);
topPanel.add(b);
if (OS_LEVEL < WIN_2k) {
topPanel.add(Box.createRigidArea(hstrut10));
}
// View button group
ButtonGroup viewButtonGroup = new ButtonGroup();
class ViewButtonListener implements ActionListener {
JFileChooser fc;
ViewButtonListener(JFileChooser fc) {
this.fc = fc;
}
public void actionPerformed(ActionEvent e) {
JToggleButton b = (JToggleButton)e.getSource();
JPanel oldViewPanel = currentViewPanel;
if (b == detailsViewButton) {
if (detailsViewPanel == null) {
detailsViewPanel = createDetailsView(fc);
detailsViewPanel.setPreferredSize(LIST_PREF_SIZE);
}
currentViewPanel = detailsViewPanel;
} else {
currentViewPanel = listViewPanel;
}
if (currentViewPanel != oldViewPanel) {
centerPanel.remove(oldViewPanel);
centerPanel.add(currentViewPanel, BorderLayout.CENTER);
centerPanel.revalidate();
centerPanel.repaint();
}
}
}
ViewButtonListener viewButtonListener = new ViewButtonListener(fc);
// List Button
listViewButton = new JToggleButton(listViewIcon);
listViewButton.setToolTipText(listViewButtonToolTipText);
listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName);
listViewButton.setFocusPainted(false);
listViewButton.setSelected(true);
listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
listViewButton.setMargin(shrinkwrap);
listViewButton.addActionListener(viewButtonListener);
topPanel.add(listViewButton);
viewButtonGroup.add(listViewButton);
// Details Button
detailsViewButton = new JToggleButton(detailsViewIcon);
detailsViewButton.setToolTipText(detailsViewButtonToolTipText);
detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName);
detailsViewButton.setFocusPainted(false);
detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
detailsViewButton.setMargin(shrinkwrap);
detailsViewButton.addActionListener(viewButtonListener);
topPanel.add(detailsViewButton);
viewButtonGroup.add(detailsViewButton);
updateUseShellFolder();
// ************************************** //
// ******* Add the directory pane ******* //
// ************************************** //
centerPanel = new JPanel(new BorderLayout());
listViewPanel = createList(fc);
listSelectionModel = list.getSelectionModel();
listViewPanel.setPreferredSize(LIST_PREF_SIZE);
centerPanel.add(listViewPanel, BorderLayout.CENTER);
currentViewPanel = listViewPanel;
centerPanel.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
JComponent accessory = fc.getAccessory();
if(accessory != null) {
getAccessoryPanel().add(accessory);
}
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));
JLabel fnl = new JLabel(fileNameLabelText);
fnl.setDisplayedMnemonic(fileNameLabelMnemonic);
fnl.setAlignmentY(0);
labelPanel.add(fnl);
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);
}
};
fnl.setLabelFor(filenameTextField);
filenameTextField.addFocusListener(
new FocusAdapter() {
public void focusGained(FocusEvent e) {
if (!getFileChooser().isMultiSelectionEnabled()) {
listSelectionModel.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(hstrut10));
// 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();
}
};
approveButton.setMnemonic(getApproveButtonMnemonic(fc));
approveButton.addActionListener(getApproveSelectionAction());
approveButton.setToolTipText(getApproveButtonToolTipText(fc));
getButtonPanel().add(Box.createRigidArea(vstrut4));
getButtonPanel().add(approveButton);
getButtonPanel().add(Box.createRigidArea(vstrut6));
cancelButton = new JButton(cancelButtonText) {
public Dimension getMaximumSize() {
return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
approveButton.getPreferredSize() : cancelButton.getPreferredSize();
}
};
cancelButton.setMnemonic(cancelButtonMnemonic);
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();
Boolean prop =
(Boolean)fc.getClientProperty("FileChooser.useShellFolder");
if (prop != null) {
useShellFolder = prop.booleanValue();
} else {
useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView());
}
if (OS_LEVEL >= WIN_2k) {
if (useShellFolder) {
if (shortCutPanel == null) {
shortCutPanel = new ShortCutPanel();
fc.add(shortCutPanel, BorderLayout.BEFORE_LINE_BEGINS);
}
} else {
if (shortCutPanel != null) {
fc.remove(shortCutPanel);
shortCutPanel = 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 = UIManager.getInt("FileChooser.lookInLabelMnemonic");
lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);
fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic");
fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);
filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic");
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);
fileNameHeaderText = UIManager.getString("FileChooser.fileNameHeaderText",l);
fileSizeHeaderText = UIManager.getString("FileChooser.fileSizeHeaderText",l);
fileTypeHeaderText = UIManager.getString("FileChooser.fileTypeHeaderText",l);
fileDateHeaderText = UIManager.getString("FileChooser.fileDateHeaderText",l);
fileAttrHeaderText = UIManager.getString("FileChooser.fileAttrHeaderText",l);
}
protected void installListeners(JFileChooser fc) {
super.installListeners(fc);
ActionMap actionMap = getActionMap();
SwingUtilities.replaceUIActionMap(fc, actionMap);
}
protected ActionMap getActionMap() {
return createActionMap();
}
protected ActionMap createActionMap() {
AbstractAction escAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (editFile != null) {
cancelEdit();
} else {
getFileChooser().cancelSelection();
}
}
public boolean isEnabled(){
return getFileChooser().isEnabled();
}
};
ActionMap map = new ActionMapUIResource();
map.put("approveSelection", getApproveSelectionAction());
map.put("cancelSelection", escAction);
map.put("Go Up", getChangeToParentDirectoryAction());
return map;
}
class ShortCutPanel extends JToolBar implements ActionListener {
JToggleButton[] buttons;
File[] files;
XPStyle xp = XPStyle.getXP();
final Dimension buttonSize = new Dimension(83, (xp != null) ? 69 : 54);
ShortCutPanel() {
super(JToolBar.VERTICAL);
setFloatable(false);
putClientProperty("JToolBar.isRollover", Boolean.TRUE);
if (xp != null) {
putClientProperty("XPStyle.subClass", "placesbar");
setBorder(new EmptyBorder(1, 1, 1, 1));
} else {
setBorder(listViewBorder);
}
Color bgColor = new Color(UIManager.getColor("ToolBar.shadow").getRGB());
setBackground(bgColor);
JFileChooser chooser = getFileChooser();
FileSystemView fsv = chooser.getFileSystemView();
files = (File[])ShellFolder.get("fileChooserShortcutPanelFolders");
buttons = new JToggleButton[files.length];
ButtonGroup buttonGroup = new ButtonGroup();
for (int i = 0; i < files.length; i++) {
if (fsv.isFileSystemRoot(files[i])) {
// Create special File wrapper for drive path
files[i] = fsv.createFileObject(files[i].getAbsolutePath());
}
String folderName = fsv.getSystemDisplayName(files[i]);
int index = folderName.lastIndexOf(File.separatorChar);
if (index >= 0 && index < folderName.length() - 1) {
folderName = folderName.substring(index + 1);
}
Icon icon = null;
if (files[i] instanceof ShellFolder) {
// We want a large icon, fsv only gives us a small.
ShellFolder sf = (ShellFolder)files[i];
icon = new ImageIcon(sf.getIcon(true), sf.getFolderType());
} else {
icon = fsv.getSystemIcon(files[i]);
}
buttons[i] = new JToggleButton(folderName, icon);
if (xp != null) {
buttons[i].setIconTextGap(2);
buttons[i].setMargin(new Insets(2, 2, 2, 2));
buttons[i].setText("<html><center>"+folderName+"</center></html>");
} else {
Color fgColor = new Color(UIManager.getColor("List.selectionForeground").getRGB());
buttons[i].setBackground(bgColor);
buttons[i].setForeground(fgColor);
}
buttons[i].setHorizontalTextPosition(JToggleButton.CENTER);
buttons[i].setVerticalTextPosition(JToggleButton.BOTTOM);
buttons[i].setAlignmentX(JComponent.CENTER_ALIGNMENT);
buttons[i].setPreferredSize(buttonSize);
buttons[i].setMaximumSize(buttonSize);
buttons[i].addActionListener(this);
add(buttons[i]);
if (i < files.length-1 && xp != null) {
add(Box.createRigidArea(vstrut1));
}
buttonGroup.add(buttons[i]);
}
doDirectoryChanged(chooser.getCurrentDirectory());
}
void doDirectoryChanged(File f) {
for (int i=0; i<buttons.length; i++) {
buttons[i].setSelected(files[i].equals(f));
}
}
public void actionPerformed(ActionEvent e) {
JToggleButton b = (JToggleButton)e.getSource();
for (int i=0; i<buttons.length; i++) {
if (b == buttons[i]) {
getFileChooser().setCurrentDirectory(files[i]);
break;
}
}
}
public Dimension getPreferredSize() {
Dimension min = super.getMinimumSize();
Dimension pref = super.getPreferredSize();
if (min.height > pref.height) {
pref = new Dimension(pref.width, min.height);
}
return pref;
}
} // class ShortCutPanel
private void updateListRowCount() {
if (smallIconsView) {
list.setVisibleRowCount(getModel().getSize() / 3);
} else {
list.setVisibleRowCount(-1);
}
}
protected JPanel createList(JFileChooser fc) {
JPanel p = new JPanel(new BorderLayout());
final JFileChooser fileChooser = fc;
list = new JList() {
public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
ListModel model = getModel();
int max = model.getSize();
if (prefix == null || startIndex < 0 || startIndex >= max) {
throw new IllegalArgumentException();
}
// start search from the next element before/after the selected element
boolean backwards = (bias == Position.Bias.Backward);
for (int i = startIndex; backwards ? i >= 0 : i < max; i += (backwards ? -1 : 1)) {
String filename = fileChooser.getName((File)model.getElementAt(i));
if (filename.regionMatches(true, 0, prefix, 0, prefix.length())) {
return i;
}
}
return -1;
}
};
list.setCellRenderer(new FileRenderer());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
updateListRowCount();
getModel().addListDataListener(new ListDataListener() {
public void intervalAdded(ListDataEvent e) {
updateListRowCount();
}
public void intervalRemoved(ListDataEvent e) {
updateListRowCount();
}
public void contentsChanged(ListDataEvent e) {
updateListRowCount();
}
});
if (fc.isMultiSelectionEnabled()) {
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
} else {
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
list.setModel(getModel());
list.addListSelectionListener(createListSelectionListener(fc));
list.addMouseListener(createDoubleClickListener(fc, list));
list.addMouseListener(createSingleClickListener(fc, list));
getModel().addListDataListener(new ListDataListener() {
public void contentsChanged(ListDataEvent e) {
// Update the selection after JList has been updated
new DelayedSelectionUpdater();
}
public void intervalAdded(ListDataEvent e) {
int i0 = e.getIndex0();
int i1 = e.getIndex1();
if (i0 == i1) {
File file = (File)getModel().getElementAt(i0);
if (file.equals(newFolderFile)) {
new DelayedSelectionUpdater(file);
newFolderFile = null;
}
}
}
public void intervalRemoved(ListDataEvent e) {
}
});
JScrollPane scrollpane = new JScrollPane(list);
XPStyle xp = XPStyle.getXP();
if (xp != null) {
Color bg = xp.getColor("listview.fillcolor", null);
if (bg != null) {
list.setBackground(bg);
}
}
if (listViewBorder != null) {
scrollpane.setBorder(listViewBorder);
}
p.add(scrollpane, BorderLayout.CENTER);
return p;
}
class DetailsTableModel extends AbstractTableModel implements ListDataListener {
String[] columnNames = {
fileNameHeaderText,
fileSizeHeaderText,
fileTypeHeaderText,
fileDateHeaderText,
fileAttrHeaderText
};
JFileChooser chooser;
ListModel listModel;
DetailsTableModel(JFileChooser fc) {
this.chooser = fc;
listModel = getModel();
listModel.addListDataListener(this);
}
public int getRowCount() {
return listModel.getSize();
}
public int getColumnCount() {
return COLUMN_COLCOUNT;
}
public String getColumnName(int column) {
return columnNames[column];
}
public Class getColumnClass(int column) {
switch (column) {
case COLUMN_FILENAME:
return File.class;
case COLUMN_FILEDATE:
return Date.class;
default:
return super.getColumnClass(column);
}
}
public Object getValueAt(int row, int col) {
// Note: It is very important to avoid getting info on drives, as
// this will trigger "No disk in A:" and similar dialogs.
//
// Use (f.exists() && !chooser.getFileSystemView().isFileSystemRoot(f)) to
// determine if it is safe to call methods directly on f.
File f = (File)listModel.getElementAt(row);
switch (col) {
case COLUMN_FILENAME:
return f;
case COLUMN_FILESIZE:
if (!f.exists() || f.isDirectory()) {
return null;
}
return (f.length() + 1023) / 1024 + "KiB";
case COLUMN_FILETYPE:
if (!f.exists()) {
return null;
}
return chooser.getFileSystemView().getSystemTypeDescription(f);
case COLUMN_FILEDATE:
if (!f.exists() || chooser.getFileSystemView().isFileSystemRoot(f)) {
return null;
}
long time = f.lastModified();
return (time == 0L) ? null : new Date(time);
case COLUMN_FILEATTR:
if (!f.exists() || chooser.getFileSystemView().isFileSystemRoot(f)) {
return null;
}
String attributes = "";
if (!f.canWrite()) {
attributes += "R";
}
if (f.isHidden()) {
attributes += "H";
}
return attributes;
}
return null;
}
public void setValueAt(Object value, int row, int col) {
if (col == COLUMN_FILENAME) {
JFileChooser chooser = getFileChooser();
File f = (File)getValueAt(row, col);
String oldDisplayName = chooser.getName(f);
String oldFileName = f.getName();
String newDisplayName = ((String)value).trim();
String newFileName;
if (!newDisplayName.equals(oldDisplayName)) {
newFileName = newDisplayName;
//Check if extension is hidden from user
int i1 = oldFileName.length();
int i2 = oldDisplayName.length();
if (i1 > i2 && oldFileName.charAt(i2) == '.') {
newFileName = newDisplayName + oldFileName.substring(i2);
}
// rename
FileSystemView fsv = chooser.getFileSystemView();
File f2 = fsv.createFileObject(f.getParentFile(), newFileName);
if (!f2.exists() && WindowsFileChooserUI.this.getModel().renameFile(f, f2)) {
if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
if (chooser.isMultiSelectionEnabled()) {
chooser.setSelectedFiles(new File[] { f2 });
} else {
chooser.setSelectedFile(f2);
}
} else {
//Could be because of delay in updating Desktop folder
//chooser.setSelectedFile(null);
}
} else {
// PENDING(jeff) - show a dialog indicating failure
}
}
}
}
public boolean isCellEditable(int row, int column) {
return (column == COLUMN_FILENAME);
}
public void contentsChanged(ListDataEvent e) {
fireTableDataChanged();
}
public void intervalAdded(ListDataEvent e) {
fireTableDataChanged();
}
public void intervalRemoved(ListDataEvent e) {
fireTableDataChanged();
}
}
class DetailsTableCellRenderer extends DefaultTableCellRenderer {
JFileChooser chooser;
DateFormat df;
DetailsTableCellRenderer(JFileChooser chooser) {
this.chooser = chooser;
df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT,
chooser.getLocale());
}
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, Math.min(width, this.getPreferredSize().width+4), height);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (column == COLUMN_FILESIZE || column == COLUMN_FILEATTR) {
setHorizontalAlignment(SwingConstants.TRAILING);
} else {
setHorizontalAlignment(SwingConstants.LEADING);
}
if (column == COLUMN_FILENAME && table.isRowSelected(row) && table.isFocusOwner()) {
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
super.setForeground(table.getForeground());
super.setBackground(table.getBackground());
}
setFont(table.getFont());
setValue(value);
return this;
}
public void setValue(Object value) {
setIcon(null);
if (value instanceof File) {
File file = (File)value;
String fileName = chooser.getName(file);
setText(fileName);
Icon icon = chooser.getIcon(file);
setIcon(icon);
} else if (value instanceof Date) {
setText((value == null) ? "" : df.format((Date)value));
} else {
super.setValue(value);
}
}
}
protected JPanel createDetailsView(JFileChooser fc) {
final JFileChooser chooser = fc;
JPanel p = new JPanel(new BorderLayout());
DetailsTableModel detailsTableModel = new DetailsTableModel(chooser);
detailsTable = new JTable(detailsTableModel) {
// Handle Escape key events here
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE && getCellEditor() == null) {
// We are not editing, forward to filechooser.
chooser.dispatchEvent(e);
return true;
}
return super.processKeyBinding(ks, e, condition, pressed);
}
};
detailsTable.setComponentOrientation(chooser.getComponentOrientation());
detailsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
detailsTable.setShowGrid(false);
detailsTable.setSelectionModel(listSelectionModel);
detailsTable.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
Font font = detailsTable.getFont();
detailsTable.setRowHeight(Math.max(font.getSize(), 19)+3);
TableColumnModel columnModel = detailsTable.getColumnModel();
TableColumn[] columns = new TableColumn[COLUMN_COLCOUNT];
for (int i = 0; i < COLUMN_COLCOUNT; i++) {
columns[i] = columnModel.getColumn(i);
columns[i].setPreferredWidth(COLUMN_WIDTHS[i]);
}
TableCellRenderer cellRenderer = new DetailsTableCellRenderer(chooser);
detailsTable.setDefaultRenderer(File.class, cellRenderer);
detailsTable.setDefaultRenderer(Date.class, cellRenderer);
detailsTable.setDefaultRenderer(Object.class, cellRenderer);
// Install cell editor for editing file name
final JTextField tf = new JTextField();
tf.addFocusListener(editorFocusListener);
columns[COLUMN_FILENAME].setCellEditor(new DefaultCellEditor(tf) {
public boolean isCellEditable(EventObject e) {
if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent)e;
int index = detailsTable.rowAtPoint(me.getPoint());
return (me.getClickCount() == 1 && detailsTable.isRowSelected(index));
}
return super.isCellEditable(e);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
Component comp = super.getTableCellEditorComponent(table, value, isSelected, row, column);
if (value instanceof File) {
tf.setText(chooser.getName((File)value));
tf.requestFocus();
tf.selectAll();
}
return comp;
}
});
JList fakeList = new JList(detailsTableModel.listModel) {
JTable table = detailsTable;
public int locationToIndex(Point location) {
return table.rowAtPoint(location);
}
public Rectangle getCellBounds(int index0, int index1) {
Rectangle r0 = table.getCellRect(index0, COLUMN_FILENAME, false);
Rectangle r1 = table.getCellRect(index1, COLUMN_FILENAME, false);
return r0.union(r1);
}
public Object getSelectedValue() {
return table.getValueAt(table.getSelectedRow(), COLUMN_FILENAME);
}
public Component add(Component comp) {
if (comp instanceof JTextField) {
return table.add(comp);
} else {
return super.add(comp);
}
}
public void repaint() {
if (table != null)
table.repaint();
}
public TransferHandler getTransferHandler() {
if (table != null) {
return table.getTransferHandler();
} else {
return super.getTransferHandler();
}
}
public void setTransferHandler(TransferHandler newHandler) {
if (table != null) {
table.setTransferHandler(newHandler);
} else {
super.setTransferHandler(newHandler);
}
}
public boolean getDragEnabled() {
if (table != null) {
return table.getDragEnabled();
} else {
return super.getDragEnabled();
}
}
public void setDragEnabled(boolean b) {
if (table != null) {
table.setDragEnabled(b);
} else {
super.setDragEnabled(b);
}
}
};
fakeList.setSelectionModel(listSelectionModel);
detailsTable.addMouseListener(createDoubleClickListener(chooser, fakeList));
//detailsTable.addMouseListener(createSingleClickListener(chooser, fakeList));
JScrollPane scrollpane = new JScrollPane(detailsTable);
scrollpane.setComponentOrientation(chooser.getComponentOrientation());
LookAndFeel.installColors(scrollpane.getViewport(), "Table.background", "Table.foreground");
scrollpane.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
JScrollPane sp = (JScrollPane)e.getComponent();
fixNameColumnWidth(sp.getViewport().getSize().width);
sp.removeComponentListener(this);
}
});
XPStyle xp = XPStyle.getXP();
if (xp != null) {
Color bg = xp.getColor("listview.fillcolor", null);
if (bg != null) {
list.setBackground(bg);
}
}
if (listViewBorder != null) {
scrollpane.setBorder(listViewBorder);
}
p.add(scrollpane, BorderLayout.CENTER);
return p;
}
private void fixNameColumnWidth(int viewWidth) {
TableColumn nameCol = detailsTable.getColumnModel().getColumn(COLUMN_FILENAME);
int tableWidth = detailsTable.getPreferredSize().width;
if (tableWidth < viewWidth) {
nameCol.setPreferredWidth(nameCol.getPreferredWidth() + viewWidth - tableWidth);
}
}
private class DelayedSelectionUpdater implements Runnable {
File editFile;
DelayedSelectionUpdater() {
this(null);
}
DelayedSelectionUpdater(File editFile) {
this.editFile = editFile;
SwingUtilities.invokeLater(this);
}
public void run() {
setFileSelected();
if (editFile != null) {
editFileName(getModel().indexOf(editFile));
editFile = null;
}
}
}
/**
* Creates a selection listener for the list of files and directories.
*
* @param fc a <code>JFileChooser</code>
* @return a <code>ListSelectionListener</code>
*/
public ListSelectionListener createListSelectionListener(JFileChooser fc) {
return new SelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
JFileChooser chooser = getFileChooser();
FileSystemView fsv = chooser.getFileSystemView();
JList list = (JList) e.getSource();
if (chooser.isMultiSelectionEnabled()) {
File[] files = null;
Object[] objects = list.getSelectedValues();
if (objects != null) {
if (objects.length == 1
&& ((File)objects[0]).isDirectory()
&& chooser.isTraversable(((File)objects[0]))
&& (chooser.getFileSelectionMode() == chooser.FILES_ONLY
|| !fsv.isFileSystem(((File)objects[0])))) {
setDirectorySelected(true);
setDirectory(((File)objects[0]));
} else {
files = new File[objects.length];
int j = 0;
for (int i = 0; i < objects.length; i++) {
File f = (File)objects[i];
boolean isDir = f.isDirectory();
boolean isFile = ShellFolder.disableFileChooserSpeedFix() ? f.isFile() : !isDir;
if ((chooser.isFileSelectionEnabled() && isFile)
|| (chooser.isDirectorySelectionEnabled()
&& fsv.isFileSystem(f)
&& isDir)) {
files[j++] = f;
}
}
if (j == 0) {
files = null;
} else if (j < objects.length) {
File[] tmpFiles = new File[j];
System.arraycopy(files, 0, tmpFiles, 0, j);
files = tmpFiles;
}
setDirectorySelected(false);
}
}
chooser.setSelectedFiles(files);
} else {
File file = (File)list.getSelectedValue();
if (file != null
&& file.isDirectory()
&& chooser.isTraversable(file)
&& (chooser.getFileSelectionMode() == chooser.FILES_ONLY
|| !fsv.isFileSystem(file))) {
setDirectorySelected(true);
setDirectory(file);
chooser.setSelectedFile(null);
} else {
setDirectorySelected(false);
if (file != null) {
chooser.setSelectedFile(file);
}
}
}
}
}
};
}
private MouseListener createSingleClickListener(JFileChooser fc, JList list) {
return new SingleClickListener(list);
}
int lastIndex = -1;
File editFile = null;
int editX = 20;
private int getEditIndex() {
return lastIndex;
}
private void setEditIndex(int i) {
lastIndex = i;
}
private void resetEditIndex() {
lastIndex = -1;
}
private void cancelEdit() {
if (editFile != null) {
editFile = null;
list.remove(editCell);
centerPanel.repaint();
} else if (detailsTable != null && detailsTable.isEditing()) {
detailsTable.getCellEditor().cancelCellEditing();
}
}
JTextField editCell = null;
private void editFileName(int index) {
ensureIndexIsVisible(index);
if (listViewPanel.isVisible()) {
editFile = (File)getModel().getElementAt(index);
Rectangle r = list.getCellBounds(index, index);
if (editCell == null) {
editCell = new JTextField();
editCell.addActionListener(new EditActionListener());
editCell.addFocusListener(editorFocusListener);
editCell.setNextFocusableComponent(list);
}
list.add(editCell);
editCell.setText(getFileChooser().getName(editFile));
if (list.getComponentOrientation().isLeftToRight()) {
editCell.setBounds(editX + r.x, r.y, r.width - editX, r.height);
} else {
editCell.setBounds(r.x, r.y, r.width - editX, r.height);
}
editCell.requestFocus();
editCell.selectAll();
} else if (detailsViewPanel.isVisible()) {
detailsTable.editCellAt(index, COLUMN_FILENAME);
}
}
protected class SingleClickListener extends MouseAdapter {
JList list;
public SingleClickListener(JList list) {
this.list = list;
}
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
if (e.getClickCount() == 1) {
JFileChooser fc = getFileChooser();
int index = list.locationToIndex(e.getPoint());
if ((!fc.isMultiSelectionEnabled() || fc.getSelectedFiles().length <= 1)
&& index >= 0 && list.isSelectedIndex(index)
&& getEditIndex() == index && editFile == null) {
editFileName(index);
} else {
if (index >= 0) {
setEditIndex(index);
} else {
resetEditIndex();
}
}
} else {
// on double click (open or drill down one directory) be
// sure to clear the edit index
resetEditIndex();
}
}
}
}
public Action getNewFolderAction() {
return newFolderAction;
}
/**
* Creates a new folder.
*/
protected class WindowsNewFolderAction extends NewFolderAction {
public void actionPerformed(ActionEvent e) {
JFileChooser fc = getFileChooser();
File oldFile = fc.getSelectedFile();
super.actionPerformed(e);
File newFile = fc.getSelectedFile();
if (newFile != null && !newFile.equals(oldFile) && newFile.isDirectory()) {
newFolderFile = newFile;
}
}
}
class EditActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
applyEdit();
}
}
private void applyEdit() {
if (editFile != null && editFile.exists()) {
JFileChooser chooser = getFileChooser();
String oldDisplayName = chooser.getName(editFile);
String oldFileName = editFile.getName();
String newDisplayName = editCell.getText().trim();
String newFileName;
if (!newDisplayName.equals(oldDisplayName)) {
newFileName = newDisplayName;
//Check if extension is hidden from user
int i1 = oldFileName.length();
int i2 = oldDisplayName.length();
if (i1 > i2 && oldFileName.charAt(i2) == '.') {
newFileName = newDisplayName + oldFileName.substring(i2);
}
// rename
FileSystemView fsv = chooser.getFileSystemView();
File f2 = fsv.createFileObject(editFile.getParentFile(), newFileName);
if (!f2.exists() && getModel().renameFile(editFile, f2)) {
if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
if (chooser.isMultiSelectionEnabled()) {
chooser.setSelectedFiles(new File[] { f2 });
} else {
chooser.setSelectedFile(f2);
}
} else {
//Could be because of delay in updating Desktop folder
//chooser.setSelectedFile(null);
}
} else {
// PENDING(jeff) - show a dialog indicating failure
}
}
}
if (detailsTable != null && detailsTable.isEditing()) {
detailsTable.getCellEditor().stopCellEditing();
}
cancelEdit();
}
protected class FileRenderer extends DefaultListCellRenderer {
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, Math.min(width, this.getPreferredSize().width+4), height);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected,
boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
File file = (File) value;
String fileName = getFileChooser().getName(file);
setText(fileName);
Icon icon = getFileChooser().getIcon(file);
setIcon(icon);
if(isSelected) {
// PENDING(jeff) - grab padding (4) below from defaults table.
editX = icon.getIconWidth() + 4;
}
return this;
}
}
public void uninstallUI(JComponent c) {
// Remove listeners
c.removePropertyChangeListener(filterComboBoxModel);
cancelButton.removeActionListener(getCancelSelectionAction());
approveButton.removeActionListener(getApproveSelectionAction());
filenameTextField.removeActionListener(getApproveSelectionAction());
super.uninstallUI(c);
}
/**
* Returns the preferred size of the specified
* <code>JFileChooser</code>.
* 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 <code>JFileChooser</code>
* @return a <code>Dimension</code> 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 <code>JFileChooser</code>.
*
* @param c a <code>JFileChooser</code>
* @return a <code>Dimension</code> specifying the minimum
* width and height of the file chooser
*/
public Dimension getMinimumSize(JComponent c) {
return MIN_SIZE;
}
/**
* Returns the maximum size of the <code>JFileChooser</code>.
*
* @param c a <code>JFileChooser</code>
* @return a <code>Dimension</code> specifying the maximum
* width and height of the file chooser
*/
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
void setFileSelected() {
if (getFileChooser().isMultiSelectionEnabled() && !isDirectorySelected()) {
File[] files = getFileChooser().getSelectedFiles(); // Should be selected
Object[] selectedObjects = list.getSelectedValues(); // Are actually selected
if (ShellFolder.disableFileChooserSpeedFix()) {
// Remove files that shouldn't be selected
for (int j = 0; j < selectedObjects.length; j++) {
boolean found = false;
for (int i = 0; i < files.length; i++) {
if (files[i].equals(selectedObjects[j])) {
found = true;
break;
}
}
if (!found) {
int index = getModel().indexOf(selectedObjects[j]);
if (index >= 0) {
listSelectionModel.removeSelectionInterval(index, index);
}
}
}
// Add files that should be selected
for (int i = 0; i < files.length; i++) {
boolean found = false;
for (int j = 0; j < selectedObjects.length; j++) {
if (files[i].equals(selectedObjects[j])) {
found = true;
break;
}
}
if (!found) {
int index = getModel().indexOf(files[i]);
if (index >= 0) {
listSelectionModel.addSelectionInterval(index, index);
}
}
}
} else {
listSelectionModel.setValueIsAdjusting(true);
try {
Arrays.sort(files);
Arrays.sort(selectedObjects);
int shouldIndex = 0;
int actuallyIndex = 0;
// Remove files that shouldn't be selected and add files which should be selected
// Note: Assume files are already sorted in compareTo order.
while (shouldIndex < files.length &&
actuallyIndex < selectedObjects.length) {
int comparison = files[shouldIndex].compareTo(selectedObjects[actuallyIndex]);
if (comparison < 0) {
int index = getModel().indexOf(files[shouldIndex]);
listSelectionModel.addSelectionInterval(index, index);
shouldIndex++;
} else if (comparison > 0) {
int index = getModel().indexOf(selectedObjects[actuallyIndex]);
listSelectionModel.removeSelectionInterval(index, index);
actuallyIndex++;
} else {
// Do nothing
shouldIndex++;
actuallyIndex++;
}
}
while (shouldIndex < files.length) {
int index = getModel().indexOf(files[shouldIndex]);
listSelectionModel.addSelectionInterval(index, index);
shouldIndex++;
}
while (actuallyIndex < selectedObjects.length) {
int index = getModel().indexOf(selectedObjects[actuallyIndex]);
listSelectionModel.removeSelectionInterval(index, index);
actuallyIndex++;
}
} finally {
listSelectionModel.setValueIsAdjusting(false);
}
}
} else {
JFileChooser chooser = getFileChooser();
File f = null;
if (isDirectorySelected()) {
f = getDirectory();
} else {
f = chooser.getSelectedFile();
}
int i;
if (f != null && (i = getModel().indexOf(f)) >= 0) {
listSelectionModel.setSelectionInterval(i, i);
ensureIndexIsVisible(i);
} else {
listSelectionModel.clearSelection();
}
}
}
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();
}
/* The following methods are used by the PropertyChange Listener */
private void doSelectedFileChanged(PropertyChangeEvent e) {
applyEdit();
File f = (File) e.getNewValue();
JFileChooser fc = getFileChooser();
if (f != null
&& ((fc.isFileSelectionEnabled() && !f.isDirectory())
|| (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {
setFileName(fileNameString(f));
setFileSelected();
}
}
private void doSelectedFilesChanged(PropertyChangeEvent e) {
applyEdit();
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));
setFileSelected();
}
}
private void doDirectoryChanged(PropertyChangeEvent e) {
JFileChooser fc = getFileChooser();
FileSystemView fsv = fc.getFileSystemView();
applyEdit();
resetEditIndex();
clearIconCache();
listSelectionModel.clearSelection();
ensureIndexIsVisible(0);
File currentDirectory = fc.getCurrentDirectory();
if (shortCutPanel != null) {
shortCutPanel.doDirectoryChanged(currentDirectory);
}
if(currentDirectory != null) {
directoryComboBoxModel.addItem(currentDirectory);
getNewFolderAction().setEnabled(currentDirectory.canWrite());
getChangeToParentDirectoryAction().setEnabled(!fsv.isRoot(currentDirectory));
if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
if (fsv.isFileSystem(currentDirectory)) {
setFileName(currentDirectory.getPath());
} else {
setFileName(null);
}
}
}
}
private void doFilterChanged(PropertyChangeEvent e) {
applyEdit();
resetEditIndex();
clearIconCache();
listSelectionModel.clearSelection();
}
private void doFileSelectionModeChanged(PropertyChangeEvent e) {
applyEdit();
resetEditIndex();
clearIconCache();
listSelectionModel.clearSelection();
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 doMultiSelectionChanged(PropertyChangeEvent e) {
if (getFileChooser().isMultiSelectionEnabled()) {
listSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
} else {
listSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listSelectionModel.clearSelection();
getFileChooser().setSelectedFiles(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.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
doMultiSelectionChanged(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.equals("componentOrientation")) {
ComponentOrientation o = (ComponentOrientation)e.getNewValue();
JFileChooser cc = (JFileChooser)e.getSource();
if (o != (ComponentOrientation)e.getOldValue()) {
cc.applyComponentOrientation(o);
}
if (detailsTable != null) {
detailsTable.setComponentOrientation(o);
detailsTable.getParent().getParent().setComponentOrientation(o);
}
} else if (s == "FileChooser.useShellFolder") {
updateUseShellFolder();
doDirectoryChanged(e);
} 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());
}
private void ensureIndexIsVisible(int i) {
if (i >= 0) {
list.ensureIndexIsVisible(i);
if (detailsTable != null) {
detailsTable.scrollRectToVisible(detailsTable.getCellRect(i, COLUMN_FILENAME, true));
}
}
}
public void ensureFileIsVisible(JFileChooser fc, File f) {
ensureIndexIsVisible(getModel().indexOf(f));
}
public void rescanCurrentDirectory(JFileChooser fc) {
getModel().validateFileCache();
}
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();
}
//
// 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;
}
directories.clear();
File[] baseFolders;
if (useShellFolder) {
baseFolders = (File[])AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return 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);
}
}
//
// 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);
setFileName(null);
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;
}
}
}
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;
}
}
}