KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > impl > highlighting > NonLexerSyntaxHighlighting


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor.impl.highlighting;
21
22 import java.util.Collection JavaDoc;
23 import java.util.ConcurrentModificationException JavaDoc;
24 import java.util.NoSuchElementException JavaDoc;
25 import java.util.WeakHashMap JavaDoc;
26 import java.util.logging.Level JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import javax.swing.event.DocumentEvent JavaDoc;
29 import javax.swing.event.DocumentListener JavaDoc;
30 import javax.swing.text.AttributeSet JavaDoc;
31 import javax.swing.text.BadLocationException JavaDoc;
32 import javax.swing.text.Document JavaDoc;
33 import javax.swing.text.SimpleAttributeSet JavaDoc;
34 import org.netbeans.api.editor.mimelookup.MimeLookup;
35 import org.netbeans.api.editor.mimelookup.MimePath;
36 import org.netbeans.api.editor.settings.FontColorSettings;
37 import org.netbeans.editor.BaseDocument;
38 import org.netbeans.editor.TokenCategory;
39 import org.netbeans.editor.TokenContextPath;
40 import org.netbeans.editor.TokenID;
41 import org.netbeans.editor.TokenItem;
42 import org.netbeans.editor.ext.ExtSyntaxSupport;
43 import org.netbeans.spi.editor.highlighting.HighlightsSequence;
44 import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
45 import org.openide.util.Lookup;
46 import org.openide.util.LookupEvent;
47 import org.openide.util.LookupListener;
48 import org.openide.util.WeakListeners;
49
50 /**
51  *
52  * @author Vita Stejskal
53  */

