Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java
38918 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.swing.plaf.synth;2526import java.awt.*;27import java.awt.event.*;28import java.beans.*;29import java.io.*;30import java.util.*;31import java.security.AccessController;32import java.security.PrivilegedAction;3334import javax.swing.*;35import javax.swing.event.*;36import javax.swing.filechooser.*;37import javax.swing.filechooser.FileFilter;38import javax.swing.plaf.basic.*;39import javax.swing.plaf.synth.*;40import javax.swing.plaf.ActionMapUIResource;4142import sun.awt.shell.ShellFolder;43import sun.swing.*;4445/**46* Synth FileChooserUI implementation.47* <p>48* Note that the classes in the com.sun.java.swing.plaf.synth49* package are not50* part of the core Java APIs. They are a part of Sun's JDK and JRE51* distributions. Although other licensees may choose to distribute52* these classes, developers cannot depend on their availability in53* non-Sun implementations. Additionally this API may change in54* incompatible ways between releases. While this class is public, it55* shoud be considered an implementation detail, and subject to change.56*57* @author Leif Samuelsson58* @author Jeff Dinkins59*/60public class SynthFileChooserUIImpl extends SynthFileChooserUI {61private JLabel lookInLabel;62private JComboBox<File> directoryComboBox;63private DirectoryComboBoxModel directoryComboBoxModel;64private Action directoryComboBoxAction = new DirectoryComboBoxAction();6566private FilterComboBoxModel filterComboBoxModel;6768private JTextField fileNameTextField;6970private FilePane filePane;71private JToggleButton listViewButton;72private JToggleButton detailsViewButton;7374private boolean readOnly;7576private JPanel buttonPanel;77private JPanel bottomPanel;7879private JComboBox<FileFilter> filterComboBox;8081private static final Dimension hstrut5 = new Dimension(5, 1);8283private static final Insets shrinkwrap = new Insets(0,0,0,0);8485// Preferred and Minimum sizes for the dialog box86private static Dimension LIST_PREF_SIZE = new Dimension(405, 135);8788// Labels, mnemonics, and tooltips (oh my!)89private int lookInLabelMnemonic = 0;90private String lookInLabelText = null;91private String saveInLabelText = null;9293private int fileNameLabelMnemonic = 0;94private String fileNameLabelText = null;95private int folderNameLabelMnemonic = 0;96private String folderNameLabelText = null;9798private int filesOfTypeLabelMnemonic = 0;99private String filesOfTypeLabelText = null;100101private String upFolderToolTipText = null;102private String upFolderAccessibleName = null;103104private String homeFolderToolTipText = null;105private String homeFolderAccessibleName = null;106107private String newFolderToolTipText = null;108private String newFolderAccessibleName = null;109110private String listViewButtonToolTipText = null;111private String listViewButtonAccessibleName = null;112113private String detailsViewButtonToolTipText = null;114private String detailsViewButtonAccessibleName = null;115116private AlignedLabel fileNameLabel;117private final PropertyChangeListener modeListener = new PropertyChangeListener() {118public void propertyChange(PropertyChangeEvent event) {119if (fileNameLabel != null) {120populateFileNameLabel();121}122}123};124125private void populateFileNameLabel() {126if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {127fileNameLabel.setText(folderNameLabelText);128fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic);129} else {130fileNameLabel.setText(fileNameLabelText);131fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);132}133}134135public SynthFileChooserUIImpl(JFileChooser b) {136super(b);137}138139140private class SynthFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {141public JFileChooser getFileChooser() {142return SynthFileChooserUIImpl.this.getFileChooser();143}144145public BasicDirectoryModel getModel() {146return SynthFileChooserUIImpl.this.getModel();147}148149public JPanel createList() {150return null;151}152153public JPanel createDetailsView() {154return null;155}156157public boolean isDirectorySelected() {158return SynthFileChooserUIImpl.this.isDirectorySelected();159}160161public File getDirectory() {162return SynthFileChooserUIImpl.this.getDirectory();163}164165public Action getChangeToParentDirectoryAction() {166return SynthFileChooserUIImpl.this.getChangeToParentDirectoryAction();167}168169public Action getApproveSelectionAction() {170return SynthFileChooserUIImpl.this.getApproveSelectionAction();171}172173public Action getNewFolderAction() {174return SynthFileChooserUIImpl.this.getNewFolderAction();175}176177public MouseListener createDoubleClickListener(JList list) {178return SynthFileChooserUIImpl.this.createDoubleClickListener(getFileChooser(),179list);180}181182public ListSelectionListener createListSelectionListener() {183return SynthFileChooserUIImpl.this.createListSelectionListener(getFileChooser());184}185}186187protected void installDefaults(JFileChooser fc) {188super.installDefaults(fc);189readOnly = UIManager.getBoolean("FileChooser.readOnly");190}191192public void installComponents(JFileChooser fc) {193super.installComponents(fc);194195SynthContext context = getContext(fc, ENABLED);196197fc.setLayout(new BorderLayout(0, 11));198199// ********************************* //200// **** Construct the top panel **** //201// ********************************* //202203// Directory manipulation buttons204JPanel topPanel = new JPanel(new BorderLayout(11, 0));205JPanel topButtonPanel = new JPanel();206topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.LINE_AXIS));207topPanel.add(topButtonPanel, BorderLayout.AFTER_LINE_ENDS);208209// Add the top panel to the fileChooser210fc.add(topPanel, BorderLayout.NORTH);211212// ComboBox Label213lookInLabel = new JLabel(lookInLabelText);214lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);215topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS);216217// CurrentDir ComboBox218directoryComboBox = new JComboBox<File>();219directoryComboBox.getAccessibleContext().setAccessibleDescription(lookInLabelText);220directoryComboBox.putClientProperty( "JComboBox.isTableCellEditor", Boolean.TRUE );221lookInLabel.setLabelFor(directoryComboBox);222directoryComboBoxModel = createDirectoryComboBoxModel(fc);223directoryComboBox.setModel(directoryComboBoxModel);224directoryComboBox.addActionListener(directoryComboBoxAction);225directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));226directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);227directoryComboBox.setAlignmentY(JComponent.TOP_ALIGNMENT);228directoryComboBox.setMaximumRowCount(8);229topPanel.add(directoryComboBox, BorderLayout.CENTER);230231filePane = new FilePane(new SynthFileChooserUIAccessor());232fc.addPropertyChangeListener(filePane);233234// Add 'Go Up' to context menu, plus 'Go Home' if on Unix235JPopupMenu contextMenu = filePane.getComponentPopupMenu();236if (contextMenu != null) {237contextMenu.insert(getChangeToParentDirectoryAction(), 0);238if (File.separatorChar == '/') {239contextMenu.insert(getGoHomeAction(), 1);240}241}242243FileSystemView fsv = fc.getFileSystemView();244245// Up Button246JButton upFolderButton = new JButton(getChangeToParentDirectoryAction());247upFolderButton.setText(null);248upFolderButton.setIcon(upFolderIcon);249upFolderButton.setToolTipText(upFolderToolTipText);250upFolderButton.getAccessibleContext().setAccessibleName(upFolderAccessibleName);251upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);252upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);253upFolderButton.setMargin(shrinkwrap);254255topButtonPanel.add(upFolderButton);256topButtonPanel.add(Box.createRigidArea(hstrut5));257258// Home Button259File homeDir = fsv.getHomeDirectory();260String toolTipText = homeFolderToolTipText;261262JButton b = new JButton(homeFolderIcon);263b.setToolTipText(toolTipText);264b.getAccessibleContext().setAccessibleName(homeFolderAccessibleName);265b.setAlignmentX(JComponent.LEFT_ALIGNMENT);266b.setAlignmentY(JComponent.CENTER_ALIGNMENT);267b.setMargin(shrinkwrap);268269b.addActionListener(getGoHomeAction());270topButtonPanel.add(b);271topButtonPanel.add(Box.createRigidArea(hstrut5));272273// New Directory Button274if (!readOnly) {275b = new JButton(filePane.getNewFolderAction());276b.setText(null);277b.setIcon(newFolderIcon);278b.setToolTipText(newFolderToolTipText);279b.getAccessibleContext().setAccessibleName(newFolderAccessibleName);280b.setAlignmentX(JComponent.LEFT_ALIGNMENT);281b.setAlignmentY(JComponent.CENTER_ALIGNMENT);282b.setMargin(shrinkwrap);283topButtonPanel.add(b);284topButtonPanel.add(Box.createRigidArea(hstrut5));285}286287// View button group288ButtonGroup viewButtonGroup = new ButtonGroup();289290// List Button291listViewButton = new JToggleButton(listViewIcon);292listViewButton.setToolTipText(listViewButtonToolTipText);293listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName);294listViewButton.setSelected(true);295listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);296listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);297listViewButton.setMargin(shrinkwrap);298listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));299topButtonPanel.add(listViewButton);300viewButtonGroup.add(listViewButton);301302// Details Button303detailsViewButton = new JToggleButton(detailsViewIcon);304detailsViewButton.setToolTipText(detailsViewButtonToolTipText);305detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName);306detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);307detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);308detailsViewButton.setMargin(shrinkwrap);309detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));310topButtonPanel.add(detailsViewButton);311viewButtonGroup.add(detailsViewButton);312313filePane.addPropertyChangeListener(new PropertyChangeListener() {314public void propertyChange(PropertyChangeEvent e) {315if ("viewType".equals(e.getPropertyName())) {316int viewType = filePane.getViewType();317switch (viewType) {318case FilePane.VIEWTYPE_LIST:319listViewButton.setSelected(true);320break;321case FilePane.VIEWTYPE_DETAILS:322detailsViewButton.setSelected(true);323break;324}325}326}327});328329// ************************************** //330// ******* Add the directory pane ******* //331// ************************************** //332fc.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);333JComponent accessory = fc.getAccessory();334if (accessory != null) {335getAccessoryPanel().add(accessory);336}337filePane.setPreferredSize(LIST_PREF_SIZE);338fc.add(filePane, BorderLayout.CENTER);339340341// ********************************** //342// **** Construct the bottom panel ** //343// ********************************** //344bottomPanel = new JPanel();345bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));346fc.add(bottomPanel, BorderLayout.SOUTH);347348// FileName label and textfield349JPanel fileNamePanel = new JPanel();350fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS));351bottomPanel.add(fileNamePanel);352bottomPanel.add(Box.createRigidArea(new Dimension(1, 5)));353354fileNameLabel = new AlignedLabel();355populateFileNameLabel();356fileNamePanel.add(fileNameLabel);357358fileNameTextField = new JTextField(35) {359public Dimension getMaximumSize() {360return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);361}362};363fileNamePanel.add(fileNameTextField);364fileNameLabel.setLabelFor(fileNameTextField);365fileNameTextField.addFocusListener(366new FocusAdapter() {367public void focusGained(FocusEvent e) {368if (!getFileChooser().isMultiSelectionEnabled()) {369filePane.clearSelection();370}371}372}373);374if (fc.isMultiSelectionEnabled()) {375setFileName(fileNameString(fc.getSelectedFiles()));376} else {377setFileName(fileNameString(fc.getSelectedFile()));378}379380381// Filetype label and combobox382JPanel filesOfTypePanel = new JPanel();383filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS));384bottomPanel.add(filesOfTypePanel);385386AlignedLabel filesOfTypeLabel = new AlignedLabel(filesOfTypeLabelText);387filesOfTypeLabel.setDisplayedMnemonic(filesOfTypeLabelMnemonic);388filesOfTypePanel.add(filesOfTypeLabel);389390filterComboBoxModel = createFilterComboBoxModel();391fc.addPropertyChangeListener(filterComboBoxModel);392filterComboBox = new JComboBox<FileFilter>(filterComboBoxModel);393filterComboBox.getAccessibleContext().setAccessibleDescription(filesOfTypeLabelText);394filesOfTypeLabel.setLabelFor(filterComboBox);395filterComboBox.setRenderer(createFilterComboBoxRenderer());396filesOfTypePanel.add(filterComboBox);397398399// buttons400buttonPanel = new JPanel();401buttonPanel.setLayout(new ButtonAreaLayout());402403buttonPanel.add(getApproveButton(fc));404buttonPanel.add(getCancelButton(fc));405406if (fc.getControlButtonsAreShown()) {407addControlButtons();408}409410groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel });411}412413protected void installListeners(JFileChooser fc) {414super.installListeners(fc);415fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener);416}417418protected void uninstallListeners(JFileChooser fc) {419fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener);420super.uninstallListeners(fc);421}422423private String fileNameString(File file) {424if (file == null) {425return null;426} else {427JFileChooser fc = getFileChooser();428if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {429return file.getPath();430} else {431return file.getName();432}433}434}435436private String fileNameString(File[] files) {437StringBuffer buf = new StringBuffer();438for (int i = 0; files != null && i < files.length; i++) {439if (i > 0) {440buf.append(" ");441}442if (files.length > 1) {443buf.append("\"");444}445buf.append(fileNameString(files[i]));446if (files.length > 1) {447buf.append("\"");448}449}450return buf.toString();451}452453public void uninstallUI(JComponent c) {454// Remove listeners455c.removePropertyChangeListener(filterComboBoxModel);456c.removePropertyChangeListener(filePane);457458if (filePane != null) {459filePane.uninstallUI();460filePane = null;461}462463super.uninstallUI(c);464}465466protected void installStrings(JFileChooser fc) {467super.installStrings(fc);468469Locale l = fc.getLocale();470471lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);472lookInLabelText = UIManager.getString("FileChooser.lookInLabelText", l);473saveInLabelText = UIManager.getString("FileChooser.saveInLabelText", l);474475fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);476fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l);477folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);478folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText", l);479480filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);481filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l);482483upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText",l);484upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l);485486homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText",l);487homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l);488489newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);490newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);491492listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l);493listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l);494495detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l);496detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l);497}498499private int getMnemonic(String key, Locale l) {500return SwingUtilities2.getUIDefaultsInt(key, l);501}502503504public String getFileName() {505if (fileNameTextField != null) {506return fileNameTextField.getText();507} else {508return null;509}510}511512public void setFileName(String fileName) {513if (fileNameTextField != null) {514fileNameTextField.setText(fileName);515}516}517518@Override public void rescanCurrentDirectory(JFileChooser fc) {519filePane.rescanCurrentDirectory();520}521522protected void doSelectedFileChanged(PropertyChangeEvent e) {523super.doSelectedFileChanged(e);524525File f = (File) e.getNewValue();526JFileChooser fc = getFileChooser();527if (f != null528&& ((fc.isFileSelectionEnabled() && !f.isDirectory())529|| (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {530531setFileName(fileNameString(f));532}533}534535protected void doSelectedFilesChanged(PropertyChangeEvent e) {536super.doSelectedFilesChanged(e);537538File[] files = (File[]) e.getNewValue();539JFileChooser fc = getFileChooser();540if (files != null541&& files.length > 0542&& (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {543setFileName(fileNameString(files));544}545}546547protected void doDirectoryChanged(PropertyChangeEvent e) {548super.doDirectoryChanged(e);549550JFileChooser fc = getFileChooser();551FileSystemView fsv = fc.getFileSystemView();552File currentDirectory = fc.getCurrentDirectory();553554if (!readOnly && currentDirectory != null) {555getNewFolderAction().setEnabled(filePane.canWrite(currentDirectory));556}557558if (currentDirectory != null) {559JComponent cb = getDirectoryComboBox();560if (cb instanceof JComboBox) {561ComboBoxModel model = ((JComboBox)cb).getModel();562if (model instanceof DirectoryComboBoxModel) {563((DirectoryComboBoxModel)model).addItem(currentDirectory);564}565}566567if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {568if (fsv.isFileSystem(currentDirectory)) {569setFileName(currentDirectory.getPath());570} else {571setFileName(null);572}573}574}575}576577578protected void doFileSelectionModeChanged(PropertyChangeEvent e) {579super.doFileSelectionModeChanged(e);580581JFileChooser fc = getFileChooser();582File currentDirectory = fc.getCurrentDirectory();583if (currentDirectory != null584&& fc.isDirectorySelectionEnabled()585&& !fc.isFileSelectionEnabled()586&& fc.getFileSystemView().isFileSystem(currentDirectory)) {587588setFileName(currentDirectory.getPath());589} else {590setFileName(null);591}592}593594protected void doAccessoryChanged(PropertyChangeEvent e) {595if (getAccessoryPanel() != null) {596if (e.getOldValue() != null) {597getAccessoryPanel().remove((JComponent)e.getOldValue());598}599JComponent accessory = (JComponent)e.getNewValue();600if (accessory != null) {601getAccessoryPanel().add(accessory, BorderLayout.CENTER);602}603}604}605606protected void doControlButtonsChanged(PropertyChangeEvent e) {607super.doControlButtonsChanged(e);608609if (getFileChooser().getControlButtonsAreShown()) {610addControlButtons();611} else {612removeControlButtons();613}614}615616protected void addControlButtons() {617if (bottomPanel != null) {618bottomPanel.add(buttonPanel);619}620}621622protected void removeControlButtons() {623if (bottomPanel != null) {624bottomPanel.remove(buttonPanel);625}626}627628629630631// *******************************************************632// ************ FileChooser UI PLAF methods **************633// *******************************************************634635protected ActionMap createActionMap() {636ActionMap map = new ActionMapUIResource();637// add standard actions638FilePane.addActionsToMap(map, filePane.getActions());639// add synth only actions640map.put("fileNameCompletion", getFileNameCompletionAction());641return map;642}643644// *****************************645// ***** Directory Actions *****646// *****************************647648protected JComponent getDirectoryComboBox() {649return directoryComboBox;650}651652protected Action getDirectoryComboBoxAction() {653return directoryComboBoxAction;654}655656protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {657return new DirectoryComboBoxRenderer(directoryComboBox.getRenderer());658}659660//661// Renderer for DirectoryComboBox662//663// Synth has some odd behavior with regards to renderers. Renderers are styled664// in a specific manner by the SynthComboBoxUI. If we extend DefaultListCellRenderer665// here, then we get none of those benefits or behaviors, leading to poor666// looking combo boxes.667// So what we do here is delegate most jobs to the "real" or original renderer,668// and simply monkey with the icon and text of the renderer.669private class DirectoryComboBoxRenderer implements ListCellRenderer<File> {670private ListCellRenderer<? super File> delegate;671IndentIcon ii = new IndentIcon();672673private DirectoryComboBoxRenderer(ListCellRenderer<? super File> delegate) {674this.delegate = delegate;675}676677@Override678public Component getListCellRendererComponent(JList<? extends File> list, File value, int index, boolean isSelected, boolean cellHasFocus) {679Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);680681assert c instanceof JLabel;682JLabel label = (JLabel)c;683if (value == null) {684label.setText("");685return label;686}687label.setText(getFileChooser().getName(value));688Icon icon = getFileChooser().getIcon(value);689ii.icon = icon;690ii.depth = directoryComboBoxModel.getDepth(index);691label.setIcon(ii);692693return label;694}695}696697final static int space = 10;698class IndentIcon implements Icon {699700Icon icon = null;701int depth = 0;702703public void paintIcon(Component c, Graphics g, int x, int y) {704if (icon != null) {705if (c.getComponentOrientation().isLeftToRight()) {706icon.paintIcon(c, g, x+depth*space, y);707} else {708icon.paintIcon(c, g, x, y);709}710}711}712713public int getIconWidth() {714return ((icon != null) ? icon.getIconWidth() : 0) + depth*space;715}716717public int getIconHeight() {718return (icon != null) ? icon.getIconHeight() : 0;719}720721}722723//724// DataModel for DirectoryComboxbox725//726protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {727return new DirectoryComboBoxModel();728}729730/**731* Data model for a type-face selection combo-box.732*/733protected class DirectoryComboBoxModel extends AbstractListModel<File> implements ComboBoxModel<File> {734Vector<File> directories = new Vector<File>();735int[] depths = null;736File selectedDirectory = null;737JFileChooser chooser = getFileChooser();738FileSystemView fsv = chooser.getFileSystemView();739740public DirectoryComboBoxModel() {741// Add the current directory to the model, and make it the742// selectedDirectory743File dir = getFileChooser().getCurrentDirectory();744if (dir != null) {745addItem(dir);746}747}748749/**750* Adds the directory to the model and sets it to be selected,751* additionally clears out the previous selected directory and752* the paths leading up to it, if any.753*/754public void addItem(File directory) {755756if (directory == null) {757return;758}759760boolean useShellFolder = FilePane.usesShellFolder(chooser);761762int oldSize = directories.size();763directories.clear();764if (oldSize > 0) {765fireIntervalRemoved(this, 0, oldSize);766}767768File[] baseFolders = (useShellFolder)769? (File[]) ShellFolder.get("fileChooserComboBoxFolders")770: fsv.getRoots();771directories.addAll(Arrays.asList(baseFolders));772773// Get the canonical (full) path. This has the side774// benefit of removing extraneous chars from the path,775// for example /foo/bar/ becomes /foo/bar776File canonical;777try {778canonical = ShellFolder.getNormalizedFile(directory);779} catch (IOException e) {780// Maybe drive is not ready. Can't abort here.781canonical = directory;782}783784// create File instances of each directory leading up to the top785try {786File sf = useShellFolder ? ShellFolder.getShellFolder(canonical)787: canonical;788File f = sf;789Vector<File> path = new Vector<File>(10);790do {791path.addElement(f);792} while ((f = f.getParentFile()) != null);793794int pathCount = path.size();795// Insert chain at appropriate place in vector796for (int i = 0; i < pathCount; i++) {797f = path.get(i);798if (directories.contains(f)) {799int topIndex = directories.indexOf(f);800for (int j = i-1; j >= 0; j--) {801directories.insertElementAt(path.get(j), topIndex+i-j);802}803break;804}805}806calculateDepths();807setSelectedItem(sf);808} catch (FileNotFoundException ex) {809calculateDepths();810}811}812813private void calculateDepths() {814depths = new int[directories.size()];815for (int i = 0; i < depths.length; i++) {816File dir = directories.get(i);817File parent = dir.getParentFile();818depths[i] = 0;819if (parent != null) {820for (int j = i-1; j >= 0; j--) {821if (parent.equals(directories.get(j))) {822depths[i] = depths[j] + 1;823break;824}825}826}827}828}829830public int getDepth(int i) {831return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;832}833834public void setSelectedItem(Object selectedDirectory) {835this.selectedDirectory = (File)selectedDirectory;836fireContentsChanged(this, -1, -1);837}838839public Object getSelectedItem() {840return selectedDirectory;841}842843public int getSize() {844return directories.size();845}846847public File getElementAt(int index) {848return directories.elementAt(index);849}850}851852/**853* Acts when DirectoryComboBox has changed the selected item.854*/855protected class DirectoryComboBoxAction extends AbstractAction {856protected DirectoryComboBoxAction() {857super("DirectoryComboBoxAction");858}859860public void actionPerformed(ActionEvent e) {861directoryComboBox.hidePopup();862JComponent cb = getDirectoryComboBox();863if (cb instanceof JComboBox) {864File f = (File)((JComboBox)cb).getSelectedItem();865getFileChooser().setCurrentDirectory(f);866}867}868}869870//871// Renderer for Types ComboBox872//873protected FilterComboBoxRenderer createFilterComboBoxRenderer() {874return new FilterComboBoxRenderer(filterComboBox.getRenderer());875}876877/**878* Render different type sizes and styles.879*/880public class FilterComboBoxRenderer implements ListCellRenderer<FileFilter> {881private ListCellRenderer<? super FileFilter> delegate;882private FilterComboBoxRenderer(ListCellRenderer<? super FileFilter> delegate) {883this.delegate = delegate;884}885886public Component getListCellRendererComponent(JList<? extends FileFilter> list, FileFilter value, int index,887boolean isSelected, boolean cellHasFocus) {888Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);889890String text = null;891if (value != null) {892text = value.getDescription();893}894895//this should always be true, since SynthComboBoxUI's SynthComboBoxRenderer896//extends JLabel897assert c instanceof JLabel;898if (text != null) {899((JLabel)c).setText(text);900}901return c;902}903}904905//906// DataModel for Types Comboxbox907//908protected FilterComboBoxModel createFilterComboBoxModel() {909return new FilterComboBoxModel();910}911912/**913* Data model for a type-face selection combo-box.914*/915protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,916PropertyChangeListener {917protected FileFilter[] filters;918protected FilterComboBoxModel() {919super();920filters = getFileChooser().getChoosableFileFilters();921}922923public void propertyChange(PropertyChangeEvent e) {924String prop = e.getPropertyName();925if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {926filters = (FileFilter[]) e.getNewValue();927fireContentsChanged(this, -1, -1);928} else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {929fireContentsChanged(this, -1, -1);930}931}932933public void setSelectedItem(Object filter) {934if(filter != null) {935getFileChooser().setFileFilter((FileFilter) filter);936fireContentsChanged(this, -1, -1);937}938}939940public Object getSelectedItem() {941// Ensure that the current filter is in the list.942// NOTE: we shouldnt' have to do this, since JFileChooser adds943// the filter to the choosable filters list when the filter944// is set. Lets be paranoid just in case someone overrides945// setFileFilter in JFileChooser.946FileFilter currentFilter = getFileChooser().getFileFilter();947boolean found = false;948if(currentFilter != null) {949for (FileFilter filter : filters) {950if (filter == currentFilter) {951found = true;952}953}954if(found == false) {955getFileChooser().addChoosableFileFilter(currentFilter);956}957}958return getFileChooser().getFileFilter();959}960961public int getSize() {962if(filters != null) {963return filters.length;964} else {965return 0;966}967}968969public FileFilter getElementAt(int index) {970if(index > getSize() - 1) {971// This shouldn't happen. Try to recover gracefully.972return getFileChooser().getFileFilter();973}974if(filters != null) {975return filters[index];976} else {977return null;978}979}980}981982983984/**985* <code>ButtonAreaLayout</code> behaves in a similar manner to986* <code>FlowLayout</code>. It lays out all components from left to987* right, flushed right. The widths of all components will be set988* to the largest preferred size width.989*/990private static class ButtonAreaLayout implements LayoutManager {991private int hGap = 5;992private int topMargin = 17;993994public void addLayoutComponent(String string, Component comp) {995}996997public void layoutContainer(Container container) {998Component[] children = container.getComponents();9991000if (children != null && children.length > 0) {1001int numChildren = children.length;1002Dimension[] sizes = new Dimension[numChildren];1003Insets insets = container.getInsets();1004int yLocation = insets.top + topMargin;1005int maxWidth = 0;10061007for (int counter = 0; counter < numChildren; counter++) {1008sizes[counter] = children[counter].getPreferredSize();1009maxWidth = Math.max(maxWidth, sizes[counter].width);1010}1011int xLocation, xOffset;1012if (container.getComponentOrientation().isLeftToRight()) {1013xLocation = container.getSize().width - insets.left - maxWidth;1014xOffset = hGap + maxWidth;1015} else {1016xLocation = insets.left;1017xOffset = -(hGap + maxWidth);1018}1019for (int counter = numChildren - 1; counter >= 0; counter--) {1020children[counter].setBounds(xLocation, yLocation,1021maxWidth, sizes[counter].height);1022xLocation -= xOffset;1023}1024}1025}10261027public Dimension minimumLayoutSize(Container c) {1028if (c != null) {1029Component[] children = c.getComponents();10301031if (children != null && children.length > 0) {1032int numChildren = children.length;1033int height = 0;1034Insets cInsets = c.getInsets();1035int extraHeight = topMargin + cInsets.top + cInsets.bottom;1036int extraWidth = cInsets.left + cInsets.right;1037int maxWidth = 0;10381039for (int counter = 0; counter < numChildren; counter++) {1040Dimension aSize = children[counter].getPreferredSize();1041height = Math.max(height, aSize.height);1042maxWidth = Math.max(maxWidth, aSize.width);1043}1044return new Dimension(extraWidth + numChildren * maxWidth +1045(numChildren - 1) * hGap,1046extraHeight + height);1047}1048}1049return new Dimension(0, 0);1050}10511052public Dimension preferredLayoutSize(Container c) {1053return minimumLayoutSize(c);1054}10551056public void removeLayoutComponent(Component c) { }1057}10581059private static void groupLabels(AlignedLabel[] group) {1060for (int i = 0; i < group.length; i++) {1061group[i].group = group;1062}1063}10641065private class AlignedLabel extends JLabel {1066private AlignedLabel[] group;1067private int maxWidth = 0;10681069AlignedLabel() {1070super();1071setAlignmentX(JComponent.LEFT_ALIGNMENT);1072}10731074AlignedLabel(String text) {1075super(text);1076setAlignmentX(JComponent.LEFT_ALIGNMENT);1077}10781079public Dimension getPreferredSize() {1080Dimension d = super.getPreferredSize();1081// Align the width with all other labels in group.1082return new Dimension(getMaxWidth() + 11, d.height);1083}10841085private int getMaxWidth() {1086if (maxWidth == 0 && group != null) {1087int max = 0;1088for (int i = 0; i < group.length; i++) {1089max = Math.max(group[i].getSuperPreferredWidth(), max);1090}1091for (int i = 0; i < group.length; i++) {1092group[i].maxWidth = max;1093}1094}1095return maxWidth;1096}10971098private int getSuperPreferredWidth() {1099return super.getPreferredSize().width;1100}1101}1102}110311041105