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: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.napi.gsfret.source;
042:
043: import java.io.IOException;
044: import java.util.Collection;
045: import javax.swing.Icon;
046: import javax.swing.SwingUtilities;
047: import javax.swing.text.StyledDocument;
048: import org.netbeans.modules.gsf.api.DeclarationFinder.DeclarationLocation;
049: import org.netbeans.modules.gsf.api.OffsetRange;
050: import org.netbeans.modules.gsf.api.Parser;
051: import org.netbeans.modules.gsf.api.ParserResult;
052: import org.netbeans.modules.gsf.api.CancellableTask;
053: import org.netbeans.modules.gsf.api.ElementHandle;
054: import org.netbeans.modules.gsf.api.ElementKind;
055: import org.netbeans.modules.gsf.api.Modifier;
056: import org.netbeans.editor.BaseDocument;
057: import org.netbeans.modules.gsf.Language;
058: import org.netbeans.modules.gsf.LanguageRegistry;
059: import org.netbeans.modules.gsfret.navigation.Icons;
060: import org.openide.ErrorManager;
061: import org.openide.cookies.EditorCookie;
062: import org.openide.cookies.LineCookie;
063: import org.openide.cookies.OpenCookie;
064: import org.openide.filesystems.FileObject;
065: import org.openide.loaders.DataObject;
066: import org.openide.loaders.DataObjectNotFoundException;
067: import org.openide.text.Line;
068: import org.openide.text.NbDocument;
069: import org.openide.util.Exceptions;
070:
071: /**
072: * This file is originally from Retouche, the Java Support
073: * infrastructure in NetBeans. I have modified the file as little
074: * as possible to make merging Retouche fixes back as simple as
075: * possible.
076: *
077: * This class contains various methods bound to visualization of Java model
078: * elements. It was formerly included under SourceUtils
079: *
080: * XXX - needs cleanup
081: *
082: * @author Jan Lahoda
083: * @author Tor Norbye
084: */
085: public final class UiUtils {
086: private UiUtils() {
087: }
088:
089: public static BaseDocument getDocument(FileObject fileObject,
090: boolean openIfNecessary) {
091: try {
092: DataObject dobj = DataObject.find(fileObject);
093:
094: EditorCookie ec = dobj.getCookie(EditorCookie.class);
095: if (ec != null) {
096: return (BaseDocument) (openIfNecessary ? ec
097: .openDocument() : ec.getDocument());
098: }
099: } catch (DataObjectNotFoundException ex) {
100: Exceptions.printStackTrace(ex);
101: } catch (IOException ex) {
102: Exceptions.printStackTrace(ex);
103: }
104:
105: return null;
106: }
107:
108: /** Gets correct icon for given ElementKind.
109: *@param modifiers Can be null for empty modifiers collection
110: */
111: public static Icon getElementIcon(ElementKind elementKind,
112: Collection<Modifier> modifiers) {
113: return Icons.getElementIcon(elementKind, modifiers);
114: }
115:
116: /**
117: * Opens given {@link ComObject}.
118: *
119: * @param cpInfo fileobject whose {@link ClasspathInfo} will be used
120: * @param el declaration to open
121: * @return true if and only if the declaration was correctly opened,
122: * false otherwise
123: */
124: public static boolean open(Source js, final ElementHandle handle) {
125: DeclarationLocation location = getOpenInfo(js, handle);
126:
127: if (location != DeclarationLocation.NONE) {
128: return doOpen(location.getFileObject(), location
129: .getOffset());
130: }
131:
132: return false;
133: }
134:
135: private static DeclarationLocation getOpenInfo(final Source js,
136: final ElementHandle handle) {
137: assert js != null;
138: assert handle != null; // Only one should be set
139:
140: try {
141: FileObject fo = js.getFileObjects().iterator().next();
142: return getElementLocation(fo, handle);
143: } catch (IOException e) {
144: ErrorManager.getDefault().notify(e);
145:
146: return DeclarationLocation.NONE;
147: }
148: }
149:
150: public static boolean open(final FileObject fo, final int offset) {
151: if (!SwingUtilities.isEventDispatchThread()) {
152: SwingUtilities.invokeLater(new Runnable() {
153: public void run() {
154: doOpen(fo, offset);
155: }
156: });
157: return true; // not exactly accurate, but....
158: }
159:
160: return doOpen(fo, offset);
161: }
162:
163: // Private methods ---------------------------------------------------------
164: private static boolean doOpen(FileObject fo, int offset) {
165: try {
166: DataObject od = DataObject.find(fo);
167: EditorCookie ec = od.getCookie(EditorCookie.class);
168: LineCookie lc = od.getCookie(LineCookie.class);
169:
170: if ((ec != null) && (lc != null) && (offset != -1)) {
171: StyledDocument doc = ec.openDocument();
172:
173: if (doc != null) {
174: int line = NbDocument.findLineNumber(doc, offset);
175: int lineOffset = NbDocument.findLineOffset(doc,
176: line);
177: int column = offset - lineOffset;
178:
179: if (line != -1) {
180: Line l = lc.getLineSet().getCurrent(line);
181:
182: if (l != null) {
183: l.show(Line.SHOW_GOTO, column);
184:
185: return true;
186: }
187: }
188: }
189: }
190:
191: OpenCookie oc = od.getCookie(OpenCookie.class);
192:
193: if (oc != null) {
194: oc.open();
195:
196: return true;
197: }
198: } catch (IOException e) {
199: ErrorManager.getDefault().notify(
200: ErrorManager.INFORMATIONAL, e);
201: }
202:
203: return false;
204: }
205:
206: private static DeclarationLocation getElementLocation(
207: final FileObject fo, final ElementHandle handle)
208: throws IOException {
209: assert handle != null;
210: final DeclarationLocation[] result = new DeclarationLocation[] { DeclarationLocation.NONE };
211:
212: Source js = Source.forFileObject(fo);
213: js.runUserActionTask(
214: new CancellableTask<CompilationController>() {
215: public void cancel() {
216: }
217:
218: public void run(CompilationController info) {
219: try {
220: info.toPhase(Phase.RESOLVED);
221: } catch (IOException ioe) {
222: ErrorManager.getDefault().notify(ioe);
223: }
224:
225: FileObject fileObject = info.getFileObject();
226: if (handle != null) {
227: fileObject = handle.getFileObject();
228: }
229: if (fileObject == null) {
230: fileObject = fo;
231: }
232:
233: if (fileObject == info.getFileObject()) {
234: Language language = LanguageRegistry
235: .getInstance()
236: .getLanguageByMimeType(
237: handle.getMimeType());
238: Parser parser = language.getParser();
239: //ParserResult pr = handle.getResult();
240: //ElementHandle file = pr.getRoot();
241: //if (file != null) {
242: try {
243: OffsetRange range = parser
244: .getPositionManager()
245: .getOffsetRange(info, handle);
246:
247: if (range != OffsetRange.NONE) {
248: result[0] = new DeclarationLocation(
249: fileObject, range
250: .getStart());
251: }
252: } catch (IllegalArgumentException iae) {
253: result[0] = new DeclarationLocation(
254: fileObject, 0);
255: }
256: //}
257: } else {
258: // The element is not in the parse tree for this parse job; it is
259: // probably something like an indexed element
260: result[0] = new DeclarationLocation(
261: fileObject, -1);
262: }
263: }
264: }, true);
265:
266: return result[0];
267: }
268: }
|