FilePane.java revision 241
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* <b>WARNING:</b> This class is an implementation detail and is only
* public so that it can be used by two packages. You should NOT consider
* this public API.
* <p>
* This component is intended to be used in a subclass of
* javax.swing.plaf.basic.BasicFileChooserUI. It realies heavily on the
* implementation of BasicFileChooserUI, and is intended to be API compatible
* with earlier implementations of MetalFileChooserUI and WindowsFileChooserUI.
*
* @author Leif Samuelsson
*/
// Constants for actions. These are used for the actions' ACTION_COMMAND_KEY
// and as keys in the action maps for FilePane and the corresponding UI classes
// "enums" for setViewType()
public static final int VIEWTYPE_LIST = 0;
public static final int VIEWTYPE_DETAILS = 1;
private static final int VIEWTYPE_COUNT = 2;
private int viewType = -1;
private JPanel currentViewPanel;
private String[] viewTypeActionNames;
private JPopupMenu contextMenu;
private String viewMenuLabelText;
private String refreshActionLabelText;
private String newFolderActionLabelText;
private String kiloByteString;
private String megaByteString;
private String gigaByteString;
private String renameErrorTitleText;
private String renameErrorText;
private String renameErrorFileExistsText;
private static final Cursor waitCursor =
private final long timeFactor;
private long lastTime = 1000L;
{
}
/**
* Moves the keyboard focus to the first element whose prefix matches
* the sequence of alphanumeric keys pressed by the user with delay
* less than value of <code>timeFactor</code>. Subsequent same key
* presses move the keyboard focus to the next object that starts with
* the same letter until another key is pressed, then it is treated
* as the prefix with appropriate number of the same letters followed
* by first typed another letter.
*/
return;
}
return;
}
if (startIndex < 0) {
startIndex = 0;
}
if (startIndex >= rowCount) {
}
char c = e.getKeyChar();
// Subsequent same key presses move the keyboard focus to the next
// object that starts with the same letter.
startIndex++;
} else {
typedString.append(c);
}
} else {
startIndex++;
typedString.append(c);
}
if (startIndex >= rowCount) {
startIndex = 0;
}
// Find next file
}
if (index >= 0) {
}
}
// Search element
return index;
}
}
return -1;
}
};
public void focusLost(FocusEvent e) {
if (! e.isTemporary()) {
applyEdit();
}
}
};
}
}
}
}
for (int i : indices) {
}
}
return;
}
}
};
private boolean smallIconsView = false;
private Border listViewBorder;
private Color listViewBackground;
private boolean listViewWindowsStyle;
private boolean readOnly;
private ListSelectionModel listSelectionModel;
private JTable detailsTable;
private static final int COLUMN_FILENAME = 0;
// Provides a way to recognize a newly created folder, so it can
// be selected when it appears in the model.
private File newFolderFile;
// Used for accessing methods in the corresponding UI class
private DetailsTableModel detailsTableModel;
private DetailsTableRowSorter rowSorter;
super(new BorderLayout());
}
public void uninstallUI() {
getModel().removePropertyChangeListener(this);
}
}
protected JFileChooser getFileChooser() {
return fileChooserUIAccessor.getFileChooser();
}
protected BasicDirectoryModel getModel() {
return fileChooserUIAccessor.getModel();
}
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
return;
}
switch (viewType) {
case VIEWTYPE_LIST:
if (p == null) {
p = createList();
}
setViewPanel(viewType, p);
}
break;
case VIEWTYPE_DETAILS:
if (p == null) {
p = createDetailsView();
}
setViewPanel(viewType, p);
}
break;
}
if (currentViewPanel != oldViewPanel) {
if (oldViewPanel != null) {
}
revalidate();
repaint();
}
}
class ViewTypeAction extends AbstractAction {
private int viewType;
ViewTypeAction(int viewType) {
super(viewTypeActionNames[viewType]);
switch (viewType) {
}
}
public void actionPerformed(ActionEvent e) {
}
}
return new ViewTypeAction(viewType);
}
if (container instanceof JComponent) {
}
int n = container.getComponentCount();
for (int i = 0; i < n; i++) {
}
}
switch (viewType) {
case VIEWTYPE_LIST:
if (listSelectionModel == null) {
if (detailsTable != null) {
}
} else {
}
break;
case VIEWTYPE_DETAILS:
if (listSelectionModel != null) {
}
break;
}
if (currentViewPanel != null) {
}
revalidate();
repaint();
}
}
protected void installDefaults() {
// TODO: On windows, get the following localized strings from the OS
}
/**
* Fetches the command list for the FilePane. These commands
* are useful for binding to events, such as in a keymap.
*
* @return the command list
*/
public Action[] getActions() {
class FilePaneAction extends AbstractAction {
}
super(name);
}
public void actionPerformed(ActionEvent e) {
if (cmd == ACTION_CANCEL) {
cancelEdit();
} else {
}
} else if (cmd == ACTION_EDIT_FILE_NAME) {
(!fc.isMultiSelectionEnabled() ||
}
} else if (cmd == ACTION_REFRESH) {
}
}
public boolean isEnabled() {
if (cmd == ACTION_CANCEL) {
return getFileChooser().isEnabled();
} else if (cmd == ACTION_EDIT_FILE_NAME) {
} else {
return true;
}
}
}
}
}
action = getNewFolderAction();
}
}
}
}
return actions;
}
protected void createActionMap() {
}
}
}
}
}
if (smallIconsView) {
} else {
}
}
public JPanel createList() {
throw new IllegalArgumentException();
}
return i;
}
}
return -1;
}
};
// 4835633 : tell BasicListUI that this is a file list
if (listViewWindowsStyle) {
}
public void intervalAdded(ListDataEvent e) {
}
public void intervalRemoved(ListDataEvent e) {
}
public void contentsChanged(ListDataEvent e) {
if (isShowing()) {
}
}
});
getModel().addPropertyChangeListener(this);
if (fileChooser.isMultiSelectionEnabled()) {
} else {
}
if (listViewBackground != null) {
}
if (listViewBorder != null) {
}
return p;
}
/**
* This model allows for sorting JList
*/
private class SortableListModel extends AbstractListModel
implements TableModelListener, RowSorterListener {
public SortableListModel() {
getRowSorter().addRowSorterListener(this);
}
public int getSize() {
}
// JList doesn't support RowSorter so far, so we put it into the list model
}
public void tableChanged(TableModelEvent e) {
}
public void sorterChanged(RowSorterEvent e) {
}
}
private DetailsTableModel getDetailsTableModel() {
if(detailsTableModel == null) {
}
return detailsTableModel;
}
int[] columnMap;
directoryModel = getModel();
}
void updateColumnInfo() {
try {
} catch (FileNotFoundException e) {
// Leave dir without changing
}
}
new ArrayList<ShellFolderColumnInfo>();
}
}
}
// check if preserved sortKeys are valid for this folder
break;
}
}
}
}
}
public int getRowCount() {
return directoryModel.getSize();
}
public int getColumnCount() {
}
// 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.
}
return (col == COLUMN_FILENAME)
? f // always return the file itself for the 1st column
}
if (col == COLUMN_FILENAME) {
if (f != null) {
//Check if extension is hidden from user
}
// rename
} else {
if (chooser.isMultiSelectionEnabled()) {
} else {
}
} else {
// Could be because of delay in updating Desktop folder
// chooser.setSelectedFile(null);
}
} else {
}
}
}
}
}
}
}
public void contentsChanged(ListDataEvent e) {
// Update the selection after the model has been updated
new DelayedSelectionUpdater();
}
public void intervalAdded(ListDataEvent e) {
new DelayedSelectionUpdater(file);
}
}
}
public void intervalRemoved(ListDataEvent e) {
}
public ShellFolderColumnInfo[] getColumns() {
return columns;
}
}
// the column must have a string resource that we try to get
}
}
// otherwise we let JTable to decide the actual width
}
}
// Install cell editor for editing file name
}
}
}
private DetailsTableRowSorter getRowSorter() {
rowSorter = new DetailsTableRowSorter();
}
return rowSorter;
}
private class DetailsTableRowSorter extends TableRowSorter {
public DetailsTableRowSorter() {
setModelWrapper(new SorterModelWrapper());
}
if (c != null) {
c = new DirectoriesFirstComparatorWrapper(i, c);
}
setComparator(i, c);
}
}
public void modelStructureChanged() {
super.modelStructureChanged();
}
private class SorterModelWrapper extends ModelWrapper {
return getDetailsTableModel();
}
public int getColumnCount() {
return getDetailsTableModel().getColumnCount();
}
public int getRowCount() {
return getDetailsTableModel().getRowCount();
}
}
return row;
}
}
}
/**
* This class sorts directories before files, comparing directory to
* directory and file to file using the wrapped comparator.
*/
private Comparator comparator;
private int column;
this.comparator = comparator;
}
// directories go first
if (traversable1 && !traversable2) {
return -1;
}
if (!traversable1 && traversable2) {
return 1;
}
}
return comparator.compare(
);
}
// For this column we need to pass the file itself (not a
// column value) to the comparator
}
}
private DetailsTableCellEditor tableCellEditor;
private DetailsTableCellEditor getDetailsTableCellEditor() {
if (tableCellEditor == null) {
}
return tableCellEditor;
}
private class DetailsTableCellEditor extends DefaultCellEditor {
private final JTextField tf;
super(tf);
}
}
return comp;
}
}
class DetailsTableCellRenderer extends DefaultTableCellRenderer {
}
// Restrict width to actual text
} else {
x -= 4;
}
}
// Provide some space between columns
i = super.getInsets(i);
i.left += 4;
i.right += 4;
return i;
}
isSelected = false;
}
}
// formatting cell text
// TODO: it's rather a temporary trick, to be revised
text = "";
if (listViewWindowsStyle) {
} else if (len < 1024L) {
} else {
len /= 1024L;
if (len < 1024L) {
} else {
len /= 1024L;
}
}
} else {
}
return this;
}
}
public JPanel createDetailsView() {
// Handle Escape key events here
// We are not editing, forward to filechooser.
chooser.dispatchEvent(e);
return true;
}
}
public void tableChanged(TableModelEvent e) {
super.tableChanged(e);
// update header with possibly changed column set
updateDetailsColumnModel(this);
}
}
};
detailsTable.setShowGrid(false);
// So that drag can be started on a mouse press
// No need to addListSelectionListener because selections are forwarded
// to our JList.
// 4835633 : tell BasicTableUI that this is a file list
if (listViewWindowsStyle) {
}
// We don't want them to navigate within the table
null);
null);
// Adjust width of first column so the table fills the viewport when
// first displayed (temporary listener).
public void componentResized(ComponentEvent e) {
sp.removeComponentListener(this);
}
});
// 4835633.
// If the mouse is pressed in the area below the Details view table, the
// event is not dispatched to the Table MouseListener but to the
// scrollpane. Listen for that here so we can clear the selection.
public void mousePressed(MouseEvent e) {
if (!e.isShiftDown() || table.getSelectionModel().getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) {
}
}
}
});
if (listViewBorder != null) {
}
return p;
} // createDetailsView
private class AlignableTableHeaderRenderer implements TableCellRenderer {
this.wrappedRenderer = wrappedRenderer;
}
}
if (c instanceof JLabel) {
}
return c;
}
}
private void fixNameColumnWidth(int viewWidth) {
if (tableWidth < viewWidth) {
}
}
private class DelayedSelectionUpdater implements Runnable {
this(null);
}
if (isShowing()) {
SwingUtilities.invokeLater(this);
}
}
public void run() {
}
}
}
/**
* Creates a selection listener for the list of files and directories.
*
* @return a <code>ListSelectionListener</code>
*/
public ListSelectionListener createListSelectionListener() {
}
int lastIndex = -1;
private int getEditIndex() {
return lastIndex;
}
private void setEditIndex(int i) {
lastIndex = i;
}
private void resetEditIndex() {
lastIndex = -1;
}
private void cancelEdit() {
repaint();
}
}
/**
* @param index visual index of the file to be edited
*/
private void editFileName(int index) {
return;
}
switch (viewType) {
case VIEWTYPE_LIST:
editCell = new JTextField();
}
// PENDING - grab padding (4) below from defaults table.
if (orientation.isLeftToRight()) {
} else {
}
break;
case VIEWTYPE_DETAILS:
break;
}
}
class EditActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
applyEdit();
}
}
private void applyEdit() {
//Check if extension is hidden from user
}
// rename
JOptionPane.showMessageDialog(chooser, MessageFormat.format(renameErrorFileExistsText, oldFileName),
} else {
if (chooser.isMultiSelectionEnabled()) {
} else {
}
} else {
//Could be because of delay in updating Desktop folder
//chooser.setSelectedFile(null);
}
} else {
}
}
}
}
}
cancelEdit();
}
protected Action newFolderAction;
public Action getNewFolderAction() {
private Action basicNewFolderAction;
// Initializer
{
if (currentDirectory != null) {
}
}
if (basicNewFolderAction == null) {
}
}
}
};
}
return newFolderAction;
}
protected class FileRenderer extends DefaultListCellRenderer {
int index, boolean isSelected,
boolean cellHasFocus) {
isSelected = false;
}
} else {
}
}
return this;
}
}
void setFileSelected() {
try {
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.
if (comparison < 0) {
} else if (comparison > 0) {
} else {
// Do nothing
shouldIndex++;
}
}
}
}
// restore the anchor and lead
if (listSelectionModel instanceof DefaultListSelectionModel) {
}
} finally {
}
} else {
File f;
if (isDirectorySelected()) {
f = getDirectory();
} else {
f = chooser.getSelectedFile();
}
int i;
} else {
}
}
}
// could be missed in the current directory if it changed
if (index >= 0) {
}
}
}
/* The following methods are used by the PropertyChange Listener */
private void doSelectedFileChanged(PropertyChangeEvent e) {
applyEdit();
if (f != null
}
}
private void doSelectedFilesChanged(PropertyChangeEvent e) {
applyEdit();
}
}
private void doDirectoryChanged(PropertyChangeEvent e) {
applyEdit();
if (currentDirectory != null) {
if (!readOnly) {
}
}
}
}
private void doFilterChanged(PropertyChangeEvent e) {
applyEdit();
}
private void doFileSelectionModeChanged(PropertyChangeEvent e) {
applyEdit();
}
private void doMultiSelectionChanged(PropertyChangeEvent e) {
if (getFileChooser().isMultiSelectionEnabled()) {
} else {
}
}
/*
* Listen for filechooser property changes, such as
* the selected file changing, or the type of the dialog changing.
*/
public void propertyChange(PropertyChangeEvent e) {
if (viewType == -1) {
}
String s = e.getPropertyName();
doFilterChanged(e);
applyEdit();
} else if (s.equals("busy")) {
} else if (s.equals("componentOrientation")) {
if (o != e.getOldValue()) {
}
if (detailsTable != null) {
}
}
}
private void ensureIndexIsVisible(int i) {
if (i >= 0) {
}
if (detailsTable != null) {
}
}
}
if (modelIndex >= 0) {
}
}
public void rescanCurrentDirectory() {
}
public void clearSelection() {
if (listSelectionModel != null) {
if (listSelectionModel instanceof DefaultListSelectionModel) {
}
}
}
public JMenu getViewMenu() {
for (int i = 0; i < VIEWTYPE_COUNT; i++) {
new JRadioButtonMenuItem(new ViewTypeAction(i));
}
}
return viewMenu;
}
private void updateViewMenu() {
if (comps[i] instanceof JRadioButtonMenuItem) {
mi.setSelected(true);
}
}
}
}
}
public JPopupMenu getComponentPopupMenu() {
return popupMenu;
}
if (contextMenu == null) {
contextMenu = new JPopupMenu();
if (listViewWindowsStyle) {
}
}
if (refreshAction != null) {
}
}
if (newFolderAction != null) {
}
}
}
return contextMenu;
}
protected Handler getMouseHandler() {
}
return handler;
}
private class Handler implements MouseListener {
private MouseListener doubleClickListener;
int index;
table.columnAtPoint(p), p)) {
return;
}
// Translate point from table to list
// Make a new event with the list as source, placing the
// click in the corresponding list cell.
evt.getXOnScreen(),
evt.getYOnScreen(),
}
} else {
return;
}
// For single click, we handle editing file name
} else {
if (index >= 0) {
} else {
}
}
// on double click (open or drill down one directory) be
// sure to clear the edit index
}
}
// Forward event to Basic
if (getDoubleClickListener() != null) {
}
}
}
}
// Forward event to Basic
if (getDoubleClickListener() != null) {
}
}
}
// Forward event to Basic
if (getDoubleClickListener() != null) {
}
}
}
// Forward event to Basic
if (getDoubleClickListener() != null) {
}
}
}
// Forward event to Basic
if (getDoubleClickListener() != null) {
}
}
}
private MouseListener getDoubleClickListener() {
// Lazy creation of Basic's listener
}
return doubleClickListener;
}
}
/**
* Property to remember whether a directory is currently selected in the UI.
*
* @return <code>true</code> iff a directory is currently selected.
*/
protected boolean isDirectorySelected() {
return fileChooserUIAccessor.isDirectorySelected();
}
/**
* Property to remember the directory that is currently selected in the UI.
*
* @return the value of the <code>directory</code> property
* @see javax.swing.plaf.basic.BasicFileChooserUI#setDirectory
*/
protected File getDirectory() {
return fileChooserUIAccessor.getDirectory();
}
int n = container.getComponentCount();
for (int i = 0; i < n; i++) {
return comp;
if (c != null) {
return c;
}
}
}
return null;
}
// Return false for non FileSystem files or if file doesn't exist.
if (!f.exists()) {
return false;
}
if (f instanceof ShellFolder) {
return ((ShellFolder) f).isFileSystem();
} else {
if (fileChooserUIAccessor.usesShellFolder()) {
try {
} catch (FileNotFoundException ex) {
// File doesn't exist
return false;
}
} else {
// Ordinary file
return true;
}
}
}
// This interface is used to access methods in the FileChooserUI
// that are not public.
public interface FileChooserUIAccessor {
public JFileChooser getFileChooser();
public BasicDirectoryModel getModel();
public JPanel createList();
public JPanel createDetailsView();
public boolean isDirectorySelected();
public File getDirectory();
public Action getApproveSelectionAction();
public Action getChangeToParentDirectoryAction();
public Action getNewFolderAction();
public boolean usesShellFolder();
}
}