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-2007 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.cnd.highlight.semantic;
043:
044: import java.awt.Color;
045: import java.lang.ref.WeakReference;
046: import java.util.Collection;
047: import java.util.Collections;
048: import javax.swing.event.DocumentEvent;
049: import javax.swing.event.DocumentListener;
050: import javax.swing.text.AttributeSet;
051: import javax.swing.text.Document;
052: import org.netbeans.api.editor.settings.FontColorSettings;
053: import org.netbeans.modules.cnd.api.model.CsmFile;
054: import org.netbeans.modules.cnd.model.tasks.CaretAwareCsmFileTaskFactory;
055: import org.netbeans.modules.cnd.api.model.xref.CsmReference;
056: import org.netbeans.modules.cnd.api.model.xref.CsmReferenceKind;
057: import org.netbeans.modules.cnd.api.model.xref.CsmReferenceRepository;
058: import org.netbeans.modules.cnd.api.model.xref.CsmReferenceResolver;
059: import org.netbeans.modules.cnd.highlight.semantic.options.SemanticHighlightingOptions;
060: import org.netbeans.modules.cnd.modelutil.CsmUtilities;
061: import org.netbeans.modules.editor.NbEditorUtilities;
062: import org.netbeans.modules.editor.errorstripe.privatespi.Mark;
063: import org.netbeans.spi.editor.highlighting.support.OffsetsBag;
064: import org.openide.filesystems.FileObject;
065: import org.openide.loaders.DataObject;
066: import org.openide.util.NbBundle;
067:
068: /**
069: *
070: * @author Sergey Grinev
071: */
072: public class MarkOccurrencesHighlighter extends HighlighterBase {
073:
074: private static AttributeSet defaultColors;
075: private final static String COLORS = "cc-highlighting-mark-occurences"; // NOI18N
076: private WeakReference<CsmFile> weakFile;
077:
078: public static OffsetsBag getHighlightsBag(Document doc) {
079: if (doc == null) {
080: return null;
081: }
082:
083: OffsetsBag bag = (OffsetsBag) doc
084: .getProperty(MarkOccurrencesHighlighter.class);
085:
086: if (bag == null) {
087: doc.putProperty(MarkOccurrencesHighlighter.class,
088: bag = new OffsetsBag(doc, false));
089:
090: final OffsetsBag bagFin = bag;
091: DocumentListener l = new DocumentListener() {
092: public void insertUpdate(DocumentEvent e) {
093: bagFin.removeHighlights(e.getOffset(), e
094: .getOffset(), false);
095: }
096:
097: public void removeUpdate(DocumentEvent e) {
098: bagFin.removeHighlights(e.getOffset(), e
099: .getOffset(), false);
100: }
101:
102: public void changedUpdate(DocumentEvent e) {
103: }
104: };
105:
106: doc.addDocumentListener(l);
107: }
108:
109: return bag;
110: }
111:
112: private CsmFile getCsmFile() {
113: if (weakFile == null || weakFile.get() == null) {
114: if (getDocument() == null) {
115: return null;
116: }
117: DataObject dobj = NbEditorUtilities
118: .getDataObject(getDocument());
119: CsmFile file = CsmUtilities.getCsmFile(dobj, false);
120: if (file != null) {
121: weakFile = new WeakReference<CsmFile>(file);
122: } else {
123: return null;
124: }
125: }
126: return weakFile.get();
127: }
128:
129: private void clean() {
130: Document doc = getDocument();
131: if (doc != null) {
132: getHighlightsBag(doc).clear();
133: OccurrencesMarkProvider.get(doc).setOccurrences(
134: Collections.<Mark> emptySet());
135: }
136: }
137:
138: public MarkOccurrencesHighlighter(Document doc) {
139: super (doc);
140: }
141:
142: public static final Color ES_COLOR = new Color(175, 172, 102);
143:
144: private boolean valid = true;
145:
146: // PhaseRunner
147: public void run(Phase phase) {
148: if (!SemanticHighlightingOptions.getEnableMarkOccurences()) {
149: clean();
150: valid = false;
151: return;
152: }
153:
154: if (phase == Phase.PARSED || phase == Phase.INIT /*&& getCsmFile().isParsed()*/) {
155: Collection<CsmReference> out = getOccurences();
156: if (out == null) {
157: if (SemanticHighlightingOptions.getKeepMarks()) {
158: return;
159: }
160: out = Collections.<CsmReference> emptyList();
161: }
162: clean();
163: Document doc = getDocument();
164: OffsetsBag obag = new OffsetsBag(doc);
165:
166: obag.clear();
167: for (CsmReference csmReference : out) {
168: obag.addHighlight(csmReference.getStartOffset(),
169: csmReference.getEndOffset(), defaultColors);
170: }
171: getHighlightsBag(doc).setHighlights(obag);
172: OccurrencesMarkProvider.get(doc).setOccurrences(
173: OccurrencesMarkProvider.createMarks(doc, out,
174: ES_COLOR, NbBundle.getMessage(
175: MarkOccurrencesHighlighter.class,
176: "LBL_ES_TOOLTIP")));
177: } else if (phase == Phase.CLEANUP) {
178: clean();
179: }
180: }
181:
182: public boolean isValid() {
183: return valid;
184: }
185:
186: private Collection<CsmReference> getOccurences() {
187: Collection<CsmReference> out = null;
188: CsmFile file = getCsmFile();
189: if (file != null && file.isParsed() && getDocument() != null) {
190: FileObject fo = CsmUtilities.getFileObject(file);
191: assert fo != null;
192: out = getOccurences(file, CaretAwareCsmFileTaskFactory
193: .getLastPosition(fo));
194: // CsmReference ref = CsmReferenceResolver.getDefault().findReference(file, CaretAwareCsmFileTaskFactory.getLastPosition(fo));
195: // if (ref!=null && ref.getReferencedObject()!=null) {
196: // out = CsmReferenceRepository.getDefault().getReferences(ref.getReferencedObject(), file, CsmReferenceKind.ALL);
197: // }
198: }
199: return out;
200: }
201:
202: /* package-local */static Collection<CsmReference> getOccurences(
203: CsmFile file, int position) {
204: Collection<CsmReference> out = null;
205: CsmReference ref = CsmReferenceResolver.getDefault()
206: .findReference(file, position);
207: if (ref != null && ref.getReferencedObject() != null) {
208: out = CsmReferenceRepository.getDefault().getReferences(
209: ref.getReferencedObject(), file,
210: CsmReferenceKind.ALL);
211: }
212: return out;
213: }
214:
215: @Override
216: protected void initFontColors(FontColorSettings fcs) {
217: defaultColors = fcs.getTokenFontColors(COLORS);
218: }
219: }
|