KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > ui > ProjectChooserAccessory


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.project.ui;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.EventQueue JavaDoc;
24 import java.awt.event.ActionEvent JavaDoc;
25 import java.awt.event.ActionListener JavaDoc;
26 import java.beans.PropertyChangeEvent JavaDoc;
27 import java.beans.PropertyChangeListener JavaDoc;
28 import java.io.File JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.net.URI JavaDoc;
31 import java.text.Collator JavaDoc;
32 import java.text.MessageFormat JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40 import javax.swing.DefaultListModel JavaDoc;
41 import javax.swing.Icon JavaDoc;
42 import javax.swing.ImageIcon JavaDoc;
43 import javax.swing.JFileChooser JavaDoc;
44 import javax.swing.ListModel JavaDoc;
45 import javax.swing.SwingUtilities JavaDoc;
46 import javax.swing.UIManager JavaDoc;
47 import javax.swing.filechooser.FileFilter JavaDoc;
48 import javax.swing.filechooser.FileSystemView JavaDoc;
49 import javax.swing.filechooser.FileView JavaDoc;
50 import org.netbeans.api.project.Project;
51 import org.netbeans.api.project.ProjectManager;
52 import org.netbeans.api.project.ProjectUtils;
53 import org.netbeans.api.queries.CollocationQuery;
54 import org.netbeans.spi.project.SubprojectProvider;
55 import org.openide.ErrorManager;
56 import org.openide.filesystems.FileObject;
57 import org.openide.filesystems.FileUtil;
58 import org.openide.util.NbBundle;
59 import org.openide.util.RequestProcessor;
60 import org.openide.util.Utilities;
61
62 /**
63  * Special component on side of project filechooser.
64  */