54 public final class NonLexerSyntaxHighlighting extends AbstractHighlightsContainer implements DocumentListener JavaDoc, LookupListener {
55     
56     private static final Logger JavaDoc LOG = Logger.getLogger(NonLexerSyntaxHighlighting.class.getName());
57     public static final String JavaDoc LAYER_TYPE_ID = "org.netbeans.modules.editor.oldlibbridge.NonLexerSyntaxHighlighting"; //NOI18N
58

59     private final Document JavaDoc document;
60     private long version = 0;
61
62     private final MimePath mimePath;
63     private final Lookup.Result<FontColorSettings> lookupResult;
64     private final WeakHashMap JavaDoc<TokenID, AttributeSet JavaDoc> attribsCache = new WeakHashMap JavaDoc<TokenID, AttributeSet JavaDoc>();
65     
66     /** Creates a new instance of NonLexerSytaxHighlighting */
67     public NonLexerSyntaxHighlighting(Document JavaDoc document, String JavaDoc mimeType) {
68         this.mimePath = MimePath.parse(mimeType);
69         this.lookupResult = MimeLookup.getLookup(mimePath).lookup(new Lookup.Template<FontColorSettings>(FontColorSettings.class));
70         this.lookupResult.addLookupListener(this);
71         
72         this.document = document;
73         this.document.addDocumentListener(WeakListeners.document(this, document));
74     }
75
76     public HighlightsSequence getHighlights(int startOffset, int endOffset) {
77         synchronized (this) {
78             if (document instanceof BaseDocument) {
79                 return new HSImpl(version, (BaseDocument) document, startOffset, endOffset);
80             } else {
81                 return HighlightsSequence.EMPTY;
82             }
83         }
84     }
85     
86     // ----------------------------------------------------------------------
87
// DocumentListener implementation
88
// ----------------------------------------------------------------------
89

90     public void insertUpdate(DocumentEvent JavaDoc e) {
91         documentChanged(e.getOffset(), e.getLength());
92     }
93
94     public void removeUpdate(DocumentEvent JavaDoc e) {
95         documentChanged(e.getOffset(), e.getLength());
96     }
97
98     public void changedUpdate(DocumentEvent JavaDoc e) {
99         documentChanged(e.getOffset(), e.getLength());
100     }
101     
102     // ----------------------------------------------------------------------
103
// LookupListener implementation
104
// ----------------------------------------------------------------------
105

106     public void resultChanged(LookupEvent ev) {
107         synchronized (this) {
108             attribsCache.clear();
109             version++;
110         }
111         
112         document.render(new Runnable JavaDoc() {
113             public void run() {
114                 fireHighlightsChange(0, Integer.MAX_VALUE);
115             }
116         });
117     }
118     
119     // ----------------------------------------------------------------------
120
// Private implementation
121
// ----------------------------------------------------------------------
122

123     private AttributeSet JavaDoc findAttribs(TokenItem tokenItem) {
124         synchronized (this) {
125             AttributeSet JavaDoc attribs = attribsCache.get(tokenItem.getTokenID());
126
127             if (attribs == null) {
128                 Collection JavaDoc<? extends FontColorSettings> allFcs = lookupResult.allInstances();
129                 if (!allFcs.isEmpty()) {
130                     FontColorSettings fcs = allFcs.iterator().next();
131
132                     attribs = findFontAndColors(fcs, tokenItem);
133                     if (attribs == null) {
134                         attribs = SimpleAttributeSet.EMPTY;
135                     }
136                     
137                     attribsCache.put(tokenItem.getTokenID(), attribs);
138                 } else {
139                     LOG.warning("Can't find FCS for mime path: '" + mimePath.getPath() + "'"); //NOI18N
140
}
141             }
142
143             return attribs == null ? SimpleAttributeSet.EMPTY : attribs;
144         }
145     }
146
147     private static AttributeSet JavaDoc findFontAndColors(FontColorSettings fcs, TokenItem tokenItem) {
148         AttributeSet JavaDoc attribs = null;
149         TokenContextPath tokenContextPath = tokenItem.getTokenContextPath();
150         
151         // First try the token's name
152
{
153             String JavaDoc name = tokenContextPath.getFullTokenName(tokenItem.getTokenID());
154             if (name != null) {
155                 attribs = fcs.getTokenFontColors(name);
156             }
157         }
158
159         // Then try the category
160
if (attribs == null) {
161             TokenCategory category = tokenItem.getTokenID().getCategory();
162             if (category != null) {
163                 String JavaDoc categoryName = tokenContextPath.getFullTokenName(category);
164                 if (categoryName != null) {
165                     attribs = fcs.getTokenFontColors(categoryName);
166                 }
167             }
168         }
169
170         return attribs;
171     }
172
173     private void documentChanged(int offset, int lenght) {
174         synchronized (this) {
175             version++;
176         }
177         
178         if (LOG.isLoggable(Level.FINE)) {
179             LOG.fine("Document changed: changeStart = " + offset + ", changeEnd = " + (offset + lenght)); //NOI18N
180
}
181         
182         if (offset < 0 || offset > document.getLength()) {
183             offset = 0;
184         }
185         
186         if (lenght <= 0 || offset + lenght > document.getLength()) {
187             lenght = document.getLength() - offset;
188         }
189         
190         fireHighlightsChange(offset, offset + lenght);
191     }
192
193     private final class HSImpl implements HighlightsSequence {
194         
195         private final long version;
196         private final BaseDocument baseDocument;
197         private final int startOffset;
198         private final int endOffset;
199
200         private boolean init = false;
201         private TokenItem tokenItem;
202         
203         public HSImpl(long version, BaseDocument baseDocument, int startOffset, int endOffset) {
204             this.version = version;
205             this.baseDocument = baseDocument;
206             this.startOffset = startOffset;
207             this.endOffset = endOffset;
208         }
209         
210         public boolean moveNext() {
211             if (!init) {
212                 init = true;
213
214                 try {
215                     ExtSyntaxSupport ess = new ExtSyntaxSupport(baseDocument);
216                     tokenItem = ess.getTokenChain(startOffset, endOffset);
217                 } catch (BadLocationException JavaDoc e) {
218                     LOG.log(Level.WARNING, "Can't get token sequence: document " + baseDocument + //NOI18N
219
", startOffset = " + startOffset + ", endOffset = " + endOffset, e); //NOI18N
220
tokenItem = null;
221                 }
222                 
223                 while(null != tokenItem) {
224                     if (tokenItem.getOffset() + tokenItem.getImage().length() > startOffset) {
225                         break;
226                     }
227
228                     if (LOG.isLoggable(Level.FINE)) {
229                         LOG.fine("Skipping tokenId: " + tokenItem.getTokenID() + //NOI18N
230
", tokenStart = " + tokenItem.getOffset() + //NOI18N
231
", tokenEnd = " + (tokenItem.getOffset() + tokenItem.getImage().length()) + //NOI18N
232
", startOffset = " + startOffset + //NOI18N
233
", endOffset = " + endOffset //NOI18N
234
);
235                     }
236                     
237                     tokenItem = tokenItem.getNext();
238                 }
239             } else if (tokenItem != null) {
240                 tokenItem = tokenItem.getNext();
241             }
242             
243             if (tokenItem != null && tokenItem.getOffset() > endOffset) {
244                 tokenItem = null;
245             }
246             
247             if (LOG.isLoggable(Level.FINE)) {
248                 if (tokenItem != null) {
249                     LOG.fine("Next tokenId: " + tokenItem.getTokenID() + //NOI18N
250
", tokenStart = " + tokenItem.getOffset() + //NOI18N
251
", tokenEnd = " + (tokenItem.getOffset() + tokenItem.getImage().length()) + //NOI18N
252
", startOffset = " + startOffset + //NOI18N
253
", endOffset = " + endOffset //NOI18N
254
);
255                 } else {
256                     LOG.fine("Next tokenId: null"); //NOI18N
257
}
258             }
259             
260             return tokenItem != null;
261         }
262
263         public int getStartOffset() {
264             synchronized (NonLexerSyntaxHighlighting.this) {
265                 checkVersion();
266                 
267                 if (!init) {
268                     throw new NoSuchElementException JavaDoc("Call moveNext() first."); //NOI18N
269
} else if (tokenItem == null) {
270                     throw new NoSuchElementException JavaDoc();
271                 }
272
273                 return Math.max(tokenItem.getOffset(), startOffset);
274             }
275         }
276
277         public int getEndOffset() {
278             synchronized (NonLexerSyntaxHighlighting.this) {
279                 checkVersion();
280                 
281                 if (!init) {
282                     throw new NoSuchElementException JavaDoc("Call moveNext() first."); //NOI18N
283
} else if (tokenItem == null) {
284                     throw new NoSuchElementException JavaDoc();
285                 }
286
287                 return Math.min(tokenItem.getOffset() + tokenItem.getImage().length(), endOffset);
288             }
289         }
290
291         public AttributeSet JavaDoc getAttributes() {
292             synchronized (NonLexerSyntaxHighlighting.this) {
293                 checkVersion();
294                 
295                 if (!init) {
296                     throw new NoSuchElementException JavaDoc("Call moveNext() first."); //NOI18N
297
} else if (tokenItem == null) {
298                     throw new NoSuchElementException JavaDoc();
299                 }
300
301                 return findAttribs(tokenItem);
302             }
303         }
304         
305         private void checkVersion() {
306             if (this.version != NonLexerSyntaxHighlighting.this.version) {
307                 throw new ConcurrentModificationException JavaDoc();
308             }
309         }
310     } // End of HSImpl class
311

312 }
313
Popular Tags