| /* MetalFileChooserUI.java -- |
| Copyright (C) 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.swing.plaf.metal; |
| |
| import java.awt.BorderLayout; |
| import java.awt.Component; |
| import java.awt.Container; |
| import java.awt.Dimension; |
| import java.awt.Graphics; |
| import java.awt.GridLayout; |
| import java.awt.Insets; |
| import java.awt.LayoutManager; |
| import java.awt.Rectangle; |
| import java.awt.Window; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.MouseAdapter; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.MouseListener; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.io.File; |
| import java.sql.Date; |
| import java.text.DateFormat; |
| import java.text.NumberFormat; |
| import java.util.List; |
| |
| import javax.swing.AbstractAction; |
| import javax.swing.AbstractListModel; |
| import javax.swing.ActionMap; |
| import javax.swing.BorderFactory; |
| import javax.swing.ButtonGroup; |
| import javax.swing.ComboBoxModel; |
| import javax.swing.DefaultListCellRenderer; |
| import javax.swing.Icon; |
| import javax.swing.JButton; |
| import javax.swing.JComboBox; |
| import javax.swing.JComponent; |
| import javax.swing.JDialog; |
| import javax.swing.JFileChooser; |
| import javax.swing.JLabel; |
| import javax.swing.JList; |
| import javax.swing.JPanel; |
| import javax.swing.JScrollPane; |
| import javax.swing.JTable; |
| import javax.swing.JTextField; |
| import javax.swing.JToggleButton; |
| import javax.swing.ListModel; |
| import javax.swing.ListSelectionModel; |
| import javax.swing.SwingUtilities; |
| import javax.swing.UIManager; |
| import javax.swing.event.ListSelectionEvent; |
| import javax.swing.event.ListSelectionListener; |
| import javax.swing.filechooser.FileFilter; |
| import javax.swing.filechooser.FileSystemView; |
| import javax.swing.filechooser.FileView; |
| import javax.swing.plaf.ComponentUI; |
| import javax.swing.plaf.basic.BasicFileChooserUI; |
| import javax.swing.table.DefaultTableCellRenderer; |
| import javax.swing.table.DefaultTableModel; |
| |
| |
| /** |
| * A UI delegate for the {@link JFileChooser} component. This class is only |
| * partially implemented and is not usable yet. |
| */ |
| public class MetalFileChooserUI |
| extends BasicFileChooserUI |
| { |
| |
| /** |
| * A renderer for the files and directories in the file chooser table. |
| */ |
| class TableFileRenderer |
| extends DefaultTableCellRenderer |
| { |
| |
| /** |
| * Creates a new renderer. |
| */ |
| public TableFileRenderer() |
| { |
| super(); |
| } |
| |
| /** |
| * Returns a component that can render the specified value. |
| * |
| * @param table the table |
| * @param value the string value of the cell |
| * @param isSelected is the item selected? |
| * @param hasFocus does the item have the focus? |
| * @param row the row |
| * @param column the column |
| * |
| * @return The renderer. |
| */ |
| public Component getTableCellRendererComponent(JTable table, Object value, |
| boolean isSelected, boolean hasFocus, int row, int column) |
| { |
| if (column == 0) |
| { |
| FileView v = getFileView(getFileChooser()); |
| ListModel lm = fileList.getModel(); |
| if (row < lm.getSize()) |
| setIcon(v.getIcon((File) lm.getElementAt(row))); |
| } |
| else |
| setIcon(null); |
| |
| setText(value.toString()); |
| setOpaque(true); |
| setEnabled(table.isEnabled()); |
| setFont(fileList.getFont()); |
| |
| if (startEditing && column == 0 || !isSelected) |
| { |
| setBackground(table.getBackground()); |
| setForeground(table.getForeground()); |
| } |
| else |
| { |
| setBackground(table.getSelectionBackground()); |
| setForeground(table.getSelectionForeground()); |
| } |
| |
| if (hasFocus) |
| setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); |
| else |
| setBorder(noFocusBorder); |
| |
| return this; |
| } |
| } |
| |
| /** |
| * ActionListener for the list view. |
| */ |
| class ListViewActionListener implements ActionListener |
| { |
| |
| /** |
| * This method is invoked when an action occurs. |
| * |
| * @param e - |
| * the <code>ActionEvent</code> that occurred |
| */ |
| public void actionPerformed(ActionEvent e) |
| { |
| if (!listView) |
| { |
| int[] index = fileTable.getSelectedRows(); |
| listView = true; |
| JFileChooser fc = getFileChooser(); |
| fc.remove(fileTablePanel); |
| createList(fc); |
| |
| fileList.getSelectionModel().clearSelection(); |
| if (index.length > 0) |
| for (int i = 0; i < index.length; i++) |
| fileList.getSelectionModel().addSelectionInterval(index[i], index[i]); |
| |
| fc.add(fileListPanel, BorderLayout.CENTER); |
| fc.revalidate(); |
| fc.repaint(); |
| } |
| } |
| } |
| |
| /** |
| * ActionListener for the details view. |
| */ |
| class DetailViewActionListener implements ActionListener |
| { |
| |
| /** |
| * This method is invoked when an action occurs. |
| * |
| * @param e - |
| * the <code>ActionEvent</code> that occurred |
| */ |
| public void actionPerformed(ActionEvent e) |
| { |
| if (listView) |
| { |
| int[] index = fileList.getSelectedIndices(); |
| JFileChooser fc = getFileChooser(); |
| listView = false; |
| fc.remove(fileListPanel); |
| |
| if (fileTable == null) |
| createDetailsView(fc); |
| else |
| updateTable(); |
| |
| fileTable.getSelectionModel().clearSelection(); |
| if (index.length > 0) |
| { |
| for (int i = 0; i < index.length; i++) |
| fileTable.getSelectionModel().addSelectionInterval(index[i], index[i]); |
| } |
| |
| fc.add(fileTablePanel, BorderLayout.CENTER); |
| fc.revalidate(); |
| fc.repaint(); |
| } |
| } |
| } |
| |
| /** |
| * A property change listener. |
| */ |
| class MetalFileChooserPropertyChangeListener |
| implements PropertyChangeListener |
| { |
| /** |
| * Default constructor. |
| */ |
| public MetalFileChooserPropertyChangeListener() |
| { |
| } |
| |
| /** |
| * Handles a property change event. |
| * |
| * @param e the event. |
| */ |
| public void propertyChange(PropertyChangeEvent e) |
| { |
| JFileChooser filechooser = getFileChooser(); |
| |
| String n = e.getPropertyName(); |
| if (n.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) |
| { |
| int mode = -1; |
| if (filechooser.isMultiSelectionEnabled()) |
| mode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION; |
| else |
| mode = ListSelectionModel.SINGLE_SELECTION; |
| |
| if (listView) |
| fileList.setSelectionMode(mode); |
| else |
| fileTable.setSelectionMode(mode); |
| } |
| else if (n.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) |
| { |
| File file = filechooser.getSelectedFile(); |
| |
| if (file != null |
| && filechooser.getDialogType() == JFileChooser.SAVE_DIALOG) |
| { |
| if (file.isDirectory() && filechooser.isTraversable(file)) |
| { |
| directoryLabel = look; |
| dirLabel.setText(directoryLabel); |
| filechooser.setApproveButtonText(openButtonText); |
| filechooser.setApproveButtonToolTipText(openButtonToolTipText); |
| } |
| else if (file.isFile()) |
| { |
| directoryLabel = save; |
| dirLabel.setText(directoryLabel); |
| filechooser.setApproveButtonText(saveButtonText); |
| filechooser.setApproveButtonToolTipText(saveButtonToolTipText); |
| } |
| } |
| |
| if (file == null) |
| setFileName(null); |
| else if (file.isFile() || filechooser.getFileSelectionMode() |
| != JFileChooser.FILES_ONLY) |
| setFileName(file.getName()); |
| int index = -1; |
| index = getModel().indexOf(file); |
| if (index >= 0) |
| { |
| if (listView) |
| { |
| fileList.setSelectedIndex(index); |
| fileList.ensureIndexIsVisible(index); |
| fileList.revalidate(); |
| fileList.repaint(); |
| } |
| else |
| { |
| fileTable.getSelectionModel().addSelectionInterval(index, index); |
| fileTable.scrollRectToVisible(fileTable.getCellRect(index, 0, true)); |
| fileTable.revalidate(); |
| fileTable.repaint(); |
| } |
| } |
| } |
| |
| else if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) |
| { |
| if (listView) |
| { |
| fileList.clearSelection(); |
| fileList.revalidate(); |
| fileList.repaint(); |
| } |
| else |
| { |
| fileTable.clearSelection(); |
| fileTable.revalidate(); |
| fileTable.repaint(); |
| } |
| |
| setDirectorySelected(false); |
| File currentDirectory = filechooser.getCurrentDirectory(); |
| setDirectory(currentDirectory); |
| boolean hasParent = currentDirectory.getParentFile() != null; |
| getChangeToParentDirectoryAction().setEnabled(hasParent); |
| } |
| |
| else if (n.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) |
| { |
| filterModel.propertyChange(e); |
| } |
| else if (n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) |
| { |
| filterModel.propertyChange(e); |
| } |
| else if (n.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) |
| || n.equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY)) |
| { |
| Window owner = SwingUtilities.windowForComponent(filechooser); |
| if (owner instanceof JDialog) |
| ((JDialog) owner).setTitle(getDialogTitle(filechooser)); |
| approveButton.setText(getApproveButtonText(filechooser)); |
| approveButton.setToolTipText( |
| getApproveButtonToolTipText(filechooser)); |
| approveButton.setMnemonic(getApproveButtonMnemonic(filechooser)); |
| } |
| |
| else if (n.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)) |
| approveButton.setText(getApproveButtonText(filechooser)); |
| |
| else if (n.equals( |
| JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) |
| approveButton.setToolTipText(getApproveButtonToolTipText(filechooser)); |
| |
| else if (n.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) |
| approveButton.setMnemonic(getApproveButtonMnemonic(filechooser)); |
| |
| else if (n.equals( |
| JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) |
| { |
| if (filechooser.getControlButtonsAreShown()) |
| { |
| topPanel.add(controls, BorderLayout.EAST); |
| } |
| else |
| topPanel.remove(controls); |
| topPanel.revalidate(); |
| topPanel.repaint(); |
| topPanel.doLayout(); |
| } |
| |
| else if (n.equals( |
| JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY)) |
| { |
| if (filechooser.isAcceptAllFileFilterUsed()) |
| filechooser.addChoosableFileFilter( |
| getAcceptAllFileFilter(filechooser)); |
| else |
| filechooser.removeChoosableFileFilter( |
| getAcceptAllFileFilter(filechooser)); |
| } |
| |
| else if (n.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) |
| { |
| JComponent old = (JComponent) e.getOldValue(); |
| if (old != null) |
| getAccessoryPanel().remove(old); |
| JComponent newval = (JComponent) e.getNewValue(); |
| if (newval != null) |
| getAccessoryPanel().add(newval); |
| } |
| |
| if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY) |
| || n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY) |
| || n.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)) |
| { |
| // Remove editing component |
| if (fileTable != null) |
| fileTable.removeAll(); |
| if (fileList != null) |
| fileList.removeAll(); |
| startEditing = false; |
| |
| // Set text on button back to original. |
| if (filechooser.getDialogType() == JFileChooser.SAVE_DIALOG) |
| { |
| directoryLabel = save; |
| dirLabel.setText(directoryLabel); |
| filechooser.setApproveButtonText(saveButtonText); |
| filechooser.setApproveButtonToolTipText(saveButtonToolTipText); |
| } |
| |
| rescanCurrentDirectory(filechooser); |
| } |
| |
| filechooser.revalidate(); |
| filechooser.repaint(); |
| } |
| }; |
| |
| /** |
| * A combo box model containing the selected directory and all its parent |
| * directories. |
| */ |
| protected class DirectoryComboBoxModel |
| extends AbstractListModel |
| implements ComboBoxModel |
| { |
| /** Storage for the items in the model. */ |
| private List items; |
| |
| /** The index of the selected item. */ |
| private int selectedIndex; |
| |
| /** |
| * Creates a new model. |
| */ |
| public DirectoryComboBoxModel() |
| { |
| items = new java.util.ArrayList(); |
| selectedIndex = -1; |
| } |
| |
| /** |
| * Returns the number of items in the model. |
| * |
| * @return The number of items in the model. |
| */ |
| public int getSize() |
| { |
| return items.size(); |
| } |
| |
| /** |
| * Returns the item at the specified index. |
| * |
| * @param index the item index. |
| * |
| * @return The item. |
| */ |
| public Object getElementAt(int index) |
| { |
| return items.get(index); |
| } |
| |
| /** |
| * Returns the depth of the item at the given <code>index</code>. |
| * |
| * @param index the item index. |
| * |
| * @return The depth. |
| */ |
| public int getDepth(int index) |
| { |
| return Math.max(index, 0); |
| } |
| |
| /** |
| * Returns the selected item, or <code>null</code> if no item is selected. |
| * |
| * @return The selected item, or <code>null</code>. |
| */ |
| public Object getSelectedItem() |
| { |
| if (selectedIndex >= 0) |
| return items.get(selectedIndex); |
| else |
| return null; |
| } |
| |
| /** |
| * Sets the selected item. This clears all the directories from the |
| * existing list, and repopulates it with the new selected directory |
| * and all its parent directories. |
| * |
| * @param selectedDirectory the selected directory. |
| */ |
| public void setSelectedItem(Object selectedDirectory) |
| { |
| items.clear(); |
| FileSystemView fsv = getFileChooser().getFileSystemView(); |
| File parent = (File) selectedDirectory; |
| while (parent != null) |
| { |
| items.add(0, parent); |
| parent = fsv.getParentDirectory(parent); |
| } |
| selectedIndex = items.indexOf(selectedDirectory); |
| fireContentsChanged(this, 0, items.size() - 1); |
| } |
| |
| } |
| |
| /** |
| * Handles changes to the selection in the directory combo box. |
| */ |
| protected class DirectoryComboBoxAction |
| extends AbstractAction |
| { |
| /** |
| * Creates a new action. |
| */ |
| protected DirectoryComboBoxAction() |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Handles the action event. |
| * |
| * @param e the event. |
| */ |
| public void actionPerformed(ActionEvent e) |
| { |
| JFileChooser fc = getFileChooser(); |
| fc.setCurrentDirectory((File) directoryModel.getSelectedItem()); |
| } |
| } |
| |
| /** |
| * A renderer for the items in the directory combo box. |
| */ |
| class DirectoryComboBoxRenderer |
| extends DefaultListCellRenderer |
| { |
| /** |
| * This is the icon that is displayed in the combobox. This wraps |
| * the standard icon and adds indendation. |
| */ |
| private IndentIcon indentIcon; |
| |
| /** |
| * Creates a new renderer. |
| */ |
| public DirectoryComboBoxRenderer(JFileChooser fc) |
| { |
| indentIcon = new IndentIcon(); |
| } |
| |
| /** |
| * Returns a component that can be used to paint the given value within |
| * the list. |
| * |
| * @param list the list. |
| * @param value the value (a {@link File}). |
| * @param index the item index. |
| * @param isSelected is the item selected? |
| * @param cellHasFocus does the list cell have focus? |
| * |
| * @return The list cell renderer. |
| */ |
| public Component getListCellRendererComponent(JList list, Object value, |
| int index, |
| boolean isSelected, |
| boolean cellHasFocus) |
| { |
| super.getListCellRendererComponent(list, value, index, isSelected, |
| cellHasFocus); |
| File file = (File) value; |
| setText(getFileChooser().getName(file)); |
| |
| // Install indented icon. |
| Icon icon = getFileChooser().getIcon(file); |
| indentIcon.setIcon(icon); |
| int depth = directoryModel.getDepth(index); |
| indentIcon.setDepth(depth); |
| setIcon(indentIcon); |
| |
| return this; |
| } |
| } |
| |
| /** |
| * An icon that wraps another icon and adds indentation. |
| */ |
| class IndentIcon |
| implements Icon |
| { |
| |
| /** |
| * The indentation level. |
| */ |
| private static final int INDENT = 10; |
| |
| /** |
| * The wrapped icon. |
| */ |
| private Icon icon; |
| |
| /** |
| * The current depth. |
| */ |
| private int depth; |
| |
| /** |
| * Sets the icon to be wrapped. |
| * |
| * @param i the icon |
| */ |
| void setIcon(Icon i) |
| { |
| icon = i; |
| } |
| |
| /** |
| * Sets the indentation depth. |
| * |
| * @param d the depth to set |
| */ |
| void setDepth(int d) |
| { |
| depth = d; |
| } |
| |
| public int getIconHeight() |
| { |
| return icon.getIconHeight(); |
| } |
| |
| public int getIconWidth() |
| { |
| return icon.getIconWidth() + depth * INDENT; |
| } |
| |
| public void paintIcon(Component c, Graphics g, int x, int y) |
| { |
| icon.paintIcon(c, g, x + depth * INDENT, y); |
| } |
| |
| } |
| |
| /** |
| * A renderer for the files and directories in the file chooser. |
| */ |
| protected class FileRenderer |
| extends DefaultListCellRenderer |
| { |
| |
| /** |
| * Creates a new renderer. |
| */ |
| protected FileRenderer() |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Returns a component that can render the specified value. |
| * |
| * @param list the list. |
| * @param value the value (a {@link File}). |
| * @param index the index. |
| * @param isSelected is the item selected? |
| * @param cellHasFocus does the item have the focus? |
| * |
| * @return The renderer. |
| */ |
| public Component getListCellRendererComponent(JList list, Object value, |
| int index, boolean isSelected, boolean cellHasFocus) |
| { |
| FileView v = getFileView(getFileChooser()); |
| File f = (File) value; |
| if (f != null) |
| { |
| setText(v.getName(f)); |
| setIcon(v.getIcon(f)); |
| } |
| else |
| { |
| setText(""); |
| setIcon(null); |
| } |
| setOpaque(true); |
| if (isSelected) |
| { |
| setBackground(list.getSelectionBackground()); |
| setForeground(list.getSelectionForeground()); |
| } |
| else |
| { |
| setBackground(list.getBackground()); |
| setForeground(list.getForeground()); |
| } |
| |
| setEnabled(list.isEnabled()); |
| setFont(list.getFont()); |
| |
| if (cellHasFocus) |
| setBorder(UIManager.getBorder("List.focusCellHighlightBorder")); |
| else |
| setBorder(noFocusBorder); |
| return this; |
| } |
| } |
| |
| /** |
| * A combo box model for the file selection filters. |
| */ |
| protected class FilterComboBoxModel |
| extends AbstractListModel |
| implements ComboBoxModel, PropertyChangeListener |
| { |
| |
| /** Storage for the filters in the model. */ |
| protected FileFilter[] filters; |
| |
| /** The index of the selected file filter. */ |
| private Object selected; |
| |
| /** |
| * Creates a new model. |
| */ |
| protected FilterComboBoxModel() |
| { |
| filters = new FileFilter[1]; |
| filters[0] = getAcceptAllFileFilter(getFileChooser()); |
| selected = filters[0]; |
| } |
| |
| /** |
| * Handles property changes. |
| * |
| * @param e the property change event. |
| */ |
| public void propertyChange(PropertyChangeEvent e) |
| { |
| if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) |
| { |
| JFileChooser fc = getFileChooser(); |
| FileFilter[] choosableFilters = fc.getChoosableFileFilters(); |
| filters = choosableFilters; |
| fireContentsChanged(this, 0, filters.length); |
| selected = e.getNewValue(); |
| fireContentsChanged(this, -1, -1); |
| } |
| else if (e.getPropertyName().equals( |
| JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) |
| { |
| // repopulate list |
| JFileChooser fc = getFileChooser(); |
| FileFilter[] choosableFilters = fc.getChoosableFileFilters(); |
| filters = choosableFilters; |
| fireContentsChanged(this, 0, filters.length); |
| } |
| } |
| |
| /** |
| * Sets the selected filter. |
| * |
| * @param filter the filter (<code>null</code> ignored). |
| */ |
| public void setSelectedItem(Object filter) |
| { |
| if (filter != null) |
| { |
| selected = filter; |
| fireContentsChanged(this, -1, -1); |
| } |
| } |
| |
| /** |
| * Returns the selected file filter. |
| * |
| * @return The selected file filter. |
| */ |
| public Object getSelectedItem() |
| { |
| return selected; |
| } |
| |
| /** |
| * Returns the number of items in the model. |
| * |
| * @return The number of items in the model. |
| */ |
| public int getSize() |
| { |
| return filters.length; |
| } |
| |
| /** |
| * Returns the item at the specified index. |
| * |
| * @param index the item index. |
| * |
| * @return The item at the specified index. |
| */ |
| public Object getElementAt(int index) |
| { |
| return filters[index]; |
| } |
| |
| } |
| |
| /** |
| * A renderer for the items in the file filter combo box. |
| */ |
| public class FilterComboBoxRenderer |
| extends DefaultListCellRenderer |
| { |
| /** |
| * Creates a new renderer. |
| */ |
| public FilterComboBoxRenderer() |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Returns a component that can be used to paint the given value within |
| * the list. |
| * |
| * @param list the list. |
| * @param value the value (a {@link FileFilter}). |
| * @param index the item index. |
| * @param isSelected is the item selected? |
| * @param cellHasFocus does the list cell have focus? |
| * |
| * @return This component as the renderer. |
| */ |
| public Component getListCellRendererComponent(JList list, Object value, |
| int index, boolean isSelected, boolean cellHasFocus) |
| { |
| super.getListCellRendererComponent(list, value, index, isSelected, |
| cellHasFocus); |
| FileFilter filter = (FileFilter) value; |
| setText(filter.getDescription()); |
| return this; |
| } |
| } |
| |
| /** |
| * A listener for selection events in the file list. |
| * |
| * @see #createListSelectionListener(JFileChooser) |
| */ |
| class MetalFileChooserSelectionListener |
| implements ListSelectionListener |
| { |
| /** |
| * Creates a new <code>SelectionListener</code> object. |
| */ |
| protected MetalFileChooserSelectionListener() |
| { |
| // Do nothing here. |
| } |
| |
| /** |
| * Makes changes to different properties when |
| * a value has changed in the filechooser's selection. |
| * |
| * @param e - the list selection event that occured. |
| */ |
| public void valueChanged(ListSelectionEvent e) |
| { |
| File f = (File) fileList.getSelectedValue(); |
| if (f == null) |
| return; |
| JFileChooser filechooser = getFileChooser(); |
| if (! filechooser.isTraversable(f)) |
| filechooser.setSelectedFile(f); |
| else |
| filechooser.setSelectedFile(null); |
| } |
| } |
| |
| /** |
| * A mouse listener for the {@link JFileChooser}. |
| * This listener is used for editing filenames. |
| */ |
| protected class SingleClickListener |
| extends MouseAdapter |
| { |
| |
| /** Stores instance of the list */ |
| JList list; |
| |
| /** |
| * Stores the current file that is being edited. |
| * It is null if nothing is currently being edited. |
| */ |
| File editFile; |
| |
| /** The current file chooser. */ |
| JFileChooser fc; |
| |
| /** The last file selected. */ |
| Object lastSelected; |
| |
| /** The textfield used for editing. */ |
| JTextField editField; |
| |
| /** |
| * Creates a new listener. |
| * |
| * @param list the directory/file list. |
| */ |
| public SingleClickListener(JList list) |
| { |
| this.list = list; |
| editFile = null; |
| fc = getFileChooser(); |
| lastSelected = null; |
| startEditing = false; |
| } |
| |
| /** |
| * Receives notification of a mouse click event. |
| * |
| * @param e the event. |
| */ |
| public void mouseClicked(MouseEvent e) |
| { |
| if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) |
| { |
| int index = list.locationToIndex(e.getPoint()); |
| File[] sf = fc.getSelectedFiles(); |
| if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1)) |
| && index >= 0 && !startEditing && list.isSelectedIndex(index)) |
| { |
| Object tmp = list.getModel().getElementAt(index); |
| if (lastSelected != null && lastSelected.equals(tmp)) |
| editFile(index); |
| lastSelected = tmp; |
| } |
| else |
| completeEditing(); |
| } |
| else |
| completeEditing(); |
| } |
| |
| /** |
| * Sets up the text editor for the current file. |
| * |
| * @param index - |
| * the current index of the item in the list to be edited. |
| */ |
| void editFile(int index) |
| { |
| Rectangle bounds = list.getCellBounds(index, index); |
| list.scrollRectToVisible(bounds); |
| editFile = (File) list.getModel().getElementAt(index); |
| if (editFile.canWrite()) |
| { |
| startEditing = true; |
| editField = new JTextField(editFile.getName()); |
| editField.addActionListener(new EditingActionListener()); |
| |
| Icon icon = getFileView(fc).getIcon(editFile); |
| if (icon != null) |
| { |
| int padding = icon.getIconWidth() + 4; |
| bounds.x += padding; |
| bounds.width -= padding; |
| } |
| editField.setBounds(bounds); |
| |
| list.add(editField); |
| |
| editField.requestFocus(); |
| editField.selectAll(); |
| } |
| else |
| completeEditing(); |
| list.repaint(); |
| } |
| |
| /** |
| * Completes the editing. |
| */ |
| void completeEditing() |
| { |
| if (editField != null && editFile != null) |
| { |
| String text = editField.getText(); |
| if (text != null && text != "" && !text.equals(fc.getName(editFile))) |
| { |
| File f = fc.getFileSystemView(). |
| createFileObject(fc.getCurrentDirectory(), text); |
| if ( editFile.renameTo(f) ) |
| rescanCurrentDirectory(fc); |
| } |
| list.remove(editField); |
| } |
| startEditing = false; |
| editFile = null; |
| lastSelected = null; |
| editField = null; |
| list.repaint(); |
| } |
| |
| /** |
| * ActionListener for the editing text field. |
| */ |
| class EditingActionListener implements ActionListener |
| { |
| |
| /** |
| * This method is invoked when an action occurs. |
| * |
| * @param e - |
| * the <code>ActionEvent</code> that occurred |
| */ |
| public void actionPerformed(ActionEvent e) |
| { |
| if (editField != null) |
| completeEditing(); |
| } |
| } |
| } |
| |
| /** |
| * A mouse listener for the {@link JFileChooser}. |
| * This listener is used for the table |
| */ |
| private class TableClickListener extends MouseAdapter |
| { |
| |
| /** Stores instance of the table */ |
| JTable table; |
| |
| /** Stores instance of the file chooser */ |
| JFileChooser fc; |
| |
| /** The last selected file. */ |
| Object lastSelected; |
| |
| /** |
| * Stores the current file that is being edited. |
| * It is null if nothing is currently being edited. |
| */ |
| File editFile; |
| |
| /** The textfield used for editing. */ |
| JTextField editField; |
| |
| /** |
| * Creates a new listener. |
| * |
| * @param table the directory/file table |
| * @param fc the JFileChooser |
| */ |
| public TableClickListener(JTable table, JFileChooser fc) |
| { |
| this.table = table; |
| this.fc = fc; |
| lastSelected = fileList.getSelectedValue(); |
| setDirectorySelected(false); |
| startEditing = false; |
| editFile = null; |
| editField = null; |
| } |
| |
| /** |
| * Receives notification of a mouse click event. |
| * |
| * @param e the event. |
| */ |
| public void mouseClicked(MouseEvent e) |
| { |
| int row = table.getSelectedRow(); |
| Object selVal = fileList.getModel().getElementAt(row); |
| if (selVal == null) |
| return; |
| FileSystemView fsv = fc.getFileSystemView(); |
| if (e.getClickCount() == 1 && |
| selVal.equals(lastSelected) && |
| e.getButton() == MouseEvent.BUTTON1) |
| { |
| File[] sf = fc.getSelectedFiles(); |
| if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1)) |
| && !startEditing) |
| { |
| editFile = (File) selVal; |
| editFile(row); |
| } |
| } |
| else if (e.getClickCount() >= 2 && |
| selVal.equals(lastSelected)) |
| { |
| if (startEditing) |
| completeEditing(); |
| File f = fsv.createFileObject(lastSelected.toString()); |
| if (fc.isTraversable(f)) |
| { |
| fc.setCurrentDirectory(f); |
| fc.rescanCurrentDirectory(); |
| } |
| else |
| { |
| fc.setSelectedFile(f); |
| fc.approveSelection(); |
| closeDialog(); |
| } |
| } |
| else |
| { |
| if (startEditing) |
| completeEditing(); |
| String path = selVal.toString(); |
| File f = fsv.createFileObject(path); |
| fc.setSelectedFile(f); |
| if (fc.isTraversable(f)) |
| { |
| setDirectorySelected(true); |
| setDirectory(f); |
| } |
| else |
| { |
| setDirectorySelected(false); |
| setDirectory(null); |
| } |
| lastSelected = selVal; |
| if (f.isFile()) |
| setFileName(path.substring(path.lastIndexOf("/") + 1)); |
| else if (fc.getFileSelectionMode() != JFileChooser.FILES_ONLY) |
| setFileName(path); |
| } |
| fileTable.repaint(); |
| } |
| |
| /** |
| * Sets up the text editor for the current file. |
| * |
| * @param row - |
| * the current row of the item in the list to be edited. |
| */ |
| void editFile(int row) |
| { |
| Rectangle bounds = table.getCellRect(row, 0, true); |
| table.scrollRectToVisible(bounds); |
| if (editFile.canWrite()) |
| { |
| startEditing = true; |
| editField = new JTextField(editFile.getName()); |
| editField.addActionListener(new EditingActionListener()); |
| |
| // Need to adjust y pos |
| bounds.y = row * table.getRowHeight(); |
| editField.setBounds(bounds); |
| |
| table.add(editField); |
| |
| editField.requestFocus(); |
| editField.selectAll(); |
| } |
| else |
| completeEditing(); |
| table.repaint(); |
| } |
| |
| /** |
| * Completes the editing. |
| */ |
| void completeEditing() |
| { |
| if (editField != null && editFile != null) |
| { |
| String text = editField.getText(); |
| if (text != null && text != "" && !text.equals(fc.getName(editFile))) |
| if (editFile.renameTo(fc.getFileSystemView().createFileObject( |
| fc.getCurrentDirectory(), text))) |
| rescanCurrentDirectory(fc); |
| table.remove(editField); |
| } |
| startEditing = false; |
| editFile = null; |
| editField = null; |
| table.repaint(); |
| } |
| |
| /** |
| * ActionListener for the editing text field. |
| */ |
| class EditingActionListener implements ActionListener |
| { |
| |
| /** |
| * This method is invoked when an action occurs. |
| * |
| * @param e - |
| * the <code>ActionEvent</code> that occurred |
| */ |
| public void actionPerformed(ActionEvent e) |
| { |
| if (editField != null) |
| completeEditing(); |
| } |
| } |
| |
| /** |
| * Closes the dialog. |
| */ |
| public void closeDialog() |
| { |
| Window owner = SwingUtilities.windowForComponent(fc); |
| if (owner instanceof JDialog) |
| ((JDialog) owner).dispose(); |
| } |
| } |
| |
| /** The text for a label describing the directory combo box. */ |
| private String directoryLabel; |
| |
| private JComboBox directoryComboBox; |
| |
| /** The model for the directory combo box. */ |
| DirectoryComboBoxModel directoryModel; |
| |
| /** The text for a label describing the file text field. */ |
| private String fileLabel; |
| |
| /** The file name text field. */ |
| private JTextField fileTextField; |
| |
| /** The text for a label describing the filter combo box. */ |
| private String filterLabel; |
| |
| /** |
| * The top panel (contains the directory combo box and the control buttons). |
| */ |
| private JPanel topPanel; |
| |
| /** A panel containing the control buttons ('up', 'home' etc.). */ |
| private JPanel controls; |
| |
| /** |
| * The panel that contains the filename field and the filter combobox. |
| */ |
| private JPanel bottomPanel; |
| |
| /** |
| * The panel that contains the 'Open' (or 'Save') and 'Cancel' buttons. |
| */ |
| private JPanel buttonPanel; |
| |
| private JButton approveButton; |
| |
| /** The file list. */ |
| JList fileList; |
| |
| /** The file table. */ |
| JTable fileTable; |
| |
| /** The panel containing the file list. */ |
| JPanel fileListPanel; |
| |
| /** The panel containing the file table. */ |
| JPanel fileTablePanel; |
| |
| /** The filter combo box model. */ |
| private FilterComboBoxModel filterModel; |
| |
| /** The action map. */ |
| private ActionMap actionMap; |
| |
| /** True if currently in list view. */ |
| boolean listView; |
| |
| /** True if we can or have started editing a cell. */ |
| boolean startEditing; |
| |
| /** The scrollpane used for the table and list. */ |
| JScrollPane scrollPane; |
| |
| /** The text for the label when saving. */ |
| String save; |
| |
| /** The text for the label when opening a directory. */ |
| String look; |
| |
| /** The label for the file combo box. */ |
| JLabel dirLabel; |
| |
| /** Listeners. */ |
| ListSelectionListener listSelList; |
| MouseListener doubleClickList; |
| SingleClickListener singleClickList; |
| TableClickListener tableClickList; |
| |
| /** |
| * A factory method that returns a UI delegate for the specified |
| * component. |
| * |
| * @param c the component (which should be a {@link JFileChooser}). |
| */ |
| public static ComponentUI createUI(JComponent c) |
| { |
| JFileChooser chooser = (JFileChooser) c; |
| return new MetalFileChooserUI(chooser); |
| } |
| |
| /** |
| * Creates a new instance of this UI delegate. |
| * |
| * @param filechooser the file chooser component. |
| */ |
| public MetalFileChooserUI(JFileChooser filechooser) |
| { |
| super(filechooser); |
| bottomPanel = new JPanel(new GridLayout(3, 2)); |
| buttonPanel = new JPanel(); |
| } |
| |
| public void installUI(JComponent c) |
| { |
| super.installUI(c); |
| actionMap = createActionMap(); |
| } |
| |
| public void uninstallUI(JComponent c) |
| { |
| super.uninstallUI(c); |
| actionMap = null; |
| } |
| |
| /** |
| * Installs the sub-components of the file chooser. |
| * |
| * @param fc the file chooser component. |
| */ |
| public void installComponents(JFileChooser fc) |
| { |
| fc.setLayout(new BorderLayout()); |
| topPanel = new JPanel(new BorderLayout()); |
| dirLabel = new JLabel(directoryLabel); |
| topPanel.add(dirLabel, BorderLayout.WEST); |
| this.controls = new JPanel(); |
| addControlButtons(); |
| |
| JPanel dirPanel = new JPanel(new VerticalMidLayout()); |
| directoryModel = createDirectoryComboBoxModel(fc); |
| directoryComboBox = new JComboBox(directoryModel); |
| directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc)); |
| dirPanel.add(directoryComboBox); |
| topPanel.add(dirPanel); |
| topPanel.add(controls, BorderLayout.EAST); |
| topPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8)); |
| fc.add(topPanel, BorderLayout.NORTH); |
| |
| JPanel list = createList(fc); |
| list.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); |
| fc.add(list, BorderLayout.CENTER); |
| |
| JPanel bottomPanel = getBottomPanel(); |
| filterModel = createFilterComboBoxModel(); |
| JComboBox fileFilterCombo = new JComboBox(filterModel); |
| fileFilterCombo.setRenderer(createFilterComboBoxRenderer()); |
| |
| fileTextField = new JTextField(); |
| JPanel fileNamePanel = new JPanel(new VerticalMidLayout()); |
| fileNamePanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 5)); |
| fileNamePanel.add(fileTextField); |
| JPanel row1 = new JPanel(new BorderLayout()); |
| row1.add(new JLabel(this.fileLabel), BorderLayout.WEST); |
| row1.add(fileNamePanel); |
| bottomPanel.add(row1); |
| |
| JPanel row2 = new JPanel(new BorderLayout()); |
| row2.add(new JLabel(this.filterLabel), BorderLayout.WEST); |
| row2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); |
| row2.add(fileFilterCombo); |
| bottomPanel.add(row2); |
| JPanel buttonPanel = new JPanel(new ButtonLayout()); |
| |
| approveButton = new JButton(getApproveSelectionAction()); |
| approveButton.setText(getApproveButtonText(fc)); |
| approveButton.setToolTipText(getApproveButtonToolTipText(fc)); |
| approveButton.setMnemonic(getApproveButtonMnemonic(fc)); |
| buttonPanel.add(approveButton); |
| buttonPanel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0)); |
| |
| JButton cancelButton = new JButton(getCancelSelectionAction()); |
| cancelButton.setText(cancelButtonText); |
| cancelButton.setToolTipText(cancelButtonToolTipText); |
| cancelButton.setMnemonic(cancelButtonMnemonic); |
| buttonPanel.add(cancelButton); |
| bottomPanel.add(buttonPanel, BorderLayout.SOUTH); |
| bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 8)); |
| fc.add(bottomPanel, BorderLayout.SOUTH); |
| |
| fc.add(getAccessoryPanel(), BorderLayout.EAST); |
| } |
| |
| /** |
| * Uninstalls the components added by |
| * {@link #installComponents(JFileChooser)}. |
| * |
| * @param fc the file chooser. |
| */ |
| public void uninstallComponents(JFileChooser fc) |
| { |
| fc.remove(bottomPanel); |
| bottomPanel = null; |
| fc.remove(fileListPanel); |
| fc.remove(fileTablePanel); |
| fileTablePanel = null; |
| fileListPanel = null; |
| fc.remove(topPanel); |
| topPanel = null; |
| |
| directoryModel = null; |
| fileTextField = null; |
| directoryComboBox = null; |
| } |
| |
| /** |
| * Returns the panel that contains the 'Open' (or 'Save') and 'Cancel' |
| * buttons. |
| * |
| * @return The panel. |
| */ |
| protected JPanel getButtonPanel() |
| { |
| return buttonPanel; |
| } |
| |
| /** |
| * Creates and returns a new panel that will be used for the controls at |
| * the bottom of the file chooser. |
| * |
| * @return A new panel. |
| */ |
| protected JPanel getBottomPanel() |
| { |
| if (bottomPanel == null) |
| bottomPanel = new JPanel(new GridLayout(3, 2)); |
| return bottomPanel; |
| } |
| |
| /** |
| * Fetches localised strings for use by the labels and buttons on the |
| * file chooser. |
| * |
| * @param fc the file chooser. |
| */ |
| protected void installStrings(JFileChooser fc) |
| { |
| super.installStrings(fc); |
| look = "Look In: "; |
| save = "Save In: "; |
| if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) |
| directoryLabel = save; |
| else |
| directoryLabel = look; |
| |
| fileLabel = "File Name: "; |
| filterLabel = "Files of Type: "; |
| |
| this.cancelButtonMnemonic = 0; |
| this.cancelButtonText = "Cancel"; |
| this.cancelButtonToolTipText = "Abort file chooser dialog"; |
| |
| this.directoryOpenButtonMnemonic = 0; |
| this.directoryOpenButtonText = "Open"; |
| this.directoryOpenButtonToolTipText = "Open selected directory"; |
| |
| this.helpButtonMnemonic = 0; |
| this.helpButtonText = "Help"; |
| this.helpButtonToolTipText = "Filechooser help"; |
| |
| this.openButtonMnemonic = 0; |
| this.openButtonText = "Open"; |
| this.openButtonToolTipText = "Open selected file"; |
| |
| this.saveButtonMnemonic = 0; |
| this.saveButtonText = "Save"; |
| this.saveButtonToolTipText = "Save selected file"; |
| |
| this.updateButtonMnemonic = 0; |
| this.updateButtonText = "Update"; |
| this.updateButtonToolTipText = "Update directory listing"; |
| } |
| |
| /** |
| * Installs the listeners required. |
| * |
| * @param fc the file chooser. |
| */ |
| protected void installListeners(JFileChooser fc) |
| { |
| directoryComboBox.setAction(new DirectoryComboBoxAction()); |
| fc.addPropertyChangeListener(filterModel); |
| listSelList = createListSelectionListener(fc); |
| doubleClickList = this.createDoubleClickListener(fc, fileList); |
| singleClickList = new SingleClickListener(fileList); |
| fileList.addListSelectionListener(listSelList); |
| fileList.addMouseListener(doubleClickList); |
| fileList.addMouseListener(singleClickList); |
| super.installListeners(fc); |
| } |
| |
| protected void uninstallListeners(JFileChooser fc) |
| { |
| super.uninstallListeners(fc); |
| fc.removePropertyChangeListener(filterModel); |
| directoryComboBox.setAction(null); |
| fileList.removeListSelectionListener(listSelList); |
| fileList.removeMouseListener(doubleClickList); |
| fileList.removeMouseListener(singleClickList); |
| |
| if (fileTable != null) |
| fileTable.removeMouseListener(tableClickList); |
| } |
| |
| protected ActionMap getActionMap() |
| { |
| if (actionMap == null) |
| actionMap = createActionMap(); |
| return actionMap; |
| } |
| |
| /** |
| * Creates and returns an action map. |
| * |
| * @return The action map. |
| */ |
| protected ActionMap createActionMap() |
| { |
| ActionMap map = new ActionMap(); |
| map.put("approveSelection", getApproveSelectionAction()); |
| map.put("cancelSelection", getCancelSelectionAction()); |
| map.put("Go Up", getChangeToParentDirectoryAction()); |
| return map; |
| } |
| |
| /** |
| * Creates a panel containing a list of files. |
| * |
| * @param fc the file chooser. |
| * |
| * @return A panel. |
| */ |
| protected JPanel createList(JFileChooser fc) |
| { |
| if (fileList == null) |
| { |
| fileListPanel = new JPanel(new BorderLayout()); |
| fileList = new JList(getModel()); |
| scrollPane = new JScrollPane(fileList); |
| fileList.setLayoutOrientation(JList.VERTICAL_WRAP); |
| fileList.setCellRenderer(new FileRenderer()); |
| } |
| else |
| { |
| fileList.setModel(getModel()); |
| fileListPanel.removeAll(); |
| scrollPane.getViewport().setView(fileList); |
| } |
| fileListPanel.add(scrollPane); |
| // This size was determined using BeanShell and dumping the JFileChooser |
| // component hierarchy. Sun has an internal FilePane class in there, but |
| // that probably doesn't matter atm. |
| fileListPanel.setPreferredSize(new Dimension(405, 135)); |
| return fileListPanel; |
| } |
| |
| /** |
| * Creates a panel containing a table within a scroll pane. |
| * |
| * @param fc the file chooser. |
| * |
| * @return The details view. |
| */ |
| protected JPanel createDetailsView(JFileChooser fc) |
| { |
| fileTablePanel = new JPanel(new BorderLayout()); |
| |
| Object[] cols = new Object[] {"Name", "Size", "Modified"}; |
| Object[][] rows = new Object[fileList.getModel().getSize()][3]; |
| |
| fileTable = new JTable(new DefaultTableModel(rows, cols)); |
| |
| if (fc.isMultiSelectionEnabled()) |
| fileTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); |
| else |
| fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| |
| fileTable.setShowGrid(false); |
| fileTable.setColumnSelectionAllowed(false); |
| fileTable.setDefaultRenderer(Object.class, new TableFileRenderer()); |
| |
| tableClickList = new TableClickListener(fileTable, fc); |
| fileTable.addMouseListener(tableClickList); |
| |
| return updateTable(); |
| } |
| |
| /** |
| * Sets the values in the table, and puts it in the panel. |
| * |
| * @return the panel containing the table. |
| */ |
| JPanel updateTable() |
| { |
| DefaultTableModel mod = (DefaultTableModel) fileTable.getModel(); |
| ListModel lm = fileList.getModel(); |
| DateFormat dt = DateFormat.getDateTimeInstance(DateFormat.SHORT, |
| DateFormat.SHORT); |
| File curr = null; |
| int size = lm.getSize(); |
| int rc = mod.getRowCount(); |
| |
| // If there are not enough rows |
| for (int x = rc; x < size; x++) |
| mod.addRow(new Object[3]); |
| |
| for (int i = 0; i < size; i++) |
| { |
| curr = (File) lm.getElementAt(i); |
| fileTable.setValueAt(curr.getName(), i, 0); |
| fileTable.setValueAt(formatSize(curr.length()), i, 1); |
| fileTable.setValueAt(dt.format(new Date(curr.lastModified())), i, 2); |
| } |
| |
| // If there are too many rows |
| while (rc > size) |
| mod.removeRow(--rc); |
| |
| scrollPane.getViewport().setView(fileTable); |
| scrollPane.setColumnHeaderView(fileTable.getTableHeader()); |
| |
| fileTablePanel.removeAll(); |
| fileTablePanel.add(scrollPane); |
| |
| return fileTablePanel; |
| } |
| |
| /** |
| * Formats bytes into the appropriate size. |
| * |
| * @param bytes the number of bytes to convert |
| * @return a string representation of the size |
| */ |
| private String formatSize(long bytes) |
| { |
| NumberFormat nf = NumberFormat.getNumberInstance(); |
| long mb = (long) Math.pow(2, 20); |
| long kb = (long) Math.pow(2, 10); |
| long gb = (long) Math.pow(2, 30); |
| double size = 0; |
| String id = ""; |
| |
| if ((bytes / gb) >= 1) |
| { |
| size = (double) bytes / (double) gb; |
| id = "GB"; |
| } |
| else if ((bytes / mb) >= 1) |
| { |
| size = (double) bytes / (double) mb; |
| id = "MB"; |
| } |
| else if ((bytes / kb) >= 1) |
| { |
| size = (double) bytes / (double) kb; |
| id = "KB"; |
| } |
| else |
| { |
| size = bytes; |
| id = "Bytes"; |
| } |
| |
| return nf.format(size) + " " + id; |
| } |
| /** |
| * Creates a listener that monitors selections in the directory/file list |
| * and keeps the {@link JFileChooser} component up to date. |
| * |
| * @param fc the file chooser. |
| * |
| * @return The listener. |
| * |
| * @see #installListeners(JFileChooser) |
| */ |
| public ListSelectionListener createListSelectionListener(JFileChooser fc) |
| { |
| return new MetalFileChooserSelectionListener(); |
| } |
| |
| /** |
| * Returns the preferred size for the file chooser component. |
| * |
| * @return The preferred size. |
| */ |
| public Dimension getPreferredSize(JComponent c) |
| { |
| Dimension tp = topPanel.getPreferredSize(); |
| Dimension bp = bottomPanel.getPreferredSize(); |
| Dimension fl = fileListPanel.getPreferredSize(); |
| return new Dimension(fl.width, tp.height + bp.height + fl.height); |
| } |
| |
| /** |
| * Returns the minimum size for the file chooser component. |
| * |
| * @return The minimum size. |
| */ |
| public Dimension getMinimumSize(JComponent c) |
| { |
| Dimension tp = topPanel.getMinimumSize(); |
| Dimension bp = bottomPanel.getMinimumSize(); |
| Dimension fl = fileListPanel.getMinimumSize(); |
| return new Dimension(fl.width, tp.height + bp.height + fl.height); |
| } |
| |
| /** |
| * Returns the maximum size for the file chooser component. |
| * |
| * @return The maximum size. |
| */ |
| public Dimension getMaximumSize(JComponent c) |
| { |
| return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); |
| } |
| |
| /** |
| * Creates a property change listener that monitors the {@link JFileChooser} |
| * for property change events and updates the component display accordingly. |
| * |
| * @param fc the file chooser. |
| * |
| * @return The property change listener. |
| * |
| * @see #installListeners(JFileChooser) |
| */ |
| public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) |
| { |
| return new MetalFileChooserPropertyChangeListener(); |
| } |
| |
| /** |
| * Creates and returns a new instance of {@link DirectoryComboBoxModel}. |
| * |
| * @return A new instance of {@link DirectoryComboBoxModel}. |
| */ |
| protected MetalFileChooserUI.DirectoryComboBoxModel |
| createDirectoryComboBoxModel(JFileChooser fc) |
| { |
| return new DirectoryComboBoxModel(); |
| } |
| |
| /** |
| * Creates a new instance of the renderer used in the directory |
| * combo box. |
| * |
| * @param fc the file chooser. |
| * |
| * @return The renderer. |
| */ |
| protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer( |
| JFileChooser fc) |
| { |
| return new DirectoryComboBoxRenderer(fc); |
| } |
| |
| /** |
| * Creates and returns a new instance of {@link FilterComboBoxModel}. |
| * |
| * @return A new instance of {@link FilterComboBoxModel}. |
| */ |
| protected FilterComboBoxModel createFilterComboBoxModel() |
| { |
| return new FilterComboBoxModel(); |
| } |
| |
| /** |
| * Creates and returns a new instance of {@link FilterComboBoxRenderer}. |
| * |
| * @return A new instance of {@link FilterComboBoxRenderer}. |
| */ |
| protected MetalFileChooserUI.FilterComboBoxRenderer |
| createFilterComboBoxRenderer() |
| { |
| return new FilterComboBoxRenderer(); |
| } |
| |
| /** |
| * Adds the control buttons ('up', 'home' etc.) to the panel. |
| */ |
| protected void addControlButtons() |
| { |
| JButton upButton = new JButton(getChangeToParentDirectoryAction()); |
| upButton.setText(null); |
| upButton.setIcon(this.upFolderIcon); |
| upButton.setMargin(new Insets(0, 0, 0, 0)); |
| controls.add(upButton); |
| |
| JButton homeButton = new JButton(getGoHomeAction()); |
| homeButton.setText(null); |
| homeButton.setIcon(this.homeFolderIcon); |
| homeButton.setMargin(new Insets(0, 0, 0, 0)); |
| controls.add(homeButton); |
| |
| JButton newFolderButton = new JButton(getNewFolderAction()); |
| newFolderButton.setText(null); |
| newFolderButton.setIcon(this.newFolderIcon); |
| newFolderButton.setMargin(new Insets(0, 0, 0, 0)); |
| controls.add(newFolderButton); |
| |
| JToggleButton listButton = new JToggleButton(this.listViewIcon); |
| listButton.setMargin(new Insets(0, 0, 0, 0)); |
| listButton.addActionListener(new ListViewActionListener()); |
| listButton.setSelected(true); |
| listView = true; |
| controls.add(listButton); |
| |
| JToggleButton detailButton = new JToggleButton(this.detailsViewIcon); |
| detailButton.setMargin(new Insets(0, 0, 0, 0)); |
| detailButton.addActionListener(new DetailViewActionListener()); |
| detailButton.setSelected(false); |
| controls.add(detailButton); |
| |
| ButtonGroup buttonGroup = new ButtonGroup(); |
| buttonGroup.add(listButton); |
| buttonGroup.add(detailButton); |
| } |
| |
| /** |
| * Removes all the buttons from the control panel. |
| */ |
| protected void removeControlButtons() |
| { |
| controls.removeAll(); |
| controls.revalidate(); |
| controls.repaint(); |
| } |
| |
| /** |
| * Updates the current directory. |
| * |
| * @param fc the file chooser to update. |
| */ |
| public void rescanCurrentDirectory(JFileChooser fc) |
| { |
| directoryModel.setSelectedItem(fc.getCurrentDirectory()); |
| getModel().validateFileCache(); |
| if (!listView) |
| updateTable(); |
| else |
| createList(fc); |
| } |
| |
| /** |
| * Returns the file name in the text field. |
| * |
| * @return The file name. |
| */ |
| public String getFileName() |
| { |
| String result = null; |
| if (fileTextField != null) |
| result = fileTextField.getText(); |
| return result; |
| } |
| |
| /** |
| * Sets the file name in the text field. |
| * |
| * @param filename the file name. |
| */ |
| public void setFileName(String filename) |
| { |
| fileTextField.setText(filename); |
| } |
| |
| /** |
| * DOCUMENT ME!! |
| * |
| * @param e - DOCUMENT ME! |
| */ |
| public void valueChanged(ListSelectionEvent e) |
| { |
| // FIXME: Not sure what we should be doing here, if anything. |
| } |
| |
| /** |
| * Returns the approve button. |
| * |
| * @return The approve button. |
| */ |
| protected JButton getApproveButton(JFileChooser fc) |
| { |
| return approveButton; |
| } |
| |
| /** |
| * A layout manager that is used to arrange the subcomponents of the |
| * {@link JFileChooser}. |
| */ |
| class VerticalMidLayout implements LayoutManager |
| { |
| /** |
| * Performs the layout. |
| * |
| * @param parent the container. |
| */ |
| public void layoutContainer(Container parent) |
| { |
| int count = parent.getComponentCount(); |
| if (count > 0) |
| { |
| Insets insets = parent.getInsets(); |
| Component c = parent.getComponent(0); |
| Dimension prefSize = c.getPreferredSize(); |
| int h = parent.getHeight() - insets.top - insets.bottom; |
| int adj = Math.max(0, (h - prefSize.height) / 2); |
| c.setBounds(insets.left, insets.top + adj, parent.getWidth() |
| - insets.left - insets.right, |
| (int) Math.min(prefSize.getHeight(), h)); |
| } |
| } |
| |
| /** |
| * Returns the minimum layout size. |
| * |
| * @param parent the container. |
| * |
| * @return The minimum layout size. |
| */ |
| public Dimension minimumLayoutSize(Container parent) |
| { |
| return preferredLayoutSize(parent); |
| } |
| |
| /** |
| * Returns the preferred layout size. |
| * |
| * @param parent the container. |
| * |
| * @return The preferred layout size. |
| */ |
| public Dimension preferredLayoutSize(Container parent) |
| { |
| if (parent.getComponentCount() > 0) |
| { |
| return parent.getComponent(0).getPreferredSize(); |
| } |
| else return null; |
| } |
| |
| /** |
| * This layout manager does not need to track components, so this |
| * method does nothing. |
| * |
| * @param name the name the component is associated with. |
| * @param component the component. |
| */ |
| public void addLayoutComponent(String name, Component component) |
| { |
| // do nothing |
| } |
| |
| /** |
| * This layout manager does not need to track components, so this |
| * method does nothing. |
| * |
| * @param component the component. |
| */ |
| public void removeLayoutComponent(Component component) |
| { |
| // do nothing |
| } |
| } |
| |
| /** |
| * A layout manager that is used to arrange buttons for the |
| * {@link JFileChooser}. |
| */ |
| class ButtonLayout implements LayoutManager |
| { |
| static final int GAP = 4; |
| |
| /** |
| * Performs the layout. |
| * |
| * @param parent the container. |
| */ |
| public void layoutContainer(Container parent) |
| { |
| int count = parent.getComponentCount(); |
| if (count > 0) |
| { |
| // first find the widest button |
| int maxW = 0; |
| for (int i = 0; i < count; i++) |
| { |
| Component c = parent.getComponent(i); |
| Dimension prefSize = c.getPreferredSize(); |
| maxW = Math.max(prefSize.width, maxW); |
| } |
| |
| // then position the buttons |
| Insets insets = parent.getInsets(); |
| int availableH = parent.getHeight() - insets.top - insets.bottom; |
| int currentX = parent.getWidth() - insets.right; |
| for (int i = count - 1; i >= 0; i--) |
| { |
| Component c = parent.getComponent(i); |
| Dimension prefSize = c.getPreferredSize(); |
| int adj = Math.max(0, (availableH - prefSize.height) / 2); |
| currentX = currentX - prefSize.width; |
| c.setBounds(currentX, insets.top + adj, prefSize.width, |
| (int) Math.min(prefSize.getHeight(), availableH)); |
| currentX = currentX - GAP; |
| } |
| } |
| } |
| |
| /** |
| * Returns the minimum layout size. |
| * |
| * @param parent the container. |
| * |
| * @return The minimum layout size. |
| */ |
| public Dimension minimumLayoutSize(Container parent) |
| { |
| return preferredLayoutSize(parent); |
| } |
| |
| /** |
| * Returns the preferred layout size. |
| * |
| * @param parent the container. |
| * |
| * @return The preferred layout size. |
| */ |
| public Dimension preferredLayoutSize(Container parent) |
| { |
| Insets insets = parent.getInsets(); |
| int maxW = 0; |
| int maxH = 0; |
| int count = parent.getComponentCount(); |
| if (count > 0) |
| { |
| for (int i = 0; i < count; i++) |
| { |
| Component c = parent.getComponent(i); |
| Dimension d = c.getPreferredSize(); |
| maxW = Math.max(d.width, maxW); |
| maxH = Math.max(d.height, maxH); |
| } |
| } |
| return new Dimension(maxW * count + GAP * (count - 1) + insets.left |
| + insets.right, maxH + insets.top + insets.bottom); |
| } |
| |
| /** |
| * This layout manager does not need to track components, so this |
| * method does nothing. |
| * |
| * @param name the name the component is associated with. |
| * @param component the component. |
| */ |
| public void addLayoutComponent(String name, Component component) |
| { |
| // do nothing |
| } |
| |
| /** |
| * This layout manager does not need to track components, so this |
| * method does nothing. |
| * |
| * @param component the component. |
| */ |
| public void removeLayoutComponent(Component component) |
| { |
| // do nothing |
| } |
| } |
| |
| } |