001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2008 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-2008 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:
042: package org.netbeans.modules.ruby.debugger;
043:
044: import java.awt.EventQueue;
045: import java.io.File;
046: import java.lang.reflect.InvocationTargetException;
047: import java.util.logging.Level;
048: import javax.swing.JEditorPane;
049: import javax.swing.SwingUtilities;
050: import javax.swing.text.Caret;
051: import javax.swing.text.StyledDocument;
052: import org.openide.cookies.EditorCookie;
053: import org.openide.cookies.LineCookie;
054: import org.openide.filesystems.FileObject;
055: import org.openide.filesystems.FileUtil;
056: import org.openide.loaders.DataObject;
057: import org.openide.loaders.DataObjectNotFoundException;
058: import org.openide.nodes.Node;
059: import org.openide.text.Line;
060: import org.openide.text.NbDocument;
061: import org.openide.windows.TopComponent;
062:
063: public final class EditorUtil {
064:
065: private EditorUtil() {
066: }
067:
068: private static DebuggerAnnotation currentLineDA;
069:
070: // public static boolean contains(final Object currentLine, final Line line) {
071: // if (currentLine == null) return false;
072: // final Annotatable[] annotables = (Annotatable[]) currentLine;
073: // for (Annotatable ann : annotables) {
074: // if (ann.equals(line)) {
075: // return true;
076: // }
077: // if (ann instanceof Line.Part && ((Line.Part) ann).getLine().equals(line)) {
078: // return true;
079: // }
080: // }
081: // return false;
082: // }
083:
084: /**
085: * Make line in the editor current - shows the line and colorizes it
086: * appropriately (green-striped by default). Note that editor counts lines
087: * from zero.
088: *
089: * @see unmarkCurrent()
090: */
091: static void markCurrent(final String filePath, final int lineNumber) {
092: markCurrent(getLineAnnotable(filePath, lineNumber));
093: }
094:
095: private static void markCurrent(final Line line) {
096: unmarkCurrent();
097: if (line == null) {
098: return;
099: }
100: currentLineDA = new DebuggerAnnotation(
101: DebuggerAnnotation.CURRENT_LINE_ANNOTATION_TYPE, line);
102: showLine(line, true);
103: }
104:
105: /**
106: * Cancel effect of {@link #markCurrent(String, int)} method. I.e. removes
107: * annotation, usually the green stripe.
108: */
109: static void unmarkCurrent() {
110: if (currentLineDA != null) {
111: currentLineDA.detach();
112: currentLineDA = null;
113: }
114: }
115:
116: public static Line getLineAnnotable(final String filePath,
117: final int lineNumber) {
118: return getLine(filePath, lineNumber);
119: }
120:
121: public static Line getLine(final String filePath,
122: final int lineNumber) {
123: if (filePath == null || lineNumber < 0) {
124: return null;
125: }
126:
127: File file = new File(filePath);
128: FileObject fileObject = FileUtil.toFileObject(FileUtil
129: .normalizeFile(file));
130: if (fileObject == null) {
131: Util.info("Cannot resolve \"" + filePath + '"');
132: return null;
133: }
134:
135: LineCookie lineCookie = getLineCookie(fileObject);
136: assert lineCookie != null;
137: return lineCookie.getLineSet().getCurrent(lineNumber);
138: }
139:
140: public static LineCookie getLineCookie(final FileObject fo) {
141: LineCookie result = null;
142: try {
143: DataObject dataObject = DataObject.find(fo);
144: if (dataObject != null) {
145: result = dataObject.getCookie(LineCookie.class);
146: }
147: } catch (DataObjectNotFoundException e) {
148: Util.LOGGER.log(Level.FINE, "Cannot find DataObject for: "
149: + fo, e.getMessage());
150: }
151: return result;
152: }
153:
154: public static void showLine(final Line lineToShow,
155: final boolean toFront) {
156: if (lineToShow == null) {
157: return;
158: }
159: EventQueue.invokeLater(new Runnable() {
160: public void run() {
161: lineToShow.show(toFront ? Line.SHOW_TOFRONT
162: : Line.SHOW_GOTO);
163: }
164: });
165: }
166:
167: public static void showLine(final Line line) {
168: showLine(line, false);
169: }
170:
171: // <editor-fold defaultstate="collapsed" desc=" Editor boilerplate ">
172: /**
173: * Returns current editor line (the line where the carret currently is).
174: * Might be <code>null</code>. Works only for {@link Util#isRubySource
175: * supported mime-types}. For unsupported ones returns <code>null</code>.
176: */
177: public static Line getCurrentLine() {
178: Node[] nodes = TopComponent.getRegistry().getCurrentNodes();
179: if (nodes == null)
180: return null;
181: if (nodes.length != 1)
182: return null;
183: Node n = nodes[0];
184: FileObject fo = n.getLookup().lookup(FileObject.class);
185: if (fo == null) {
186: DataObject dobj = n.getLookup().lookup(DataObject.class);
187: if (dobj != null) {
188: fo = dobj.getPrimaryFile();
189: }
190: }
191: if (fo == null) {
192: return null;
193: }
194: if (!Util.isRubySource(fo)) {
195: return null;
196: }
197: LineCookie lineCookie = n.getCookie(LineCookie.class);
198: if (lineCookie == null)
199: return null;
200: EditorCookie editorCookie = n.getCookie(EditorCookie.class);
201: if (editorCookie == null)
202: return null;
203: JEditorPane jEditorPane = getEditorPane(editorCookie);
204: if (jEditorPane == null)
205: return null;
206: StyledDocument document = editorCookie.getDocument();
207: if (document == null)
208: return null;
209: Caret caret = jEditorPane.getCaret();
210: if (caret == null)
211: return null;
212: int lineNumber = NbDocument.findLineNumber(document, caret
213: .getDot());
214: try {
215: Line.Set lineSet = lineCookie.getLineSet();
216: assert lineSet != null : lineCookie;
217: return lineSet.getCurrent(lineNumber);
218: } catch (IndexOutOfBoundsException ex) {
219: return null;
220: }
221: }
222:
223: private static JEditorPane getEditorPane_(EditorCookie editorCookie) {
224: JEditorPane[] op = editorCookie.getOpenedPanes();
225: if ((op == null) || (op.length < 1))
226: return null;
227: return op[0];
228: }
229:
230: private static JEditorPane getEditorPane(
231: final EditorCookie editorCookie) {
232: if (SwingUtilities.isEventDispatchThread()) {
233: return getEditorPane_(editorCookie);
234: } else {
235: final JEditorPane[] ce = new JEditorPane[1];
236: try {
237: EventQueue.invokeAndWait(new Runnable() {
238: public void run() {
239: ce[0] = getEditorPane_(editorCookie);
240: }
241: });
242: } catch (InvocationTargetException ex) {
243: Util.severe(ex);
244: } catch (InterruptedException ex) {
245: Util.severe(ex);
246: Thread.currentThread().interrupt();
247: }
248: return ce[0];
249: }
250: }
251: // </editor-fold>
252:
253: }
|