0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: /**
0019: * @author Anton Avtamonov, Sergey Burlak
0020: * @version $Revision$
0021: */package javax.swing.plaf.metal;
0022:
0023: import java.awt.BorderLayout;
0024: import java.awt.Component;
0025: import java.awt.Dimension;
0026: import java.awt.FlowLayout;
0027: import java.awt.Graphics;
0028: import java.awt.GridBagConstraints;
0029: import java.awt.GridBagLayout;
0030: import java.awt.GridLayout;
0031: import java.awt.Insets;
0032: import java.awt.KeyboardFocusManager;
0033: import java.awt.Rectangle;
0034: import java.awt.event.ActionEvent;
0035: import java.awt.event.ActionListener;
0036: import java.awt.event.FocusAdapter;
0037: import java.awt.event.FocusEvent;
0038: import java.awt.event.FocusListener;
0039: import java.awt.event.HierarchyEvent;
0040: import java.awt.event.HierarchyListener;
0041: import java.awt.event.KeyEvent;
0042: import java.awt.event.MouseAdapter;
0043: import java.awt.event.MouseEvent;
0044: import java.awt.event.MouseListener;
0045: import java.beans.PropertyChangeEvent;
0046: import java.beans.PropertyChangeListener;
0047: import java.io.File;
0048: import java.text.DateFormat;
0049: import java.util.ArrayList;
0050: import java.util.Arrays;
0051: import java.util.Date;
0052: import java.util.EventObject;
0053: import java.util.LinkedList;
0054: import java.util.List;
0055: import java.util.WeakHashMap;
0056:
0057: import javax.swing.AbstractAction;
0058: import javax.swing.AbstractListModel;
0059: import javax.swing.Action;
0060: import javax.swing.ActionMap;
0061: import javax.swing.BorderFactory;
0062: import javax.swing.Box;
0063: import javax.swing.ButtonGroup;
0064: import javax.swing.ComboBoxModel;
0065: import javax.swing.DefaultCellEditor;
0066: import javax.swing.DefaultListCellRenderer;
0067: import javax.swing.Icon;
0068: import javax.swing.JButton;
0069: import javax.swing.JComboBox;
0070: import javax.swing.JComponent;
0071: import javax.swing.JFileChooser;
0072: import javax.swing.JLabel;
0073: import javax.swing.JList;
0074: import javax.swing.JMenu;
0075: import javax.swing.JMenuItem;
0076: import javax.swing.JPanel;
0077: import javax.swing.JPopupMenu;
0078: import javax.swing.JRadioButtonMenuItem;
0079: import javax.swing.JScrollPane;
0080: import javax.swing.JTable;
0081: import javax.swing.JTextField;
0082: import javax.swing.JToggleButton;
0083: import javax.swing.KeyStroke;
0084: import javax.swing.ListSelectionModel;
0085: import javax.swing.SwingConstants;
0086: import javax.swing.SwingUtilities;
0087: import javax.swing.TransferHandler;
0088: import javax.swing.UIManager;
0089: import javax.swing.event.DocumentEvent;
0090: import javax.swing.event.DocumentListener;
0091: import javax.swing.event.ListDataEvent;
0092: import javax.swing.event.ListDataListener;
0093: import javax.swing.event.ListSelectionEvent;
0094: import javax.swing.event.ListSelectionListener;
0095: import javax.swing.filechooser.FileFilter;
0096: import javax.swing.filechooser.FileSystemView;
0097: import javax.swing.plaf.ActionMapUIResource;
0098: import javax.swing.plaf.ComponentUI;
0099: import javax.swing.plaf.basic.BasicFileChooserUI;
0100: import javax.swing.table.AbstractTableModel;
0101: import javax.swing.table.DefaultTableCellRenderer;
0102: import javax.swing.table.TableModel;
0103: import javax.swing.text.JTextComponent;
0104: import javax.swing.text.Position.Bias;
0105:
0106: import org.apache.harmony.x.swing.StringConstants;
0107: import org.apache.harmony.x.swing.Utilities;
0108:
0109: public class MetalFileChooserUI extends BasicFileChooserUI {
0110:
0111: protected class DirectoryComboBoxAction extends AbstractAction {
0112: public void actionPerformed(final ActionEvent e) {
0113: JComboBox source = (JComboBox) e.getSource();
0114: File selected = (File) source.getSelectedItem();
0115: getFileChooser().setCurrentDirectory(selected);
0116: }
0117: }
0118:
0119: protected class DirectoryComboBoxModel extends AbstractListModel
0120: implements ComboBoxModel {
0121: private final List files = new LinkedList();
0122: private final List predefinedStructure = new ArrayList();
0123: private Object selectedItem;
0124: private File currentDirectory;
0125:
0126: public DirectoryComboBoxModel() {
0127: setCurrentDirectory(getFileChooser().getCurrentDirectory());
0128: }
0129:
0130: public int getDepth(final int i) {
0131: if (i < 0 || i >= files.size()) {
0132: return 0;
0133: }
0134: File file = (File) files.get(i);
0135: int result = 0;
0136: while (file != null
0137: && !getFileChooser().getFileSystemView().isRoot(
0138: file)) {
0139: file = getFileChooser().getFileSystemView()
0140: .getParentDirectory(file);
0141: result++;
0142: }
0143:
0144: return result;
0145: }
0146:
0147: public void setSelectedItem(final Object selectedDirectory) {
0148: if (selectedItem != selectedDirectory) {
0149: selectedItem = selectedDirectory;
0150: fireContentsChanged(this , 0, files.size() - 1);
0151: }
0152: }
0153:
0154: public Object getSelectedItem() {
0155: return selectedItem;
0156: }
0157:
0158: public int getSize() {
0159: return files.size();
0160: }
0161:
0162: public Object getElementAt(final int index) {
0163: return files.get(index);
0164: }
0165:
0166: private void setCurrentDirectory(final File file) {
0167: createPredefinedStructure();
0168: if (currentDirectory != null
0169: && currentDirectory.equals(file)) {
0170: return;
0171: }
0172: files.clear();
0173: files.addAll(predefinedStructure);
0174:
0175: appendFileStructure(file, files);
0176: currentDirectory = file;
0177:
0178: rescanCurrentDirectory(getFileChooser());
0179: SwingUtilities.invokeLater(new Runnable() {
0180: public void run() {
0181: if (getModel() != null && getModel().getSize() > 0) {
0182: list.ensureIndexIsVisible(0);
0183: }
0184: }
0185: });
0186:
0187: setSelectedItem(file);
0188:
0189: setupListAnchor();
0190: }
0191:
0192: private void setupListAnchor() {
0193: ListSelectionModel selectionModel = getViewRepresentation()
0194: .getSelectionModel();
0195:
0196: int selectionAnchor = selectionModel
0197: .getLeadSelectionIndex();
0198: selectionModel.clearSelection();
0199: if (selectionAnchor >= 0
0200: && selectionAnchor < getModel().getSize()) {
0201: selectionModel.setAnchorSelectionIndex(selectionAnchor);
0202: selectionModel.setLeadSelectionIndex(selectionAnchor);
0203: }
0204: }
0205:
0206: private void appendFileStructure(final File file,
0207: final List target) {
0208: List appendFiles = new LinkedList();
0209: File curFile = file;
0210: while (curFile != null && !target.contains(curFile)) {
0211: appendFiles.add(0, curFile);
0212: curFile = getFileChooser().getFileSystemView()
0213: .getParentDirectory(curFile);
0214: }
0215: if (curFile != null) {
0216: target.addAll(target.indexOf(curFile) + 1, appendFiles);
0217: }
0218: }
0219:
0220: private void createPredefinedStructure() {
0221: predefinedStructure.clear();
0222: processRoots();
0223: appendFileStructure(getFileChooser().getFileSystemView()
0224: .getDefaultDirectory(), predefinedStructure);
0225: }
0226:
0227: private void processRoots() {
0228: FileSystemView fileSystemView = getFileChooser()
0229: .getFileSystemView();
0230: File[] roots = fileSystemView.getRoots();
0231: for (int i = 0; i < roots.length; i++) {
0232: predefinedStructure.add(roots[i]);
0233: File[] children = fileSystemView.getFiles(roots[i],
0234: false);
0235: if (children != null) {
0236: for (int j = 0; j < children.length; j++) {
0237: processRoot(children[j]);
0238: }
0239: }
0240: }
0241: }
0242:
0243: private void processRoot(final File root) {
0244: FileSystemView fileSystemView = getFileChooser()
0245: .getFileSystemView();
0246: if (!fileSystemView.isFileSystem(root)
0247: || fileSystemView.isFileSystemRoot(root)) {
0248: predefinedStructure.add(root);
0249: if (!fileSystemView.isFileSystemRoot(root)) {
0250: File[] children = fileSystemView.getFiles(root,
0251: false);
0252: if (files != null) {
0253: for (int i = 0; i < children.length; i++) {
0254: if (fileSystemView
0255: .isFileSystemRoot(children[i])) {
0256: predefinedStructure.add(children[i]);
0257: }
0258: }
0259: }
0260: }
0261: }
0262: }
0263: }
0264:
0265: protected class FileRenderer extends DefaultListCellRenderer {
0266: public Component getListCellRendererComponent(final JList list,
0267: final Object value, final int index,
0268: final boolean isSelected, final boolean cellHasFocus) {
0269:
0270: File renderingFile = (File) value;
0271: String displayValue = getFileChooser().getName(
0272: renderingFile);
0273:
0274: JLabel result = (JLabel) super
0275: .getListCellRendererComponent(list, displayValue,
0276: index, isSelected, cellHasFocus);
0277: result.setIcon(getFileChooser().getIcon(renderingFile));
0278:
0279: return result;
0280: }
0281: }
0282:
0283: protected class FilterComboBoxModel extends AbstractListModel
0284: implements ComboBoxModel, PropertyChangeListener {
0285: protected FileFilter[] filters = getFileChooser()
0286: .getChoosableFileFilters();
0287:
0288: private Object selectedFilter;
0289:
0290: protected FilterComboBoxModel() {
0291: getFileChooser().addPropertyChangeListener(this );
0292: }
0293:
0294: public void propertyChange(final PropertyChangeEvent e) {
0295: String changedProperty = e.getPropertyName();
0296: if (JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY
0297: .equals(changedProperty)) {
0298: filters = (FileFilter[]) e.getNewValue();
0299: fireContentsChanged(this , 0, filters.length - 1);
0300: } else if (JFileChooser.FILE_FILTER_CHANGED_PROPERTY
0301: .equals(changedProperty)) {
0302: setSelectedItem(e.getNewValue());
0303: if (!Arrays.asList(filters).contains(e.getNewValue())) {
0304: getFileChooser().addChoosableFileFilter(
0305: (FileFilter) e.getNewValue());
0306: }
0307: }
0308: }
0309:
0310: public void setSelectedItem(final Object filter) {
0311: selectedFilter = filter;
0312: getViewRepresentation().getSelectionModel()
0313: .clearSelection();
0314: fireContentsChanged(this , -1, -1);
0315: }
0316:
0317: public Object getSelectedItem() {
0318: if (selectedFilter == null && filters.length > 0) {
0319: selectedFilter = filters[0];
0320: }
0321: return selectedFilter;
0322: }
0323:
0324: public int getSize() {
0325: return filters.length;
0326: }
0327:
0328: public Object getElementAt(final int index) {
0329: return filters[index];
0330: }
0331: }
0332:
0333: public class FilterComboBoxRenderer extends DefaultListCellRenderer {
0334: public Component getListCellRendererComponent(final JList list,
0335: final Object value, final int index,
0336: final boolean isSelected, final boolean cellHasFocus) {
0337:
0338: Object displayableValue = value;
0339: if (value instanceof FileFilter) {
0340: FileFilter filter = (FileFilter) value;
0341: displayableValue = filter.getDescription();
0342: }
0343: return super .getListCellRendererComponent(list,
0344: displayableValue, index, isSelected, cellHasFocus);
0345: }
0346: }
0347:
0348: protected class SingleClickListener extends MouseAdapter {
0349: private class CellEditor extends JTextField {
0350: private final int editingIndex;
0351:
0352: public CellEditor(final int index) {
0353: editingIndex = index;
0354: installListeners();
0355: }
0356:
0357: public void configure() {
0358: Rectangle editorBounds = list.getCellBounds(
0359: editingIndex, editingIndex);
0360: if (list.getCellRenderer() != null) {
0361: JLabel renderer = (JLabel) list.getCellRenderer()
0362: .getListCellRendererComponent(
0363: list,
0364: list.getModel().getElementAt(
0365: editingIndex),
0366: editingIndex, true, true);
0367: String text = renderer.getText();
0368: setText(text);
0369: Icon icon = renderer.getIcon();
0370: if (icon != null) {
0371: int offset = icon.getIconWidth()
0372: + renderer.getIconTextGap();
0373: editorBounds.x += offset;
0374: editorBounds.width -= offset;
0375: }
0376: }
0377: setBounds(editorBounds);
0378: requestFocus();
0379: selectAll();
0380: }
0381:
0382: private void installListeners() {
0383: final FocusListener focusListener = new FocusAdapter() {
0384: public void focusLost(final FocusEvent e) {
0385: list.remove(CellEditor.this );
0386: list.requestFocus();
0387: updateListValue();
0388: }
0389: };
0390: addFocusListener(focusListener);
0391: registerKeyboardAction(new ActionListener() {
0392: public void actionPerformed(final ActionEvent e) {
0393: list.remove(CellEditor.this );
0394: }
0395: }, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
0396: JComponent.WHEN_FOCUSED);
0397: registerKeyboardAction(new ActionListener() {
0398: public void actionPerformed(final ActionEvent e) {
0399: removeFocusListener(focusListener);
0400: list.remove(CellEditor.this );
0401: list.requestFocus();
0402: }
0403: }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
0404: JComponent.WHEN_FOCUSED);
0405: }
0406:
0407: private void updateListValue() {
0408: File editingFile = (File) list.getModel().getElementAt(
0409: editingIndex);
0410: if (!Utilities.isEmptyString(getText())
0411: && !getText().equals(editingFile.getName())) {
0412: getModel().renameFile(
0413: editingFile,
0414: new File(editingFile.getParentFile(),
0415: getText()));
0416: }
0417: }
0418: }
0419:
0420: private JList list;
0421: private Object preSelectedValue;
0422:
0423: public SingleClickListener(final JList list) {
0424: this .list = list;
0425: }
0426:
0427: public void mouseClicked(final MouseEvent e) {
0428: if (e.getButton() != MouseEvent.BUTTON1) {
0429: return;
0430: }
0431: int clickIndex = list.getUI().locationToIndex(list,
0432: e.getPoint());
0433: if (clickIndex == -1 || e.getClickCount() != 1
0434: || list.getSelectedValues().length != 1) {
0435:
0436: preSelectedValue = null;
0437: return;
0438: }
0439:
0440: Object clickValue = list.getModel()
0441: .getElementAt(clickIndex);
0442: if (clickValue != preSelectedValue) {
0443: preSelectedValue = clickValue;
0444: return;
0445: }
0446:
0447: preSelectedValue = null;
0448: CellEditor editor = new CellEditor(clickIndex);
0449: list.add(editor);
0450: editor.configure();
0451: }
0452: }
0453:
0454: private class DetailedFileViewModel extends AbstractTableModel {
0455: private String[] columnNames;
0456:
0457: public int getRowCount() {
0458: return getModel().getSize();
0459: }
0460:
0461: public int getColumnCount() {
0462: return 5;
0463: }
0464:
0465: public Object getValueAt(final int rowIndex,
0466: final int columnIndex) {
0467: File file = (File) getModel().getElementAt(rowIndex);
0468: if (columnIndex == 0) {
0469: return file.getName();
0470: } else if (columnIndex == 1) {
0471: return file.isDirectory() ? null
0472: : getAdjustedFileSize(file);
0473: } else if (columnIndex == 2) {
0474: return getFileChooser().getTypeDescription(file);
0475: } else if (columnIndex == 3) {
0476: return getFileChooser().getFileSystemView().isDrive(
0477: file) ? null : new Date(file.lastModified());
0478: } else if (columnIndex == 4) {
0479: if (file.isDirectory()) {
0480: return null;
0481: }
0482: if (file.canWrite() && !file.isHidden()) {
0483: return null;
0484: } else {
0485: StringBuffer result = new StringBuffer();
0486: if (!file.canWrite()) {
0487: result.append("R");
0488: }
0489: if (file.isHidden()) {
0490: result.append("H");
0491: }
0492:
0493: return result.toString();
0494: }
0495: }
0496:
0497: return null;
0498: }
0499:
0500: public void setValueAt(final Object value, final int rowIndex,
0501: final int columnIndex) {
0502: File editingFile = (File) list.getModel().getElementAt(
0503: rowIndex);
0504: if (!Utilities.isEmptyString((String) value)
0505: && !value.equals(editingFile.getName())) {
0506: getModel().renameFile(
0507: editingFile,
0508: new File(editingFile.getParentFile(),
0509: (String) value));
0510: }
0511: }
0512:
0513: public Class getColumnClass(final int columnIndex) {
0514: if (columnIndex == 3) {
0515: return Date.class;
0516: }
0517: return String.class;
0518: }
0519:
0520: public boolean isCellEditable(final int rowIndex,
0521: final int columnIndex) {
0522: return columnIndex == 0;
0523: }
0524:
0525: public String getColumnName(final int column) {
0526: if (columnNames == null) {
0527: initColumnNames();
0528: }
0529: return columnNames[column];
0530: }
0531:
0532: private void initColumnNames() {
0533: columnNames = new String[5];
0534: columnNames[0] = UIManager
0535: .getString("FileChooser.fileNameHeaderText");
0536: columnNames[1] = UIManager
0537: .getString("FileChooser.fileSizeHeaderText");
0538: columnNames[2] = UIManager
0539: .getString("FileChooser.fileTypeHeaderText");
0540: columnNames[3] = UIManager
0541: .getString("FileChooser.fileDateHeaderText");
0542: columnNames[4] = UIManager
0543: .getString("FileChooser.fileAttrHeaderText");
0544: }
0545: }
0546:
0547: private class DirectoryComboBoxRenderer extends
0548: DefaultListCellRenderer {
0549: private WeakHashMap iconMap = new WeakHashMap();
0550:
0551: public Component getListCellRendererComponent(final JList list,
0552: final Object value, final int index,
0553: final boolean isSelected, final boolean cellHasFocus) {
0554:
0555: File renderingFile = (File) value;
0556: Object displayValue = getFileChooser().getName(
0557: renderingFile);
0558:
0559: JLabel result = (JLabel) super
0560: .getListCellRendererComponent(list, displayValue,
0561: index, isSelected, cellHasFocus);
0562: Icon icon;
0563: if (index == -1) {
0564: icon = getFileChooser().getIcon(renderingFile);
0565: } else {
0566: icon = (Icon) iconMap.get(value);
0567: if (icon == null) {
0568: icon = new IndentedIcon(getFileChooser().getIcon(
0569: renderingFile), directoryModel
0570: .getDepth(index));
0571: iconMap.put(value, icon);
0572: }
0573: }
0574: result.setIcon(icon);
0575:
0576: return result;
0577: }
0578: }
0579:
0580: private abstract class ChangeViewAction extends AbstractAction {
0581: protected void updateFileChooser() {
0582: if (isDetailedViewActivated) {
0583: detailedViewButton.setSelected(true);
0584: detailedViewItem.setSelected(true);
0585: } else {
0586: listViewButton.setSelected(true);
0587: listViewItem.setSelected(true);
0588: }
0589: getFileChooser().revalidate();
0590: getFileChooser().repaint();
0591: SwingUtilities.invokeLater(new Runnable() {
0592: public void run() {
0593: if (getViewRepresentation().getSelectedValue() != null) {
0594: getViewRepresentation().ensureIndexIsVisible(
0595: getModel().indexOf(
0596: getViewRepresentation()
0597: .getSelectedValue()));
0598: }
0599: }
0600: });
0601: }
0602: }
0603:
0604: private class ListViewAction extends ChangeViewAction {
0605: public ListViewAction() {
0606: putValue(AbstractAction.NAME, listViewButtonText);
0607: putValue(AbstractAction.SHORT_DESCRIPTION,
0608: listViewButtonToolTipText);
0609: putValue(AbstractAction.SMALL_ICON, listViewIcon);
0610: }
0611:
0612: public void actionPerformed(final ActionEvent e) {
0613: getFileChooser().remove(detailedView);
0614: getFileChooser().add(listView, BorderLayout.CENTER);
0615: isDetailedViewActivated = false;
0616: updateFileChooser();
0617: }
0618: }
0619:
0620: private class DetailedViewAction extends ChangeViewAction {
0621: public DetailedViewAction() {
0622: putValue(AbstractAction.NAME, detailedViewButtonText);
0623: putValue(AbstractAction.SHORT_DESCRIPTION,
0624: detailedViewButtonToolTipText);
0625: putValue(AbstractAction.SMALL_ICON, detailsViewIcon);
0626: }
0627:
0628: public void actionPerformed(final ActionEvent e) {
0629: getFileChooser().remove(listView);
0630: getFileChooser().add(detailedView, BorderLayout.CENTER);
0631: isDetailedViewActivated = true;
0632: updateFileChooser();
0633: }
0634: }
0635:
0636: private class OpenDirectoryAction extends AbstractAction {
0637: public OpenDirectoryAction() {
0638: putValue(AbstractAction.NAME, openButtonText);
0639: putValue(AbstractAction.SHORT_DESCRIPTION,
0640: openButtonToolTipText);
0641: }
0642:
0643: public void actionPerformed(final ActionEvent e) {
0644: File selectedDir = getViewRepresentation()
0645: .getSelectedValue();
0646: if (selectedDir == null) {
0647: selectedDir = translateFile(getFileName());
0648: }
0649: getFileChooser().setCurrentDirectory(selectedDir);
0650: }
0651: }
0652:
0653: private static class IndentedIcon implements Icon {
0654: private static final int INDENT_WIDTH = 10;
0655: private Icon icon;
0656: private int indent;
0657:
0658: public IndentedIcon(final Icon icon, final int indent) {
0659: this .icon = icon;
0660: this .indent = indent * INDENT_WIDTH;
0661: }
0662:
0663: public void paintIcon(final Component c, final Graphics g,
0664: final int x, final int y) {
0665: if (icon != null) {
0666: icon.paintIcon(c, g, c.getComponentOrientation()
0667: .isLeftToRight() ? x + indent : x, y);
0668: }
0669: }
0670:
0671: public int getIconWidth() {
0672: return indent + (icon != null ? icon.getIconWidth() : 0);
0673: }
0674:
0675: public int getIconHeight() {
0676: return icon != null ? icon.getIconHeight() : 1;
0677: }
0678: }
0679:
0680: private interface ViewRepresentation {
0681: public ListSelectionModel getSelectionModel();
0682:
0683: public File getSelectedValue();
0684:
0685: public Object[] getSelectedValues();
0686:
0687: public void setSelectedValue(Object value, boolean scroll);
0688:
0689: public void ensureIndexIsVisible(final int index);
0690: }
0691:
0692: private class DetailedRepresentation implements ViewRepresentation {
0693: public ListSelectionModel getSelectionModel() {
0694: return table.getSelectionModel();
0695: }
0696:
0697: public File getSelectedValue() {
0698: return (File) (table.getSelectedRow() >= 0 ? getModel()
0699: .getElementAt(table.getSelectedRow()) : null);
0700: }
0701:
0702: public Object[] getSelectedValues() {
0703: File[] result;
0704: if (table.getSelectedRow() != -1) {
0705: int[] selectedRows = table.getSelectedRows();
0706: result = new File[selectedRows.length];
0707: for (int i = 0; i < selectedRows.length; i++) {
0708: result[i] = (File) getModel().getElementAt(
0709: selectedRows[i]);
0710: }
0711: } else {
0712: result = new File[0];
0713: }
0714:
0715: return result;
0716: }
0717:
0718: public void setSelectedValue(final Object value,
0719: final boolean scroll) {
0720: int row = getModel().indexOf(value);
0721: if (row < 0) {
0722: return;
0723: }
0724: getSelectionModel().setSelectionInterval(row, row);
0725: if (scroll) {
0726: ensureIndexIsVisible(row);
0727: }
0728: }
0729:
0730: public void ensureIndexIsVisible(final int index) {
0731: Rectangle cellRect = table.getCellRect(index, 0, false);
0732: table.scrollRectToVisible(cellRect);
0733: }
0734: }
0735:
0736: private class ListRepresentation implements ViewRepresentation {
0737: public ListSelectionModel getSelectionModel() {
0738: return list.getSelectionModel();
0739: }
0740:
0741: public File getSelectedValue() {
0742: return (File) list.getSelectedValue();
0743: }
0744:
0745: public Object[] getSelectedValues() {
0746: return list.getSelectedValues();
0747: }
0748:
0749: public void setSelectedValue(final Object value,
0750: final boolean scroll) {
0751: list.setSelectedValue(value, scroll);
0752: }
0753:
0754: public void ensureIndexIsVisible(final int index) {
0755: list.ensureIndexIsVisible(index);
0756: }
0757: }
0758:
0759: private JPanel buttonPanel;
0760: private JPanel bottomPanel;
0761: private JLabel actionLabel;
0762: private JButton approveButton;
0763: private JList list;
0764: private JTable table;
0765: private JPanel listView;
0766: private JPanel detailedView;
0767: private DirectoryComboBoxModel directoryModel;
0768: private JTextField fileNameField;
0769: private Action approveSelectionAction;
0770: private Action openDirectoryAction;
0771:
0772: private Action listViewAction;
0773: private Action detailedViewAction;
0774: private boolean isDetailedViewActivated;
0775:
0776: private String listViewButtonText;
0777: private String listViewButtonToolTipText;
0778: private String detailedViewButtonText;
0779: private String detailedViewButtonToolTipText;
0780:
0781: private JMenuItem listViewItem;
0782: private JMenuItem detailedViewItem;
0783: private JToggleButton listViewButton;
0784: private JToggleButton detailedViewButton;
0785:
0786: private ViewRepresentation listViewRepresentation = new ListRepresentation();
0787: private ViewRepresentation detailedViewRepresentation = new DetailedRepresentation();
0788:
0789: public MetalFileChooserUI(final JFileChooser filechooser) {
0790: super (filechooser);
0791: buttonPanel = new JPanel(new BorderLayout());
0792: bottomPanel = new JPanel(new GridBagLayout());
0793: actionLabel = new JLabel();
0794: }
0795:
0796: public static ComponentUI createUI(final JComponent c) {
0797: return new MetalFileChooserUI((JFileChooser) c);
0798: }
0799:
0800: public void installUI(final JComponent c) {
0801: c.setLayout(new BorderLayout());
0802: super .installUI(c);
0803:
0804: openDirectoryAction = new OpenDirectoryAction();
0805: }
0806:
0807: public void uninstallUI(final JComponent c) {
0808: super .uninstallUI(c);
0809: c.setLayout(null);
0810: }
0811:
0812: public void installComponents(final JFileChooser fc) {
0813: super .installComponents(fc);
0814:
0815: listViewAction = new ListViewAction();
0816: detailedViewAction = new DetailedViewAction();
0817:
0818: approveSelectionAction = getApproveSelectionAction();
0819: approveButton = new JButton(approveSelectionAction);
0820:
0821: fc.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
0822:
0823: listView = createList(fc);
0824: detailedView = createDetailsView(fc);
0825:
0826: fc.add(listView, BorderLayout.CENTER);
0827: fc.add(createTopPanel(fc), BorderLayout.NORTH);
0828:
0829: JPanel southPanel = new JPanel(new BorderLayout());
0830: bottomPanel.setBorder(BorderFactory.createEmptyBorder(6, 0, 12,
0831: 0));
0832: southPanel.add(bottomPanel, BorderLayout.CENTER);
0833: fillBottomPanel();
0834:
0835: southPanel.add(buttonPanel, BorderLayout.SOUTH);
0836: addControlButtons();
0837: fc.add(southPanel, BorderLayout.SOUTH);
0838:
0839: JPopupMenu popupMenu = createPopupMenu();
0840: list.setComponentPopupMenu(popupMenu);
0841: table.setComponentPopupMenu(popupMenu);
0842:
0843: customizeFileChooserLabels(fc);
0844: }
0845:
0846: public void uninstallComponents(final JFileChooser fc) {
0847: super .uninstallComponents(fc);
0848: list.setTransferHandler(null);
0849: removeControlButtons();
0850: list.setComponentPopupMenu(null);
0851: table.setComponentPopupMenu(null);
0852: }
0853:
0854: public ListSelectionListener createListSelectionListener(
0855: final JFileChooser fc) {
0856: return new ListSelectionListener() {
0857: public void valueChanged(final ListSelectionEvent e) {
0858: MetalFileChooserUI.this .valueChanged(e);
0859: }
0860: };
0861: }
0862:
0863: public PropertyChangeListener createPropertyChangeListener(
0864: final JFileChooser fc) {
0865: return new PropertyChangeListener() {
0866: public void propertyChange(final PropertyChangeEvent event) {
0867: String changedProperty = event.getPropertyName();
0868: if (JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY
0869: .equals(changedProperty)
0870: || JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY
0871: .equals(changedProperty)) {
0872: customizeFileChooserLabels(fc);
0873: } else if (JFileChooser.DIRECTORY_CHANGED_PROPERTY
0874: .equals(changedProperty)) {
0875: File file = (File) event.getNewValue();
0876: directoryModel.setCurrentDirectory(file);
0877: getChangeToParentDirectoryAction().setEnabled(
0878: !getFileChooser().getFileSystemView()
0879: .isRoot(file));
0880: } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY
0881: .equals(changedProperty)) {
0882: File selectedFile = (File) event.getNewValue();
0883: if (selectedFile != null) {
0884: File parentDirectory = getFileChooser()
0885: .getFileSystemView()
0886: .getParentDirectory(selectedFile);
0887: if (parentDirectory != null) {
0888: directoryModel
0889: .setCurrentDirectory(parentDirectory);
0890: getViewRepresentation().setSelectedValue(
0891: selectedFile, true);
0892: }
0893: }
0894: if (selectedFile != null) {
0895: fileNameField.setText(fileToText(selectedFile));
0896: }
0897: } else if (JFileChooser.SELECTED_FILES_CHANGED_PROPERTY
0898: .equals(changedProperty)) {
0899: File[] selectedFiles = (File[]) event.getNewValue();
0900: if (Utilities.isEmptyArray(selectedFiles)) {
0901: return;
0902: }
0903:
0904: StringBuffer textSelection = new StringBuffer();
0905: if (selectedFiles.length == 1) {
0906: textSelection
0907: .append(fileToText(selectedFiles[0]));
0908: getViewRepresentation().setSelectedValue(
0909: selectedFiles[0], true);
0910: } else {
0911: if (!equals(getViewRepresentation()
0912: .getSelectedValues(), selectedFiles)) {
0913: updateListSelection(selectedFiles);
0914: }
0915:
0916: for (int i = 0; i < selectedFiles.length; i++) {
0917: if (textSelection.length() > 0) {
0918: textSelection.append(" ");
0919: }
0920: textSelection.append('\"').append(
0921: fileToText(selectedFiles[i]))
0922: .append('\"');
0923: }
0924: }
0925: fileNameField.setText(textSelection.toString());
0926: } else if (JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY
0927: .equals(changedProperty)) {
0928: getViewRepresentation()
0929: .getSelectionModel()
0930: .setSelectionMode(
0931: ((Boolean) event.getNewValue())
0932: .booleanValue() ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
0933: : ListSelectionModel.SINGLE_SELECTION);
0934: } else if (JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY
0935: .equals(changedProperty)) {
0936: if (((Integer) event.getNewValue()).intValue() == JFileChooser.DIRECTORIES_ONLY) {
0937: fileNameField
0938: .setText(fileToText(getFileChooser()
0939: .getCurrentDirectory()));
0940: }
0941: } else if (JFileChooser.ACCESSORY_CHANGED_PROPERTY
0942: .equals(changedProperty)) {
0943: final JComponent old = (JComponent) event
0944: .getOldValue();
0945:
0946: if (old != null) {
0947: getAccessoryPanel().remove(old);
0948: }
0949:
0950: getAccessoryPanel().add(
0951: (JComponent) event.getNewValue());
0952: } else if (StringConstants.TRANSFER_HANDLER_PROPERTY_NAME
0953: .equals(changedProperty)) {
0954: list.setTransferHandler((TransferHandler) event
0955: .getNewValue());
0956: table.setTransferHandler((TransferHandler) event
0957: .getNewValue());
0958: }
0959: }
0960:
0961: private String fileToText(final File file) {
0962: if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
0963: return file.getAbsolutePath();
0964: } else {
0965: return file.getName();
0966: }
0967: }
0968:
0969: private boolean equals(final Object[] files1,
0970: final Object[] files2) {
0971: if (files1.length != files2.length) {
0972: return false;
0973: }
0974:
0975: for (int i = 0; i < files1.length; i++) {
0976: if (!contains(files2, files1[i])) {
0977: return false;
0978: }
0979: }
0980:
0981: return true;
0982: }
0983:
0984: private boolean contains(final Object[] files,
0985: final Object file) {
0986: for (int i = 0; i < files.length; i++) {
0987: if (files[i].equals(file)) {
0988: return true;
0989: }
0990: }
0991:
0992: return false;
0993: }
0994: };
0995: }
0996:
0997: public Dimension getPreferredSize(final JComponent c) {
0998: return getFileChooser().getLayout().preferredLayoutSize(
0999: getFileChooser());
1000: }
1001:
1002: public Dimension getMinimumSize(final JComponent c) {
1003: return super .getMinimumSize(c);
1004: }
1005:
1006: public Dimension getMaximumSize(final JComponent c) {
1007: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
1008: }
1009:
1010: public void ensureFileIsVisible(final JFileChooser fc, final File f) {
1011: int index = getModel().indexOf(f);
1012: if (index != -1) {
1013: getViewRepresentation().ensureIndexIsVisible(index);
1014: }
1015: }
1016:
1017: public void rescanCurrentDirectory(final JFileChooser fc) {
1018: if (fc.isShowing()) {
1019: getModel().validateFileCache();
1020: }
1021: }
1022:
1023: public String getFileName() {
1024: return fileNameField.getText();
1025: }
1026:
1027: public void setFileName(final String fileName) {
1028: fileNameField.setText(fileName);
1029: }
1030:
1031: public String getDirectoryName() {
1032: return super .getDirectoryName();
1033: }
1034:
1035: public void setDirectoryName(final String name) {
1036: super .setDirectoryName(name);
1037: }
1038:
1039: public void valueChanged(final ListSelectionEvent e) {
1040: if (e.getValueIsAdjusting()) {
1041: return;
1042: }
1043:
1044: File selectedFile = getViewRepresentation().getSelectedValue();
1045: Object[] selectedValues = getViewRepresentation()
1046: .getSelectedValues();
1047:
1048: if (selectedValues.length == 1 && selectedFile.isDirectory()) {
1049: setDirectorySelected(true);
1050: setDirectory(selectedFile);
1051: } else {
1052: setDirectorySelected(false);
1053: setDirectory(null);
1054: }
1055:
1056: configureApproveButton(selectedFile, selectedValues.length == 1);
1057:
1058: if (getFileChooser().isMultiSelectionEnabled()) {
1059: List selectedFiles = new LinkedList();
1060: for (int i = 0; i < selectedValues.length; i++) {
1061: File currentFile = (File) selectedValues[i];
1062: if (isSelectableFile(currentFile)) {
1063: selectedFiles.add(currentFile);
1064: }
1065: }
1066: getFileChooser().setSelectedFiles(
1067: (File[]) selectedFiles
1068: .toArray(new File[selectedFiles.size()]));
1069: } else {
1070: if (selectedFile == null || !isSelectableFile(selectedFile)) {
1071: selectedFile = null;
1072: }
1073: getFileChooser().setSelectedFile(selectedFile);
1074: }
1075: }
1076:
1077: protected void setDirectorySelected(final boolean directorySelected) {
1078: super .setDirectorySelected(directorySelected);
1079: }
1080:
1081: protected JPanel getButtonPanel() {
1082: return buttonPanel;
1083: }
1084:
1085: protected JPanel getBottomPanel() {
1086: return bottomPanel;
1087: }
1088:
1089: protected void installStrings(final JFileChooser fc) {
1090: super .installStrings(fc);
1091: listViewButtonText = UIManager
1092: .getString("FileChooser.listViewButtonAccessibleName");
1093: listViewButtonToolTipText = UIManager
1094: .getString("FileChooser.listViewButtonToolTipText");
1095:
1096: detailedViewButtonText = UIManager
1097: .getString("FileChooser.detailsViewButtonAccessibleName");
1098: detailedViewButtonToolTipText = UIManager
1099: .getString("FileChooser.detailsViewButtonToolTipText");
1100: }
1101:
1102: protected void installListeners(final JFileChooser fc) {
1103: super .installListeners(fc);
1104: fc.addPropertyChangeListener(createPropertyChangeListener(fc));
1105:
1106: fc.getActionMap().put("Go Up", new AbstractAction() {
1107: public void actionPerformed(final ActionEvent e) {
1108: if (!(KeyboardFocusManager
1109: .getCurrentKeyboardFocusManager()
1110: .getFocusOwner() instanceof JTextComponent)) {
1111: getChangeToParentDirectoryAction().actionPerformed(
1112: e);
1113: }
1114: }
1115: });
1116: fc.getActionMap().put("approveSelection", new AbstractAction() {
1117: public void actionPerformed(final ActionEvent e) {
1118: approveButton.getAction().actionPerformed(e);
1119: }
1120: });
1121:
1122: fc.addHierarchyListener(new HierarchyListener() {
1123: public void hierarchyChanged(final HierarchyEvent e) {
1124: if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0
1125: && fc.isShowing()) {
1126: fileNameField.requestFocus();
1127: fileNameField.selectAll();
1128:
1129: rescanCurrentDirectory(getFileChooser());
1130: if (getFileChooser().isMultiSelectionEnabled()) {
1131: File[] selectedFiles = getFileChooser()
1132: .getSelectedFiles();
1133: if (selectedFiles.length > 0) {
1134: updateListSelection(selectedFiles);
1135: getViewRepresentation()
1136: .ensureIndexIsVisible(
1137: getModel()
1138: .indexOf(
1139: selectedFiles[selectedFiles.length - 1]));
1140: }
1141: } else {
1142: File selectedFile = getFileChooser()
1143: .getSelectedFile();
1144: if (selectedFile != null) {
1145: updateListSelection(new File[] { selectedFile });
1146: getViewRepresentation()
1147: .ensureIndexIsVisible(
1148: getModel().indexOf(
1149: selectedFile));
1150: }
1151: }
1152: directoryModel.setCurrentDirectory(getFileChooser()
1153: .getCurrentDirectory());
1154: }
1155: }
1156: });
1157:
1158: MouseListener showPopupListener = new MouseAdapter() {
1159: public void mousePressed(final MouseEvent e) {
1160: processPopupMenu(e);
1161: }
1162:
1163: public void mouseReleased(final MouseEvent e) {
1164: processPopupMenu(e);
1165: }
1166:
1167: private void processPopupMenu(final MouseEvent e) {
1168: if (!e.isPopupTrigger()) {
1169: return;
1170: }
1171:
1172: ((JComponent) e.getComponent()).getComponentPopupMenu()
1173: .show(e.getComponent(), e.getX(), e.getY());
1174: }
1175: };
1176: list.addMouseListener(showPopupListener);
1177: table.addMouseListener(showPopupListener);
1178: }
1179:
1180: protected ActionMap getActionMap() {
1181: return createActionMap();
1182: }
1183:
1184: protected ActionMap createActionMap() {
1185: ActionMap result = new ActionMapUIResource();
1186: result.put("approveSelection", getApproveSelectionAction());
1187: result.put("cancelSelection", getCancelSelectionAction());
1188: result.put("Go Up", getChangeToParentDirectoryAction());
1189:
1190: return result;
1191: }
1192:
1193: protected JPanel createList(final JFileChooser fc) {
1194: JPanel result = new JPanel(new BorderLayout());
1195: result.setPreferredSize(new Dimension(300, 200));
1196: result.setBorder(MetalBorders.getTextFieldBorder());
1197:
1198: list = new JList(getModel()) {
1199: public int getNextMatch(final String prefix,
1200: final int startIndex, final Bias bias) {
1201: return Utilities.getNextMatch(
1202: new Utilities.ListModelAccessor() {
1203: public Object getElementAt(final int index) {
1204: return ((File) getModel().getElementAt(
1205: index)).getName();
1206: }
1207:
1208: public int getSize() {
1209: return getModel().getSize();
1210: }
1211:
1212: }, prefix, startIndex, bias);
1213: }
1214: };
1215: list
1216: .setSelectionMode(fc.isMultiSelectionEnabled() ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1217: : ListSelectionModel.SINGLE_SELECTION);
1218: list.setLayoutOrientation(JList.VERTICAL_WRAP);
1219: list.setVisibleRowCount(-1);
1220: list.addListSelectionListener(createListSelectionListener(fc));
1221: result.add(new JScrollPane(list), BorderLayout.CENTER);
1222: result.add(getAccessoryPanel(), BorderLayout.LINE_END);
1223:
1224: list.setCellRenderer(new FileRenderer());
1225: list.addMouseListener(new SingleClickListener(list));
1226: list.addMouseListener(createDoubleClickListener(fc, list));
1227: list.setTransferHandler(fc.getTransferHandler());
1228:
1229: return result;
1230: }
1231:
1232: protected JPanel createDetailsView(final JFileChooser fc) {
1233: JPanel result = new JPanel(new BorderLayout());
1234: result.setPreferredSize(new Dimension(300, 200));
1235: result.setBorder(MetalBorders.getTextFieldBorder());
1236:
1237: TableModel model = new DetailedFileViewModel();
1238: table = new JTable(model) {
1239: protected void processKeyEvent(final KeyEvent event) {
1240: if (event.getKeyCode() == KeyEvent.VK_ENTER
1241: || event.getKeyCode() == KeyEvent.VK_ESCAPE) {
1242:
1243: KeyEvent fcEvent = new KeyEvent(getFileChooser(),
1244: event.getID(), event.getWhen(), event
1245: .getModifiers(),
1246: event.getKeyCode(), event.getKeyChar(),
1247: event.getKeyLocation());
1248: SwingUtilities.processKeyBindings(fcEvent);
1249: return;
1250: }
1251:
1252: super .processKeyEvent(event);
1253: }
1254: };
1255: table.setShowGrid(false);
1256: table.setSelectionModel(list.getSelectionModel());
1257: result.add(new JScrollPane(table), BorderLayout.CENTER);
1258: result.add(getAccessoryPanel(), BorderLayout.LINE_END);
1259:
1260: table.setFocusTraversalKeys(
1261: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
1262: table.setFocusTraversalKeys(
1263: KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
1264:
1265: table.getColumnModel().getColumn(0).setPreferredWidth(150);
1266: table.getColumnModel().getColumn(1).setPreferredWidth(30);
1267: table.getColumnModel().getColumn(2).setPreferredWidth(50);
1268: table.getColumnModel().getColumn(3).setPreferredWidth(50);
1269: table.getColumnModel().getColumn(4).setPreferredWidth(20);
1270:
1271: table.getColumn(model.getColumnName(0)).setCellRenderer(
1272: new DefaultTableCellRenderer() {
1273: public Component getTableCellRendererComponent(
1274: final JTable table, final Object value,
1275: final boolean isSelected,
1276: final boolean hasFocus, final int row,
1277: final int column) {
1278:
1279: File renderingFile = (File) getModel()
1280: .getElementAt(row);
1281: String displayValue = getFileChooser().getName(
1282: renderingFile);
1283:
1284: JLabel result = (JLabel) super
1285: .getTableCellRendererComponent(table,
1286: displayValue, isSelected,
1287: hasFocus, row, column);
1288: result.setIcon(getFileChooser().getIcon(
1289: renderingFile));
1290:
1291: return result;
1292: }
1293: });
1294: table.getColumn(model.getColumnName(1)).setCellRenderer(
1295: new DefaultTableCellRenderer() {
1296: public Component getTableCellRendererComponent(
1297: final JTable table, final Object value,
1298: final boolean isSelected,
1299: final boolean hasFocus, final int row,
1300: final int column) {
1301:
1302: JLabel result = (JLabel) super
1303: .getTableCellRendererComponent(table,
1304: value, isSelected, hasFocus,
1305: row, column);
1306: result
1307: .setHorizontalAlignment(SwingConstants.RIGHT);
1308: return result;
1309: }
1310: });
1311: table.getColumn(model.getColumnName(3)).setCellRenderer(
1312: new DefaultTableCellRenderer() {
1313: public Component getTableCellRendererComponent(
1314: final JTable table, final Object value,
1315: final boolean isSelected,
1316: final boolean hasFocus, final int row,
1317: final int column) {
1318:
1319: Date date = (Date) value;
1320: if (date != null) {
1321: JLabel result = (JLabel) super
1322: .getTableCellRendererComponent(
1323: table,
1324: DateFormat
1325: .getDateTimeInstance()
1326: .format(date),
1327: isSelected, hasFocus, row,
1328: column);
1329: result
1330: .setHorizontalAlignment(SwingConstants.RIGHT);
1331: return result;
1332: }
1333: return super .getTableCellRendererComponent(
1334: table, value, isSelected, hasFocus,
1335: row, column);
1336: }
1337: });
1338: table.setDefaultEditor(String.class, new DefaultCellEditor(
1339: new JTextField()) {
1340: public boolean isCellEditable(final EventObject event) {
1341: return event == null;
1342: }
1343: });
1344:
1345: getModel().addListDataListener(new ListDataListener() {
1346: public void intervalAdded(final ListDataEvent e) {
1347: fireTableChanged();
1348: }
1349:
1350: public void intervalRemoved(final ListDataEvent e) {
1351: fireTableChanged();
1352: }
1353:
1354: public void contentsChanged(final ListDataEvent e) {
1355: fireTableChanged();
1356: }
1357:
1358: private void fireTableChanged() {
1359: if (isDetailedViewActivated) {
1360: ((AbstractTableModel) table.getModel())
1361: .fireTableDataChanged();
1362: }
1363: }
1364: });
1365:
1366: table.addMouseListener(new MouseAdapter() {
1367: public void mouseClicked(final MouseEvent e) {
1368: if (e.getButton() != MouseEvent.BUTTON1) {
1369: return;
1370: }
1371:
1372: if (e.getClickCount() != 2) {
1373: return;
1374: }
1375: File file = getViewRepresentation().getSelectedValue();
1376: if (file != null && file.isDirectory()) {
1377: getFileChooser().setCurrentDirectory(file);
1378: return;
1379: }
1380:
1381: approveSelectionAction.actionPerformed(null);
1382: }
1383: });
1384:
1385: return result;
1386: }
1387:
1388: protected void addControlButtons() {
1389: JPanel alignPanel = new JPanel(new GridLayout(1, 2, 6, 0));
1390: buttonPanel.add(alignPanel, BorderLayout.LINE_END);
1391: alignPanel.add(approveButton);
1392:
1393: JButton cancelButton = new JButton(getCancelSelectionAction());
1394: cancelButton.setText(UIManager
1395: .getString("FileChooser.cancelButtonText"));
1396: alignPanel.add(cancelButton);
1397: }
1398:
1399: protected void removeControlButtons() {
1400: buttonPanel.removeAll();
1401: }
1402:
1403: protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
1404: final JFileChooser fc) {
1405: return new DirectoryComboBoxRenderer();
1406: }
1407:
1408: protected DirectoryComboBoxModel createDirectoryComboBoxModel(
1409: final JFileChooser fc) {
1410: return new DirectoryComboBoxModel();
1411: }
1412:
1413: protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
1414: return new FilterComboBoxRenderer();
1415: }
1416:
1417: protected FilterComboBoxModel createFilterComboBoxModel() {
1418: return new FilterComboBoxModel();
1419: }
1420:
1421: protected JButton getApproveButton(final JFileChooser fc) {
1422: return approveButton;
1423: }
1424:
1425: private void customizeFileChooserLabels(final JFileChooser fc) {
1426: if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
1427: actionLabel.setText(UIManager
1428: .getString("FileChooser.saveInLabelText"));
1429: } else {
1430: actionLabel.setText(UIManager
1431: .getString("FileChooser.lookInLabelText"));
1432: }
1433: }
1434:
1435: private void fillBottomPanel() {
1436: GridBagConstraints c = new GridBagConstraints();
1437:
1438: c.fill = GridBagConstraints.BOTH;
1439:
1440: c.insets = new Insets(0, 0, 6, 0);
1441: c.gridwidth = 1;
1442: c.weightx = 0.0;
1443: JLabel fileNameLabel = new JLabel(UIManager
1444: .getString("FileChooser.fileNameLabelText"));
1445: fileNameLabel.setDisplayedMnemonic(UIManager
1446: .getInt("FileChooser.fileNameLabelMnemonic"));
1447: bottomPanel.add(fileNameLabel, c);
1448: bottomPanel.add(Box.createHorizontalStrut(6), c);
1449:
1450: c.weightx = 1.0;
1451: c.gridwidth = 1;
1452: c.gridwidth = GridBagConstraints.REMAINDER;
1453: fileNameField = new JTextField();
1454:
1455: fileNameLabel.setLabelFor(fileNameField);
1456:
1457: fileNameField.getDocument().addDocumentListener(
1458: new DocumentListener() {
1459: public void insertUpdate(final DocumentEvent e) {
1460: onChange();
1461: }
1462:
1463: public void removeUpdate(final DocumentEvent e) {
1464: onChange();
1465: }
1466:
1467: public void changedUpdate(final DocumentEvent e) {
1468: onChange();
1469: }
1470:
1471: private void onChange() {
1472: configureApproveButton(
1473: translateFile(fileNameField.getText()),
1474: true);
1475: }
1476: });
1477: fileNameField.addFocusListener(new FocusAdapter() {
1478: public void focusGained(final FocusEvent e) {
1479: getViewRepresentation().getSelectionModel()
1480: .clearSelection();
1481: configureApproveButton(translateFile(fileNameField
1482: .getText()), true);
1483: }
1484: });
1485: bottomPanel.add(fileNameField, c);
1486:
1487: c.insets = new Insets(0, 0, 0, 0);
1488: c.gridwidth = 1;
1489: c.weightx = 0.0;
1490: JLabel filesOfTypeLabel = new JLabel(UIManager
1491: .getString("FileChooser.filesOfTypeLabelText"));
1492: filesOfTypeLabel.setDisplayedMnemonic(UIManager
1493: .getInt("FileChooser.filesOfTypeLabelMnemonic"));
1494: bottomPanel.add(filesOfTypeLabel, c);
1495: bottomPanel.add(Box.createHorizontalStrut(6), c);
1496:
1497: c.gridwidth = GridBagConstraints.REMAINDER;
1498: c.weightx = 1.0;
1499: final JComboBox fileFilterCombo = new JComboBox(
1500: createFilterComboBoxModel());
1501:
1502: filesOfTypeLabel.setLabelFor(fileFilterCombo);
1503:
1504: fileFilterCombo.addActionListener(new ActionListener() {
1505: public void actionPerformed(final ActionEvent e) {
1506: fileNameField.setText("");
1507: getFileChooser().setFileFilter(
1508: (FileFilter) fileFilterCombo.getSelectedItem());
1509: }
1510: });
1511: fileFilterCombo.setRenderer(createFilterComboBoxRenderer());
1512: bottomPanel.add(fileFilterCombo, c);
1513: }
1514:
1515: private JPanel createTopPanel(final JFileChooser fc) {
1516: final int topPanelHeight = 25;
1517: JPanel result = new JPanel(new BorderLayout());
1518: result.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0));
1519: actionLabel = new JLabel();
1520:
1521: directoryModel = createDirectoryComboBoxModel(fc);
1522: JComboBox directoryComboBox = new JComboBox(directoryModel);
1523: directoryComboBox.setPreferredSize(new Dimension(300,
1524: topPanelHeight));
1525: directoryComboBox.setBorder(BorderFactory.createEmptyBorder(0,
1526: 6, 0, 6));
1527: directoryComboBox
1528: .setRenderer(createDirectoryComboBoxRenderer(fc));
1529: directoryComboBox.setAction(new DirectoryComboBoxAction());
1530:
1531: JPanel viewButtonsPanel = new JPanel(new FlowLayout(
1532: FlowLayout.LEFT, 0, 0));
1533: JButton parentDirButton = new JButton(
1534: getChangeToParentDirectoryAction());
1535: parentDirButton.setText(null);
1536: Dimension buttonPreferredSize = new Dimension(topPanelHeight,
1537: topPanelHeight);
1538: parentDirButton.setPreferredSize(buttonPreferredSize);
1539: JButton goHomeButton = new JButton(getGoHomeAction());
1540: goHomeButton.setText(null);
1541: goHomeButton.setPreferredSize(buttonPreferredSize);
1542: JButton newFolderButton = new JButton(getNewFolderAction());
1543: newFolderButton.setText(null);
1544: newFolderButton.setPreferredSize(buttonPreferredSize);
1545:
1546: viewButtonsPanel.add(parentDirButton);
1547: viewButtonsPanel.add(Box.createHorizontalStrut(6));
1548: viewButtonsPanel.add(goHomeButton);
1549: viewButtonsPanel.add(Box.createHorizontalStrut(6));
1550: viewButtonsPanel.add(newFolderButton);
1551: viewButtonsPanel.add(Box.createHorizontalStrut(6));
1552:
1553: listViewButton = new JToggleButton(listViewAction);
1554: listViewButton.setText(null);
1555: listViewButton.setPreferredSize(buttonPreferredSize);
1556: detailedViewButton = new JToggleButton(detailedViewAction);
1557: detailedViewButton.setText(null);
1558: detailedViewButton.setPreferredSize(buttonPreferredSize);
1559: ButtonGroup viewGroup = new ButtonGroup();
1560: viewGroup.add(listViewButton);
1561: viewGroup.add(detailedViewButton);
1562: viewButtonsPanel.add(listViewButton);
1563: viewButtonsPanel.add(detailedViewButton);
1564: listViewButton.setSelected(true);
1565:
1566: result.add(actionLabel, BorderLayout.LINE_START);
1567: result.add(directoryComboBox, BorderLayout.CENTER);
1568:
1569: actionLabel.setDisplayedMnemonic(UIManager
1570: .getInt("FileChooser.lookInLabelMnemonic"));
1571: actionLabel.setLabelFor(directoryComboBox);
1572:
1573: result.add(viewButtonsPanel, BorderLayout.LINE_END);
1574:
1575: return result;
1576: }
1577:
1578: private void updateListSelection(final File[] files) {
1579: getViewRepresentation().getSelectionModel()
1580: .setValueIsAdjusting(true);
1581: getViewRepresentation().getSelectionModel().clearSelection();
1582: for (int i = 0; i < files.length; i++) {
1583: int index = getModel().indexOf(files[i]);
1584: if (index != -1) {
1585: getViewRepresentation().getSelectionModel()
1586: .addSelectionInterval(index, index);
1587: }
1588: }
1589: getViewRepresentation().getSelectionModel()
1590: .setValueIsAdjusting(false);
1591: }
1592:
1593: private boolean isSelectableFile(final File file) {
1594: return (getFileChooser().isDirectorySelectionEnabled()
1595: && file.isDirectory()
1596: && (!getFileChooser().getFileSystemView()
1597: .isFileSystemRoot(file) || getFileChooser()
1598: .getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) || file
1599: .isFile()
1600: && getFileChooser().isFileSelectionEnabled())
1601: && getFileChooser().getFileSystemView().isFileSystem(
1602: file);
1603: }
1604:
1605: private JPopupMenu createPopupMenu() {
1606: JMenu viewMenu = new JMenu("View");
1607:
1608: listViewItem = new JRadioButtonMenuItem(listViewAction);
1609: listViewItem.setIcon(null);
1610: detailedViewItem = new JRadioButtonMenuItem(detailedViewAction);
1611: detailedViewItem.setIcon(null);
1612: ButtonGroup bg = new ButtonGroup();
1613: bg.add(listViewItem);
1614: bg.add(detailedViewItem);
1615: viewMenu.add(listViewItem);
1616: viewMenu.add(detailedViewItem);
1617:
1618: JMenuItem refreshItem = new JMenuItem(getUpdateAction());
1619: refreshItem.setIcon(null);
1620: JMenuItem newFolderItem = new JMenuItem(getNewFolderAction());
1621: newFolderItem.setIcon(null);
1622:
1623: JPopupMenu result = new JPopupMenu() {
1624: public void show(final Component invoker, final int x,
1625: final int y) {
1626: if (isDetailedViewActivated) {
1627: detailedViewItem.setSelected(true);
1628: } else {
1629: listViewItem.setSelected(true);
1630: }
1631:
1632: super .show(invoker, x, y);
1633: }
1634: };
1635:
1636: result.add(viewMenu);
1637: result.add(refreshItem);
1638: result.add(newFolderItem);
1639:
1640: return result;
1641: }
1642:
1643: private ViewRepresentation getViewRepresentation() {
1644: return isDetailedViewActivated ? detailedViewRepresentation
1645: : listViewRepresentation;
1646: }
1647:
1648: private static String getAdjustedFileSize(final File file) {
1649: long length = file.length();
1650: long num = length >> 30;
1651: if (num > 0) {
1652: return num + " GB";
1653: }
1654: num = length >> 20;
1655: if (num > 0) {
1656: return num + " MB";
1657: }
1658: num = length >> 10;
1659: if (num == 0) {
1660: num = 1;
1661: }
1662: return num + " KB";
1663: }
1664:
1665: private void configureApproveButton(final File selectedFile,
1666: final boolean singleFileSelected) {
1667: Action approveAction;
1668: if (singleFileSelected
1669: && selectedFile != null
1670: && selectedFile.isDirectory()
1671: && getFileChooser().isTraversable(selectedFile)
1672: && (!getFileChooser().isDirectorySelectionEnabled()
1673: || !getFileChooser().getFileSystemView()
1674: .isFileSystem(selectedFile) || (getFileChooser()
1675: .getFileSystemView().isFileSystemRoot(
1676: selectedFile) && getFileChooser()
1677: .getFileSelectionMode() != JFileChooser.DIRECTORIES_ONLY))) {
1678:
1679: approveAction = openDirectoryAction;
1680: } else {
1681: approveAction = approveSelectionAction;
1682: }
1683: if (approveButton.getAction() != approveAction) {
1684: approveButton.setAction(approveAction);
1685: }
1686:
1687: }
1688:
1689: private File translateFile(final String fileName) {
1690: if (Utilities.isEmptyString(fileName)) {
1691: return null;
1692: }
1693:
1694: File candidateFile = new File(fileName);
1695: if (candidateFile.isAbsolute()) {
1696: return candidateFile;
1697: }
1698:
1699: if (fileName.startsWith("\"")) {
1700: String nakedFileName = fileName.endsWith("\"") ? fileName
1701: .substring(1, fileName.length() - 1) : fileName
1702: .substring(1);
1703:
1704: File fileInCurrentDir = getFileChooser()
1705: .getFileSystemView().getChild(
1706: getFileChooser().getCurrentDirectory(),
1707: nakedFileName);
1708: if (fileInCurrentDir != null
1709: && fileInCurrentDir.exists()
1710: && getFileChooser().getFileSystemView()
1711: .isFileSystem(fileInCurrentDir)) {
1712:
1713: return fileInCurrentDir;
1714: } else {
1715: return getFileChooser().getFileSystemView()
1716: .createFileObject(nakedFileName);
1717: }
1718: } else {
1719: return getFileChooser().getFileSystemView()
1720: .createFileObject(
1721: getFileChooser().getCurrentDirectory(),
1722: fileName);
1723: }
1724: }
1725:
1726: }
|