65 public class ProjectChooserAccessory extends javax.swing.JPanel JavaDoc
66     implements ActionListener JavaDoc, PropertyChangeListener JavaDoc {
67
68     private RequestProcessor.Task updateSubprojectsTask;
69     private ModelUpdater modelUpdater;
70
71     private Boolean JavaDoc tempSetAsMain;
72
73     private Map JavaDoc<Project,Set JavaDoc<? extends Project>> subprojectsCache = new HashMap JavaDoc<Project,Set JavaDoc<? extends Project>>(); // #59098
74

75     /** Creates new form ProjectChooserAccessory */
76     public ProjectChooserAccessory( JFileChooser JavaDoc chooser, boolean isOpenSubprojects, boolean isOpenAsMain ) {
77         initComponents();
78
79         modelUpdater = new ModelUpdater();
80         updateSubprojectsTask = new RequestProcessor(ModelUpdater.class.getName()).create(modelUpdater);
81         updateSubprojectsTask.setPriority( Thread.MIN_PRIORITY );
82
83         // Listen on the subproject checkbox to change the option accordingly
84
jCheckBoxSubprojects.setSelected( isOpenSubprojects );
85         jCheckBoxSubprojects.addActionListener( this );
86
87         // Listen on the main checkbox to change the option accordingly
88
jCheckBoxMain.setSelected( isOpenAsMain );
89         jCheckBoxMain.addActionListener( this );
90
91         // Listen on the chooser to update the Accessory
92
chooser.addPropertyChangeListener( this );
93
94         // Set default list model for the subprojects list
95
jListSubprojects.setModel( new DefaultListModel JavaDoc() );
96
97         // Disable the Accessory. JFileChooser does not select a file
98
// by default
99
setAccessoryEnablement( false, 0 );
100     }
101
102     /** This method is called from within the constructor to
103      * initialize the form.
104      * WARNING: Do NOT modify this code. The content of this method is
105      * always regenerated by the Form Editor.
106      */

107     private void initComponents() {//GEN-BEGIN:initComponents
108
java.awt.GridBagConstraints JavaDoc gridBagConstraints;
109
110         jLabelProjectName = new javax.swing.JLabel JavaDoc();
111         jTextFieldProjectName = new javax.swing.JTextField JavaDoc();
112         jCheckBoxMain = new javax.swing.JCheckBox JavaDoc();
113         jCheckBoxSubprojects = new javax.swing.JCheckBox JavaDoc();
114         jScrollPaneSubprojects = new javax.swing.JScrollPane JavaDoc();
115         jListSubprojects = new javax.swing.JList JavaDoc();
116
117         setLayout(new java.awt.GridBagLayout JavaDoc());
118
119         setBorder(new javax.swing.border.EmptyBorder JavaDoc(new java.awt.Insets JavaDoc(0, 12, 0, 0)));
120         jLabelProjectName.setLabelFor(jTextFieldProjectName);
121         org.openide.awt.Mnemonics.setLocalizedText(jLabelProjectName, org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "LBL_PrjChooser_ProjectName_Label"));
122         gridBagConstraints = new java.awt.GridBagConstraints JavaDoc();
123         gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
124         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
125         gridBagConstraints.insets = new java.awt.Insets JavaDoc(0, 0, 2, 0);
126         add(jLabelProjectName, gridBagConstraints);
127         jLabelProjectName.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "AN_ProjectName"));
128         jLabelProjectName.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "AD_ProjectName"));
129
130         jTextFieldProjectName.setEditable(false);
131         gridBagConstraints = new java.awt.GridBagConstraints JavaDoc();
132         gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
133         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
134         gridBagConstraints.weightx = 1.0;
135         gridBagConstraints.insets = new java.awt.Insets JavaDoc(0, 0, 6, 0);
136         add(jTextFieldProjectName, gridBagConstraints);
137
138         org.openide.awt.Mnemonics.setLocalizedText(jCheckBoxMain, org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "LBL_PrjChooser_Main_CheckBox"));
139         jCheckBoxMain.setMargin(new java.awt.Insets JavaDoc(2, 0, 2, 2));
140         gridBagConstraints = new java.awt.GridBagConstraints JavaDoc();
141         gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
142         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
143         gridBagConstraints.insets = new java.awt.Insets JavaDoc(0, 0, 12, 0);
144         add(jCheckBoxMain, gridBagConstraints);
145         jCheckBoxMain.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "ACSD_ProjectChooserAccessory_jCheckBoxMain"));
146
147         org.openide.awt.Mnemonics.setLocalizedText(jCheckBoxSubprojects, org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "LBL_PrjChooser_Subprojects_CheckBox"));
148         jCheckBoxSubprojects.setMargin(new java.awt.Insets JavaDoc(2, 0, 2, 2));
149         gridBagConstraints = new java.awt.GridBagConstraints JavaDoc();
150         gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
151         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
152         gridBagConstraints.insets = new java.awt.Insets JavaDoc(0, 0, 2, 0);
153         add(jCheckBoxSubprojects, gridBagConstraints);
154         jCheckBoxSubprojects.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "ACSD_ProjectChooserAccessory_jCheckBoxSubprojects"));
155
156         jListSubprojects.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
157         jListSubprojects.setEnabled(false);
158         jScrollPaneSubprojects.setViewportView(jListSubprojects);
159         jListSubprojects.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "ACSN_ProjectChooserAccessory_jListSubprojects"));
160         jListSubprojects.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "ACSD_ProjectChooserAccessory_jListSubprojects"));
161
162         gridBagConstraints = new java.awt.GridBagConstraints JavaDoc();
163         gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
164         gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
165         gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
166         gridBagConstraints.weightx = 1.0;
167         gridBagConstraints.weighty = 1.0;
168         add(jScrollPaneSubprojects, gridBagConstraints);
169
170     }//GEN-END:initComponents
171

172
173     // Variables declaration - do not modify//GEN-BEGIN:variables
174
private javax.swing.JCheckBox JavaDoc jCheckBoxMain;
175     private javax.swing.JCheckBox JavaDoc jCheckBoxSubprojects;
176     private javax.swing.JLabel JavaDoc jLabelProjectName;
177     private javax.swing.JList JavaDoc jListSubprojects;
178     private javax.swing.JScrollPane JavaDoc jScrollPaneSubprojects;
179     private javax.swing.JTextField JavaDoc jTextFieldProjectName;
180     // End of variables declaration//GEN-END:variables
181

182     // Implementation of action listener ---------------------------------------
183

