KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > java > project > support > ui > PackageRootNode


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.spi.java.project.support.ui;
21
22 import java.awt.Image JavaDoc;
23 import java.awt.datatransfer.DataFlavor JavaDoc;
24 import java.awt.datatransfer.Transferable JavaDoc;
25 import java.awt.datatransfer.UnsupportedFlavorException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Set JavaDoc;
33 import javax.swing.Action JavaDoc;
34 import javax.swing.Icon JavaDoc;
35 import org.netbeans.api.project.SourceGroup;
36 import org.netbeans.spi.project.ui.support.CommonProjectActions;
37 import org.openide.ErrorManager;
38 import org.openide.actions.FileSystemAction;
39 import org.openide.actions.FindAction;
40 import org.openide.actions.PasteAction;
41 import org.openide.actions.ToolsAction;
42 import org.openide.filesystems.FileObject;
43 import org.openide.filesystems.FileStateInvalidException;
44 import org.openide.filesystems.FileStatusEvent;
45 import org.openide.filesystems.FileStatusListener;
46 import org.openide.filesystems.FileSystem;
47 import org.openide.filesystems.FileUtil;
48 import org.openide.loaders.DataFolder;
49 import org.openide.loaders.DataObject;
50 import org.openide.nodes.AbstractNode;
51 import org.openide.nodes.Node;
52 import org.openide.nodes.Node.PropertySet;
53 import org.openide.nodes.NodeNotFoundException;
54 import org.openide.nodes.NodeOp;
55 import org.openide.nodes.PropertySupport;
56 import org.openide.nodes.Sheet;
57 import org.openide.util.Lookup;
58 import org.openide.util.NbBundle;
59 import org.openide.util.RequestProcessor;
60 import org.openide.util.Utilities;
61 import org.openide.util.actions.SystemAction;
62 import org.openide.util.datatransfer.ExTransferable;
63 import org.openide.util.datatransfer.MultiTransferObject;
64 import org.openide.util.datatransfer.PasteType;
65 import org.openide.util.lookup.AbstractLookup;
66 import org.openide.util.lookup.InstanceContent;
67 import org.openide.util.lookup.Lookups;
68 import org.openide.util.lookup.ProxyLookup;
69 import org.openidex.search.SearchInfo;
70 import org.openidex.search.SearchInfoFactory;
71
72 /** Node displaying a packages in given SourceGroup
73  * @author Petr Hrebejk
74  */

