2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.bluej;
44
import java.awt.Image;
45
import java.util.ArrayList;
46
import java.util.Arrays;
47
import java.util.Collection;
48
import java.util.Enumeration;
49
import java.util.List;
50
import javax.swing.event.ChangeEvent;
51
import javax.swing.event.ChangeListener;
52
import org.netbeans.api.java.source.ClasspathInfo;
53
import org.netbeans.api.java.source.SourceUtils;
54
import org.netbeans.api.project.FileOwnerQuery;
55
import org.netbeans.api.project.Project;
56
import org.netbeans.api.project.Sources;
57
import org.netbeans.api.queries.FileBuiltQuery;
58
import org.netbeans.bluej.nodes.BluejLogicalViewRootNode;
59
import org.netbeans.spi.java.project.support.ui.PackageView;
60
import org.netbeans.spi.project.ui.LogicalViewProvider;
61
import org.openide.filesystems.FileAttributeEvent;
62
import org.openide.filesystems.FileChangeListener;
63
import org.openide.filesystems.FileEvent;
64
import org.openide.filesystems.FileObject;
65
import org.openide.filesystems.FileRenameEvent;
66
import org.openide.filesystems.FileUtil;
67
import org.openide.loaders.DataFolder;
68
import org.openide.loaders.DataObject;
69
import org.openide.nodes.Children;
70
import org.openide.nodes.FilterNode;
71
import org.openide.nodes.Node;
72
import org.openide.util.Lookup;
73
import org.openide.util.RequestProcessor;
74
import org.openide.util.Utilities;
75
import org.openide.util.lookup.Lookups;
78
* Support for creating logical views.
79
* @author Milos Kleint
81
public class BluejLogicalViewProvider implements LogicalViewProvider, org.netbeans.bluej.api.BluejLogicalViewProvider {
83
// private static final RequestProcessor BROKEN_LINKS_RP = new RequestProcessor("BluejPhysicalViewProvider.BROKEN_LINKS_RP"); // NOI18N
85
private final BluejProject project;
86
private List changeListeners;
89
// private static final Object KEY_SERVICE_REFS = "serviceRefs"; // NOI18N
91
public BluejLogicalViewProvider(BluejProject project) {
92
this.project = project;
93
assert project != null;
96
public Node createLogicalView() {
97
return new BluejLogicalViewRootNode(createLookup(project));
100
public Node findPath(Node root, Object target) {
101
Project project = (Project) root.getLookup().lookup(Project.class);
102
if (project == null) {
106
if (target instanceof FileObject) {
107
FileObject fo = (FileObject) target;
108
Project owner = FileOwnerQuery.getOwner(fo);
109
if (!project.equals(owner)) {
110
return null; // Don't waste time if project does not own the fo
113
Node[] nodes = root.getChildren().getNodes(true);
114
for (int i = 0; i < nodes.length; i++) {
115
Node result = PackageView.findPath(nodes[i], target);
116
if (result != null) {
127
public synchronized void addChangeListener(ChangeListener l) {
128
if (this.changeListeners == null) {
129
this.changeListeners = new ArrayList();
131
this.changeListeners.add(l);
134
public synchronized void removeChangeListener(ChangeListener l) {
135
if (this.changeListeners == null) {
138
this.changeListeners.remove(l);
142
* Used by J2SEProjectCustomizer to mark the project as broken when it warns user
143
* about project's broken references and advices him to use BrokenLinksAction to correct it.
146
public void testBroken() {
147
ChangeListener[] _listeners;
148
synchronized (this) {
149
if (this.changeListeners == null) {
152
_listeners = (ChangeListener[]) this.changeListeners.toArray(
153
new ChangeListener[this.changeListeners.size()]);
155
ChangeEvent event = new ChangeEvent(this);
156
for (int i=0; i < _listeners.length; i++) {
157
_listeners[i].stateChanged(event);
161
private static Lookup createLookup( Project project ) {
162
DataFolder rootFolder = DataFolder.findFolder(project.getProjectDirectory());
163
// XXX Remove root folder after FindAction rewrite
164
return Lookups.fixed(new Object[] {project, rootFolder});
167
public Node getBigIconRootNode() {
168
return new BigIconFilterNode(createLogicalView());
171
private static class BigIconFilterNode extends FilterNode {
172
private String iconPath = null;
173
private FileBuiltQuery.Status status = null;
174
private boolean attached = false;
176
BigIconFilterNode(Node original) {
177
this(original, new BigIconFilterChilden(original));
180
BigIconFilterNode(Node original, org.openide.nodes.Children children) {
181
super(original, children);
182
DataObject dobj = (DataObject)original.getLookup().lookup(DataObject.class);
184
if ("java".equalsIgnoreCase(dobj.getPrimaryFile().getExt())) { //NOI18N
185
String name = dobj.getPrimaryFile().getName();
186
if (name.endsWith("Test")) {
187
name = name.substring(0, name.length() - "Test".length()); //NOI18N
188
//#77306 - remove the icon padding..
189
// if (dobj.getPrimaryFile().getParent().getFileObject(name, "java") != null) { //NOI18N
190
// iconPath = "org/netbeans/bluej/resources/bluej-testclass.png"; //NOI18N
193
iconPath = "org/netbeans/bluej/resources/bluej-testclass-unattached.png"; //NOI18N
196
iconPath = "org/netbeans/bluej/resources/bluej-class.png"; //NOI18N
198
status = FileBuiltQuery.getStatus(dobj.getPrimaryFile());
200
if ("readme.txt".equalsIgnoreCase(dobj.getPrimaryFile().getNameExt())) { //NOI18N
201
iconPath = "org/netbeans/bluej/resources/readme.png"; //NOI18N
207
public Image getIcon(int type) {
209
if (iconPath != null) {
210
retValue = Utilities.loadImage(iconPath);
211
if (status != null && !status.isBuilt()) {
212
retValue = Utilities.mergeImages(retValue, Utilities.loadImage("org/netbeans/bluej/resources/compiled.png"), //NOI18N
213
attached ? 8 : 3, attached ? 11 : 13);
216
retValue = Utilities.mergeImages(retValue, Utilities.loadImage("org/netbeans/bluej/resources/executable-badge.gif"), //NOI18N
217
attached ? 44 : 41, attached ? 5 : 7);
220
retValue = super.getIcon(type);
222
// if (type == BeanInfo.ICON_COLOR_32x32 && retValue.getHeight(null) == 16) {
223
// System.out.println("scaling");
224
retValue = retValue.getScaledInstance(-1, 32, Image.SCALE_DEFAULT);
229
private boolean hasMain() {
230
DataObject dobj = (DataObject)getLookup().lookup(DataObject.class);
232
FileObject fo = dobj.getPrimaryFile();
236
Project prj = FileOwnerQuery.getOwner(fo);
237
String path = FileUtil.getRelativePath(prj.getProjectDirectory(), fo);
238
path = path.replace('/', '.').replace('\\', '.');
239
path = path.substring(0, path.length() - (fo.getExt().length() + 1));
240
return SourceUtils.isMainClass(path, ClasspathInfo.create(fo));
248
private static class BigIconFilterChilden extends FilterNode.Children {
250
private RootFileOobjectListener listener = null;
251
BigIconFilterChilden(Node orig) {
253
DataObject dobj = (DataObject)orig.getLookup().lookup(DataObject.class);
255
Project prj = FileOwnerQuery.getOwner(dobj.getPrimaryFile());
257
rootDir = prj.getProjectDirectory();
262
protected Node[] createNodes(Node object) {
263
Node orig = (Node)object;
264
DataObject dobj = (DataObject)orig.getLookup().lookup(DataObject.class);
266
// this has to be copied from the logicalviewrootnode, because
267
// we need to construct the children from the root package directly from DataObjects..
269
FileObject fo = dobj.getPrimaryFile();
270
if ("bluej.pkg".equals(fo.getNameExt()) || //NOI18N
271
"build.xml".equals(fo.getNameExt()) || //NOI18N
272
"bluej.pkh".equals(fo.getNameExt()) || //NOI18N
273
("+libs".equals(fo.getName()) && fo.isFolder()) || //NOI18N
274
".DS_Store".equals(fo.getNameExt()) || //NOI18N
275
"ctxt".equals(fo.getExt()) || //NOI18N
276
"class".equals(fo.getExt()) || //NOI18N
277
(fo.isFolder() && fo.getFileObject("bluej.pkg") == null)) { //NOI18N
280
if (rootDir != null && rootDir.equals(fo)) {
281
if (listener == null) {
283
listener = new RootFileOobjectListener(this, orig, fo);
284
fo.addFileChangeListener(listener);
286
Enumeration en = ((DataFolder)dobj).children();
287
Collection col = new ArrayList();
288
while (en.hasMoreElements()) {
289
DataObject d2 = (DataObject)en.nextElement();
290
if (d2.getPrimaryFile().isData()) {
291
col.addAll(Arrays.asList(createNodes(d2.getNodeDelegate().cloneNode())));
294
return (Node[])col.toArray(new Node[col.size()]);
296
return new Node[] {new BigIconFilterNode(orig, fo.isData() ? Children.LEAF : new BigIconFilterChilden(orig))};
301
public void doRefresh(Node original) {
302
refreshKey(original);
305
private static class RootFileOobjectListener implements FileChangeListener {
307
private BigIconFilterChilden children;
311
private FileObject fileObject;
313
RootFileOobjectListener(BigIconFilterChilden childs, Node nd, FileObject fo) {
319
public void fileAttributeChanged(FileAttributeEvent fileAttributeEvent) {
321
public void fileChanged(FileEvent fileEvent) {
322
//#75991 not posting it results in ugly assertions/exceptions from mdr.
323
RequestProcessor.getDefault().post(new Runnable() {
325
children.doRefresh(node);
329
public void fileDataCreated(FileEvent fileEvent) {
330
children.doRefresh(node);
332
public void fileDeleted(FileEvent fileEvent) {
333
children.doRefresh(node);
335
public void fileFolderCreated(FileEvent fileEvent) {
336
children.doRefresh(node);
338
public void fileRenamed(FileRenameEvent fileRenameEvent) {
339
children.doRefresh(node);
b'\\ No newline at end of file'