184     public void actionPerformed( ActionEvent JavaDoc e ) {
185         if ( e.getSource() == jCheckBoxSubprojects ) {
186             OpenProjectListSettings.getInstance().setOpenSubprojects( jCheckBoxSubprojects.isSelected() );
187         }
188         else if ( e.getSource() == jCheckBoxMain ) {
189             OpenProjectListSettings.getInstance().setOpenAsMain( jCheckBoxMain.isSelected() );
190         }
191     }
192
193     public void propertyChange( PropertyChangeEvent JavaDoc e ) {
194         if ( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals( e.getPropertyName() ) ||
195              JFileChooser.SELECTED_FILES_CHANGED_PROPERTY.equals( e.getPropertyName() ) ) {
196
197             // We have to update the Accessory
198
JFileChooser JavaDoc chooser = (JFileChooser JavaDoc)e.getSource();
199             final ListModel JavaDoc spListModel = jListSubprojects.getModel();
200
201
202             final File JavaDoc[] projectDirs;
203             if ( chooser.isMultiSelectionEnabled() ) {
204                 projectDirs = chooser.getSelectedFiles();
205             }
206             else {
207                 projectDirs = new File JavaDoc[] { chooser.getSelectedFile() };
208             }
209
210             // #87119: do not block EQ loading projects
211
jTextFieldProjectName.setText(NbBundle.getMessage(ProjectChooserAccessory.class, "MSG_PrjChooser_WaitMessage"));
212             RequestProcessor.getDefault().post(new Runnable JavaDoc() {
213                 public void run() {
214
215             final List JavaDoc<Project> projects = new ArrayList JavaDoc<Project>( projectDirs.length );
216             for (File JavaDoc dir : projectDirs) {
217                 if (dir != null) {
218                     Project project = getProject(FileUtil.normalizeFile(dir));
219                     if ( project != null ) {
220                         projects.add( project );
221                     }
222                 }
223             }
224
225             EventQueue.invokeLater(new Runnable JavaDoc() {
226                 public void run() {
227
228             if ( !projects.isEmpty() ) {
229                 // Enable all components acessory
230
setAccessoryEnablement( true, projects.size() );
231
232                 if ( projects.size() == 1 ) {
233                     String JavaDoc projectName = ProjectUtils.getInformation(projects.get(0)).getDisplayName();
234                     jTextFieldProjectName.setText( projectName );
235                     jTextFieldProjectName.setToolTipText( projectName );
236                 }
237                 else {
238                     jTextFieldProjectName.setText(NbBundle.getMessage(ProjectChooserAccessory.class, "LBL_PrjChooser_Multiselection", projects.size()));
239
240                     StringBuffer JavaDoc toolTipText = new StringBuffer JavaDoc( "<html>" ); // NOI18N
241
for(Iterator JavaDoc<Project> it = projects.iterator(); it.hasNext();) {
242                         Project p = it.next();
243                         toolTipText.append( ProjectUtils.getInformation( p ).getDisplayName() );
244                         if ( it.hasNext() ) {
245                             toolTipText.append( "<br>" ); // NOI18N
246
}
247                     }
248                     toolTipText.append( "</html>" ); // NOI18N
249
jTextFieldProjectName.setToolTipText( toolTipText.toString() );
250                 }
251
252                 if (spListModel instanceof DefaultListModel JavaDoc) {
253                     ((DefaultListModel JavaDoc)spListModel).clear();
254                 } else {
255                     jListSubprojects.setListData (new String JavaDoc[0]);
256                 }
257
258                 if (modelUpdater != null) { // #72495
259
modelUpdater.projects = projects;
260                     updateSubprojectsTask.schedule( 100 );
261                 }
262             }
263             else {
264                 // Clear the accessory data if the dir is not project dir
265
jTextFieldProjectName.setText( "" ); // NOI18N
266
if (modelUpdater != null) { // #72495
267
modelUpdater.projects = null;
268                 }
269
270                 if (spListModel instanceof DefaultListModel JavaDoc) {
271                     ((DefaultListModel JavaDoc)spListModel).clear();
272                 } else {
273                     jListSubprojects.setListData (new String JavaDoc[0]);
274                 }
275
276                 // Disable all components in accessory
277
setAccessoryEnablement( false, 0 );
278
279                 // But, in case it is a load error, show that:
280
if (projectDirs.length == 1 && projectDirs[0] != null) {
281                     File JavaDoc dir = FileUtil.normalizeFile(projectDirs[0]);
282                     FileObject fo = FileUtil.toFileObject(dir);
283                     if (fo != null && fo.isFolder() && ProjectManager.getDefault().isProject(fo)) {
284                         try {
285                             Project prj = ProjectManager.getDefault().findProject(fo);
286                             if (prj == null) {
287                                 jTextFieldProjectName.setText(NbBundle.getMessage(ProjectChooserAccessory.class, "LBL_PrjChooser_Unrecognized"));
288                                 // Only so it can be focussed and message scrolled accessibly:
289
jLabelProjectName.setEnabled(true);
290                                 jTextFieldProjectName.setEnabled(true);
291                             }
292                         } catch (IOException JavaDoc x) {
293                             String JavaDoc msg = x.toString();
294                             ErrorManager.Annotation[] anns = ErrorManager.getDefault().findAnnotations(x);
295                             for (int i = 0; i < anns.length; i++) {
296                                 if (anns[i].getLocalizedMessage() != null) {
297                                     msg = anns[i].getLocalizedMessage();
298                                     break;
299                                 }
300                             }
301                             jTextFieldProjectName.setText(msg);
302                             jTextFieldProjectName.setCaretPosition(0);
303                             Color JavaDoc error = UIManager.getColor("nb.errorForeground"); // NOI18N
304
if (error != null) {
305                                 jTextFieldProjectName.setForeground(error);
306                             }
307                             // Only so it can be focussed and message scrolled accessibly:
308
jLabelProjectName.setEnabled(true);
309                             jTextFieldProjectName.setEnabled(true);
310                         }
311                     }
312                 }
313             }
314
315                         }
316                     });
317                 }
318             });
319         }
320         else if ( JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals( e.getPropertyName() ) ) {
321             // Selection lost => disable accessory
322
setAccessoryEnablement( false, 0 );
323         }
324     }
325
326
327     // Private methods ---------------------------------------------------------
328

