KickJava   Java API By Example, From Geeks To Geeks.

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


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.Component JavaDoc;
23 import java.awt.Image JavaDoc;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.IdentityHashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.SortedSet JavaDoc;
32 import java.util.TreeSet JavaDoc;
33 import javax.swing.ComboBoxModel JavaDoc;
34 import javax.swing.DefaultComboBoxModel JavaDoc;
35 import javax.swing.Icon JavaDoc;
36 import javax.swing.ImageIcon JavaDoc;
37 import javax.swing.JLabel JavaDoc;
38 import javax.swing.JList JavaDoc;
39 import javax.swing.ListCellRenderer JavaDoc;
40 import javax.swing.plaf.UIResource JavaDoc;
41 import org.netbeans.api.progress.ProgressHandle;
42 import org.netbeans.api.progress.ProgressHandleFactory;
43 import org.netbeans.api.project.SourceGroup;
44 import org.netbeans.api.queries.VisibilityQuery;
45 import org.netbeans.modules.java.project.PackageDisplayUtils;
46 import org.netbeans.modules.java.project.JavaProjectSettings;
47 import org.openide.filesystems.FileObject;
48 import org.openide.filesystems.FileUtil;
49 import org.openide.nodes.AbstractNode;
50 import org.openide.nodes.FilterNode;
51 import org.openide.nodes.Node;
52 import org.openide.util.NbBundle;
53 import org.openide.util.WeakListeners;
54
55 /**
56  * Factory for package views.
57  * @see org.netbeans.spi.project.ui.LogicalViewProvider
58  * @author Jesse Glick
59  */

