001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.modules.profiler.utils;
042:
043: import org.netbeans.api.project.Project;
044: import org.netbeans.api.project.ProjectUtils;
045: import org.netbeans.api.project.Sources;
046: import org.netbeans.api.project.ui.OpenProjects;
047: import org.netbeans.spi.project.ui.LogicalViewProvider;
048: import org.openide.ErrorManager;
049: import org.openide.nodes.AbstractNode;
050: import org.openide.nodes.Children;
051: import org.openide.nodes.Node;
052: import org.openide.util.NbBundle;
053: import org.openide.util.RequestProcessor;
054: import java.lang.ref.WeakReference;
055: import java.text.Collator;
056: import java.util.*;
057: import javax.swing.*;
058: import javax.swing.event.ChangeEvent;
059: import javax.swing.event.ChangeListener;
060:
061: /**
062: * Root node for list of open projects
063: *
064: * @author Tomas Hurka
065: * @author Petr Hrebejk
066: */
067: public final class ProjectsRootNode extends AbstractNode {
068: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
069:
070: private static final class Handle implements Node.Handle {
071: //~ Static fields/initializers -------------------------------------------------------------------------------------------
072:
073: private static final long serialVersionUID = 78374332058L;
074:
075: //~ Constructors ---------------------------------------------------------------------------------------------------------
076:
077: public Handle() {
078: }
079:
080: //~ Methods --------------------------------------------------------------------------------------------------------------
081:
082: public Node getNode() {
083: return new ProjectsRootNode();
084: }
085: }
086:
087: private static final class ProjectChildren extends Children.Keys
088: implements ChangeListener {
089: //~ Inner Classes --------------------------------------------------------------------------------------------------------
090:
091: public static final class ProjectByDisplayNameComparator
092: implements Comparator {
093: //~ Static fields/initializers ---------------------------------------------------------------------------------------
094:
095: private static final Comparator COLLATOR = Collator
096: .getInstance();
097:
098: //~ Methods ----------------------------------------------------------------------------------------------------------
099:
100: public final int compare(final Object o1, final Object o2) {
101: if (!(o1 instanceof Project)) {
102: return 1;
103: }
104:
105: if (!(o2 instanceof Project)) {
106: return -1;
107: }
108:
109: final Project p1 = (Project) o1;
110: final Project p2 = (Project) o2;
111:
112: return COLLATOR.compare(ProjectUtils.getInformation(p1)
113: .getDisplayName(), ProjectUtils.getInformation(
114: p2).getDisplayName());
115: }
116: }
117:
118: //~ Static fields/initializers -------------------------------------------------------------------------------------------
119:
120: public static final Comparator PROJECT_BY_DISPLAYNAME = new ProjectByDisplayNameComparator();
121:
122: //~ Instance fields ------------------------------------------------------------------------------------------------------
123:
124: private final java.util.Map /*<Sources,Reference<Project>>*/sources2projects = new WeakHashMap();
125:
126: //~ Constructors ---------------------------------------------------------------------------------------------------------
127:
128: public ProjectChildren() {
129: }
130:
131: //~ Methods --------------------------------------------------------------------------------------------------------------
132:
133: // Own methods ---------------------------------------------------------
134: public Collection getKeys() {
135: final List projects = Arrays.asList(OpenProjects
136: .getDefault().getOpenProjects());
137: Collections.sort(projects, PROJECT_BY_DISPLAYNAME);
138:
139: return projects;
140: }
141:
142: // Children.Keys impl --------------------------------------------------
143: public void addNotify() {
144: setKeys(getKeys());
145: }
146:
147: public void removeNotify() {
148: for (Iterator it = sources2projects.keySet().iterator(); it
149: .hasNext();) {
150: final Sources sources = (Sources) it.next();
151: sources.removeChangeListener(this );
152: }
153:
154: sources2projects.clear();
155: setKeys(Collections.EMPTY_LIST);
156: }
157:
158: // Change listener impl ------------------------------------------------
159: public void stateChanged(final ChangeEvent e) {
160: final WeakReference projectRef = (WeakReference) sources2projects
161: .get(e.getSource());
162:
163: if (projectRef == null) {
164: return;
165: }
166:
167: final Project project = (Project) projectRef.get();
168:
169: if (project == null) {
170: return;
171: }
172:
173: // Fix for 50259, callers sometimes hold locks
174: rp.post(new Runnable() {
175: public void run() {
176: refreshKey(project);
177: }
178: });
179: }
180:
181: protected Node[] createNodes(final Object key) {
182: final Project project = (Project) key;
183: final LogicalViewProvider lvp = (LogicalViewProvider) project
184: .getLookup().lookup(LogicalViewProvider.class);
185:
186: Node[] nodes;
187:
188: if (lvp == null) {
189: ErrorManager
190: .getDefault()
191: .log(
192: ErrorManager.WARNING,
193: "Warning - project "
194: + ProjectUtils.getInformation(
195: project).getName()
196: + " failed to supply LogicalViewProvider in it's lookup"); // NOI18N
197:
198: final Sources sources = ProjectUtils
199: .getSources(project);
200: sources.removeChangeListener(this );
201: sources.addChangeListener(this );
202: nodes = new Node[] { Node.EMPTY };
203: } else {
204: nodes = new Node[] { lvp.createLogicalView() };
205:
206: if (nodes[0].getLookup().lookup(Project.class) != project) {
207: // Various actions, badging, etc. are not going to work.
208: ErrorManager
209: .getDefault()
210: .log(
211: ErrorManager.WARNING,
212: "Warning - project "
213: + ProjectUtils
214: .getInformation(
215: project)
216: .getName()
217: + " failed to supply itself in the lookup of the root node of its own logical view"); // NOI18N
218: }
219: }
220:
221: return nodes;
222: }
223: }
224:
225: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
226:
227: // -----
228: // I18N String constants
229: private static final String OPEN_PROJECTS_NODE_NAME = NbBundle
230: .getMessage(ProjectsRootNode.class,
231: "ProjectsRootNode_OpenProjectsNodeName"); // NOI18N
232: private static final String ICON_BASE = "org/netbeans/modules/profiler/utils/projectsRootNode.gif"; //NOI18N
233: private static final Action[] NO_ACTIONS = new Action[0];
234: private static Action[] ACTIONS;
235: private static final RequestProcessor rp = new RequestProcessor();
236:
237: //~ Instance fields ----------------------------------------------------------------------------------------------------------
238:
239: private final Node.Handle handle;
240:
241: //~ Constructors -------------------------------------------------------------------------------------------------------------
242:
243: public ProjectsRootNode() {
244: super (new ProjectChildren());
245: setIconBaseWithExtension(ICON_BASE);
246: handle = new Handle();
247: }
248:
249: //~ Methods ------------------------------------------------------------------------------------------------------------------
250:
251: public Action[] getActions(final boolean context) {
252: if (context) {
253: return NO_ACTIONS;
254: } else {
255: if (ACTIONS == null) {
256: ACTIONS = new Action[0]; // no action sprovided
257: }
258:
259: return ACTIONS;
260: }
261: }
262:
263: public String getDisplayName() {
264: return OPEN_PROJECTS_NODE_NAME;
265: }
266:
267: public Node.Handle getHandle() {
268: return handle;
269: }
270:
271: public String getName() {
272: return ("OpenProjects"); // NOI18N
273: }
274:
275: public boolean canRename() {
276: return false;
277: }
278:
279: /**
280: * Finds node for given object in the view
281: *
282: * @return the node or null if the node was not found
283: */
284: Node findNode(final Object target) {
285: final ProjectChildren ch = (ProjectChildren) getChildren();
286:
287: final Node[] nodes = ch.getNodes(true);
288:
289: for (int i = 0; i < nodes.length; i++) {
290: final Project p = (Project) nodes[i].getLookup().lookup(
291: Project.class);
292:
293: if (p == null) {
294: continue;
295: }
296:
297: final LogicalViewProvider lvp = (LogicalViewProvider) p
298: .getLookup().lookup(LogicalViewProvider.class);
299:
300: if (lvp != null) {
301: final Node selectedNode = lvp
302: .findPath(nodes[i], target);
303:
304: if (selectedNode != null) {
305: return selectedNode;
306: }
307: }
308: }
309:
310: return null;
311: }
312: }
|