/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.look.fc; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; import java.util.Enumeration; import java.util.LinkedList; import java.util.Locale; import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.AbstractListModel; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.Box; import javax.swing.BoxLayout; 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.JFileChooser; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileSystemView; import javax.swing.filechooser.FileView; import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicFileChooserUI; import sun.awt.shell.ShellFolder; import com.rapidminer.gui.look.borders.Borders; import com.rapidminer.gui.tools.ExtendedJToolBar; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceActionAdapter; import com.rapidminer.gui.tools.ResourceActionTransmitter; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.components.DropDownButton; import com.rapidminer.gui.tools.dialogs.ButtonDialog; import com.rapidminer.tools.I18N; /** * The UI for the extended file chooser. * * @author Ingo Mierswa, Tobias Malbrecht */ public class FileChooserUI extends BasicFileChooserUI { // TODO: add property specification via I18N public static final String FILECHOOSER_VIEW_TYPE = "FILECHOOSER_VIEW_TYPE"; public static final String FILECHOOSER_VIEW_THUMBNAIL = I18N.getMessage(I18N.getGUIBundle(), "gui.menu.file_chooser.view.thumbnails.label"); public static final String FILECHOOSER_VIEW_ICON = I18N.getMessage(I18N.getGUIBundle(), "gui.menu.file_chooser.view.icons.label"); public static final String FILECHOOSER_VIEW_LIST = I18N.getMessage(I18N.getGUIBundle(), "gui.menu.file_chooser.view.list.label"); public static final String FILECHOOSER_VIEW_DETAILS = I18N.getMessage(I18N.getGUIBundle(), "gui.menu.file_chooser.view.details.label"); public static final Icon FILECHOOSER_OPEN_ICON = SwingTools.createIcon("24/folder.png"); public static final Icon FILECHOOSER_SELECT_ICON = SwingTools.createIcon("24/folder.png"); public static final Icon FILECHOOSER_SAVE_ICON = SwingTools.createIcon("24/floppy_disk.png"); public static final Icon FILECHOOSER_CLOSE_ICON = SwingTools.createIcon("24/delete.png"); /** * Creates a new folder. */ private class NewFolderAction extends ResourceAction { private static final long serialVersionUID = -119998626996460617L; protected NewFolderAction() { super("file_chooser.new_folder"); } public void actionPerformed(ActionEvent e) { if (UIManager.getBoolean("FileChooser.readOnly")) { return; } JFileChooser fc = getFileChooser(); File currentDirectory = fc.getCurrentDirectory(); File newFolder = null; String name = SwingTools.showInputDialog("file_chooser.new_folder", ""); try { if ((name != null ) && (!"".equals(name))) { newFolder = fc.getFileSystemView().createNewFolder(currentDirectory); if (newFolder.renameTo(new File(newFolder.getParentFile(), name))) { newFolder = new File(newFolder.getParentFile(), name); } else { SwingTools.showVerySimpleErrorMessage("file_chooser.new_folder.rename", name); } } } catch (IOException exc) { SwingTools.showVerySimpleErrorMessage("file_chooser.new_folder.create", name); return; } catch (Exception exp) { // do nothing } if (fc.isMultiSelectionEnabled()) { fc.setSelectedFiles(new File[] { newFolder }); } else { fc.setSelectedFile(newFolder); } fc.rescanCurrentDirectory(); } } private static class AlignedLabel extends JLabel { private static final long serialVersionUID = 4912090609095372381L; private AlignedLabel[] group; private int maxWidth = 0; AlignedLabel(String text) { super(text); setAlignmentX(Component.LEFT_ALIGNMENT); } @Override public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); // Align the width with all other labels in group. return new Dimension(getMaxWidth(), d.height); } private int getMaxWidth() { if ((this.maxWidth == 0) && (this.group != null)) { int max = 0; for (AlignedLabel element : this.group) { max = Math.max(element.getSuperPreferredWidth(), max); } for (AlignedLabel element : this.group) { element.maxWidth = max; } } return this.maxWidth; } private int getSuperPreferredWidth() { if (getText() == null) { return super.getPreferredSize().width; } else { return super.getPreferredSize().width + 11; } } } private class DirectoryComboBoxAction extends AbstractAction { private static final long serialVersionUID = -6851838331146924117L; protected DirectoryComboBoxAction() { super("DirectoryComboBoxAction"); } public void actionPerformed(ActionEvent e) { File f = (File) FileChooserUI.this.directoryComboBox.getSelectedItem(); setCurrentDirectoryOfFileChooser(f); FileChooserUI.this.fileNameTextField.requestFocus(); } } private class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { private static final long serialVersionUID = -7578988904254755349L; private FileFilter[] filters; protected FilterComboBoxModel() { super(); this.filters = getFileChooser().getChoosableFileFilters(); } public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { this.filters = (FileFilter[]) e.getNewValue(); fireContentsChanged(this, -1, -1); } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { fireContentsChanged(this, -1, -1); } } public void setSelectedItem(Object filter) { if (filter != null) { getFileChooser().setFileFilter((FileFilter) filter); setFileName(null); fireContentsChanged(this, -1, -1); } } public Object getSelectedItem() { FileFilter currentFilter = getFileChooser().getFileFilter(); boolean found = false; if (currentFilter != null) { for (FileFilter element : this.filters) { if (element == currentFilter) { found = true; } } if (found == false) { getFileChooser().addChoosableFileFilter(currentFilter); } } return getFileChooser().getFileFilter(); } public int getSize() { if (this.filters != null) { return this.filters.length; } else { return 0; } } public Object getElementAt(int index) { if (index > getSize() - 1) { // This shouldn't happen. Try to recover gracefully. return getFileChooser().getFileFilter(); } if (this.filters != null) { return this.filters[index]; } else { return null; } } } private class FilterComboBoxRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = 7024419790190737084L; @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if ((value != null) && (value instanceof FileFilter)) { setText(((FileFilter) value).getDescription()); } if (isSelected && (index > -1)) { setBorder(FileChooserUI.this.roundComboboxListRendererBorder); } return this; } } private class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { private static final long serialVersionUID = -7566898679781533334L; private Vector<File> directories = new Vector<File>(); private int[] depths = null; private File selectedDirectory = null; private JFileChooser chooser = getFileChooser(); private FileSystemView fileSystemView = this.chooser.getFileSystemView(); public DirectoryComboBoxModel() { File dir = getFileChooser().getCurrentDirectory(); if (dir != null) { addItem(dir); } } private void addItem(File directory) { if (directory == null) { return; } this.directories.clear(); File[] baseFolders = this.fileSystemView.getRoots(); this.directories.addAll(Arrays.asList(baseFolders)); File canonical = null; try { canonical = directory.getCanonicalFile(); } catch (IOException e) { canonical = directory; } try { File sf = ShellFolder.getShellFolder(canonical); File f = sf; Vector<File> path = new Vector<File>(10); do { path.addElement(f); } while ((f = f.getParentFile()) != null); int pathCount = path.size(); for (int i = 0; i < pathCount; i++) { f = path.get(i); if (this.directories.contains(f)) { int topIndex = this.directories.indexOf(f); for (int j = i - 1; j >= 0; j--) { this.directories.insertElementAt(path.get(j), topIndex + i - j); } break; } } calculateDepths(); setSelectedItem(sf); } catch (FileNotFoundException ex) { calculateDepths(); } } private void calculateDepths() { this.depths = new int[this.directories.size()]; for (int i = 0; i < this.depths.length; i++) { File dir = this.directories.get(i); File parent = dir.getParentFile(); this.depths[i] = 0; if (parent != null) { for (int j = i - 1; j >= 0; j--) { if (parent.equals(this.directories.get(j))) { this.depths[i] = this.depths[j] + 1; break; } } } } } public int getDepth(int i) { return ((this.depths != null) && (i >= 0) && (i < this.depths.length)) ? this.depths[i] : 0; } public void setSelectedItem(Object selectedDirectory) { this.selectedDirectory = (File) selectedDirectory; fireContentsChanged(this, -1, -1); } public Object getSelectedItem() { return this.selectedDirectory; } public int getSize() { return this.directories.size(); } public Object getElementAt(int index) { return this.directories.elementAt(index); } } private static class IndentIcon implements Icon { private Icon icon; private int depth = 0; public void paintIcon(Component c, Graphics g, int x, int y) { if (icon != null) { if (c.getComponentOrientation().isLeftToRight()) { this.icon.paintIcon(c, g, x + this.depth * INDENT_SPACE, y); } else { this.icon.paintIcon(c, g, x, y); } } } public int getIconWidth() { if (icon == null) { return depth * INDENT_SPACE; } else { return this.icon.getIconWidth() + this.depth * INDENT_SPACE; } } public int getIconHeight() { if (icon == null) { return 0; } else { return this.icon.getIconHeight(); } } } private class DirectoryComboBoxRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = 4597909127976297943L; private IndentIcon indentIcon = new IndentIcon(); @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value == null) { setText(""); return this; } File directory = (File) value; setText(getFileChooser().getName(directory)); Icon icon = getFileChooser().getIcon(directory); if (icon == null) { icon = UIManager.getIcon("FileChooser.defaultDirectoryIcon"); } this.indentIcon.icon = icon; this.indentIcon.depth = FileChooserUI.this.directoryComboBoxModel.getDepth(index); setIcon(this.indentIcon); if (isSelected && (index > -1)) { setBorder(FileChooserUI.this.roundComboboxListRendererBorder); } return this; } } private class RapidLookFileView extends BasicFileView { @Override public Icon getIcon(File f) { Icon icon = getCachedIcon(f); if (icon != null) { return icon; } if (f != null) { icon = getFileChooser().getFileSystemView().getSystemIcon(f); } if (icon == null) { icon = super.getIcon(f); } cacheIcon(f, icon); return icon; } } private class BookmarkAction extends ResourceAction { private static final long serialVersionUID = -654304868192207741L; public BookmarkAction() { super("file_chooser.add_to_bookmarks"); } public void actionPerformed(ActionEvent e) { FileChooserUI.this.fileList.addToBookmarks(); } } private class GoBackAction extends ResourceAction { private static final long serialVersionUID = 5132122622014626886L; protected GoBackAction() { super("file_chooser.go_back"); } public void actionPerformed(ActionEvent e) { goBack(); } } private class CancelSelectionAction extends AbstractAction { private static final long serialVersionUID = 2080395201063859907L; public void actionPerformed(ActionEvent e) { FileChooserUI.this.fileList.stopThumbnailGeneration(); getFileChooser().cancelSelection(); } } private class ExtendedApproveSelectionAction extends ApproveSelectionAction { private static final long serialVersionUID = 4061933557078579689L; @Override public void actionPerformed(ActionEvent e) { FileChooserUI.this.fileList.stopThumbnailGeneration(); super.actionPerformed(e); } } private class ChangeToParentDirectoryAction extends ResourceAction { private static final long serialVersionUID = -3805300411336163058L; protected ChangeToParentDirectoryAction() { super("file_chooser.change_to_parent_directory"); } public void actionPerformed(ActionEvent e) { getFileChooser().changeToParentDirectory(); } } private class changeViewActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { updateView(e.getActionCommand()); } } private static class ChangeViewAction extends ResourceActionAdapter { private static final long serialVersionUID = 6720057807081456009L; public ChangeViewAction() { super("file_chooser.view"); } } public transient final Action NEW_FOLDER_ACTION = new NewFolderAction(); public final Action CHANGE_VIEW_ACTION = new ChangeViewAction(); public final Action ADD_TO_BOOKMARKS_ACTION = new BookmarkAction(); public final Action GO_BACK_ACTION = new GoBackAction(); public final Action GO_HOME_ACTION = new ResourceActionTransmitter("file_chooser.go_home", super.getGoHomeAction()); public final Action CHANGE_TO_PARENT_DIRECTORY = new ChangeToParentDirectoryAction(); private static File userHomeDirectory; private final static int INDENT_SPACE = 10; private ButtonGroup changeViewButtonGroup; public String viewType = FILECHOOSER_VIEW_DETAILS; protected Vector<String> backPathVector = new Vector<String>(); protected JButton bookmarksButton; private JPopupMenu changeViewPopup; private final Border roundComboboxListRendererBorder = Borders.getComboBoxListCellRendererFocusBorder(); private DropDownButton changeViewButton; protected FileList fileList; private JLabel lookInLabel; private JComboBox directoryComboBox; private DirectoryComboBoxModel directoryComboBoxModel; private Action directoryComboBoxAction = new DirectoryComboBoxAction(); private FilterComboBoxModel filterComboBoxModel; private JTextField fileNameTextField; private JButton approveButton; private JButton cancelButton; private JPanel buttonPanel; private JPanel bottomPanel; private JComboBox filterComboBox; private int lookInLabelMnemonic = 0; private String lookInLabelText = null; private String saveInLabelText = null; private int fileNameLabelMnemonic = 0; private String fileNameLabelText = null; private int filesOfTypeLabelMnemonic = 0; private String filesOfTypeLabelText = null; private BasicFileView fileView = new RapidLookFileView(); private Action cancelSelectionAction = new CancelSelectionAction(); private Action approveSelectionAction = new ExtendedApproveSelectionAction(); private boolean selected = false; private LinkedList<ChangeListener> listeners = new LinkedList<ChangeListener>(); public void addChangeListener(ChangeListener l) { listeners.add(l); } public void removeChangeListener(ChangeListener l) { listeners.remove(l); } protected ActionMap createActions() { final AbstractAction escAction = new AbstractAction() { private static final long serialVersionUID = -3976059968191425942L; public void actionPerformed(ActionEvent e) { FileChooserUI.this.fileList.stopThumbnailGeneration(); getFileChooser().cancelSelection(); } @Override public boolean isEnabled() { return getFileChooser().isEnabled(); } }; final ActionMap map = new ActionMapUIResource(); map.put("approveSelection", getApproveSelectionAction()); map.put("cancelSelection", escAction); return map; } @Override public Action getCancelSelectionAction() { return this.cancelSelectionAction; } @Override public Action getApproveSelectionAction() { return this.approveSelectionAction; } public String getView() { return this.viewType; } public static ComponentUI createUI(JComponent c) { return new FileChooserUI((JFileChooser) c); } public FileChooserUI(JFileChooser filechooser) { super(filechooser); } @Override public void installUI(JComponent c) { super.installUI(c); } @Override public void uninstallComponents(JFileChooser fc) { fc.removeAll(); this.bottomPanel = null; this.buttonPanel = null; this.fileList = null; super.uninstallComponents(fc); } @Override public void installComponents(JFileChooser fc) { FileSystemView fsv = fc.getFileSystemView(); userHomeDirectory = fsv.getHomeDirectory(); this.changeViewPopup = createViewPopupMenu(); fc.setLayout(new BorderLayout()); // ********************************* // // **** Construct the top panel **** // // ********************************* // // Directory manipulation buttons JToolBar topPanel = new ExtendedJToolBar(); topPanel.setFloatable(false); topPanel.setBorder(null); topPanel.setOpaque(false); JPanel panel = new JPanel(new BorderLayout(0, ButtonDialog.GAP)); panel.add(topPanel, BorderLayout.NORTH); // ComboBox Label this.lookInLabel = new JLabel(this.lookInLabelText); this.lookInLabel.setDisplayedMnemonic(this.lookInLabelMnemonic); topPanel.add(this.lookInLabel, BorderLayout.BEFORE_LINE_BEGINS); // CurrentDir ComboBox this.directoryComboBox = new JComboBox(); this.directoryComboBox.setOpaque(false); this.directoryComboBox.getAccessibleContext().setAccessibleDescription(this.lookInLabelText); this.directoryComboBox.putClientProperty("JComboBox.lightweightKeyboardNavigation", "Lightweight"); this.lookInLabel.setLabelFor(this.directoryComboBox); this.directoryComboBoxModel = createDirectoryComboBoxModel(fc); this.directoryComboBox.setModel(this.directoryComboBoxModel); this.directoryComboBox.addActionListener(this.directoryComboBoxAction); this.directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc)); this.directoryComboBox.setMaximumRowCount(9); topPanel.add(this.directoryComboBox); topPanel.addSeparator(); //back button JButton backButton = new JButton(GO_BACK_ACTION); backButton.setText(null); backButton.setRolloverEnabled(true); backButton.setIcon((Icon) GO_BACK_ACTION.getValue(Action.SMALL_ICON)); backButton.setToolTipText((String) GO_BACK_ACTION.getValue(Action.SHORT_DESCRIPTION)); backButton.getAccessibleContext().setAccessibleName((String) GO_BACK_ACTION.getValue(Action.ACCELERATOR_KEY)); backButton.setAlignmentX(Component.LEFT_ALIGNMENT); backButton.setAlignmentY(Component.CENTER_ALIGNMENT); backButton.setBackground((Color) UIManager.get("control")); backButton.setOpaque(false); backButton.setFocusable(false); topPanel.add(backButton); // Up Button JButton upFolderButton = new JButton(CHANGE_TO_PARENT_DIRECTORY); upFolderButton.setText(null); upFolderButton.setRolloverEnabled(true); upFolderButton.setIcon((Icon) CHANGE_TO_PARENT_DIRECTORY.getValue(Action.SMALL_ICON)); upFolderButton.setToolTipText((String) CHANGE_TO_PARENT_DIRECTORY.getValue(Action.SHORT_DESCRIPTION)); upFolderButton.getAccessibleContext().setAccessibleName((String) CHANGE_TO_PARENT_DIRECTORY.getValue(Action.ACCELERATOR_KEY)); upFolderButton.setAlignmentX(Component.LEFT_ALIGNMENT); upFolderButton.setAlignmentY(Component.CENTER_ALIGNMENT); upFolderButton.setBackground((Color) UIManager.get("control")); upFolderButton.setFocusable(false); upFolderButton.setOpaque(false); topPanel.add(upFolderButton); this.bookmarksButton = new JButton(ADD_TO_BOOKMARKS_ACTION); this.bookmarksButton.setText(null); this.bookmarksButton.setRolloverEnabled(true); this.bookmarksButton.setOpaque(false); this.bookmarksButton.setIcon((Icon) ADD_TO_BOOKMARKS_ACTION.getValue(Action.SMALL_ICON)); this.bookmarksButton.setFocusable(false); this.bookmarksButton.setToolTipText((String) ADD_TO_BOOKMARKS_ACTION.getValue(Action.SHORT_DESCRIPTION)); this.bookmarksButton.getAccessibleContext().setAccessibleName((String) ADD_TO_BOOKMARKS_ACTION.getValue(Action.ACCELERATOR_KEY)); this.bookmarksButton.setAlignmentX(Component.LEFT_ALIGNMENT); this.bookmarksButton.setAlignmentY(Component.CENTER_ALIGNMENT); this.bookmarksButton.setBackground((Color) UIManager.get("control")); topPanel.add(this.bookmarksButton); // Home Button File homeDir = fsv.getHomeDirectory(); String toolTipText = (String) GO_HOME_ACTION.getValue(Action.SHORT_DESCRIPTION); if (fsv.isRoot(homeDir)) { toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop". } JButton b = new JButton(GO_HOME_ACTION); b.setText(""); b.setRolloverEnabled(true); b.setIcon((Icon) GO_HOME_ACTION.getValue(Action.SMALL_ICON)); b.setToolTipText(toolTipText); b.getAccessibleContext().setAccessibleName((String) GO_HOME_ACTION.getValue(Action.ACCELERATOR_KEY)); b.setAlignmentX(Component.LEFT_ALIGNMENT); b.setAlignmentY(Component.CENTER_ALIGNMENT); b.setFocusable(false); b.setOpaque(false); topPanel.add(b); // New Directory Button b = new JButton(NEW_FOLDER_ACTION); b.setText(null); b.setRolloverEnabled(true); b.setIcon((Icon) NEW_FOLDER_ACTION.getValue(Action.SMALL_ICON)); b.setOpaque(false); b.setFocusable(false); b.setToolTipText((String) NEW_FOLDER_ACTION.getValue(Action.SHORT_DESCRIPTION)); b.getAccessibleContext().setAccessibleName((String) NEW_FOLDER_ACTION.getValue(Action.ACCELERATOR_KEY)); b.setAlignmentX(Component.LEFT_ALIGNMENT); b.setAlignmentY(Component.CENTER_ALIGNMENT); topPanel.add(b); // views button this.changeViewButton = new DropDownButton(CHANGE_VIEW_ACTION) { private static final long serialVersionUID = -2115601230879074911L; @Override protected JPopupMenu getPopupMenu() { return changeViewPopup; } }; this.changeViewButton.setText(null); this.changeViewButton.setRolloverEnabled(true); this.changeViewButton.setIcon((Icon) CHANGE_VIEW_ACTION.getValue(Action.SMALL_ICON)); this.changeViewButton.setToolTipText((String) CHANGE_VIEW_ACTION.getValue(Action.SHORT_DESCRIPTION)); this.changeViewButton.getAccessibleContext().setAccessibleName((String) CHANGE_VIEW_ACTION.getValue(Action.ACCELERATOR_KEY)); this.changeViewButton.setAlignmentX(Component.LEFT_ALIGNMENT); this.changeViewButton.setAlignmentY(Component.CENTER_ALIGNMENT); this.changeViewButton.setBackground((Color) UIManager.get("control")); this.changeViewButton.setOpaque(false); this.changeViewButton.setFocusable(false); this.changeViewButton.addToToolBar(topPanel); topPanel.setBackground((Color) UIManager.get("control")); // ************************************** // // ******* Add the directory pane ******* // // ************************************** // this.fileList = new FileList(this, fc); fc.addPropertyChangeListener(this.fileList); this.fileList.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS); JComponent accessory = fc.getAccessory(); if (accessory != null) { getAccessoryPanel().add(accessory); } panel.add(this.fileList, BorderLayout.CENTER); // ********************************** // // **** Construct the bottom panel ** // // ********************************** // JPanel bottomPanel = new JPanel(); bottomPanel.setOpaque(false); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); bottomPanel.setBorder(null); panel.add(bottomPanel, BorderLayout.SOUTH); fc.add(panel, BorderLayout.CENTER); // FileName label and textfield JPanel fileNamePanel = new JPanel(); fileNamePanel.setOpaque(false); fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS)); bottomPanel.add(fileNamePanel); bottomPanel.add(Box.createRigidArea(new Dimension(1, ButtonDialog.GAP))); AlignedLabel fileNameLabel = new AlignedLabel(this.fileNameLabelText); fileNameLabel.setDisplayedMnemonic(this.fileNameLabelMnemonic); fileNamePanel.add(fileNameLabel); this.fileNameTextField = new JTextField(); this.fileNameTextField.setPreferredSize(new Dimension(fileNameTextField.getWidth(), 26)); this.fileNameTextField.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { setFileSelected(); } @Override public void keyTyped(KeyEvent e) {} }); fileNamePanel.add(this.fileNameTextField); if (fc.isMultiSelectionEnabled()) { setFileName(fileNameString(fc.getSelectedFiles())); } else { setFileName(fileNameString(fc.getSelectedFile())); } // Filetype label and combobox JPanel filesOfTypePanel = new JPanel(); filesOfTypePanel.setOpaque(false); filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS)); bottomPanel.add(filesOfTypePanel); AlignedLabel filesOfTypeLabel = new AlignedLabel(this.filesOfTypeLabelText); filesOfTypeLabel.setDisplayedMnemonic(this.filesOfTypeLabelMnemonic); filesOfTypePanel.add(filesOfTypeLabel); this.filterComboBoxModel = createFilterComboBoxModel(); fc.addPropertyChangeListener(this.filterComboBoxModel); this.filterComboBox = new JComboBox(this.filterComboBoxModel); this.filterComboBox.setPreferredSize(new Dimension(filterComboBox.getWidth(), 26)); this.filterComboBox.setOpaque(false); this.filterComboBox.getAccessibleContext().setAccessibleDescription(this.filesOfTypeLabelText); filesOfTypeLabel.setLabelFor(this.filterComboBox); this.filterComboBox.setRenderer(createFilterComboBoxRenderer()); filesOfTypePanel.add(this.filterComboBox); // buttons fc.add(getBottomPanel(), BorderLayout.SOUTH); getButtonPanel().setLayout(new FlowLayout(FlowLayout.RIGHT)); this.approveButton = new JButton(getApproveButtonText(fc)); this.approveButton.setOpaque(false); this.approveButton.addActionListener(getApproveSelectionAction()); this.approveButton.setToolTipText(getApproveButtonToolTipText(fc)); this.approveButton.setIcon(getApproveButtonIcon(fc)); this.approveButton.setEnabled(false); getButtonPanel().add(this.approveButton); this.cancelButton = new JButton(this.cancelButtonText, FILECHOOSER_CLOSE_ICON); this.cancelButton.setOpaque(false); this.cancelButton.setToolTipText(this.cancelButtonToolTipText); this.cancelButton.addActionListener(getCancelSelectionAction()); getButtonPanel().add(this.cancelButton); if (fc.getControlButtonsAreShown()) { addControlButtons(); } groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel }); updateView(FILECHOOSER_VIEW_DETAILS); } @Override public Action getNewFolderAction() { Action newFolderAction = new NewFolderAction(); // Note: Don't return null for readOnly, it might // break older apps. if (UIManager.getBoolean("FileChooser.readOnly")) { newFolderAction.setEnabled(false); } return newFolderAction; } protected JPanel getButtonPanel() { if (this.buttonPanel == null) { this.buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); this.buttonPanel.setOpaque(false); this.buttonPanel.setBorder(null); } return this.buttonPanel; } protected JPanel getBottomPanel() { if (this.bottomPanel == null) { this.bottomPanel = new JPanel(); this.bottomPanel.setOpaque(false); this.bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); this.bottomPanel.setBorder(null); } return this.bottomPanel; } @Override protected void installStrings(JFileChooser fc) { super.installStrings(fc); Locale l = fc.getLocale(); this.lookInLabelMnemonic = UIManager.getInt("FileChooser.lookInLabelMnemonic"); this.lookInLabelText = UIManager.getString("FileChooser.lookInLabelText", l); this.saveInLabelText = UIManager.getString("FileChooser.saveInLabelText", l); this.fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic"); this.fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l); this.filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic"); this.filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l); // this.upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText", l); // this.upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName", l); // // this.homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText", l); // this.homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName", l); // this.newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText", l); // this.newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName", l); } @Override protected void installListeners(JFileChooser fc) { super.installListeners(fc); // this.changeViewPopup.addPropertyChangeListener(new PropertyChangeListener() { // public void propertyChange(PropertyChangeEvent e) { // if (e.getPropertyName().toLowerCase().equals("visible")) { // FileChooserUI.this.changeViewButton.setSelected(Boolean.parseBoolean(e.getNewValue().toString())); // } // } // }); ActionMap actionMap = getActions(); SwingUtilities.replaceUIActionMap(fc, actionMap); } protected ActionMap getActions() { return createActions(); } @Override public void uninstallUI(JComponent c) { c.removePropertyChangeListener(this.filterComboBoxModel); this.cancelButton.removeActionListener(getCancelSelectionAction()); this.approveButton.removeActionListener(getApproveSelectionAction()); this.fileNameTextField.removeActionListener(getApproveSelectionAction()); super.uninstallUI(c); } @Override public Dimension getMaximumSize(JComponent c) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } private void setFileSelected() { this.selected = fileNameTextField.getText() != null && !"".equals(fileNameTextField.getText()); approveButton.setEnabled(selected); for (ChangeListener l : listeners) { l.stateChanged(new ChangeEvent(this)); } } public boolean isFileSelected() { return this.selected; } private String fileNameString(File file) { if (file == null) { return null; } else { JFileChooser fc = getFileChooser(); if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { return file.getPath(); } else { return file.getName(); } } } private String fileNameString(File[] files) { StringBuffer buf = new StringBuffer(); for (int i = 0; (files != null) && (i < files.length); i++) { if (i > 0) { buf.append(" "); } if (files.length > 1) { buf.append("\""); } buf.append(fileNameString(files[i])); if (files.length > 1) { buf.append("\""); } } return buf.toString(); } /* The following methods are used by the PropertyChange Listener */ private void doSelectedFileChanged(PropertyChangeEvent e) { File f = (File) e.getNewValue(); JFileChooser fc = getFileChooser(); if ((f != null) && ((fc.isFileSelectionEnabled() && !f.isDirectory()) || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) { setFileName(fileNameString(f)); setFileSelected(); } } private void doSelectedFilesChanged(PropertyChangeEvent e) { File[] files = (File[]) e.getNewValue(); JFileChooser fc = getFileChooser(); if ((files != null) && (files.length > 0) && ((files.length > 1) || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) { setFileName(fileNameString(files)); } else { setFileName(""); } setFileSelected(); } private void doDirectoryChanged(PropertyChangeEvent e) { JFileChooser fc = getFileChooser(); FileSystemView fsv = fc.getFileSystemView(); clearIconCache(); File currentDirectory = fc.getCurrentDirectory(); this.fileList.updatePath(currentDirectory); if (currentDirectory != null) { this.directoryComboBoxModel.addItem(currentDirectory); getNewFolderAction().setEnabled(currentDirectory.canWrite()); getChangeToParentDirectoryAction().setEnabled(!fsv.isRoot(currentDirectory)); getChangeToParentDirectoryAction().setEnabled(!fsv.isRoot(currentDirectory)); getGoHomeAction().setEnabled(!userHomeDirectory.equals(currentDirectory)); if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { if (fsv.isFileSystem(currentDirectory)) { setFileName(currentDirectory.getPath()); } else { setFileName(null); } setFileSelected(); } } } private void doFilterChanged(PropertyChangeEvent e) { this.fileList.doFilterChanged(); } private void doFileSelectionModeChanged(PropertyChangeEvent e) { doFilterChanged(e); JFileChooser fc = getFileChooser(); File currentDirectory = fc.getCurrentDirectory(); if ((currentDirectory != null) && fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystem(currentDirectory)) { setFileName(currentDirectory.getPath()); } else { setFileName(null); } setFileSelected(); } private void doMultiSelectionChanged(PropertyChangeEvent e) { if (getFileChooser().isMultiSelectionEnabled()) { } else { getFileChooser().setSelectedFiles(null); } } private void doAccessoryChanged(PropertyChangeEvent e) { if (getAccessoryPanel() != null) { if (e.getOldValue() != null) { getAccessoryPanel().remove((JComponent) e.getOldValue()); } JComponent accessory = (JComponent) e.getNewValue(); if (accessory != null) { getAccessoryPanel().add(accessory, BorderLayout.CENTER); } } } private Icon getApproveButtonIcon(JFileChooser fc) { if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) { return FILECHOOSER_OPEN_ICON; } if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) { return FILECHOOSER_SAVE_ICON; } if (fc.getDialogType() == JFileChooser.CUSTOM_DIALOG) { return FILECHOOSER_SELECT_ICON; } return FILECHOOSER_SELECT_ICON; } private void doApproveButtonTextChanged(PropertyChangeEvent e) { JFileChooser chooser = getFileChooser(); this.approveButton.setText(getApproveButtonText(chooser)); this.approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); this.approveButton.setIcon(getApproveButtonIcon(chooser)); } private void doDialogTypeChanged(PropertyChangeEvent e) { JFileChooser chooser = getFileChooser(); this.approveButton.setText(getApproveButtonText(chooser)); this.approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); this.approveButton.setIcon(getApproveButtonIcon(chooser)); if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) { this.lookInLabel.setText(this.saveInLabelText); } else { this.lookInLabel.setText(this.lookInLabelText); } } private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) {} private void doControlButtonsChanged(PropertyChangeEvent e) { if (getFileChooser().getControlButtonsAreShown()) { addControlButtons(); } else { removeControlButtons(); } } @Override public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { return new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { String s = e.getPropertyName(); if (s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) { doSelectedFileChanged(e); } else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) { doSelectedFilesChanged(e); } else if (s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) { doDirectoryChanged(e); } else if (s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { doFilterChanged(e); } else if (s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) { doFileSelectionModeChanged(e); } else if (s.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) { doMultiSelectionChanged(e); } else if (s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) { doAccessoryChanged(e); } else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) || s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) { doApproveButtonTextChanged(e); } else if (s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) { doDialogTypeChanged(e); } else if (s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) { doApproveButtonMnemonicChanged(e); } else if (s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) { doControlButtonsChanged(e); } else if (s.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)) { FileChooserUI.this.fileList.doFilterChanged(); } else if (s.equals("componentOrientation")) { ComponentOrientation o = (ComponentOrientation) e.getNewValue(); JFileChooser cc = (JFileChooser) e.getSource(); if (o != (ComponentOrientation) e.getOldValue()) { cc.applyComponentOrientation(o); } } else if (s.equals("ancestor")) { if ((e.getOldValue() == null) && (e.getNewValue() != null)) { // Ancestor was added, set initial focus FileChooserUI.this.fileNameTextField.selectAll(); FileChooserUI.this.fileList.itemPanel.requestFocus(); } } } }; } protected void removeControlButtons() { getBottomPanel().remove(getButtonPanel()); } protected void addControlButtons() { getBottomPanel().add(getButtonPanel()); } public JButton getApproveButton() { return this.approveButton; } public JButton getCancelButton() { return this.cancelButton; } @Override public void ensureFileIsVisible(JFileChooser fc, File f) {} @Override public void rescanCurrentDirectory(JFileChooser fc) { this.fileList.rescanDirectory(); } @Override public String getFileName() { if (this.fileNameTextField != null) { return this.fileNameTextField.getText(); } else { return null; } } @Override public void setFileName(String filename) { if (this.fileNameTextField != null) { this.fileNameTextField.setText(filename); } } @Override protected void setDirectorySelected(boolean directorySelected) { super.setDirectorySelected(directorySelected); JFileChooser chooser = getFileChooser(); if (directorySelected) { this.approveButton.setText(this.directoryOpenButtonText); this.approveButton.setToolTipText(this.directoryOpenButtonToolTipText); } else { this.approveButton.setText(getApproveButtonText(chooser)); this.approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); } } @Override public String getDirectoryName() { return null; } @Override public void setDirectoryName(String dirname) {} protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { return new DirectoryComboBoxRenderer(); } protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) { return new DirectoryComboBoxModel(); } protected FilterComboBoxRenderer createFilterComboBoxRenderer() { return new FilterComboBoxRenderer(); } protected FilterComboBoxModel createFilterComboBoxModel() { return new FilterComboBoxModel(); } public void valueChanged(ListSelectionEvent e) { JFileChooser fc = getFileChooser(); File f = fc.getSelectedFile(); if (!e.getValueIsAdjusting() && (f != null) && !getFileChooser().isTraversable(f)) { setFileName(fileNameString(f)); setFileSelected(); } } protected void setCurrentDirectoryOfFileChooser(File f) { getFileChooser().setCurrentDirectory(f); } @Override protected JButton getApproveButton(JFileChooser fc) { return this.approveButton; } private static void groupLabels(AlignedLabel[] group) { for (AlignedLabel element : group) { element.group = group; } } @Override public FileView getFileView(JFileChooser fc) { return this.fileView; } public void goBack() { if (this.backPathVector.size() > 0) { setCurrentDirectoryOfFileChooser(new File(this.backPathVector.elementAt(this.backPathVector.size() - 1))); if (this.backPathVector.size() > 1) { this.backPathVector.setSize(this.backPathVector.size() - 2); } else { this.backPathVector.setSize(this.backPathVector.size() - 1); } if (this.backPathVector.size() <= 0) { getGoBackAction().setEnabled(false); } } } public Action getGoBackAction() { return GO_BACK_ACTION; } @Override public Action getGoHomeAction() { return GO_HOME_ACTION; } @Override public Action getChangeToParentDirectoryAction() { return CHANGE_TO_PARENT_DIRECTORY; } public JPopupMenu createViewPopupMenu() { JMenuItem menuItem; changeViewActionListener mal = new changeViewActionListener(); this.changeViewPopup = new JPopupMenu(); this.changeViewButtonGroup = new ButtonGroup(); menuItem = new JRadioButtonMenuItem(FILECHOOSER_VIEW_THUMBNAIL); this.changeViewButtonGroup.add(menuItem); menuItem.setActionCommand(FILECHOOSER_VIEW_THUMBNAIL); menuItem.addActionListener(mal); this.changeViewPopup.add(menuItem); menuItem = new JRadioButtonMenuItem(FILECHOOSER_VIEW_ICON); menuItem.setActionCommand(FILECHOOSER_VIEW_ICON); this.changeViewButtonGroup.add(menuItem); menuItem.addActionListener(mal); this.changeViewPopup.add(menuItem); menuItem = new JRadioButtonMenuItem(FILECHOOSER_VIEW_LIST); menuItem.setActionCommand(FILECHOOSER_VIEW_LIST); this.changeViewButtonGroup.add(menuItem); menuItem.addActionListener(mal); menuItem.setSelected(true); this.changeViewPopup.add(menuItem); menuItem = new JRadioButtonMenuItem(FILECHOOSER_VIEW_DETAILS); menuItem.setActionCommand(FILECHOOSER_VIEW_DETAILS); this.changeViewButtonGroup.add(menuItem); menuItem.addActionListener(mal); this.changeViewPopup.add(menuItem); return this.changeViewPopup; } protected void updateView(String s) { if (!s.equals(FILECHOOSER_VIEW_DETAILS) && !s.equals(FILECHOOSER_VIEW_ICON) && !s.equals(FILECHOOSER_VIEW_LIST) && !s.equals(FILECHOOSER_VIEW_THUMBNAIL)) { return; } this.viewType = s; this.fileList.changeCardForView(); //synchronizing menu's JRadioButtonMenuItem rbm; Enumeration en = this.changeViewButtonGroup.getElements(); while (en.hasMoreElements()) { rbm = (JRadioButtonMenuItem) en.nextElement(); if (rbm.getActionCommand().equals(this.getView())) { this.changeViewButtonGroup.setSelected(rbm.getModel(), true); } } } }