329     private static boolean isProjectDir( File JavaDoc dir ) {
330         boolean retVal = false;
331         if (dir != null) {
332             FileObject fo = convertToValidDir(dir);
333             if (fo != null) {
334                 if ( Utilities.isUnix() && fo.getParent() != null && fo.getParent().getParent() == null ) {
335                     retVal = false; // Ignore all subfolders of / on unixes (e.g. /net, /proc)
336
}
337                 else {
338                     retVal = ProjectManager.getDefault().isProject( fo );
339                 }
340             }
341         }
342         return retVal;
343     }
344
345     private static FileObject convertToValidDir(File JavaDoc f) {
346         FileObject fo;
347         File JavaDoc testFile = new File JavaDoc( f.getPath() );
348         if ( testFile == null || testFile.getParent() == null ) {
349             // BTW this means that roots of file systems can't be project
350
// directories.
351
return null;
352         }
353
354         /**ATTENTION: on Windows may occur dir.isDirectory () == dir.isFile () == true then
355          * its used testFile instead of dir.
356         */

357         if ( !testFile.isDirectory() ) {
358             return null;
359         }
360
361         fo = FileUtil.toFileObject(FileUtil.normalizeFile(f));
362         return fo;
363     }
364
365     private static Project getProject( File JavaDoc dir ) {
366         return OpenProjectList.fileToProject( dir );
367     }
368
369     private void setAccessoryEnablement( boolean enable, int numberOfProjects ) {
370         jLabelProjectName.setEnabled( enable );
371         jTextFieldProjectName.setEnabled( enable );
372         jTextFieldProjectName.setForeground(/* i.e. L&F default */null);
373         jCheckBoxSubprojects.setEnabled( enable );
374         jScrollPaneSubprojects.setEnabled( enable );
375
376         if ( numberOfProjects <= 1 ) {
377             if ( tempSetAsMain != null ) {
378                 jCheckBoxMain.setSelected(tempSetAsMain);
379                 tempSetAsMain = null;
380             }
381             jCheckBoxMain.setEnabled( enable );
382         }
383         else if ( tempSetAsMain == null ) {
384             tempSetAsMain = jCheckBoxMain.isSelected();
385             jCheckBoxMain.setSelected( false );
386             jCheckBoxMain.setEnabled( false );
387         }
388
389     }
390
391     /** Gets all subprojects recursively
392      */