75 final class PackageRootNode extends AbstractNode implements Runnable JavaDoc, FileStatusListener {
76
77     static Image JavaDoc PACKAGE_BADGE = Utilities.loadImage( "org/netbeans/spi/java/project/support/ui/packageBadge.gif" ); // NOI18N
78

79     private static Action JavaDoc actions[];
80
81     private SourceGroup group;
82
83     private final FileObject file;
84     private final Set JavaDoc<FileObject> files;
85     private FileStatusListener fileSystemListener;
86     private RequestProcessor.Task task;
87     private volatile boolean iconChange;
88     private volatile boolean nameChange;
89     
90     PackageRootNode( SourceGroup group ) {
91         this( group, new InstanceContent() );
92     }
93     
94     private PackageRootNode( SourceGroup group, InstanceContent ic ) {
95         super( new PackageViewChildren(group),
96                 new ProxyLookup(createLookup(group), new AbstractLookup(ic)));
97         ic.add(alwaysSearchableSearchInfo(SearchInfoFactory.createSearchInfoBySubnodes(this)));
98         this.group = group;
99         file = group.getRootFolder();
100         files = Collections.singleton(file);
101         try {
102             FileSystem fs = file.getFileSystem();
103             fileSystemListener = FileUtil.weakFileStatusListener(this, fs);
104             fs.addFileStatusListener(fileSystemListener);
105         } catch (FileStateInvalidException e) {
106             ErrorManager err = ErrorManager.getDefault();
107             err.annotate(e, "Can not get " + file + " filesystem, ignoring..."); // NO18N
108
err.notify(ErrorManager.INFORMATIONAL, e);
109         }
110         setName( group.getName() );
111         setDisplayName( group.getDisplayName() );
112         // setIconBase("org/netbeans/modules/java/j2seproject/ui/resources/packageRoot");
113
}
114
115     public Image JavaDoc getIcon( int type ) {
116         return computeIcon( false, type );
117     }
118         
119     public Image JavaDoc getOpenedIcon( int type ) {
120         return computeIcon( true, type );
121     }
122     
123     public String JavaDoc getDisplayName () {
124         String JavaDoc s = super.getDisplayName ();
125
126         try {
127             s = file.getFileSystem ().getStatus ().annotateName (s, files);
128         } catch (FileStateInvalidException e) {
129             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
130         }
131
132         return s;
133     }
134
135     public String JavaDoc getHtmlDisplayName() {
136          try {
137              FileSystem.Status stat = file.getFileSystem().getStatus();
138              if (stat instanceof FileSystem.HtmlStatus) {
139                  FileSystem.HtmlStatus hstat = (FileSystem.HtmlStatus) stat;
140
141                  String JavaDoc result = hstat.annotateNameHtml (
142                      super.getDisplayName(), files);
143
144                  //Make sure the super string was really modified
145
if (!super.getDisplayName().equals(result)) {
146                      return result;
147                  }
148              }
149          } catch (FileStateInvalidException e) {
150              ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
151          }
152          return super.getHtmlDisplayName();
153     }
154
155     public void run() {
156         if (iconChange) {
157             fireIconChange();
158             fireOpenedIconChange();
159             iconChange = false;
160         }
161         if (nameChange) {
162             fireDisplayNameChange(null, null);
163             nameChange = false;
164         }
165     }
166
167     public void annotationChanged(FileStatusEvent event) {
168         if (task == null) {
169             task = RequestProcessor.getDefault().create(this);
170         }
171
172         if ((iconChange == false && event.isIconChange()) || (nameChange == false && event.isNameChange())) {
173             if (event.hasChanged(file)) {
174                 iconChange |= event.isIconChange();
175                 nameChange |= event.isNameChange();
176             }
177         }
178
179         task.schedule(50); // batch by 50 ms
180
}
181     
182     public Action JavaDoc[] getActions( boolean context ) {
183
184         if ( actions == null ) {
185             actions = new Action JavaDoc[] {
186                 CommonProjectActions.newFileAction(),
187                 null,
188                 SystemAction.get( FileSystemAction.class ),
189                 null,
190                 SystemAction.get( FindAction.class ),
191                 null,
192                 SystemAction.get( PasteAction.class ),
193                 null,
194                 SystemAction.get( ToolsAction.class ),
195             };
196         }
197         return actions;
198     }
199
200     // Show reasonable properties of the DataFolder,
201
//it shows the sorting names as rw property, the name as ro property and the path to root as ro property
202
public PropertySet[] getPropertySets() {
203         PropertySet[] properties = getDataFolderNodeDelegate().getPropertySets();
204         for (int i=0; i< properties.length; i++) {
205             if (Sheet.PROPERTIES.equals(properties[i].getName())) {
206                 //Replace the Sheet.PROPERTIES by the new one
207
//having the ro name property and ro path property
208
properties[i] = Sheet.createPropertiesSet();
209                 ((Sheet.Set) properties[i]).put(new PropertySupport.ReadOnly<String JavaDoc>(DataObject.PROP_NAME, String JavaDoc.class,
210                         NbBundle.getMessage(PackageRootNode.class,"PROP_name"), NbBundle.getMessage(PackageRootNode.class,"HINT_name")) {
211                     @Override JavaDoc
212                     public String JavaDoc getValue() {
213                         return PackageRootNode.this.getDisplayName();
214                     }
215                 });
216                 ((Sheet.Set) properties[i]).put(new PropertySupport.ReadOnly<String JavaDoc>("ROOT_PATH", String JavaDoc.class, //NOI18N
217
NbBundle.getMessage(PackageRootNode.class,"PROP_rootpath"), NbBundle.getMessage(PackageRootNode.class,"HINT_rootpath")) {
218                     @Override JavaDoc
219                     public String JavaDoc getValue() {
220                         return FileUtil.getFileDisplayName(PackageRootNode.this.file);
221                     }
222                 });
223             }
224         }
225         return properties;
226     }
227
228     // XXX Paste types - probably not very nice
229
public void createPasteTypes(Transferable JavaDoc t, List JavaDoc<PasteType> list) {
230         if (t.isDataFlavorSupported(ExTransferable.multiFlavor)) {
231             try {
232                 MultiTransferObject mto = (MultiTransferObject) t.getTransferData(ExTransferable.multiFlavor);
233                 List JavaDoc<PackageViewChildren.PackageNode> l = new ArrayList JavaDoc<PackageViewChildren.PackageNode>();
234                 boolean isPackageFlavor = false;
235                 boolean hasTheSameRoot = false;
236                 int op = -1;
237                 for (int i=0; i < mto.getCount(); i++) {
238                     Transferable JavaDoc pt = mto.getTransferableAt(i);
239                     DataFlavor JavaDoc[] flavors = mto.getTransferDataFlavors(i);
240                     for (int j=0; j< flavors.length; j++) {
241                         if (PackageViewChildren.SUBTYPE.equals(flavors[j].getSubType ()) &&
242                                 PackageViewChildren.PRIMARY_TYPE.equals(flavors[j].getPrimaryType ())) {
243                             if (op == -1) {
244                                 op = Integer.valueOf (flavors[j].getParameter (PackageViewChildren.MASK)).intValue ();
245                             }
246                             PackageViewChildren.PackageNode pkgNode = (PackageViewChildren.PackageNode) pt.getTransferData(flavors[j]);
247                             if ( !((PackageViewChildren)getChildren()).getRoot().equals( pkgNode.getRoot() ) ) {
248                                 l.add(pkgNode);
249                             }
250                             else {
251                                 hasTheSameRoot = true;
252                             }
253                             isPackageFlavor = true;
254                         }
255                     }
256                 }
257                 if (isPackageFlavor && !hasTheSameRoot) {
258                     list.add(new PackageViewChildren.PackagePasteType(this.group.getRootFolder(),
259                             l.toArray(new PackageViewChildren.PackageNode[l.size()]),
260                             op));
261                 }
262                 else if (!isPackageFlavor) {
263                     list.addAll( Arrays.asList( getDataFolderNodeDelegate().getPasteTypes( t ) ) );
264                 }
265             } catch (UnsupportedFlavorException JavaDoc e) {
266                 ErrorManager.getDefault().notify(e);
267             } catch (IOException JavaDoc e) {
268                 ErrorManager.getDefault().notify(e);
269             }
270         }
271         else {
272             DataFlavor JavaDoc[] flavors = t.getTransferDataFlavors();
273             FileObject root = this.group.getRootFolder();
274             boolean isPackageFlavor = false;
275             if (root!= null && root.canWrite()) {
276                 for (DataFlavor JavaDoc flavor : flavors) {
277                     if (PackageViewChildren.SUBTYPE.equals(flavor.getSubType ()) &&
278                             PackageViewChildren.PRIMARY_TYPE.equals(flavor.getPrimaryType ())) {
279                         isPackageFlavor = true;
280                         try {
281                             int op = Integer.parseInt(flavor.getParameter(PackageViewChildren.MASK));
282                             PackageViewChildren.PackageNode pkgNode = (PackageViewChildren.PackageNode) t.getTransferData(flavor);
283                             if ( !((PackageViewChildren)getChildren()).getRoot().equals( pkgNode.getRoot() ) ) {
284                                 list.add(new PackageViewChildren.PackagePasteType (root, new PackageViewChildren.PackageNode[] {pkgNode}, op));
285                             }
286                         } catch (IOException JavaDoc ioe) {
287                             ErrorManager.getDefault().notify(ioe);
288                         }
289                         catch (UnsupportedFlavorException JavaDoc ufe) {
290                             ErrorManager.getDefault().notify(ufe);
291                         }
292                     }
293                 }
294             }
295             if (!isPackageFlavor) {
296                 list.addAll( Arrays.asList( getDataFolderNodeDelegate().getPasteTypes( t ) ) );
297             }
298         }
299     }
300     
301     @Override JavaDoc
302     public PasteType getDropType(Transferable JavaDoc t, int action, int index) {
303         PasteType pasteType = super.getDropType(t, action, index);
304         //The pasteType can be:
305
// 1) PackagePasteType - the t.flavor is package flavor
306
// 2) null or DataPasteType - the t.flavor in not package flavor
307
if (pasteType instanceof PackageViewChildren.PackagePasteType) {
308             ((PackageViewChildren.PackagePasteType)pasteType).setOperation (action);
309         }
310         return pasteType;
311     }
312
313     // Private methods ---------------------------------------------------------
314

315     private Node getDataFolderNodeDelegate() {
316         return getLookup().lookup(DataFolder.class).getNodeDelegate();
317     }
318     
319     private Image JavaDoc computeIcon( boolean opened, int type ) {
320         Image JavaDoc image;
321         Icon JavaDoc icon = group.getIcon( opened );
322         
323         if ( icon == null ) {
324             image = opened ? getDataFolderNodeDelegate().getOpenedIcon( type ) :
325                              getDataFolderNodeDelegate().getIcon( type );
326             image = Utilities.mergeImages( image, PACKAGE_BADGE, 7, 7 );
327         }
328         else {
329             image = Utilities.icon2Image(icon);
330         }
331         
332         return image;
333     }
334     
335     private static Lookup createLookup( SourceGroup group ) {
336         // XXX Remove DataFolder when paste, find and refresh are reimplemented
337
FileObject rootFolder = group.getRootFolder();
338         DataFolder dataFolder = DataFolder.findFolder( rootFolder );
339         return Lookups.fixed(dataFolder, new PathFinder(group));
340     }
341     
342     /** If contained in the lookup can perform the search for a node
343      */

344     public static class PathFinder {
345         
346         private SourceGroup group;
347         
348         public PathFinder( SourceGroup group ) {
349             this.group = group;
350         }
351         
352         public Node findPath( Node root, Object JavaDoc object ) {
353             FileObject fo;
354             if (object instanceof FileObject) {
355                 fo = (FileObject) object;
356             } else if (object instanceof DataObject) {
357                 fo = ((DataObject) object).getPrimaryFile();
358             } else {
359                 return null;
360             }
361             
362             FileObject groupRoot = group.getRootFolder();
363             if ( FileUtil.isParentOf( groupRoot, fo ) /* && group.contains( fo ) */ ) {
364                 // The group contains the object
365

366                 String JavaDoc relPath = FileUtil.getRelativePath( groupRoot, fo.isFolder() ? fo : fo.getParent() );
367
368                 String JavaDoc[] path = new String JavaDoc[] { relPath.replace( '/', '.' ) };
369                 try {
370                     Node packageNode = NodeOp.findPath( root, path );
371                     if (fo.isFolder()) {
372                         return packageNode;
373                     } else {
374                         for (Node child : packageNode.getChildren().getNodes(true)) {
375                            DataObject dobj = child.getLookup().lookup(DataObject.class);
376                            if (dobj != null && dobj.getPrimaryFile().getNameExt().equals(fo.getNameExt())) {
377                                return child;
378                            }
379                         }
380                     }
381                 }
382                 catch ( NodeNotFoundException e ) {
383                     // did not manage to find it after all... why?
384
return null;
385                 }
386             }
387             else if ( groupRoot.equals( fo ) ) {
388                 // First try to find default package
389
try {
390                     return NodeOp.findPath( root, new String JavaDoc[] { "" } ); // NOI18N
391
}
392                 catch ( NodeNotFoundException e ) {
393                     // If it does not exists return this node
394
}
395                 return root;
396             }
397
398             return null;
399         }
400         
401         public String JavaDoc toString() {
402             return "PathFinder[" + group + "]"; // NOI18N
403
}
404                     
405     }
406     
407     /**
408      * Produce a {@link SearchInfo} variant that is always searchable, for speed.
409      * @see "#48685"
410      */

411     static SearchInfo alwaysSearchableSearchInfo(SearchInfo i) {
412         return new AlwaysSearchableSearchInfo(i);
413     }
414     
415     private static final class AlwaysSearchableSearchInfo implements SearchInfo {
416         
417         private final SearchInfo delegate;
418         
419         public AlwaysSearchableSearchInfo(SearchInfo delegate) {
420             this.delegate = delegate;
421         }
422
423         public boolean canSearch() {
424             return true;
425         }
426
427         public Iterator JavaDoc/*<DataObject>*/ objectsToSearch() {
428             return delegate.objectsToSearch();
429         }
430         
431     }
432     
433 }
434
Popular Tags