Source Code Cross Referenced for DirectoryChooserUI.java in  » IDE-Netbeans » library » org » netbeans » swing » dirchooser » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » library » org.netbeans.swing.dirchooser 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         *
0041:         * Contributor(s): Soot Phengsy
0042:         */
0043:
0044:        package org.netbeans.swing.dirchooser;
0045:
0046:        import java.util.logging.Level;
0047:        import javax.swing.*;
0048:        import javax.swing.Box;
0049:        import javax.swing.BoxLayout;
0050:        import javax.swing.Timer;
0051:        import javax.swing.event.TreeExpansionListener;
0052:        import javax.swing.event.TreeSelectionEvent;
0053:        import javax.swing.event.TreeSelectionListener;
0054:        import javax.swing.filechooser.*;
0055:        import javax.swing.plaf.basic.*;
0056:        import java.awt.*;
0057:        import java.awt.event.ActionEvent;
0058:        import java.awt.event.ActionListener;
0059:        import java.awt.event.FocusAdapter;
0060:        import java.awt.event.FocusEvent;
0061:        import java.awt.event.FocusListener;
0062:        import java.awt.event.KeyAdapter;
0063:        import java.awt.event.KeyEvent;
0064:        import java.awt.event.MouseAdapter;
0065:        import java.awt.event.MouseEvent;
0066:        import java.beans.PropertyChangeEvent;
0067:        import java.beans.PropertyChangeListener;
0068:        import java.io.File;
0069:        import java.io.IOException;
0070:        import java.lang.ref.WeakReference;
0071:        import java.lang.reflect.Constructor;
0072:        import java.security.AccessControlException;
0073:        import java.text.MessageFormat;
0074:        import java.util.*;
0075:        import java.util.logging.Logger;
0076:        import java.util.regex.Matcher;
0077:        import java.util.regex.Pattern;
0078:        import javax.swing.border.EmptyBorder;
0079:        import javax.swing.event.CellEditorListener;
0080:        import javax.swing.event.ChangeEvent;
0081:        import javax.swing.event.DocumentEvent;
0082:        import javax.swing.event.DocumentListener;
0083:        import javax.swing.event.TreeExpansionEvent;
0084:        import javax.swing.plaf.ActionMapUIResource;
0085:        import javax.swing.plaf.ComponentUI;
0086:        import javax.swing.plaf.UIResource;
0087:        import javax.swing.tree.DefaultTreeModel;
0088:        import javax.swing.tree.TreeCellEditor;
0089:        import javax.swing.tree.TreePath;
0090:        import javax.swing.tree.TreeCellRenderer;
0091:        import javax.swing.tree.TreeNode;
0092:        import javax.swing.tree.TreeSelectionModel;
0093:        import org.openide.awt.HtmlRenderer;
0094:        import org.openide.filesystems.FileObject;
0095:        import org.openide.filesystems.FileUtil;
0096:        import org.openide.util.NbBundle;
0097:        import org.openide.util.RequestProcessor;
0098:        import org.openide.util.Utilities;
0099:
0100:        /**
0101:         * An implementation of a customized filechooser.
0102:         *
0103:         * @author Soot Phengsy, inspired by Jeff Dinkins' Swing version
0104:         */
0105:        public class DirectoryChooserUI extends BasicFileChooserUI {
0106:
0107:            private static final Dimension horizontalStrut1 = new Dimension(25,
0108:                    1);
0109:            private static final Dimension verticalStrut1 = new Dimension(1, 4);
0110:            private static final Dimension verticalStrut2 = new Dimension(1, 6);
0111:            private static final Dimension verticalStrut3 = new Dimension(1, 8);
0112:            private static Dimension PREF_SIZE = new Dimension(425, 245);
0113:            private static Dimension MIN_SIZE = new Dimension(425, 245);
0114:            private static Dimension TREE_PREF_SIZE = new Dimension(380, 230);
0115:            private static final int ACCESSORY_WIDTH = 250;
0116:
0117:            /** icon representing netbeans project folder */
0118:            private static Icon projectIcon;
0119:
0120:            private JPanel centerPanel;
0121:
0122:            private JLabel lookInComboBoxLabel;
0123:
0124:            private JComboBox directoryComboBox;
0125:
0126:            private DirectoryComboBoxModel directoryComboBoxModel;
0127:
0128:            private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction();
0129:
0130:            private FilterTypeComboBoxModel filterTypeComboBoxModel;
0131:
0132:            private JTextField filenameTextField;
0133:
0134:            private JComponent placesBar;
0135:            private boolean placesBarFailed = false;
0136:
0137:            private JButton approveButton;
0138:            private JButton cancelButton;
0139:
0140:            private JPanel buttonPanel;
0141:            private JPanel bottomPanel;
0142:
0143:            private JComboBox filterTypeComboBox;
0144:
0145:            private int lookInLabelMnemonic = 0;
0146:            private String lookInLabelText = null;
0147:            private String saveInLabelText = null;
0148:
0149:            private int fileNameLabelMnemonic = 0;
0150:            private String fileNameLabelText = null;
0151:
0152:            private int filesOfTypeLabelMnemonic = 0;
0153:            private String filesOfTypeLabelText = null;
0154:
0155:            private String upFolderToolTipText = null;
0156:            private String upFolderAccessibleName = null;
0157:
0158:            private String newFolderToolTipText = null;
0159:
0160:            private Action newFolderAction = new NewDirectoryAction();
0161:
0162:            private BasicFileView fileView = new DirectoryChooserFileView();
0163:
0164:            private static JTree tree;
0165:
0166:            private DirectoryTreeModel model;
0167:
0168:            private DirectoryNode newFolderNode;
0169:
0170:            private JComponent treeViewPanel;
0171:
0172:            private InputBlocker blocker;
0173:
0174:            private static JFileChooser fileChooser;
0175:
0176:            private boolean changeDirectory = true;
0177:
0178:            private boolean showPopupCompletion = false;
0179:
0180:            private boolean addNewDirectory = false;
0181:
0182:            private JPopupMenu popupMenu;
0183:
0184:            private FileCompletionPopup completionPopup;
0185:
0186:            private RequestProcessor.Task updateWorker;
0187:
0188:            private boolean useShellFolder = false;
0189:
0190:            private JButton upFolderButton;
0191:            private JButton newFolderButton;
0192:
0193:            private JComponent topCombo, topComboWrapper, topToolbar;
0194:
0195:            public static ComponentUI createUI(JComponent c) {
0196:                return new DirectoryChooserUI((JFileChooser) c);
0197:            }
0198:
0199:            public DirectoryChooserUI(JFileChooser filechooser) {
0200:                super (filechooser);
0201:            }
0202:
0203:            public void installUI(JComponent c) {
0204:                super .installUI(c);
0205:            }
0206:
0207:            public void uninstallComponents(JFileChooser fc) {
0208:                fc.removeAll();
0209:                super .uninstallComponents(fc);
0210:            }
0211:
0212:            public void installComponents(JFileChooser fc) {
0213:                fileChooser = fc;
0214:
0215:                fc.setFocusCycleRoot(true);
0216:                fc.setBorder(new EmptyBorder(4, 10, 10, 10));
0217:                fc.setLayout(new BorderLayout(8, 8));
0218:
0219:                updateUseShellFolder();
0220:                createCenterPanel(fc);
0221:                fc.add(centerPanel, BorderLayout.CENTER);
0222:
0223:                if (fc.isMultiSelectionEnabled()) {
0224:                    setFileName(getStringOfFileNames(fc.getSelectedFiles()));
0225:                } else {
0226:                    setFileName(getStringOfFileName(fc.getSelectedFile()));
0227:                }
0228:
0229:                if (fc.getControlButtonsAreShown()) {
0230:                    addControlButtons();
0231:                }
0232:
0233:                createPopup();
0234:            }
0235:
0236:            private void updateUseShellFolder() {
0237:                // Decide whether to use the ShellFolder class to populate shortcut
0238:                // panel and combobox.
0239:
0240:                Boolean prop = (Boolean) fileChooser
0241:                        .getClientProperty("FileChooser.useShellFolder");
0242:                if (prop != null) {
0243:                    useShellFolder = prop.booleanValue();
0244:                } else {
0245:                    // See if FileSystemView.getRoots() returns the desktop folder,
0246:                    // i.e. the normal Windows hierarchy.
0247:                    useShellFolder = false;
0248:                    File[] roots = fileChooser.getFileSystemView().getRoots();
0249:                    if (roots != null && roots.length == 1) {
0250:                        File[] cbFolders = getShellFolderRoots();
0251:                        if (cbFolders != null && cbFolders.length > 0
0252:                                && roots[0] == cbFolders[0]) {
0253:                            useShellFolder = true;
0254:                        }
0255:                    }
0256:                }
0257:
0258:                if (Utilities.isWindows()) {
0259:                    if (useShellFolder) {
0260:                        if (placesBar == null) {
0261:                            placesBar = getPlacesBar();
0262:                        }
0263:                        if (placesBar != null) {
0264:                            fileChooser.add(placesBar,
0265:                                    BorderLayout.BEFORE_LINE_BEGINS);
0266:                            if (placesBar instanceof  PropertyChangeListener) {
0267:                                fileChooser
0268:                                        .addPropertyChangeListener((PropertyChangeListener) placesBar);
0269:                            }
0270:                        }
0271:                    } else {
0272:                        if (placesBar != null) {
0273:                            fileChooser.remove(placesBar);
0274:                            if (placesBar instanceof  PropertyChangeListener) {
0275:                                fileChooser
0276:                                        .removePropertyChangeListener((PropertyChangeListener) placesBar);
0277:                            }
0278:                            placesBar = null;
0279:                        }
0280:                    }
0281:                }
0282:            }
0283:
0284:            /** Returns instance of WindowsPlacesBar class or null in case of failure
0285:             */
0286:            private JComponent getPlacesBar() {
0287:                if (placesBarFailed) {
0288:                    return null;
0289:                }
0290:                try {
0291:                    Class<?> clazz = Class
0292:                            .forName("sun.swing.WindowsPlacesBar");
0293:                    Class[] params = new Class[] { JFileChooser.class,
0294:                            Boolean.TYPE };
0295:                    Constructor<?> constr = clazz.getConstructor(params);
0296:                    return (JComponent) constr.newInstance(fileChooser,
0297:                            isXPStyle().booleanValue());
0298:                } catch (Exception exc) {
0299:                    // reflection not succesfull, just log the exception and return null
0300:                    Logger.getLogger(DirectoryChooserUI.class.getName()).log(
0301:                            Level.FINE,
0302:                            "WindowsPlacesBar class can't be instantiated.",
0303:                            exc);
0304:                    placesBarFailed = true;
0305:                    return null;
0306:                }
0307:            }
0308:
0309:            /** Reflection alternative of
0310:             * sun.awt.shell.ShellFolder.getShellFolder(file)
0311:             */
0312:            private File getShellFolderForFile(File file) {
0313:                try {
0314:                    Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
0315:                    return (File) clazz.getMethod("getShellFolder", File.class)
0316:                            .invoke(null, file);
0317:                } catch (Exception exc) {
0318:                    // reflection not succesfull, just log the exception and return null
0319:                    Logger.getLogger(DirectoryChooserUI.class.getName()).log(
0320:                            Level.FINE, "ShellFolder can't be used.", exc);
0321:                    return null;
0322:                }
0323:            }
0324:
0325:            /** Reflection alternative of
0326:             * sun.awt.shell.ShellFolder.getShellFolder(dir).getLinkLocation()
0327:             */
0328:            private File getShellFolderForFileLinkLoc(File file) {
0329:                try {
0330:                    Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
0331:                    Object sf = clazz.getMethod("getShellFolder", File.class)
0332:                            .invoke(null, file);
0333:                    return (File) clazz.getMethod("getLinkLocation").invoke(sf);
0334:                } catch (Exception exc) {
0335:                    // reflection not succesfull, just log the exception and return null
0336:                    Logger.getLogger(DirectoryChooserUI.class.getName()).log(
0337:                            Level.FINE, "ShellFolder can't be used.", exc);
0338:                    return null;
0339:                }
0340:
0341:            }
0342:
0343:            /** Reflection alternative of
0344:             * sun.awt.shell.ShellFolder.get("fileChooserComboBoxFolders")
0345:             */
0346:            private File[] getShellFolderRoots() {
0347:                try {
0348:                    Class<?> clazz = Class.forName("sun.awt.shell.ShellFolder");
0349:                    return (File[]) clazz.getMethod("get", String.class)
0350:                            .invoke(null, "fileChooserComboBoxFolders");
0351:                } catch (Exception exc) {
0352:                    // reflection not succesfull, just log the exception and return null
0353:                    Logger.getLogger(DirectoryChooserUI.class.getName()).log(
0354:                            Level.FINE, "ShellFolder can't be used.", exc);
0355:                    return null;
0356:                }
0357:            }
0358:
0359:            private void createBottomPanel(JFileChooser fc) {
0360:                bottomPanel = new JPanel();
0361:                bottomPanel.setLayout(new BoxLayout(bottomPanel,
0362:                        BoxLayout.LINE_AXIS));
0363:                JPanel labelPanel = new JPanel();
0364:                labelPanel.setLayout(new BoxLayout(labelPanel,
0365:                        BoxLayout.PAGE_AXIS));
0366:                labelPanel.add(Box.createRigidArea(verticalStrut1));
0367:
0368:                JLabel fnl = new JLabel(fileNameLabelText);
0369:                fnl.setDisplayedMnemonic(fileNameLabelMnemonic);
0370:                fnl.setAlignmentY(0);
0371:                labelPanel.add(fnl);
0372:
0373:                labelPanel.add(Box.createRigidArea(new Dimension(1, 12)));
0374:
0375:                JLabel ftl = new JLabel(filesOfTypeLabelText);
0376:                ftl.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
0377:                labelPanel.add(ftl);
0378:
0379:                bottomPanel.add(labelPanel);
0380:                bottomPanel.add(Box.createRigidArea(new Dimension(15, 0)));
0381:
0382:                JPanel fileAndFilterPanel = new JPanel();
0383:                fileAndFilterPanel.add(Box.createRigidArea(verticalStrut3));
0384:                fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel,
0385:                        BoxLayout.Y_AXIS));
0386:
0387:                filenameTextField = new JTextField(24) {
0388:                    public Dimension getMaximumSize() {
0389:                        return new Dimension(Short.MAX_VALUE, super 
0390:                                .getPreferredSize().height);
0391:                    }
0392:                };
0393:
0394:                filenameTextField.getDocument().addDocumentListener(
0395:                        new DocumentListener() {
0396:                            public void insertUpdate(DocumentEvent e) {
0397:                                updateCompletions();
0398:                            }
0399:
0400:                            public void removeUpdate(DocumentEvent e) {
0401:                                updateCompletions();
0402:                            }
0403:
0404:                            public void changedUpdate(DocumentEvent e) {
0405:                            }
0406:                        });
0407:
0408:                filenameTextField.addKeyListener(new TextFieldKeyListener());
0409:
0410:                fnl.setLabelFor(filenameTextField);
0411:                filenameTextField.addFocusListener(new FocusAdapter() {
0412:                    public void focusGained(FocusEvent e) {
0413:                        if (!getFileChooser().isMultiSelectionEnabled()) {
0414:                            tree.clearSelection();
0415:                        }
0416:                    }
0417:                });
0418:
0419:                // disable TAB focus transfer, we need it for completion
0420:                Set<AWTKeyStroke> tKeys = filenameTextField
0421:                        .getFocusTraversalKeys(java.awt.KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
0422:                Set<AWTKeyStroke> newTKeys = new HashSet<AWTKeyStroke>(tKeys);
0423:                newTKeys.remove(AWTKeyStroke
0424:                        .getAWTKeyStroke(KeyEvent.VK_TAB, 0));
0425:                // #107305: enable at least Ctrl+TAB if we have TAB for completion
0426:                newTKeys.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0427:                        KeyEvent.CTRL_DOWN_MASK));
0428:                filenameTextField.setFocusTraversalKeys(
0429:                        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newTKeys);
0430:
0431:                fileAndFilterPanel.add(filenameTextField);
0432:                fileAndFilterPanel.add(Box.createRigidArea(verticalStrut3));
0433:
0434:                filterTypeComboBoxModel = createFilterComboBoxModel();
0435:                fc.addPropertyChangeListener(filterTypeComboBoxModel);
0436:                filterTypeComboBox = new JComboBox(filterTypeComboBoxModel);
0437:                ftl.setLabelFor(filterTypeComboBox);
0438:                filterTypeComboBox.setRenderer(createFilterComboBoxRenderer());
0439:                fileAndFilterPanel.add(filterTypeComboBox);
0440:
0441:                bottomPanel.add(fileAndFilterPanel);
0442:                bottomPanel.add(Box.createRigidArea(horizontalStrut1));
0443:                createButtonsPanel(fc);
0444:            }
0445:
0446:            private void createButtonsPanel(JFileChooser fc) {
0447:                buttonPanel = new JPanel();
0448:                buttonPanel.setLayout(new BoxLayout(buttonPanel,
0449:                        BoxLayout.Y_AXIS));
0450:
0451:                approveButton = new JButton(getApproveButtonText(fc)) {
0452:                    public Dimension getMaximumSize() {
0453:                        return approveButton.getPreferredSize().width > cancelButton
0454:                                .getPreferredSize().width ? approveButton
0455:                                .getPreferredSize() : cancelButton
0456:                                .getPreferredSize();
0457:                    }
0458:                };
0459:                // #107791: No mnemonics desirable on Mac 
0460:                if (!Utilities.isMac()) {
0461:                    approveButton.setMnemonic(getApproveButtonMnemonic(fc));
0462:                }
0463:                approveButton.addActionListener(getApproveSelectionAction());
0464:                approveButton.setToolTipText(getApproveButtonToolTipText(fc));
0465:                buttonPanel.add(Box.createRigidArea(verticalStrut1));
0466:                buttonPanel.add(approveButton);
0467:                buttonPanel.add(Box.createRigidArea(verticalStrut2));
0468:
0469:                cancelButton = new JButton(cancelButtonText) {
0470:                    public Dimension getMaximumSize() {
0471:                        return approveButton.getPreferredSize().width > cancelButton
0472:                                .getPreferredSize().width ? approveButton
0473:                                .getPreferredSize() : cancelButton
0474:                                .getPreferredSize();
0475:                    }
0476:                };
0477:                // #107791: No mnemonics desirable on Mac 
0478:                if (!Utilities.isMac()) {
0479:                    cancelButton.setMnemonic(cancelButtonMnemonic);
0480:                }
0481:                cancelButton.setToolTipText(cancelButtonToolTipText);
0482:                cancelButton.addActionListener(getCancelSelectionAction());
0483:                buttonPanel.add(cancelButton);
0484:            }
0485:
0486:            private void createCenterPanel(final JFileChooser fc) {
0487:                centerPanel = new JPanel(new BorderLayout());
0488:                treeViewPanel = createTree();
0489:                treeViewPanel.setPreferredSize(TREE_PREF_SIZE);
0490:                JPanel treePanel = new JPanel();
0491:                treePanel.setLayout(new BorderLayout());
0492:                JComponent accessory = fc.getAccessory();
0493:                topToolbar = createTopToolbar();
0494:                topCombo = createTopCombo(fc);
0495:                topComboWrapper = new JPanel(new BorderLayout());
0496:                topComboWrapper.add(topCombo, BorderLayout.CENTER);
0497:                if (accessory == null) {
0498:                    topComboWrapper.add(topToolbar, BorderLayout.EAST);
0499:                }
0500:                treePanel.add(topComboWrapper, BorderLayout.NORTH);
0501:                treePanel.add(treeViewPanel, BorderLayout.CENTER);
0502:                centerPanel.add(treePanel, BorderLayout.CENTER);
0503:                // #97049: control width of accessory panel, don't allow to jump (change width)
0504:                JPanel wrapAccessory = new JPanel() {
0505:                    private Dimension prefSize = new Dimension(ACCESSORY_WIDTH,
0506:                            0);
0507:                    private Dimension minSize = new Dimension(ACCESSORY_WIDTH,
0508:                            0);
0509:
0510:                    public Dimension getMinimumSize() {
0511:                        if (fc.getAccessory() != null) {
0512:                            minSize.height = getAccessoryPanel()
0513:                                    .getMinimumSize().height;
0514:                            return minSize;
0515:                        }
0516:                        return super .getMinimumSize();
0517:                    }
0518:
0519:                    public Dimension getPreferredSize() {
0520:                        if (fc.getAccessory() != null) {
0521:                            prefSize.height = getAccessoryPanel()
0522:                                    .getPreferredSize().height;
0523:                            return prefSize;
0524:                        }
0525:                        return super .getPreferredSize();
0526:                    }
0527:                };
0528:                wrapAccessory.setLayout(new BorderLayout());
0529:                JPanel accessoryPanel = getAccessoryPanel();
0530:                if (accessory != null) {
0531:                    accessoryPanel.add(topToolbar, BorderLayout.NORTH);
0532:                    accessoryPanel.add(accessory, BorderLayout.CENTER);
0533:                }
0534:                wrapAccessory.add(accessoryPanel, BorderLayout.CENTER);
0535:                centerPanel.add(wrapAccessory, BorderLayout.EAST);
0536:                createBottomPanel(fc);
0537:                centerPanel.add(bottomPanel, BorderLayout.SOUTH);
0538:            }
0539:
0540:            private JComponent createTopCombo(JFileChooser fc) {
0541:                JPanel panel = new JPanel();
0542:                if (fc.getAccessory() != null) {
0543:                    panel
0544:                            .setBorder(BorderFactory.createEmptyBorder(4, 0, 8,
0545:                                    0));
0546:                } else {
0547:                    panel.setBorder(BorderFactory
0548:                            .createEmptyBorder(6, 0, 10, 0));
0549:                }
0550:                panel.setLayout(new BorderLayout());
0551:
0552:                Box labelBox = Box.createHorizontalBox();
0553:
0554:                lookInComboBoxLabel = new JLabel(lookInLabelText);
0555:                lookInComboBoxLabel.setDisplayedMnemonic(lookInLabelMnemonic);
0556:                lookInComboBoxLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
0557:                lookInComboBoxLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT);
0558:
0559:                labelBox.add(lookInComboBoxLabel);
0560:                labelBox.add(Box.createRigidArea(new Dimension(9, 0)));
0561:
0562:                // fixed #97525, made the height of the
0563:                // combo box bigger.
0564:                directoryComboBox = new JComboBox() {
0565:                    public Dimension getMinimumSize() {
0566:                        Dimension d = super .getMinimumSize();
0567:                        d.width = 60;
0568:                        return d;
0569:                    }
0570:
0571:                    public Dimension getPreferredSize() {
0572:                        Dimension d = super .getPreferredSize();
0573:                        // Must be small enough to not affect total width and height.
0574:                        d.height = 24;
0575:                        d.width = 150;
0576:                        return d;
0577:                    }
0578:                };
0579:                directoryComboBox.putClientProperty(
0580:                        "JComboBox.lightweightKeyboardNavigation",
0581:                        "Lightweight");
0582:                lookInComboBoxLabel.setLabelFor(directoryComboBox);
0583:                directoryComboBoxModel = createDirectoryComboBoxModel(fc);
0584:                directoryComboBox.setModel(directoryComboBoxModel);
0585:                directoryComboBox.addActionListener(directoryComboBoxAction);
0586:                directoryComboBox
0587:                        .setRenderer(createDirectoryComboBoxRenderer(fc));
0588:                directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
0589:                directoryComboBox.setAlignmentY(JComponent.CENTER_ALIGNMENT);
0590:                directoryComboBox.setMaximumRowCount(8);
0591:
0592:                panel.add(labelBox, BorderLayout.WEST);
0593:                panel.add(directoryComboBox, BorderLayout.CENTER);
0594:
0595:                return panel;
0596:            }
0597:
0598:            private JComponent createTopToolbar() {
0599:                JToolBar topPanel = new JToolBar();
0600:                topPanel.setFloatable(false);
0601:
0602:                if (Utilities.isWindows()) {
0603:                    topPanel.putClientProperty("JToolBar.isRollover",
0604:                            Boolean.TRUE);
0605:                }
0606:
0607:                upFolderButton = new JButton(getChangeToParentDirectoryAction());
0608:                upFolderButton.setText(null);
0609:                // fixed bug #97049
0610:                final boolean isMac = Utilities.isMac();
0611:                Icon upFolderIcon = null;
0612:                if (!isMac) {
0613:                    upFolderIcon = UIManager
0614:                            .getIcon("FileChooser.upFolderIcon");
0615:                }
0616:                // on Mac all icons from UIManager are the same, some default, so load our own.
0617:                // it's also fallback if icon from UIManager not found, may happen
0618:                if (isMac || upFolderIcon == null) {
0619:                    upFolderIcon = new ImageIcon(
0620:                            Utilities
0621:                                    .loadImage("org/netbeans/swing/dirchooser/resources/upFolderIcon.gif"));
0622:                }
0623:                upFolderButton.setIcon(upFolderIcon);
0624:                upFolderButton.setToolTipText(upFolderToolTipText);
0625:                upFolderButton.getAccessibleContext().setAccessibleName(
0626:                        upFolderAccessibleName);
0627:                upFolderButton.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
0628:                upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
0629:
0630:                if (useShellFolder) {
0631:                    upFolderButton.setFocusPainted(false);
0632:                }
0633:
0634:                topPanel.add(upFolderButton);
0635:                topPanel.add(Box.createRigidArea(new Dimension(2, 0)));
0636:
0637:                // no home on Win platform
0638:                if (!Utilities.isWindows()) {
0639:                    JButton homeButton = new JButton(getGoHomeAction());
0640:                    Icon homeIcon = null;
0641:                    if (!isMac) {
0642:                        homeIcon = UIManager
0643:                                .getIcon("FileChooser.homeFolderIcon");
0644:                    }
0645:                    if (isMac || homeIcon == null) {
0646:                        homeIcon = new ImageIcon(
0647:                                Utilities
0648:                                        .loadImage("org/netbeans/swing/dirchooser/resources/homeIcon.gif"));
0649:                    }
0650:                    homeButton.setIcon(homeIcon);
0651:                    homeButton.setText(null);
0652:
0653:                    topPanel.add(homeButton);
0654:                }
0655:
0656:                newFolderButton = new JButton(newFolderAction);
0657:                newFolderButton.setText(null);
0658:                // fixed bug #97049
0659:                Icon newFolderIcon = null;
0660:                if (!isMac) {
0661:                    newFolderIcon = UIManager
0662:                            .getIcon("FileChooser.newFolderIcon");
0663:                }
0664:                // on Mac all icons from UIManager are the same, some default, so load our own.
0665:                // it's also fallback if icon from UIManager not found, may happen
0666:                if (isMac || newFolderIcon == null) {
0667:                    newFolderIcon = new ImageIcon(
0668:                            Utilities
0669:                                    .loadImage("org/netbeans/swing/dirchooser/resources/newFolderIcon.gif"));
0670:                }
0671:                newFolderButton.setIcon(newFolderIcon);
0672:                newFolderButton.setToolTipText(newFolderToolTipText);
0673:                newFolderButton.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
0674:                newFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
0675:
0676:                if (useShellFolder) {
0677:                    newFolderButton.setFocusPainted(false);
0678:                }
0679:
0680:                topPanel.add(newFolderButton);
0681:                topPanel.add(Box.createRigidArea(new Dimension(2, 0)));
0682:
0683:                JPanel panel = new JPanel();
0684:                panel.setLayout(new BorderLayout());
0685:                panel.setBorder(BorderFactory.createEmptyBorder(4, 9, 8, 0));
0686:                panel.add(topPanel, BorderLayout.CENTER);
0687:
0688:                return panel;
0689:            }
0690:
0691:            private JComponent createTree() {
0692:                final DirectoryHandler dirHandler = createDirectoryHandler(fileChooser);
0693:                // #106011: don't show "colors, food, sports" sample model after init :-)
0694:                tree = new JTree(new Object[0]) {
0695:
0696:                    @Override
0697:                    protected void processMouseEvent(MouseEvent e) {
0698:                        dirHandler.preprocessMouseEvent(e);
0699:                        super .processMouseEvent(e);
0700:                    }
0701:
0702:                    @Override
0703:                    /* #106223: Always compute row height from cell renderer, don't allow fixed
0704:                     * row height */
0705:                    public int getRowHeight() {
0706:                        return 0;
0707:                    }
0708:
0709:                };
0710:                // #105642: start with right content in tree 
0711:                File curDir = fileChooser.getCurrentDirectory();
0712:                if (curDir == null) {
0713:                    curDir = fileChooser.getFileSystemView().getRoots()[0];
0714:                }
0715:                updateTree(curDir);
0716:
0717:                tree.setFocusable(true);
0718:                tree.setOpaque(true);
0719:                tree.setRootVisible(false);
0720:                tree.setShowsRootHandles(true);
0721:                tree.setToggleClickCount(0);
0722:                tree.addTreeExpansionListener(new TreeExpansionHandler());
0723:                TreeKeyHandler keyHandler = new TreeKeyHandler();
0724:                tree.addKeyListener(keyHandler);
0725:                tree.addFocusListener(keyHandler);
0726:                tree.addMouseListener(dirHandler);
0727:                tree.addFocusListener(dirHandler);
0728:                tree.addTreeSelectionListener(dirHandler);
0729:
0730:                if (fileChooser.isMultiSelectionEnabled()) {
0731:                    tree.getSelectionModel().setSelectionMode(
0732:                            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
0733:                } else {
0734:                    tree.getSelectionModel().setSelectionMode(
0735:                            TreeSelectionModel.SINGLE_TREE_SELECTION);
0736:                }
0737:
0738:                TreeCellEditor tce = new DirectoryCellEditor(tree, fileChooser,
0739:                        new JTextField());
0740:                tree.setCellEditor(tce);
0741:                tce.addCellEditorListener(dirHandler);
0742:                tree.setCellRenderer(new DirectoryTreeRenderer());
0743:                JScrollPane scrollBar = new JScrollPane(tree);
0744:                scrollBar.setViewportView(tree);
0745:                tree.setInvokesStopCellEditing(true);
0746:
0747:                return scrollBar;
0748:            }
0749:
0750:            /** 
0751:             * Handles keyboard quick search in tree and delete action.
0752:             */
0753:            class TreeKeyHandler extends KeyAdapter implements  FocusListener {
0754:
0755:                StringBuffer searchBuf = new StringBuffer();
0756:
0757:                java.util.List<TreePath> paths;
0758:
0759:                public void keyPressed(KeyEvent evt) {
0760:                    if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
0761:                        deleteAction();
0762:                    }
0763:
0764:                    // F2 as rename shortcut
0765:                    if (evt.getKeyCode() == KeyEvent.VK_F2) {
0766:                        DirectoryNode node = (DirectoryNode) tree
0767:                                .getLastSelectedPathComponent();
0768:                        if (node != null) {
0769:                            applyEdit(node);
0770:                        }
0771:                    }
0772:
0773:                    if (isCharForSearch(evt)) {
0774:                        evt.consume();
0775:                    } else {
0776:                        resetBuffer();
0777:                    }
0778:
0779:                    // #105527: keyboard invocation of tree's popup menu 
0780:                    if ((evt.getKeyCode() == KeyEvent.VK_F10)
0781:                            && evt.isShiftDown() && !popupMenu.isShowing()) {
0782:                        JTree tree = (JTree) evt.getSource();
0783:                        int selRow = tree.getLeadSelectionRow();
0784:                        if (selRow >= 0) {
0785:                            Rectangle bounds = tree.getRowBounds(selRow);
0786:                            popupMenu.show(tree, bounds.x + bounds.width / 2,
0787:                                    bounds.y + bounds.height * 3 / 5);
0788:                            evt.consume();
0789:                        }
0790:                    }
0791:                }
0792:
0793:                @Override
0794:                public void keyTyped(KeyEvent evt) {
0795:                    char keyChar = evt.getKeyChar();
0796:                    if (isCharForSearch(evt)) {
0797:                        if (paths == null) {
0798:                            paths = getVisiblePaths();
0799:                        }
0800:                        searchBuf.append(keyChar);
0801:                        String searchedText = searchBuf.toString()
0802:                                .toLowerCase();
0803:                        String curFileName = null;
0804:                        for (TreePath path : paths) {
0805:                            curFileName = fileChooser
0806:                                    .getName(((DirectoryNode) path
0807:                                            .getLastPathComponent()).getFile());
0808:                            if (curFileName != null
0809:                                    && curFileName.toLowerCase().startsWith(
0810:                                            searchedText)) {
0811:                                tree.makeVisible(path);
0812:                                tree.scrollPathToVisible(path);
0813:                                tree.setSelectionPath(path);
0814:                                break;
0815:                            }
0816:                        }
0817:                    } else {
0818:                        resetBuffer();
0819:                    }
0820:                }
0821:
0822:                public void focusGained(FocusEvent e) {
0823:                    resetBuffer();
0824:                }
0825:
0826:                public void focusLost(FocusEvent e) {
0827:                    resetBuffer();
0828:                }
0829:
0830:                private boolean isCharForSearch(KeyEvent evt) {
0831:                    char ch = evt.getKeyChar();
0832:                    // refuse backspace key
0833:                    if ((int) ch == 8) {
0834:                        return false;
0835:                    }
0836:                    // #110975: refuse modifiers
0837:                    if (evt.getModifiers() != 0) {
0838:                        return false;
0839:                    }
0840:                    return (Character.isJavaIdentifierPart(ch) && !Character
0841:                            .isIdentifierIgnorable(ch))
0842:                            || Character.isSpaceChar(ch);
0843:                }
0844:
0845:                private void resetBuffer() {
0846:                    searchBuf.delete(0, searchBuf.length());
0847:                    paths = null;
0848:                }
0849:
0850:            }
0851:
0852:            private java.util.List<TreePath> getVisiblePaths() {
0853:                int rowCount = tree.getRowCount();
0854:                DirectoryNode node = null;
0855:                java.util.List<TreePath> result = new ArrayList<TreePath>(
0856:                        rowCount);
0857:                for (int i = 0; i < rowCount; i++) {
0858:                    result.add(tree.getPathForRow(i));
0859:                }
0860:                return result;
0861:            }
0862:
0863:            private void createPopup() {
0864:                popupMenu = new JPopupMenu();
0865:                JMenuItem item1 = new JMenuItem(getBundle().getString(
0866:                        "LBL_NewFolder"));
0867:                item1.addActionListener(newFolderAction);
0868:
0869:                JMenuItem item2 = new JMenuItem(getBundle().getString(
0870:                        "LBL_Rename"));
0871:                item2.addActionListener(new ActionListener() {
0872:                    public void actionPerformed(ActionEvent e) {
0873:                        DirectoryNode node = (DirectoryNode) tree
0874:                                .getLastSelectedPathComponent();
0875:                        applyEdit(node);
0876:                    }
0877:                });
0878:
0879:                JMenuItem item3 = new JMenuItem(getBundle().getString(
0880:                        "LBL_Delete"));
0881:                item3.addActionListener(new ActionListener() {
0882:                    public void actionPerformed(ActionEvent e) {
0883:                        deleteAction();
0884:                    }
0885:                });
0886:
0887:                popupMenu.add(item1);
0888:                popupMenu.add(item2);
0889:                popupMenu.add(item3);
0890:            }
0891:
0892:            // remove multiple directories
0893:            private void deleteAction() {
0894:                // fixed #97079 to be able to delete one or more folders
0895:                final TreePath[] nodePath = tree.getSelectionPaths();
0896:
0897:                if (nodePath == null) {
0898:                    return;
0899:                }
0900:                String message = "";
0901:
0902:                if (nodePath.length == 1) {
0903:
0904:                    File file = ((DirectoryNode) nodePath[0]
0905:                            .getLastPathComponent()).getFile();
0906:                    // Don't do anything if it's a special file
0907:                    if (!canWrite(file)) {
0908:                        return;
0909:                    }
0910:                    message = MessageFormat.format(getBundle().getString(
0911:                            "MSG_Delete"), file.getName());
0912:                } else {
0913:                    message = MessageFormat.format(getBundle().getString(
0914:                            "MSG_Delete_Multiple"), nodePath.length);
0915:                }
0916:
0917:                int answer = JOptionPane.showConfirmDialog(fileChooser,
0918:                        message, getBundle().getString("MSG_Confirm"),
0919:                        JOptionPane.YES_NO_OPTION);
0920:
0921:                if (answer == JOptionPane.YES_OPTION) {
0922:
0923:                    RequestProcessor.getDefault().post(new Runnable() {
0924:                        DirectoryNode node;
0925:                        ArrayList<File> list = new ArrayList<File>();
0926:                        int cannotDelete;
0927:
0928:                        public void run() {
0929:                            if (!EventQueue.isDispatchThread()) {
0930:                                // first pass, out of EQ thread, deletes files
0931:                                setCursor(fileChooser, Cursor.WAIT_CURSOR);
0932:                                cannotDelete = 0;
0933:                                for (int i = 0; i < nodePath.length; i++) {
0934:                                    DirectoryNode nodeToDelete = (DirectoryNode) nodePath[i]
0935:                                            .getLastPathComponent();
0936:                                    try {
0937:                                        DefaultTreeModel model = (DefaultTreeModel) tree
0938:                                                .getModel();
0939:                                        FileObject fo = FileUtil
0940:                                                .toFileObject(nodeToDelete
0941:                                                        .getFile());
0942:                                        fo.delete();
0943:                                        model
0944:                                                .removeNodeFromParent(nodeToDelete);
0945:                                    } catch (IOException ignore) {
0946:                                        cannotDelete++;
0947:
0948:                                        if (canWrite(nodeToDelete.getFile())) {
0949:                                            list.add(nodeToDelete.getFile());
0950:                                        }
0951:                                    }
0952:                                }
0953:                                // send to second pass
0954:                                EventQueue.invokeLater(this );
0955:                            } else {
0956:                                // second pass, in EQ thread
0957:                                setCursor(fileChooser, Cursor.DEFAULT_CURSOR);
0958:                                if (cannotDelete > 0) {
0959:                                    String message = "";
0960:
0961:                                    if (cannotDelete == 1) {
0962:                                        message = cannotDelete
0963:                                                + " "
0964:                                                + getBundle().getString(
0965:                                                        "MSG_Sing_Delete");
0966:                                    } else {
0967:                                        message = cannotDelete
0968:                                                + " "
0969:                                                + getBundle().getString(
0970:                                                        "MSG_Plur_Delete");
0971:                                    }
0972:
0973:                                    setSelected((File[]) list
0974:                                            .toArray(new File[list.size()]));
0975:
0976:                                    JOptionPane.showConfirmDialog(fileChooser,
0977:                                            message, getBundle().getString(
0978:                                                    "MSG_Confirm"),
0979:                                            JOptionPane.OK_OPTION);
0980:                                } else {
0981:                                    setSelected(new File[] { null });
0982:                                    setFileName("");
0983:                                }
0984:                            }
0985:                        }
0986:                    });
0987:                }
0988:            }
0989:
0990:            private void updateCompletions() {
0991:                String name = normalizeFile(getFileName());
0992:                boolean showPopup = true;
0993:                int slash = name.lastIndexOf(File.separatorChar);
0994:                if (slash != -1) {
0995:                    String prefix = name.substring(0, slash + 1);
0996:                    File d = new File(prefix);
0997:                    if (d.isDirectory()) {
0998:                        File[] children = d.listFiles();
0999:                        if (children != null) {
1000:                            Vector list = buildList(name, children);
1001:
1002:                            if (completionPopup == null) {
1003:                                showPopup = true;
1004:                            }
1005:
1006:                            if ((completionPopup != null)
1007:                                    && completionPopup.isVisible()) {
1008:                                showPopup = false;
1009:                            }
1010:
1011:                            if (showPopup) {
1012:                                completionPopup = new FileCompletionPopup(
1013:                                        fileChooser, filenameTextField, list);
1014:
1015:                                if (showPopupCompletion
1016:                                        && fileChooser.isShowing()) {
1017:                                    java.awt.Point los = filenameTextField
1018:                                            .getLocation();
1019:                                    int popX = los.x;
1020:                                    int popY = los.y
1021:                                            + filenameTextField.getHeight() - 6;
1022:                                    completionPopup.showPopup(
1023:                                            filenameTextField, popX, popY);
1024:                                }
1025:                            } else {
1026:                                completionPopup.setDataList(list);
1027:                            }
1028:                        }
1029:                    }
1030:                }
1031:            }
1032:
1033:            public Vector<File> buildList(String text, File[] children) {
1034:                Vector<File> files = new Vector<File>(children.length);
1035:
1036:                for (int i = children.length - 1; i >= 0; i--) {
1037:                    File completion = children[i];
1038:
1039:                    if (fileChooser.accept(completion)) {
1040:                        String path = completion.getAbsolutePath();
1041:
1042:                        if (path.regionMatches(true, 0, text, 0, text.length())) {
1043:
1044:                            if (fileChooser.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
1045:                                if (completion.isDirectory()) {
1046:                                    files.add(completion);
1047:                                }
1048:                            } else if (fileChooser.getFileSelectionMode() == JFileChooser.FILES_ONLY) {
1049:                                if (completion.isFile()) {
1050:                                    files.add(completion);
1051:                                }
1052:                            } else if (fileChooser.getFileSelectionMode() == JFileChooser.FILES_AND_DIRECTORIES) {
1053:                                files.add(completion);
1054:                            }
1055:                        }
1056:                    }
1057:                }
1058:
1059:                Collections.sort(files, DirectoryNode.FILE_NAME_COMPARATOR);
1060:                return files;
1061:            }
1062:
1063:            private static String normalizeFile(String text) {
1064:                // See #21690 for background.
1065:                // XXX what are legal chars for var names? bash manual says only:
1066:                // "The braces are required when PARAMETER [...] is followed by a
1067:                // character that is not to be interpreted as part of its name."
1068:                Pattern p = Pattern.compile("(^|[^\\\\])\\$([a-zA-Z_0-9.]+)");
1069:                Matcher m;
1070:                while ((m = p.matcher(text)).find()) {
1071:                    // Have an env var to subst...
1072:                    // XXX handle ${PATH} too? or don't bother
1073:                    String var = System.getenv(m.group(2));
1074:                    if (var == null) {
1075:                        // Try Java system props too, and fall back to "".
1076:                        var = System.getProperty(m.group(2), "");
1077:                    }
1078:                    // XXX full readline compat would mean vars were also completed with TAB...
1079:                    text = text.substring(0, m.end(1)) + var
1080:                            + text.substring(m.end(2));
1081:                }
1082:                if (text.equals("~")) {
1083:                    return System.getProperty("user.home");
1084:                } else if (text.startsWith("~" + File.separatorChar)) {
1085:                    return System.getProperty("user.home") + text.substring(1);
1086:                } else {
1087:                    int i = text.lastIndexOf("//");
1088:                    if (i != -1) {
1089:                        // Treat /home/me//usr/local as /usr/local
1090:                        // (so that you can use "//" to start a new path, without selecting & deleting)
1091:                        return text.substring(i + 1);
1092:                    }
1093:                    i = text.lastIndexOf(File.separatorChar + "~"
1094:                            + File.separatorChar);
1095:                    if (i != -1) {
1096:                        // Treat /usr/local/~/stuff as /home/me/stuff
1097:                        return System.getProperty("user.home")
1098:                                + text.substring(i + 2);
1099:                    }
1100:                    return text;
1101:                }
1102:            }
1103:
1104:            private static ResourceBundle getBundle() {
1105:                return NbBundle.getBundle(DirectoryChooserUI.class);
1106:            }
1107:
1108:            private void updateTree(final File file) {
1109:                // fixed bug #97522
1110:                if (updateWorker != null) {
1111:                    // try to cancel previous update if possible
1112:                    if (!updateWorker.isFinished()) {
1113:                        updateWorker.cancel();
1114:                    }
1115:                    // #105642 - wait for previous update, to keep time order
1116:                    updateWorker.waitFinished();
1117:                }
1118:
1119:                updateWorker = RequestProcessor.getDefault().post(
1120:                        new Runnable() {
1121:                            DirectoryNode node;
1122:
1123:                            public void run() {
1124:                                if (!EventQueue.isDispatchThread()) {
1125:                                    // first pass, out of EQ thread
1126:                                    setCursor(fileChooser, Cursor.WAIT_CURSOR);
1127:                                    node = new DirectoryNode(file);
1128:                                    node.loadChildren(fileChooser, true);
1129:                                    // send to second pass
1130:                                    EventQueue.invokeLater(this );
1131:                                } else {
1132:                                    // second pass, in EQ thread
1133:                                    model = new DirectoryTreeModel(node);
1134:                                    tree.setModel(model);
1135:                                    tree.repaint();
1136:                                    setCursor(fileChooser,
1137:                                            Cursor.DEFAULT_CURSOR);
1138:                                }
1139:                            }
1140:                        });
1141:
1142:            }
1143:
1144:            private Boolean isXPStyle() {
1145:                Toolkit toolkit = Toolkit.getDefaultToolkit();
1146:                Boolean themeActive = (Boolean) toolkit
1147:                        .getDesktopProperty("win.xpstyle.themeActive");
1148:                if (themeActive == null)
1149:                    themeActive = Boolean.FALSE;
1150:                if (themeActive.booleanValue()
1151:                        && System.getProperty("swing.noxp") == null) {
1152:                    themeActive = Boolean.TRUE;
1153:                }
1154:                return themeActive;
1155:            }
1156:
1157:            protected void installStrings(JFileChooser fc) {
1158:                super .installStrings(fc);
1159:
1160:                Locale l = fc.getLocale();
1161:
1162:                lookInLabelMnemonic = UIManager
1163:                        .getInt("FileChooser.lookInLabelMnemonic");
1164:                lookInLabelText = UIManager.getString(
1165:                        "FileChooser.lookInLabelText", l);
1166:                saveInLabelText = UIManager.getString(
1167:                        "FileChooser.saveInLabelText", l);
1168:
1169:                fileNameLabelMnemonic = UIManager
1170:                        .getInt("FileChooser.fileNameLabelMnemonic");
1171:                fileNameLabelText = UIManager.getString(
1172:                        "FileChooser.fileNameLabelText", l);
1173:
1174:                filesOfTypeLabelMnemonic = UIManager
1175:                        .getInt("FileChooser.filesOfTypeLabelMnemonic");
1176:                filesOfTypeLabelText = UIManager.getString(
1177:                        "FileChooser.filesOfTypeLabelText", l);
1178:
1179:                upFolderToolTipText = UIManager.getString(
1180:                        "FileChooser.upFolderToolTipText", l);
1181:                upFolderAccessibleName = UIManager.getString(
1182:                        "FileChooser.upFolderAccessibleName", l);
1183:
1184:                newFolderToolTipText = UIManager.getString(
1185:                        "FileChooser.newFolderToolTipText", l);
1186:
1187:            }
1188:
1189:            protected void installListeners(JFileChooser fc) {
1190:                super .installListeners(fc);
1191:                ActionMap actionMap = getActionMap();
1192:                SwingUtilities.replaceUIActionMap(fc, actionMap);
1193:            }
1194:
1195:            protected ActionMap getActionMap() {
1196:                return createActionMap();
1197:            }
1198:
1199:            protected ActionMap createActionMap() {
1200:                AbstractAction escAction = new AbstractAction() {
1201:                    public void actionPerformed(ActionEvent e) {
1202:                        getFileChooser().cancelSelection();
1203:                    }
1204:
1205:                    public boolean isEnabled() {
1206:                        return getFileChooser().isEnabled();
1207:                    }
1208:                };
1209:                ActionMap map = new ActionMapUIResource();
1210:                map.put("approveSelection", getApproveSelectionAction());
1211:                map.put("cancelSelection", escAction);
1212:                map.put("Go Up", getChangeToParentDirectoryAction());
1213:                return map;
1214:            }
1215:
1216:            public Action getNewFolderAction() {
1217:                return newFolderAction;
1218:            }
1219:
1220:            public void uninstallUI(JComponent c) {
1221:                c.removePropertyChangeListener(filterTypeComboBoxModel);
1222:                cancelButton.removeActionListener(getCancelSelectionAction());
1223:                approveButton.removeActionListener(getApproveSelectionAction());
1224:                filenameTextField
1225:                        .removeActionListener(getApproveSelectionAction());
1226:                super .uninstallUI(c);
1227:            }
1228:
1229:            /**
1230:             * Returns the preferred size of the specified
1231:             * <code>JFileChooser</code>.
1232:             * The preferred size is at least as large,
1233:             * in both height and width,
1234:             * as the preferred size recommended
1235:             * by the file chooser's layout manager.
1236:             *
1237:             * @param c  a <code>JFileChooser</code>
1238:             * @return   a <code>Dimension</code> specifying the preferred
1239:             *           width and height of the file chooser
1240:             */
1241:            public Dimension getPreferredSize(JComponent c) {
1242:                int prefWidth = PREF_SIZE.width;
1243:                Dimension d = c.getLayout().preferredLayoutSize(c);
1244:                if (d != null) {
1245:                    return new Dimension(d.width < prefWidth ? prefWidth
1246:                            : d.width,
1247:                            d.height < PREF_SIZE.height ? PREF_SIZE.height
1248:                                    : d.height);
1249:                } else {
1250:                    return new Dimension(prefWidth, PREF_SIZE.height);
1251:                }
1252:            }
1253:
1254:            /**
1255:             * Returns the minimum size of the <code>JFileChooser</code>.
1256:             *
1257:             * @param c  a <code>JFileChooser</code>
1258:             * @return   a <code>Dimension</code> specifying the minimum
1259:             *           width and height of the file chooser
1260:             */
1261:            public Dimension getMinimumSize(JComponent c) {
1262:                return MIN_SIZE;
1263:            }
1264:
1265:            /**
1266:             * Returns the maximum size of the <code>JFileChooser</code>.
1267:             *
1268:             * @param c  a <code>JFileChooser</code>
1269:             * @return   a <code>Dimension</code> specifying the maximum
1270:             *           width and height of the file chooser
1271:             */
1272:            public Dimension getMaximumSize(JComponent c) {
1273:                return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
1274:            }
1275:
1276:            private String getStringOfFileName(File file) {
1277:                if (file == null) {
1278:                    return null;
1279:                } else {
1280:                    JFileChooser fc = getFileChooser();
1281:                    if (fc.isDirectorySelectionEnabled()
1282:                            && !fc.isFileSelectionEnabled()) {
1283:                        if (fc.getFileSystemView().isDrive(file)) {
1284:                            return file.getPath();
1285:                        } else {
1286:                            return file.getPath();
1287:                        }
1288:                    } else {
1289:                        return file.getName();
1290:                    }
1291:                }
1292:            }
1293:
1294:            private String getStringOfFileNames(File[] files) {
1295:                StringBuffer buf = new StringBuffer();
1296:                for (int i = 0; files != null && i < files.length; i++) {
1297:                    if (i > 0) {
1298:                        buf.append(" ");
1299:                    }
1300:                    if (files.length > 1) {
1301:                        buf.append("\"");
1302:                    }
1303:                    buf.append(getStringOfFileName(files[i]));
1304:                    if (files.length > 1) {
1305:                        buf.append("\"");
1306:                    }
1307:                }
1308:                return buf.toString();
1309:            }
1310:
1311:            /* The following methods are used by the PropertyChange Listener */
1312:
1313:            private void fireSelectedFileChanged(PropertyChangeEvent e) {
1314:                File f = (File) e.getNewValue();
1315:                JFileChooser fc = getFileChooser();
1316:                if (f != null
1317:                        && ((fc.isFileSelectionEnabled() && !f.isDirectory()) || (f
1318:                                .isDirectory() && fc
1319:                                .isDirectorySelectionEnabled()))) {
1320:
1321:                    setFileName(getStringOfFileName(f));
1322:                }
1323:            }
1324:
1325:            private void fireSelectedFilesChanged(PropertyChangeEvent e) {
1326:                File[] files = (File[]) e.getNewValue();
1327:                JFileChooser fc = getFileChooser();
1328:                if (files != null
1329:                        && files.length > 0
1330:                        && (files.length > 1
1331:                                || fc.isDirectorySelectionEnabled() || !files[0]
1332:                                .isDirectory())) {
1333:                    setFileName(getStringOfFileNames(files));
1334:                }
1335:            }
1336:
1337:            private void fireDirectoryChanged(PropertyChangeEvent e) {
1338:                JFileChooser fc = getFileChooser();
1339:                FileSystemView fsv = fc.getFileSystemView();
1340:                showPopupCompletion = false;
1341:                setFileName("");
1342:                clearIconCache();
1343:                File currentDirectory = fc.getCurrentDirectory();
1344:                if (currentDirectory != null) {
1345:                    directoryComboBoxModel.addItem(currentDirectory);
1346:                    newFolderAction.setEnabled(currentDirectory.canWrite());
1347:                    getChangeToParentDirectoryAction().setEnabled(
1348:                            !fsv.isRoot(currentDirectory));
1349:                    updateTree(currentDirectory);
1350:                    if (fc.isDirectorySelectionEnabled()
1351:                            && !fc.isFileSelectionEnabled()) {
1352:                        if (fsv.isFileSystem(currentDirectory)) {
1353:                            setFileName(getStringOfFileName(currentDirectory));
1354:                        } else {
1355:                            setFileName(null);
1356:                        }
1357:                    }
1358:                }
1359:            }
1360:
1361:            private void fireFilterChanged(PropertyChangeEvent e) {
1362:                clearIconCache();
1363:            }
1364:
1365:            private void fireFileSelectionModeChanged(PropertyChangeEvent e) {
1366:                clearIconCache();
1367:                JFileChooser fc = getFileChooser();
1368:
1369:                File currentDirectory = fc.getCurrentDirectory();
1370:                if (currentDirectory != null
1371:                        && fc.isDirectorySelectionEnabled()
1372:                        && !fc.isFileSelectionEnabled()
1373:                        && fc.getFileSystemView()
1374:                                .isFileSystem(currentDirectory)) {
1375:
1376:                    setFileName(currentDirectory.getPath());
1377:                } else {
1378:                    setFileName(null);
1379:                }
1380:            }
1381:
1382:            private void fireMultiSelectionChanged(PropertyChangeEvent e) {
1383:                if (getFileChooser().isMultiSelectionEnabled()) {
1384:                    tree.getSelectionModel().setSelectionMode(
1385:                            TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
1386:                } else {
1387:                    tree.getSelectionModel().setSelectionMode(
1388:                            TreeSelectionModel.SINGLE_TREE_SELECTION);
1389:                    getFileChooser().setSelectedFiles(null);
1390:                }
1391:            }
1392:
1393:            private void fireAccessoryChanged(PropertyChangeEvent e) {
1394:                if (getAccessoryPanel() != null) {
1395:                    JComponent oldAcc = (JComponent) e.getOldValue();
1396:                    JComponent newAcc = (JComponent) e.getNewValue();
1397:                    JComponent accessoryPanel = getAccessoryPanel();
1398:                    if (oldAcc != null) {
1399:                        accessoryPanel.remove(oldAcc);
1400:                    }
1401:                    if (oldAcc != null && newAcc == null) {
1402:                        accessoryPanel.remove(topToolbar);
1403:                        topComboWrapper.add(topToolbar, BorderLayout.EAST);
1404:                        topCombo.setBorder(BorderFactory.createEmptyBorder(6,
1405:                                0, 10, 0));
1406:                        topCombo.revalidate();
1407:                    }
1408:
1409:                    if (newAcc != null) {
1410:                        getAccessoryPanel().add(newAcc, BorderLayout.CENTER);
1411:                    }
1412:
1413:                    if (oldAcc == null && newAcc != null) {
1414:                        topComboWrapper.remove(topToolbar);
1415:                        topCombo.setBorder(BorderFactory.createEmptyBorder(4,
1416:                                0, 8, 0));
1417:                        accessoryPanel.add(topToolbar, BorderLayout.NORTH);
1418:                    }
1419:
1420:                }
1421:            }
1422:
1423:            private void fireApproveButtonTextChanged(PropertyChangeEvent e) {
1424:                JFileChooser chooser = getFileChooser();
1425:                approveButton.setText(getApproveButtonText(chooser));
1426:                approveButton
1427:                        .setToolTipText(getApproveButtonToolTipText(chooser));
1428:                // #107791: No mnemonics desirable on Mac 
1429:                if (!Utilities.isMac()) {
1430:                    approveButton
1431:                            .setMnemonic(getApproveButtonMnemonic(chooser));
1432:                }
1433:            }
1434:
1435:            private void fireDialogTypeChanged(PropertyChangeEvent e) {
1436:                JFileChooser chooser = getFileChooser();
1437:                approveButton.setText(getApproveButtonText(chooser));
1438:                approveButton
1439:                        .setToolTipText(getApproveButtonToolTipText(chooser));
1440:                // #107791: No mnemonics desirable on Mac 
1441:                if (!Utilities.isMac()) {
1442:                    approveButton
1443:                            .setMnemonic(getApproveButtonMnemonic(chooser));
1444:                }
1445:                if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) {
1446:                    lookInComboBoxLabel.setText(saveInLabelText);
1447:                } else {
1448:                    lookInComboBoxLabel.setText(lookInLabelText);
1449:                }
1450:            }
1451:
1452:            private void fireApproveButtonMnemonicChanged(PropertyChangeEvent e) {
1453:                // #107791: No mnemonics desirable on Mac 
1454:                if (!Utilities.isMac()) {
1455:                    approveButton
1456:                            .setMnemonic(getApproveButtonMnemonic(getFileChooser()));
1457:                }
1458:            }
1459:
1460:            private void fireControlButtonsChanged(PropertyChangeEvent e) {
1461:                if (getFileChooser().getControlButtonsAreShown()) {
1462:                    addControlButtons();
1463:                } else {
1464:                    removeControlButtons();
1465:                }
1466:            }
1467:
1468:            /*
1469:             * Listen for filechooser property changes, such as
1470:             * the selected file changing, or the type of the dialog changing.
1471:             */
1472:            public PropertyChangeListener createPropertyChangeListener(
1473:                    JFileChooser fc) {
1474:                return new PropertyChangeListener() {
1475:                    public void propertyChange(PropertyChangeEvent e) {
1476:                        String s = e.getPropertyName();
1477:                        if (s
1478:                                .equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
1479:                            fireSelectedFileChanged(e);
1480:                        } else if (s
1481:                                .equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
1482:                            fireSelectedFilesChanged(e);
1483:                        } else if (s
1484:                                .equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
1485:                                && changeDirectory) {
1486:                            fireDirectoryChanged(e);
1487:                        } else if (s
1488:                                .equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
1489:                            fireFilterChanged(e);
1490:                        } else if (s
1491:                                .equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
1492:                            fireFileSelectionModeChanged(e);
1493:                        } else if (s
1494:                                .equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
1495:                            fireMultiSelectionChanged(e);
1496:                        } else if (s
1497:                                .equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
1498:                            fireAccessoryChanged(e);
1499:                        } else if (s
1500:                                .equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)
1501:                                || s
1502:                                        .equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) {
1503:                            fireApproveButtonTextChanged(e);
1504:                        } else if (s
1505:                                .equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
1506:                            fireDialogTypeChanged(e);
1507:                        } else if (s
1508:                                .equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) {
1509:                            fireApproveButtonMnemonicChanged(e);
1510:                        } else if (s
1511:                                .equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
1512:                            fireControlButtonsChanged(e);
1513:                        } else if (s.equals("FileChooser.useShellFolder")) {
1514:                            updateUseShellFolder();
1515:                            fireDirectoryChanged(e);
1516:                        } else if (s.equals("componentOrientation")) {
1517:                            ComponentOrientation o = (ComponentOrientation) e
1518:                                    .getNewValue();
1519:                            JFileChooser cc = (JFileChooser) e.getSource();
1520:                            if (o != (ComponentOrientation) e.getOldValue()) {
1521:                                cc.applyComponentOrientation(o);
1522:                            }
1523:                        } else if (s.equals("ancestor")) {
1524:                            if (e.getOldValue() == null
1525:                                    && e.getNewValue() != null) {
1526:                                filenameTextField.selectAll();
1527:                                filenameTextField.requestFocus();
1528:                            }
1529:                        }
1530:                    }
1531:                };
1532:            }
1533:
1534:            protected void removeControlButtons() {
1535:                bottomPanel.remove(buttonPanel);
1536:            }
1537:
1538:            protected void addControlButtons() {
1539:                bottomPanel.add(buttonPanel);
1540:            }
1541:
1542:            public String getFileName() {
1543:                if (filenameTextField != null) {
1544:                    return filenameTextField.getText();
1545:                } else {
1546:                    return null;
1547:                }
1548:            }
1549:
1550:            public void setFileName(String filename) {
1551:                if (filenameTextField != null) {
1552:                    filenameTextField.setText(filename);
1553:                }
1554:            }
1555:
1556:            private DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
1557:                    JFileChooser fc) {
1558:                return new DirectoryComboBoxRenderer();
1559:            }
1560:
1561:            protected DirectoryComboBoxModel createDirectoryComboBoxModel(
1562:                    JFileChooser fc) {
1563:                return new DirectoryComboBoxModel();
1564:            }
1565:
1566:            protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
1567:                return new FilterComboBoxRenderer();
1568:            }
1569:
1570:            protected FilterTypeComboBoxModel createFilterComboBoxModel() {
1571:                return new FilterTypeComboBoxModel();
1572:            }
1573:
1574:            protected JButton getApproveButton(JFileChooser fc) {
1575:                return approveButton;
1576:            }
1577:
1578:            public FileView getFileView(JFileChooser fc) {
1579:
1580:                // fix bug #96957, should use DirectoryChooserFileView
1581:                // only on windows
1582:                if (Utilities.isWindows()) {
1583:                    if (useShellFolder) {
1584:                        fileView = new DirectoryChooserFileView();
1585:                    }
1586:                } else {
1587:                    fileView = (BasicFileView) super .getFileView(fileChooser);
1588:                }
1589:                return fileView;
1590:            }
1591:
1592:            private void setSelected(File[] files) {
1593:                changeDirectory = false;
1594:                fileChooser.setSelectedFiles(files);
1595:                changeDirectory = true;
1596:            }
1597:
1598:            private DirectoryHandler createDirectoryHandler(JFileChooser chooser) {
1599:                return new DirectoryHandler(chooser);
1600:            }
1601:
1602:            private void addNewDirectory(final TreePath path) {
1603:                RequestProcessor.getDefault().post(new Runnable() {
1604:                    public void run() {
1605:                        EventQueue.invokeLater(new Runnable() {
1606:                            public void run() {
1607:                                DirectoryNode selectedNode = (DirectoryNode) path
1608:                                        .getLastPathComponent();
1609:
1610:                                if (selectedNode == null
1611:                                        || !canWrite(selectedNode.getFile())) {
1612:                                    return;
1613:                                }
1614:
1615:                                try {
1616:                                    newFolderNode = new DirectoryNode(
1617:                                            fileChooser.getFileSystemView()
1618:                                                    .createNewFolder(
1619:                                                            selectedNode
1620:                                                                    .getFile()));
1621:                                    model.insertNodeInto(newFolderNode,
1622:                                            selectedNode, selectedNode
1623:                                                    .getChildCount());
1624:                                    applyEdit(newFolderNode);
1625:                                } catch (IOException ex) {
1626:                                    ex.printStackTrace();
1627:                                }
1628:                            }
1629:                        });
1630:                    }
1631:                });
1632:            }
1633:
1634:            private void applyEdit(DirectoryNode node) {
1635:                TreeNode[] nodes = model.getPathToRoot(node);
1636:                TreePath editingPath = new TreePath(nodes);
1637:                tree.setEditable(true);
1638:                tree.makeVisible(editingPath);
1639:                tree.scrollPathToVisible(editingPath);
1640:                tree.setSelectionPath(editingPath);
1641:                tree.startEditingAtPath(editingPath);
1642:
1643:                JTextField editField = DirectoryCellEditor.getTextField();
1644:                editField.setCursor(Cursor
1645:                        .getPredefinedCursor(Cursor.TEXT_CURSOR));
1646:                editField.setRequestFocusEnabled(true);
1647:                editField.requestFocus();
1648:                editField.setSelectionStart(0);
1649:                editField.setSelectionEnd(editField.getText().length());
1650:            }
1651:
1652:            private static boolean canWrite(File f) {
1653:                boolean writeable = false;
1654:                if (f != null) {
1655:                    try {
1656:                        writeable = f.canWrite();
1657:                    } catch (AccessControlException ex) {
1658:                        writeable = false;
1659:                    }
1660:                }
1661:                return writeable;
1662:            }
1663:
1664:            private void expandNode(final JFileChooser fileChooser,
1665:                    final TreePath path) {
1666:
1667:                RequestProcessor.getDefault().post(new Runnable() {
1668:                    DirectoryNode node;
1669:
1670:                    public void run() {
1671:                        if (!EventQueue.isDispatchThread()) {
1672:                            // first pass, out of EQ thread, loads data
1673:                            setCursor(fileChooser, Cursor.WAIT_CURSOR);
1674:                            node = (DirectoryNode) path.getLastPathComponent();
1675:                            node.loadChildren(fileChooser, true);
1676:                            // send to second pass
1677:                            EventQueue.invokeLater(this );
1678:                        } else {
1679:                            // second pass, in EQ thread
1680:                            ((DefaultTreeModel) tree.getModel())
1681:                                    .nodeStructureChanged(node);
1682:                            /*
1683:                             * This happens when the add new directory action is called
1684:                             * and the node is not loaded.  Furthermore, it ensures that
1685:                             * adding a new directory execute after the UI has finished
1686:                             * displaying the children of the expanded node.
1687:                             */
1688:                            if (addNewDirectory) {
1689:                                addNewDirectory(path);
1690:                                addNewDirectory = false;
1691:                            }
1692:                            setCursor(fileChooser, Cursor.DEFAULT_CURSOR);
1693:                        }
1694:                    }
1695:                });
1696:            }
1697:
1698:            private void setCursor(JComponent comp, int type) {
1699:                Window window = SwingUtilities.getWindowAncestor(comp);
1700:                if (window != null) {
1701:                    Cursor cursor = Cursor.getPredefinedCursor(type);
1702:                    window.setCursor(cursor);
1703:                    window.setFocusable(true);
1704:                }
1705:
1706:                JRootPane pane = fileChooser.getRootPane();
1707:                blocker = new InputBlocker();
1708:                if (pane != null) {
1709:                    pane.setGlassPane(blocker);
1710:                }
1711:
1712:                if (type == Cursor.WAIT_CURSOR) {
1713:                    blocker.block();
1714:                } else if (type == Cursor.DEFAULT_CURSOR) {
1715:                    blocker.unBlock();
1716:                }
1717:            }
1718:
1719:            private Icon getNbProjectIcon() {
1720:                if (projectIcon == null) {
1721:                    projectIcon = new ImageIcon(
1722:                            Utilities
1723:                                    .loadImage("org/netbeans/swing/dirchooser/resources/main_project_16.png"));
1724:                }
1725:                return projectIcon;
1726:            }
1727:
1728:            /*************** HELPER CLASSES ***************/
1729:
1730:            private class IconIndenter implements  Icon {
1731:                final static int space = 10;
1732:                Icon icon = null;
1733:                int depth = 0;
1734:
1735:                public void paintIcon(Component c, Graphics g, int x, int y) {
1736:                    if (c.getComponentOrientation().isLeftToRight()) {
1737:                        icon.paintIcon(c, g, x + depth * space, y);
1738:                    } else {
1739:                        icon.paintIcon(c, g, x, y);
1740:                    }
1741:                }
1742:
1743:                public int getIconWidth() {
1744:                    return icon.getIconWidth() + depth * space;
1745:                }
1746:
1747:                public int getIconHeight() {
1748:                    return icon.getIconHeight();
1749:                }
1750:
1751:            }
1752:
1753:            private class DirectoryComboBoxRenderer extends JLabel implements 
1754:                    ListCellRenderer, UIResource {
1755:                IconIndenter indenter = new IconIndenter();
1756:
1757:                public DirectoryComboBoxRenderer() {
1758:                    setOpaque(true);
1759:                }
1760:
1761:                public Component getListCellRendererComponent(JList list,
1762:                        Object value, int index, boolean isSelected,
1763:                        boolean cellHasFocus) {
1764:                    // #89393: GTK needs name to render cell renderer "natively"
1765:                    setName("ComboBox.listRenderer"); // NOI18N
1766:
1767:                    if (value == null) {
1768:                        setText("");
1769:                        return this ;
1770:                    }
1771:                    File directory = (File) value;
1772:                    setText(getFileChooser().getName(directory));
1773:                    Icon icon;
1774:                    if (DirectoryNode.isNetBeansProject(directory)) {
1775:                        icon = getNbProjectIcon();
1776:                    } else {
1777:                        icon = getFileChooser().getIcon(directory);
1778:                    }
1779:                    indenter.icon = icon;
1780:                    indenter.depth = directoryComboBoxModel.getDepth(index);
1781:                    setIcon(indenter);
1782:                    if (isSelected) {
1783:                        setBackground(list.getSelectionBackground());
1784:                        setForeground(list.getSelectionForeground());
1785:                    } else {
1786:                        setBackground(list.getBackground());
1787:                        setForeground(list.getForeground());
1788:                    }
1789:
1790:                    return this ;
1791:                }
1792:
1793:                // #89393: GTK needs name to render cell renderer "natively"
1794:                @Override
1795:                public String getName() {
1796:                    String name = super .getName();
1797:                    return name == null ? "ComboBox.renderer" : name; // NOI18N
1798:                }
1799:            } // end of DirectoryComboBoxRenderer
1800:
1801:            /**
1802:             * Data model for a type-face selection combo-box.
1803:             */
1804:            private class DirectoryComboBoxModel extends AbstractListModel
1805:                    implements  ComboBoxModel {
1806:                Vector<File> directories = new Vector<File>();
1807:                int[] depths = null;
1808:                File selectedDirectory = null;
1809:                JFileChooser chooser = getFileChooser();
1810:                FileSystemView fsv = chooser.getFileSystemView();
1811:
1812:                public DirectoryComboBoxModel() {
1813:                    // Add the current directory to the model, and make it the
1814:                    // selectedDirectory
1815:                    File dir = getFileChooser().getCurrentDirectory();
1816:                    if (dir != null) {
1817:                        addItem(dir);
1818:                    }
1819:                }
1820:
1821:                /**
1822:                 * Adds the directory to the model and sets it to be selected,
1823:                 * additionally clears out the previous selected directory and
1824:                 * the paths leading up to it, if any.
1825:                 */
1826:                private void addItem(File directory) {
1827:
1828:                    if (directory == null) {
1829:                        return;
1830:                    }
1831:
1832:                    directories.clear();
1833:
1834:                    if (useShellFolder) {
1835:                        directories
1836:                                .addAll(Arrays.asList(getShellFolderRoots()));
1837:                    } else {
1838:                        directories.addAll(Arrays.asList(fileChooser
1839:                                .getFileSystemView().getRoots()));
1840:                    }
1841:
1842:                    // Get the canonical (full) path. This has the side
1843:                    // benefit of removing extraneous chars from the path,
1844:                    // for example /foo/bar/ becomes /foo/bar
1845:                    File canonical = null;
1846:                    try {
1847:                        canonical = directory.getCanonicalFile();
1848:                    } catch (IOException e) {
1849:                        // Maybe drive is not ready. Can't abort here.
1850:                        canonical = directory;
1851:                    }
1852:
1853:                    // create File instances of each directory leading up to the top
1854:                    File sf = getShellFolderForFile(canonical);
1855:                    File f = sf;
1856:                    Vector<File> path = new Vector<File>(10);
1857:
1858:                    do {
1859:                        path.addElement(f);
1860:                    } while ((f = f.getParentFile()) != null);
1861:
1862:                    int pathCount = path.size();
1863:                    // Insert chain at appropriate place in vector
1864:                    for (int i = 0; i < pathCount; i++) {
1865:                        f = path.get(i);
1866:                        if (directories.contains(f)) {
1867:                            int topIndex = directories.indexOf(f);
1868:                            for (int j = i - 1; j >= 0; j--) {
1869:                                directories.insertElementAt(path.get(j),
1870:                                        topIndex + i - j);
1871:                            }
1872:                            break;
1873:                        }
1874:                    }
1875:                    calculateDepths();
1876:                    setSelectedItem(sf);
1877:                }
1878:
1879:                private void calculateDepths() {
1880:                    depths = new int[directories.size()];
1881:                    for (int i = 0; i < depths.length; i++) {
1882:                        File dir = directories.get(i);
1883:                        File parent = dir.getParentFile();
1884:                        depths[i] = 0;
1885:                        if (parent != null) {
1886:                            for (int j = i - 1; j >= 0; j--) {
1887:                                if (parent.equals(directories.get(j))) {
1888:                                    depths[i] = depths[j] + 1;
1889:                                    break;
1890:                                }
1891:                            }
1892:                        }
1893:                    }
1894:                }
1895:
1896:                public int getDepth(int i) {
1897:                    return (depths != null && i >= 0 && i < depths.length) ? depths[i]
1898:                            : 0;
1899:                }
1900:
1901:                public void setSelectedItem(Object selectedDirectory) {
1902:                    this .selectedDirectory = (File) selectedDirectory;
1903:                    fireContentsChanged(this , -1, -1);
1904:                }
1905:
1906:                public Object getSelectedItem() {
1907:                    return selectedDirectory;
1908:                }
1909:
1910:                public int getSize() {
1911:                    return directories.size();
1912:                }
1913:
1914:                public Object getElementAt(int index) {
1915:                    return directories.elementAt(index);
1916:                }
1917:            }
1918:
1919:            /**
1920:             * Render different type sizes and styles.
1921:             */
1922:            private class FilterComboBoxRenderer extends JLabel implements 
1923:                    ListCellRenderer, UIResource {
1924:
1925:                public FilterComboBoxRenderer() {
1926:                    setOpaque(true);
1927:                }
1928:
1929:                public Component getListCellRendererComponent(JList list,
1930:                        Object value, int index, boolean isSelected,
1931:                        boolean cellHasFocus) {
1932:
1933:                    // #89393: GTK needs name to render cell renderer "natively"
1934:                    setName("ComboBox.listRenderer"); // NOI18N
1935:
1936:                    if (value != null && value instanceof  FileFilter) {
1937:                        setText(((FileFilter) value).getDescription());
1938:                    }
1939:
1940:                    if (isSelected) {
1941:                        setBackground(list.getSelectionBackground());
1942:                        setForeground(list.getSelectionForeground());
1943:                    } else {
1944:                        setBackground(list.getBackground());
1945:                        setForeground(list.getForeground());
1946:                    }
1947:
1948:                    return this ;
1949:                }
1950:
1951:                // #89393: GTK needs name to render cell renderer "natively"
1952:                public String getName() {
1953:                    String name = super .getName();
1954:                    return name == null ? "ComboBox.renderer" : name; // NOI18N
1955:                }
1956:
1957:            } // end of FilterComboBoxRenderer
1958:
1959:            /**
1960:             * Data model for a type-face selection combo-box.
1961:             */
1962:            protected class FilterTypeComboBoxModel extends AbstractListModel
1963:                    implements  ComboBoxModel, PropertyChangeListener {
1964:                protected FileFilter[] filters;
1965:
1966:                protected FilterTypeComboBoxModel() {
1967:                    super ();
1968:                    filters = getFileChooser().getChoosableFileFilters();
1969:                }
1970:
1971:                public void propertyChange(PropertyChangeEvent e) {
1972:                    String prop = e.getPropertyName();
1973:                    if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
1974:                        filters = (FileFilter[]) e.getNewValue();
1975:                        fireContentsChanged(this , -1, -1);
1976:                    } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
1977:                        fireContentsChanged(this , -1, -1);
1978:                    }
1979:                }
1980:
1981:                public void setSelectedItem(Object filter) {
1982:                    if (filter != null) {
1983:                        getFileChooser().setFileFilter((FileFilter) filter);
1984:                        setFileName(null);
1985:                        fireContentsChanged(this , -1, -1);
1986:                    }
1987:                }
1988:
1989:                public Object getSelectedItem() {
1990:                    // Ensure that the current filter is in the list.
1991:                    // NOTE: we shouldnt' have to do this, since JFileChooser adds
1992:                    // the filter to the choosable filters list when the filter
1993:                    // is set. Lets be paranoid just in case someone overrides
1994:                    // setFileFilter in JFileChooser.
1995:                    FileFilter currentFilter = getFileChooser().getFileFilter();
1996:                    boolean found = false;
1997:                    if (currentFilter != null) {
1998:                        for (int i = 0; i < filters.length; i++) {
1999:                            if (filters[i] == currentFilter) {
2000:                                found = true;
2001:                            }
2002:                        }
2003:                        if (found == false) {
2004:                            getFileChooser().addChoosableFileFilter(
2005:                                    currentFilter);
2006:                        }
2007:                    }
2008:                    return getFileChooser().getFileFilter();
2009:                }
2010:
2011:                public int getSize() {
2012:                    if (filters != null) {
2013:                        return filters.length;
2014:                    } else {
2015:                        return 0;
2016:                    }
2017:                }
2018:
2019:                public Object getElementAt(int index) {
2020:                    if (index > getSize() - 1) {
2021:                        // This shouldn't happen. Try to recover gracefully.
2022:                        return getFileChooser().getFileFilter();
2023:                    }
2024:                    if (filters != null) {
2025:                        return filters[index];
2026:                    } else {
2027:                        return null;
2028:                    }
2029:                }
2030:            }
2031:
2032:            /**
2033:             * Gets calls when the ComboBox has changed the selected item.
2034:             */
2035:            private class DirectoryComboBoxAction implements  ActionListener {
2036:                public void actionPerformed(ActionEvent e) {
2037:                    File f = (File) directoryComboBox.getSelectedItem();
2038:                    getFileChooser().setCurrentDirectory(f);
2039:                }
2040:            }
2041:
2042:            private class DirectoryChooserFileView extends BasicFileView {
2043:
2044:                public Icon getIcon(File f) {
2045:
2046:                    Icon icon = getCachedIcon(f);
2047:                    if (icon != null) {
2048:                        return icon;
2049:                    }
2050:
2051:                    if (f != null) {
2052:                        icon = fileChooser.getFileSystemView().getSystemIcon(f);
2053:                    }
2054:
2055:                    if (icon == null) {
2056:                        icon = super .getIcon(f);
2057:                    }
2058:
2059:                    cacheIcon(f, icon);
2060:                    return icon;
2061:                }
2062:            }
2063:
2064:            private class TextFieldKeyListener extends KeyAdapter {
2065:                public void keyPressed(KeyEvent evt) {
2066:                    showPopupCompletion = true;
2067:                    int keyCode = evt.getKeyCode();
2068:                    // #105801: completionPopup might not be ready when updateCompletions not called (empty text field)
2069:                    if (completionPopup != null && !completionPopup.isVisible()) {
2070:                        if (keyCode == KeyEvent.VK_ENTER) {
2071:                            File file = new File(filenameTextField.getText());
2072:                            if (file.exists() && file.isDirectory()) {
2073:                                setSelected(new File[] { file });
2074:                                fileChooser.approveSelection();
2075:                            }
2076:                        }
2077:
2078:                        if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_DOWN)
2079:                                || (keyCode == KeyEvent.VK_RIGHT && (filenameTextField
2080:                                        .getCaretPosition() >= (filenameTextField
2081:                                        .getDocument().getLength() - 1)))) {
2082:                            updateCompletions();
2083:                        }
2084:
2085:                    }
2086:
2087:                    if (filenameTextField.isFocusOwner()
2088:                            && (completionPopup == null || !completionPopup
2089:                                    .isVisible())
2090:                            && keyCode == KeyEvent.VK_ESCAPE) {
2091:                        fileChooser.cancelSelection();
2092:                    }
2093:                }
2094:            }
2095:
2096:            private class DirectoryHandler extends MouseAdapter implements 
2097:                    TreeSelectionListener, CellEditorListener, ActionListener,
2098:                    FocusListener, Runnable {
2099:                private JFileChooser fileChooser;
2100:                /** current selection holder */
2101:                private WeakReference<TreePath> curSelPath;
2102:                /** timer for slow click to rename feature */
2103:                private Timer renameTimer;
2104:                /** path to rename for slow click to rename feature */
2105:                private TreePath pathToRename;
2106:
2107:                public DirectoryHandler(JFileChooser fileChooser) {
2108:                    this .fileChooser = fileChooser;
2109:                }
2110:
2111:                /************ imple of TreeSelectionListener *******/
2112:
2113:                public void valueChanged(TreeSelectionEvent e) {
2114:                    showPopupCompletion = false;
2115:                    FileSystemView fsv = fileChooser.getFileSystemView();
2116:                    JTree tree = (JTree) e.getSource();
2117:                    TreePath path = tree.getSelectionPath();
2118:                    TreePath curSel = e.getNewLeadSelectionPath();
2119:                    curSelPath = (curSel != null) ? new WeakReference<TreePath>(
2120:                            curSel)
2121:                            : null;
2122:
2123:                    if (path != null) {
2124:
2125:                        DirectoryNode node = (DirectoryNode) path
2126:                                .getLastPathComponent();
2127:                        File file = node.getFile();
2128:
2129:                        if (file != null) {
2130:                            setSelected(getSelectedNodes(tree
2131:                                    .getSelectionPaths()));
2132:                            newFolderAction.setEnabled(canWrite(file)
2133:                                    && file.isDirectory());
2134:
2135:                            if (file.isDirectory()) {
2136:                                setDirectorySelected(true);
2137:                            }
2138:                        }
2139:                    }
2140:                }
2141:
2142:                private File[] getSelectedNodes(TreePath[] paths) {
2143:                    Vector<File> files = new Vector<File>();
2144:                    for (int i = 0; i < paths.length; i++) {
2145:                        File file = ((DirectoryNode) paths[i]
2146:                                .getLastPathComponent()).getFile();
2147:                        if (file.isDirectory()
2148:                                && fileChooser.isTraversable(file)
2149:                                && !fileChooser.getFileSystemView()
2150:                                        .isFileSystem(file)) {
2151:                            continue;
2152:                        }
2153:                        files.add(file);
2154:                    }
2155:                    return files.toArray(new File[files.size()]);
2156:                }
2157:
2158:                /********* impl of MouseListener ***********/
2159:
2160:                public void mouseClicked(MouseEvent e) {
2161:                    final JTree tree = (JTree) e.getSource();
2162:                    Point p = e.getPoint();
2163:                    final int x = e.getX();
2164:                    final int y = e.getY();
2165:                    int row = tree.getRowForLocation(x, y);
2166:                    TreePath path = tree.getPathForRow(row);
2167:
2168:                    if (path != null) {
2169:
2170:                        DirectoryNode node = (DirectoryNode) path
2171:                                .getLastPathComponent();
2172:                        newFolderAction.setEnabled(canWrite(node.getFile()));
2173:
2174:                        if (SwingUtilities.isLeftMouseButton(e)
2175:                                && (e.getClickCount() == 2)) {
2176:                            cancelRename();
2177:                            if (node.isNetBeansProject()) {
2178:                                fileChooser.approveSelection();
2179:                            } else if (node.getFile().isFile()
2180:                                    && !node.getFile().getPath().endsWith(
2181:                                            ".lnk")) {
2182:                                fileChooser.approveSelection();
2183:                            } else {
2184:                                changeTreeDirectory(node.getFile());
2185:                            }
2186:
2187:                        }
2188:
2189:                        // handles click to rename feature
2190:                        if (SwingUtilities.isLeftMouseButton(e)
2191:                                && (e.getClickCount() == 1)) {
2192:                            if (pathToRename != null) {
2193:                                if (renameTimer != null) {
2194:                                    renameTimer.stop();
2195:                                }
2196:                                // start slow click rename timer
2197:                                renameTimer = new Timer(800, this );
2198:                                renameTimer.setRepeats(false);
2199:                                renameTimer.start();
2200:                            }
2201:                        }
2202:
2203:                        ((DirectoryTreeModel) tree.getModel())
2204:                                .nodeChanged(node);
2205:                        if (row == 0) {
2206:                            tree.revalidate();
2207:                            tree.repaint();
2208:                        }
2209:                    }
2210:                }
2211:
2212:                @Override
2213:                public void mousePressed(MouseEvent e) {
2214:                    handlePopupMenu(e);
2215:                }
2216:
2217:                @Override
2218:                public void mouseReleased(MouseEvent e) {
2219:                    handlePopupMenu(e);
2220:                }
2221:
2222:                private void handlePopupMenu(MouseEvent e) {
2223:                    if (!e.isPopupTrigger()) {
2224:                        return;
2225:                    }
2226:                    final JTree tree = (JTree) e.getSource();
2227:                    Point p = e.getPoint();
2228:                    int x = e.getX();
2229:                    int y = e.getY();
2230:                    int row = tree.getRowForLocation(x, y);
2231:                    TreePath path = tree.getPathForRow(row);
2232:
2233:                    if (path != null) {
2234:                        DirectoryNode node = (DirectoryNode) path
2235:                                .getLastPathComponent();
2236:                        ((DirectoryTreeModel) tree.getModel())
2237:                                .nodeChanged(node);
2238:                        if (!fileChooser.getFileSystemView().isFileSystem(
2239:                                node.getFile())) {
2240:                            return;
2241:                        }
2242:
2243:                        tree.setSelectionPath(path);
2244:                        popupMenu.show(tree, x, y);
2245:                    }
2246:                }
2247:
2248:                private void changeTreeDirectory(File dir) {
2249:                    if (File.separatorChar == '\\'
2250:                            && dir.getPath().endsWith(".lnk")) {
2251:                        File linkLocation = getShellFolderForFileLinkLoc(dir);
2252:                        if (linkLocation != null
2253:                                && fileChooser.isTraversable(linkLocation)) {
2254:                            dir = linkLocation;
2255:                        } else {
2256:                            return;
2257:                        }
2258:                    }
2259:                    fileChooser.setCurrentDirectory(dir);
2260:                }
2261:
2262:                /********** implementation of CellEditorListener ****************/
2263:
2264:                /** Refresh filename text field after rename */
2265:                public void editingStopped(ChangeEvent e) {
2266:                    DirectoryNode node = (DirectoryNode) tree
2267:                            .getLastSelectedPathComponent();
2268:                    if (node != null) {
2269:                        setFileName(getStringOfFileName(node.getFile()));
2270:                    }
2271:                }
2272:
2273:                public void editingCanceled(ChangeEvent e) {
2274:                    // no operation
2275:                }
2276:
2277:                /********** ActionListener impl, slow-double-click rename ******/
2278:
2279:                public void actionPerformed(ActionEvent e) {
2280:                    if (tree.isFocusOwner() && isSelectionKept(pathToRename)) {
2281:                        DirectoryNode node = (DirectoryNode) tree
2282:                                .getLastSelectedPathComponent();
2283:                        if (node != null) {
2284:                            applyEdit(node);
2285:                        }
2286:                    }
2287:                    // clear
2288:                    cancelRename();
2289:                }
2290:
2291:                void preprocessMouseEvent(MouseEvent e) {
2292:                    if ((e.getID() != MouseEvent.MOUSE_PRESSED)
2293:                            || (e.getButton() != MouseEvent.BUTTON1)) {
2294:                        return;
2295:                    }
2296:                    TreePath clickedPath = tree.getPathForLocation(e.getX(), e
2297:                            .getY());
2298:                    if (clickedPath != null && isSelectionKept(clickedPath)) {
2299:                        pathToRename = clickedPath;
2300:                    }
2301:                }
2302:
2303:                private boolean isSelectionKept(TreePath selPath) {
2304:                    if (curSelPath != null) {
2305:                        TreePath oldSel = curSelPath.get();
2306:                        if (oldSel != null && oldSel.equals(selPath)) {
2307:                            return true;
2308:                        }
2309:                    }
2310:                    return false;
2311:                }
2312:
2313:                private void cancelRename() {
2314:                    if (renameTimer != null) {
2315:                        renameTimer.stop();
2316:                        renameTimer = null;
2317:                    }
2318:                    pathToRename = null;
2319:                }
2320:
2321:                /******** implementation of focus listener, for slow click rename cancelling ******/
2322:
2323:                public void focusGained(FocusEvent e) {
2324:                    // don't allow to invoke click to rename immediatelly after focus gain
2325:                    // what may happen is that tree gains focus by mouse
2326:                    // click on selected item - on some platforms selected item
2327:                    // is not visible without focus and click to rename will
2328:                    // be unwanted and surprising for users
2329:
2330:                    // see run method
2331:                    SwingUtilities.invokeLater(this );
2332:                }
2333:
2334:                public void run() {
2335:                    cancelRename();
2336:                }
2337:
2338:                public void focusLost(FocusEvent e) {
2339:                    cancelRename();
2340:                }
2341:
2342:            }
2343:
2344:            private class TreeExpansionHandler implements  TreeExpansionListener {
2345:                public void treeExpanded(TreeExpansionEvent evt) {
2346:                    TreePath path = evt.getPath();
2347:                    DirectoryNode node = (DirectoryNode) path
2348:                            .getLastPathComponent();
2349:                    if (!node.isLoaded()) {
2350:                        expandNode(fileChooser, path);
2351:                    } else {
2352:                        // fixed #96954, to be able to add a new directory
2353:                        // when the node has been already loaded
2354:                        if (addNewDirectory) {
2355:                            addNewDirectory(path);
2356:                            addNewDirectory = false;
2357:                        }
2358:                    }
2359:                }
2360:
2361:                public void treeCollapsed(TreeExpansionEvent event) {
2362:                }
2363:            }
2364:
2365:            private class NewDirectoryAction extends AbstractAction {
2366:                public void actionPerformed(ActionEvent e) {
2367:                    final TreePath path = tree.getSelectionPath();
2368:
2369:                    if (path == null) {
2370:                        // if no nodes are selected, get the root node
2371:                        // fixed #96954, to be able to add a new directory
2372:                        // in the current directory shown in the tree
2373:                        addNewDirectory(new TreePath(model
2374:                                .getPathToRoot((DirectoryNode) tree.getModel()
2375:                                        .getRoot())));
2376:                    }
2377:
2378:                    if (path != null) {
2379:                        if (tree.isExpanded(path)) {
2380:                            addNewDirectory(path);
2381:                        } else {
2382:                            addNewDirectory = true;
2383:                            tree.expandPath(path);
2384:                        }
2385:                    }
2386:                }
2387:            }
2388:
2389:            private class DirectoryTreeRenderer implements  TreeCellRenderer {
2390:                HtmlRenderer.Renderer renderer = HtmlRenderer.createRenderer();
2391:
2392:                public Component getTreeCellRendererComponent(JTree tree,
2393:                        Object value, boolean isSelected, boolean expanded,
2394:                        boolean leaf, int row, boolean hasFocus) {
2395:
2396:                    if (!tree.isFocusOwner()) {
2397:                        isSelected = false;
2398:                    }
2399:
2400:                    Component stringDisplayer = renderer
2401:                            .getTreeCellRendererComponent(tree, value,
2402:                                    isSelected, expanded, leaf, row, hasFocus);
2403:
2404:                    if (value instanceof  DirectoryNode) {
2405:                        tree.setShowsRootHandles(true);
2406:                        DirectoryNode node = (DirectoryNode) value;
2407:                        ((JLabel) stringDisplayer).setIcon(getNodeIcon(node));
2408:                        ((JLabel) stringDisplayer).setText(getNodeText(node
2409:                                .getFile()));
2410:                    }
2411:                    Font f = stringDisplayer.getFont();
2412:                    stringDisplayer.setPreferredSize(new Dimension(
2413:                            stringDisplayer.getPreferredSize().width, 30));
2414:
2415:                    // allow some space around icon of items
2416:                    ((JComponent) stringDisplayer).setBorder(BorderFactory
2417:                            .createEmptyBorder(1, 0, 1, 0));
2418:                    stringDisplayer.setSize(stringDisplayer.getPreferredSize());
2419:
2420:                    return stringDisplayer;
2421:                }
2422:
2423:                private Icon getNodeIcon(DirectoryNode node) {
2424:                    if (node.isNetBeansProject()) {
2425:                        return getNbProjectIcon();
2426:                    }
2427:                    File file = node.getFile();
2428:                    if (file.exists()) {
2429:                        return fileChooser.getIcon(file);
2430:                    } else {
2431:                        return null;
2432:                    }
2433:                }
2434:
2435:                private String getNodeText(File file) {
2436:                    if (file.exists()) {
2437:                        return "<html>" + fileChooser.getName(file) + "</html>";
2438:                    } else {
2439:                        return "<html></html>";
2440:                    }
2441:                }
2442:            }
2443:
2444:            private class DirectoryTreeModel extends DefaultTreeModel {
2445:
2446:                public DirectoryTreeModel(TreeNode root) {
2447:                    super (root);
2448:                }
2449:
2450:                public void valueForPathChanged(TreePath path, Object newValue) {
2451:                    boolean refreshTree = false;
2452:                    DirectoryNode node = (DirectoryNode) path
2453:                            .getLastPathComponent();
2454:                    File f = node.getFile();
2455:                    File newFile = new File(f.getParentFile(),
2456:                            (String) newValue);
2457:
2458:                    if (f.renameTo(newFile)) {
2459:                        // fix bug #97521, #96960
2460:                        if (tree.isExpanded(path)) {
2461:                            tree.collapsePath(path);
2462:                            refreshTree = true;
2463:                        }
2464:
2465:                        node.setFile(newFile);
2466:                        node.removeAllChildren();
2467:
2468:                        ((DefaultTreeModel) tree.getModel())
2469:                                .nodeStructureChanged(node);
2470:                        if (refreshTree) {
2471:                            tree.expandPath(path);
2472:                        }
2473:                    }
2474:                }
2475:            }
2476:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.