393     static void addSubprojects(Project p, List JavaDoc<Project> result, Map JavaDoc<Project,Set JavaDoc<? extends Project>> cache) {
394         Set JavaDoc<? extends Project> subprojects = cache.get(p);
395         if (subprojects == null) {
396             SubprojectProvider spp = p.getLookup().lookup(SubprojectProvider.class);
397             if (spp != null) {
398                 subprojects = spp.getSubprojects();
399             } else {
400                 subprojects = Collections.emptySet();
401             }
402             cache.put(p, subprojects);
403         }
404         for (Project sp : subprojects) {
405             if ( !result.contains( sp ) ) {
406                 result.add( sp );
407
408                 //#70029: only add sp's subprojects if sp is not already in result,
409
//to prevent StackOverflow caused by misconfigured projects:
410
addSubprojects(sp, result, cache);
411             }
412         }
413
414     }
415
416     /**
417      * Get a slash-separated relative path from f1 to f2, if they are collocated
418      * and this is possible.
419      * May return null.
420      */

421     private static String JavaDoc relativizePath(File JavaDoc f1, File JavaDoc f2) {
422         if (f1 == null || f2 == null) {
423             return null;
424         }
425         if (!CollocationQuery.areCollocated(f1, f2)) {
426             return null;
427         }
428         // Copied from PropertyUtils.relativizeFile, more or less:
429
StringBuffer JavaDoc b = new StringBuffer JavaDoc();
430         File JavaDoc base = f1;
431         String JavaDoc filepath = f2.getAbsolutePath();
432         while (!filepath.startsWith(slashify(base.getAbsolutePath()))) {
433             base = base.getParentFile();
434             if (base == null) {
435                 return null;
436             }
437             if (base.equals(f2)) {
438                 // #61687: file is a parent of basedir
439
b.append(".."); // NOI18N
440
return b.toString();
441             }
442             b.append("../"); // NOI18N
443
}
444         URI JavaDoc u = base.toURI().relativize(f2.toURI());
445         assert !u.isAbsolute() : u + " from " + f1 + " and " + f2 + " with common root " + base;
446         b.append(u.getPath());
447         if (b.charAt(b.length() - 1) == '/') {
448             // file is an existing directory and file.toURI ends in /
449
// we do not want the trailing slash
450
b.setLength(b.length() - 1);
451         }
452         return b.toString();
453     }
454     private static String JavaDoc slashify(String JavaDoc path) {
455         if (path.endsWith(File.separator)) {
456             return path;
457         } else {
458             return path + File.separatorChar;
459         }
460     }
461
462
463     // Other methods -----------------------------------------------------------
464

465     /** Factory method for project chooser
466      */

467     public static JFileChooser JavaDoc createProjectChooser( boolean defaultAccessory ) {
468
469         ProjectManager.getDefault().clearNonProjectCache(); // #41882
470

471         OpenProjectListSettings opls = OpenProjectListSettings.getInstance();
472         JFileChooser JavaDoc chooser = new ProjectFileChooser();
473         chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
474
475         if ("GTK".equals(javax.swing.UIManager.getLookAndFeel().getID())) { // NOI18N
476
// see BugTraq #5027268
477
chooser.putClientProperty("GTKFileChooser.showDirectoryIcons", Boolean.TRUE); // NOI18N
478
//chooser.putClientProperty("GTKFileChooser.showFileIcons", Boolean.TRUE); // NOI18N
479
}
480
481         chooser.setApproveButtonText( NbBundle.getMessage( ProjectChooserAccessory.class, "BTN_PrjChooser_ApproveButtonText" ) ); // NOI18N
482
chooser.setApproveButtonMnemonic( NbBundle.getMessage( ProjectChooserAccessory.class, "MNM_PrjChooser_ApproveButtonText" ).charAt (0) ); // NOI18N
483
chooser.setApproveButtonToolTipText (NbBundle.getMessage( ProjectChooserAccessory.class, "BTN_PrjChooser_ApproveButtonTooltipText")); // NOI18N
484
// chooser.setMultiSelectionEnabled( true );
485
chooser.setDialogTitle( NbBundle.getMessage( ProjectChooserAccessory.class, "LBL_PrjChooser_Title" ) ); // NOI18N
486
//#61789 on old macosx (jdk 1.4.1) these two method need to be called in this order.
487
chooser.setAcceptAllFileFilterUsed( false );
488         chooser.setFileFilter( ProjectDirFilter.INSTANCE );
489
490         // A11Y
491
chooser.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "AN_ProjectChooserAccessory"));
492         chooser.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ProjectChooserAccessory.class, "AD_ProjectChooserAccessory"));
493
494
495         if ( defaultAccessory ) {
496             chooser.setAccessory( new ProjectChooserAccessory( chooser, opls.isOpenSubprojects(), opls.isOpenAsMain() ) );
497         }
498
499         File JavaDoc currDir = null;
500         String JavaDoc dir = opls.getLastOpenProjectDir();
501         if ( dir != null ) {
502             File JavaDoc d = new File JavaDoc( dir );
503             if ( d.exists() && d.isDirectory() ) {
504                 currDir = d;
505             }
506         }
507
508         FileUtil.preventFileChooserSymlinkTraversal(chooser, currDir);
509         chooser.setFileView( new ProjectFileView( chooser.getFileSystemView() ) );
510
511         return chooser;
512
513     }
514
515     public void removeNotify() { // #72006
516
super.removeNotify();
517         modelUpdater = null;
518         subprojectsCache = null;
519         updateSubprojectsTask = null;
520     }
521
522     // Aditional innerclasses for the file chooser -----------------------------
523