60 public class PackageView {
61         
62     private PackageView() {}
63     
64     /**
65      * Create a node which will contain package-oriented view of a source group.
66      * <p>
67      * The precise structure of this node is <em>not</em> specified by the API
68      * and is subject to arbitrary change (perhaps at user option).
69      * Callers should not make assumptions about the nature of subnodes, the
70      * code or display names of certain nodes, and so on. You may use cookies/lookup
71      * to find if particular subnodes correspond to folders or files.
72      * </p>
73      * @param group a source group which should be represented
74      * @return node which will display packages in given group
75      */

76     public static Node createPackageView( SourceGroup group ) {
77         return new RootNode (group);
78     }
79     
80     /**
81      * Finds the node representing given object, if any.
82      * The current implementation works only for {@link org.openide.filesystems.FileObject}s
83      * and {@link org.openide.loaders.DataObject}s.
84      * @param rootNode a node some descendant of which should contain the object
85      * @param object object to find
86      * @return a node representing the given object, or null if no such node was found
87      */

88     public static Node findPath(Node rootNode, Object JavaDoc object) {
89         
90         PackageRootNode.PathFinder pf = rootNode.getLookup().lookup(PackageRootNode.PathFinder.class);
91         
92         if ( pf != null ) {
93             return pf.findPath( rootNode, object );
94         } else {
95             TreeRootNode.PathFinder pf2 = rootNode.getLookup().lookup(TreeRootNode.PathFinder.class);
96             if (pf2 != null) {
97                 return pf2.findPath(rootNode, object);
98             } else {
99                 return null;
100             }
101         }
102     }
103     
104     /**
105      * Create a list or combo box model suitable for {@link javax.swing.JList} from a source group
106      * showing all Java packages in the source group.
107      * To display it you will also need {@link #listRenderer}.
108      * <p>No particular guarantees are made as to the nature of the model objects themselves,
109      * except that {@link Object#toString} will give the fully-qualified package name
110      * (or <code>""</code> for the default package), regardless of what the renderer
111      * actually displays.</p>
112      * @param group a Java-like source group
113      * @return a model of its packages
114      * @since org.netbeans.modules.java.project/1 1.3
115      */

116     
117     public static ComboBoxModel JavaDoc createListView(SourceGroup group) {
118         SortedSet JavaDoc<PackageItem> data = new TreeSet JavaDoc<PackageItem>();
119         findNonExcludedPackages(null, data, group.getRootFolder(), group, false);
120         return new DefaultComboBoxModel JavaDoc(data.toArray(new PackageItem[data.size()]));
121     }
122     
123     /** Fills given collection with flattened packages under given folder
124      *@param target The collection to be filled
125      *@param fo The folder to be scanned
126      * @param group the group to scan
127      * @param createPackageItems if false the collection will be filled with file objects; if
128      * true PackageItems will be created.
129      * @param showProgress whether to show a progress handle or not
130      */

131     static void findNonExcludedPackages(PackageViewChildren children, Collection JavaDoc<PackageItem> target, FileObject fo, SourceGroup group, boolean showProgress) {
132         if (showProgress) {
133             ProgressHandle progress = ProgressHandleFactory.createHandle(NbBundle.getMessage(PackageView.class, "PackageView.find_packages_progress", FileUtil.getFileDisplayName(fo)));
134             progress.start(1000);
135             findNonExcludedPackages(children, target, fo, group, progress, 0, 1000);
136             progress.finish();
137         } else {
138             findNonExcludedPackages(children, target, fo, group, null, 0, 0);
139         }
140     }
141
142     private static void findNonExcludedPackages(PackageViewChildren children, Collection JavaDoc<PackageItem> target, FileObject fo, SourceGroup group, ProgressHandle progress, int start, int end) {
143         
144         assert fo.isFolder() : "Package view only accepts folders"; // NOI18N
145

146         if (progress != null) {
147             String JavaDoc path = FileUtil.getRelativePath(children.getRoot(), fo);
148             assert path != null : fo + " in " + children.getRoot();
149             progress.progress(path.replace('/', '.'), start);
150         }
151                
152         if ( !VisibilityQuery.getDefault().isVisible( fo ) ) {
153             return; // Don't show hidden packages
154
}
155         
156         boolean hasSubfolders = false;
157         boolean hasFiles = false;
158         List JavaDoc<FileObject> folders = new ArrayList JavaDoc<FileObject>();
159         for (FileObject kid : fo.getChildren()) {
160             // XXX could use PackageDisplayUtils.isSignificant here
161
if (VisibilityQuery.getDefault().isVisible(kid) && group.contains(kid)) {
162                 if (kid.isFolder()) {
163                     folders.add(kid);
164                     hasSubfolders = true;
165                 }
166                 else {
167                     hasFiles = true;
168                 }
169             }
170         }
171         if (hasFiles || !hasSubfolders) {
172             if (target != null) {
173                 target.add( new PackageItem(group, fo, !hasFiles ) );
174             }
175             else {
176                 children.add( fo, !hasFiles );
177             }
178         }
179         if (!folders.isEmpty()) {
180             int diff = (end - start) / folders.size();
181             int c = 0;
182             for (FileObject kid : folders) {
183                 // Do this after adding the parent, so we get a pre-order traversal.
184
// Also see PackageViewChildren.findChild: prefer to get root first.
185
findNonExcludedPackages(children, target, kid, group, progress, start + c * diff, start + (c + 1) * diff);
186                 c++;
187             }
188         }
189     }
190          
191 // public static ComboBoxModel createListView(SourceGroup group) {
192
// DefaultListModel model = new DefaultListModel();
193
// SortedSet/*<PackageItem>*/ items = new TreeSet();
194
// FileObject root = group.getRootFolder();
195
// if (PackageDisplayUtils.isSignificant(root)) {
196
// items.add(new PackageItem(group, root));
197
// }
198
// Enumeration/*<FileObject>*/ files = root.getChildren(true);
199
// while (files.hasMoreElements()) {
200
// FileObject f = (FileObject) files.nextElement();
201
// if (f.isFolder() && PackageDisplayUtils.isSignificant(f)) {
202
// items.add(new PackageItem(group, f));
203
// }
204
// }
205
// return new DefaultComboBoxModel(items.toArray(new PackageItem[items.size()]));
206
// }
207

208     
209     /**
210      * Create a renderer suited to rendering models created using {@link #createListView}.
211      * The exact nature of the display is not specified.
212      * Instances of String can also be rendered.
213      * @return a suitable package renderer
214      * @since org.netbeans.modules.java.project/1 1.3
215      */

216     public static ListCellRenderer JavaDoc listRenderer() {
217         return new PackageListCellRenderer();
218     }
219     
220     /**
221      * FilterNode which listens on the PackageViewSettings and changes the view to
222      * the package view or tree view
223      *
224      */

225     private static final class RootNode extends FilterNode implements PropertyChangeListener JavaDoc {
226         
227         private SourceGroup sourceGroup;
228         
229         private RootNode (SourceGroup group) {
230             super(getOriginalNode(group));
231             this.sourceGroup = group;
232             JavaProjectSettings.addPropertyChangeListener(WeakListeners.propertyChange(this, JavaProjectSettings.class));
233             group.addPropertyChangeListener(WeakListeners.propertyChange(this, group));
234         }
235         
236         public void propertyChange (PropertyChangeEvent JavaDoc event) {
237             String JavaDoc prop = event.getPropertyName();
238             if (JavaProjectSettings.PROP_PACKAGE_VIEW_TYPE.equals(prop) || SourceGroup.PROP_CONTAINERSHIP.equals(prop)) {
239                 changeOriginal(getOriginalNode(sourceGroup), true);
240             }
241         }
242         
243         private static Node getOriginalNode(SourceGroup group) {
244             FileObject root = group.getRootFolder();
245             //Guard condition, if the project is (closed) and deleted but not yet gced
246
// and the view is switched, the source group is not valid.
247
if ( root == null || !root.isValid()) {
248                 return new AbstractNode (Children.LEAF);
249             }
250             switch (JavaProjectSettings.getPackageViewType()) {
251                 case JavaProjectSettings.TYPE_PACKAGE_VIEW:
252                     return new PackageRootNode(group);
253                 case JavaProjectSettings.TYPE_TREE:
254                     return new TreeRootNode(group);
255                 default:
256                     assert false : "Unknown PackageView Type"; //NOI18N
257
return new PackageRootNode(group);
258             }
259         }
260     }
261     
262     /**
263      * Model item representing one package.
264      */

265     static final class PackageItem implements Comparable JavaDoc<PackageItem> {
266         
267         private static Map JavaDoc<Image JavaDoc,Icon JavaDoc> image2icon = new IdentityHashMap JavaDoc<Image JavaDoc,Icon JavaDoc>();
268         
269         private final boolean empty;
270         private final FileObject pkg;
271         private final String JavaDoc pkgname;
272         private Icon JavaDoc icon;
273         
274         public PackageItem(SourceGroup group, FileObject pkg, boolean empty) {
275             this.pkg = pkg;
276             this.empty = empty;
277             String JavaDoc path = FileUtil.getRelativePath(group.getRootFolder(), pkg);
278             assert path != null : "No " + pkg + " in " + group;
279             pkgname = path.replace('/', '.');
280         }
281         
282         public String JavaDoc toString() {
283             return pkgname;
284         }
285         
286         public String JavaDoc getLabel() {
287             return PackageDisplayUtils.getDisplayLabel(pkgname);
288         }
289         
290         public Icon JavaDoc getIcon() {
291             if ( icon == null ) {
292                 Image JavaDoc image = PackageDisplayUtils.getIcon(pkg, pkgname, empty);
293                 icon = image2icon.get(image);
294                 if ( icon == null ) {
295                     icon = new ImageIcon JavaDoc( image );
296                     image2icon.put( image, icon );
297                 }
298             }
299             return icon;
300         }
301
302         public int compareTo(PackageItem p) {
303             return pkgname.compareTo(p.pkgname);
304         }
305         
306     }
307     
308     /**
309      * The renderer which just displays {@link PackageItem#getLabel} and {@link PackageItem#getIcon}.
310      */

311     private static final class PackageListCellRenderer extends JLabel JavaDoc implements ListCellRenderer JavaDoc, UIResource JavaDoc {
312         
313         public PackageListCellRenderer() {
314             setOpaque(true);
315         }
316
317         public Component JavaDoc getListCellRendererComponent(JList JavaDoc list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus) {
318             // #93658: GTK needs name to render cell renderer "natively"
319
setName("ComboBox.listRenderer"); // NOI18N
320

321             if (value instanceof PackageItem) {
322                 PackageItem pkgitem = (PackageItem) value;
323                 setText(pkgitem.getLabel());
324                 setIcon(pkgitem.getIcon());
325             } else {
326                 // #49954: render a specially inserted package somehow.
327
String JavaDoc pkgitem = (String JavaDoc) value;
328                 setText(pkgitem);
329                 setIcon(null);
330             }
331             
332             if ( isSelected ) {
333                 setBackground(list.getSelectionBackground());
334                 setForeground(list.getSelectionForeground());
335             }
336             else {
337                 setBackground(list.getBackground());
338                 setForeground(list.getForeground());
339             }
340             
341             return this;
342         }
343         
344         // #93658: GTK needs name to render cell renderer "natively"
345
public String JavaDoc getName() {
346             String JavaDoc name = super.getName();
347             return name == null ? "ComboBox.renderer" : name; // NOI18N
348
}
349     
350     }
351     
352     
353 }
354
Popular Tags