524     private static class ProjectFileChooser extends JFileChooser JavaDoc {
525
526         public void approveSelection() {
527             File JavaDoc dir = FileUtil.normalizeFile(getSelectedFile());
528
529             if ( isProjectDir( dir ) && getProject( dir ) != null ) {
530                 super.approveSelection();
531             }
532             else {
533                 setCurrentDirectory( dir );
534             }
535
536         }
537
538
539     }
540
541     private static class ProjectDirFilter extends FileFilter JavaDoc {
542
543         private static final FileFilter JavaDoc INSTANCE = new ProjectDirFilter( );
544
545         public boolean accept( File JavaDoc f ) {
546
547             if ( f.isDirectory() ) {
548                 return true; // Directory selected
549
}
550
551             return false;
552         }
553
554         public String JavaDoc getDescription() {
555             return NbBundle.getMessage( ProjectDirFilter.class, "LBL_PrjChooser_ProjectDirectoryFilter_Name" ); // NOI18N
556
}
557
558     }
559
560     private static class ProjectFileView extends FileView JavaDoc {
561
562         private static final Icon JavaDoc BADGE = new ImageIcon JavaDoc(Utilities.loadImage("org/netbeans/modules/project/ui/resources/projectBadge.gif")); // NOI18N
563
private static final Icon JavaDoc EMPTY = new ImageIcon JavaDoc(Utilities.loadImage("org/netbeans/modules/project/ui/resources/empty.gif")); // NOI18N
564

565         private FileSystemView JavaDoc fsv;
566         private Icon JavaDoc lastOriginal;
567         private Icon JavaDoc lastMerged;
568
569         public ProjectFileView( FileSystemView JavaDoc fsv ) {
570             this.fsv = fsv;
571         }
572
573         public Icon JavaDoc getIcon(File JavaDoc _f) {
574             if (!_f.exists()) {
575                 // Can happen when a file was deleted on disk while project
576
// dialog was still open. In that case, throws an exception
577
// repeatedly from FSV.gSI during repaint.
578
return null;
579             }
580             File JavaDoc f = FileUtil.normalizeFile(_f);
581             Icon JavaDoc original = fsv.getSystemIcon(f);
582             if (original == null) {
583                 // L&F (e.g. GTK) did not specify any icon.
584
original = EMPTY;
585             }
586             if ( isProjectDir( f ) ) {
587                 if ( original.equals( lastOriginal ) ) {
588                     return lastMerged;
589                 }
590                 lastOriginal = original;
591                 lastMerged = new MergedIcon(original, BADGE, -1, -1);
592                 return lastMerged;
593             }
594             else {
595                 return original;
596             }
597         }
598
599
600     }
601
602     private static class MergedIcon implements Icon JavaDoc {
603
604         private Icon JavaDoc icon1;
605         private Icon JavaDoc icon2;
606         private int xMerge;
607         private int yMerge;
608
609         MergedIcon( Icon JavaDoc icon1, Icon JavaDoc icon2, int xMerge, int yMerge ) {
610
611             this.icon1 = icon1;
612             this.icon2 = icon2;
613
614             if ( xMerge == -1 ) {
615                 xMerge = icon1.getIconWidth() - icon2.getIconWidth();
616             }
617
618             if ( yMerge == -1 ) {
619                 yMerge = icon1.getIconHeight() - icon2.getIconHeight();
620             }
621
622             this.xMerge = xMerge;
623             this.yMerge = yMerge;
624         }
625
626         public int getIconHeight() {
627             return Math.max( icon1.getIconHeight(), yMerge + icon2.getIconHeight() );
628         }
629
630         public int getIconWidth() {
631             return Math.max( icon1.getIconWidth(), yMerge + icon2.getIconWidth() );
632         }
633
634         public void paintIcon(java.awt.Component JavaDoc c, java.awt.Graphics JavaDoc g, int x, int y) {
635             icon1.paintIcon( c, g, x, y );
636             icon2.paintIcon( c, g, x + xMerge, y + yMerge );
637         }
638
639     }
640
641     private class ModelUpdater implements Runnable JavaDoc {
642
643         // volatile Project project;
644
volatile List JavaDoc<Project> projects;
645         private DefaultListModel JavaDoc subprojectsToSet;
646
647         public void run() {
648
649             if ( !SwingUtilities.isEventDispatchThread() ) {
650                 List JavaDoc<Project> currentProjects = projects;
651                 if ( currentProjects == null ) {
652                     return;
653                 }
654                 Map JavaDoc<Project,Set JavaDoc<? extends Project>> cache = subprojectsCache;
655                 if (cache == null) {
656                     return;
657                 }
658
659                 jListSubprojects.setListData (new String JavaDoc [] {NbBundle.getMessage (ProjectChooserAccessory.class, "MSG_PrjChooser_WaitMessage")});
660
661                 List JavaDoc<Project> subprojects = new ArrayList JavaDoc<Project>(currentProjects.size() * 5);
662                 for (Project p : currentProjects) {
663                     addSubprojects(p, subprojects, cache); // Find the projects recursively
664
}
665
666         List JavaDoc<String JavaDoc> subprojectNames = new ArrayList JavaDoc<String JavaDoc>(subprojects.size());
667                 if ( !subprojects.isEmpty() ) {
668                     String JavaDoc pattern = NbBundle.getMessage( ProjectChooserAccessory.class, "LBL_PrjChooser_SubprojectName_Format" ); // NOI18N
669
File JavaDoc pDir = currentProjects.size() == 1 ?
670                                 FileUtil.toFile( currentProjects.get(0).getProjectDirectory() ) :
671                                 null;
672
673                     // Replace projects in the list with formated names
674
for (Project p : subprojects) {
675                         FileObject spDir = p.getProjectDirectory();
676
677                         // Try to compute relative path
678
String JavaDoc relPath = null;
679                         if ( pDir != null ) { // If only one project is selected
680
relPath = relativizePath(pDir, FileUtil.toFile( spDir ));
681                         }
682
683                         if (relPath == null) {
684                             // Cannot get a relative path; display it as absolute.
685
relPath = FileUtil.getFileDisplayName(spDir);
686                         }
687                         String JavaDoc displayName = MessageFormat.format(
688                             pattern,
689                             ProjectUtils.getInformation(p).getDisplayName(),
690                             relPath);
691                         subprojectNames.add(displayName);
692                     }
693
694                     // Sort the list
695
Collections.sort( subprojectNames, Collator.getInstance() );
696                 }
697                 if ( currentProjects != projects ) {
698                     return;
699                 }
700                 DefaultListModel JavaDoc listModel = new DefaultListModel JavaDoc();
701                 // Put all the strings into the list model
702
for (String JavaDoc displayName : subprojectNames) {
703                     listModel.addElement(displayName);
704                 }
705                 subprojectsToSet = listModel;
706                 SwingUtilities.invokeLater( this );
707                 return;
708             }
709             else {
710                 if ( projects == null ) {
711                     ListModel JavaDoc spListModel = jListSubprojects.getModel();
712                     if (spListModel instanceof DefaultListModel JavaDoc) {
713                         ((DefaultListModel JavaDoc)spListModel).clear();
714                     } else {
715                         jListSubprojects.setListData (new String JavaDoc[0]);
716                     }
717                     jCheckBoxSubprojects.setEnabled( false );
718                 }
719                 else {
720                     jListSubprojects.setModel(subprojectsToSet);
721                     // If no soubprojects checkbox should be disabled
722
jCheckBoxSubprojects.setEnabled( !subprojectsToSet.isEmpty() );
723                     projects = null;
724                 }
725             }
726
727         }
728
729
730     }
731
732
733 }
734
Popular Tags