KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > NbEditorDocument


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;
21
22 import java.awt.Font JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.Component JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.text.AttributedCharacterIterator JavaDoc;
28 import javax.swing.text.AttributeSet JavaDoc;
29 import javax.swing.JEditorPane JavaDoc;
30 import org.netbeans.editor.BaseKit;
31 import org.netbeans.editor.GuardedDocument;
32 import org.netbeans.editor.PrintContainer;
33 import org.netbeans.editor.Formatter;
34 import org.netbeans.editor.Settings;
35 import org.netbeans.editor.SettingsChangeEvent;
36 import org.netbeans.editor.Utilities;
37 import org.openide.text.NbDocument;
38 import org.openide.text.AttributedCharacters;
39 import javax.swing.text.Position JavaDoc;
40 import org.openide.text.Annotation;
41 import java.beans.PropertyChangeListener JavaDoc;
42 import java.beans.PropertyChangeEvent JavaDoc;
43 import java.util.Dictionary JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.WeakHashMap JavaDoc;
46 import javax.swing.JToolBar JavaDoc;
47 import javax.swing.event.ChangeEvent JavaDoc;
48 import javax.swing.event.ChangeListener JavaDoc;
49 import org.netbeans.editor.BaseDocument;
50 import javax.swing.text.BadLocationException JavaDoc;
51 import javax.swing.text.Document JavaDoc;
52 import org.netbeans.editor.AnnotationDesc;
53
54 /**
55 * BaseDocument extension managing the readonly blocks of text
56 *
57 * @author Miloslav Metelka
58 * @version 1.00
59 */

60
61 public class NbEditorDocument extends GuardedDocument
62 implements NbDocument.PositionBiasable, NbDocument.WriteLockable,
63 NbDocument.Printable, NbDocument.CustomEditor, NbDocument.CustomToolbar, NbDocument.Annotatable {
64
65     /** Name of the formatter setting. */
66     public static final String JavaDoc FORMATTER = "formatter"; // NOI18N
67

68     /** Mime type of the document. The name of this property corresponds
69      * to the property that is filled in the document by CloneableEditorSupport.
70      */

71     public static final String JavaDoc MIME_TYPE_PROP = "mimeType"; // NOI18N
72

73     /** Indent engine for the given kitClass. */
74     public static final String JavaDoc INDENT_ENGINE = "indentEngine"; // NOI18N
75

76     /** Formatter being used. */
77     private Formatter formatter;
78
79     /** Map of [Annotation, AnnotationDesc] */
80     private HashMap JavaDoc annoMap;
81
82     // #39718 hotfix
83
private WeakHashMap JavaDoc annoBlackList;
84
85     public NbEditorDocument(Class JavaDoc kitClass) {
86         super(kitClass);
87         addStyleToLayerMapping(NbDocument.BREAKPOINT_STYLE_NAME,
88                                NbDocument.BREAKPOINT_STYLE_NAME + "Layer:10"); // NOI18N
89
addStyleToLayerMapping(NbDocument.ERROR_STYLE_NAME,
90                                NbDocument.ERROR_STYLE_NAME + "Layer:20"); // NOI18N
91
addStyleToLayerMapping(NbDocument.CURRENT_STYLE_NAME,
92                                NbDocument.CURRENT_STYLE_NAME + "Layer:30"); // NOI18N
93
setNormalStyleName(NbDocument.NORMAL_STYLE_NAME);
94         
95         annoMap = new HashMap JavaDoc(20);
96         annoBlackList = new WeakHashMap JavaDoc();
97     }
98
99     public void settingsChange(SettingsChangeEvent evt) {
100         super.settingsChange(evt);
101
102         // Check whether the mimeType is set
103
Object JavaDoc o = getProperty(MIME_TYPE_PROP);
104         if (!(o instanceof String JavaDoc)) {
105             BaseKit kit = BaseKit.getKit(getKitClass());
106             putProperty(MIME_TYPE_PROP, kit.getContentType());
107         }
108
109         // Fill in the indentEngine property
110
putProperty(INDENT_ENGINE,
111             new BaseDocument.PropertyEvaluator() {
112
113                 private Object JavaDoc cached;
114
115                 public Object JavaDoc getValue() {
116                     if (cached == null) {
117                         cached = Settings.getValue(getKitClass(), INDENT_ENGINE);
118                     }
119                     
120                     return cached;
121                 }
122             }
123         );
124
125         // Refresh formatter
126
formatter = null;
127
128     }
129
130     public void setCharacterAttributes(int offset, int length, AttributeSet JavaDoc s,
131                                        boolean replace) {
132         if (s != null) {
133             Object JavaDoc val = s.getAttribute(NbDocument.GUARDED);
134             if (val != null && val instanceof Boolean JavaDoc) {
135                 if (((Boolean JavaDoc)val).booleanValue() == true) { // want make guarded
136
super.setCharacterAttributes(offset, length, guardedSet, replace);
137                 } else { // want make unguarded
138
super.setCharacterAttributes(offset, length, unguardedSet, replace);
139                 }
140             } else { // not special values, just pass
141
super.setCharacterAttributes(offset, length, s, replace);
142             }
143         }
144     }
145
146     public java.text.AttributedCharacterIterator JavaDoc[] createPrintIterators() {
147         NbPrintContainer npc = new NbPrintContainer();
148         print(npc);
149         return npc.getIterators();
150     }
151
152     public Component JavaDoc createEditor(JEditorPane JavaDoc j) {
153         return Utilities.getEditorUI(j).getExtComponent();
154     }
155
156     public JToolBar JavaDoc createToolbar(JEditorPane JavaDoc j) {
157         return Utilities.getEditorUI(j).getToolBarComponent();
158     }
159     
160     public Formatter getFormatter() {
161         Formatter f = formatter;
162         if (f == null) {
163             formatter = (Formatter)Settings.getValue(getKitClass(), FORMATTER);
164             f = formatter;
165         }
166
167         return (f != null) ? f : super.getFormatter();
168     }
169
170     /** Add annotation to the document. For annotation of whole line
171      * the length parameter can be ignored (specify value -1).
172      * @param startPos position which represent begining
173      * of the annotated text
174      * @param length length of the annotated text. If -1 is specified
175      * the whole line will be annotated
176      * @param annotation annotation which is attached to this text */

177     public void addAnnotation(Position JavaDoc startPos, int length, Annotation annotation) {
178         Integer JavaDoc count = (Integer JavaDoc)annoBlackList.get(annotation);
179         if (count != null) {
180             // #39718 hotfix - test whether the annotation was already removed; if so, just remove it from the black list and return
181
if (count.intValue() == -1) {
182                 annoBlackList.remove(annotation);
183                 return;
184             } else if (count.intValue() < -1) {
185                 annoBlackList.put(annotation, new Integer JavaDoc(count.intValue() + 1));
186                 return;
187             }
188         }
189         // partial fix of #33165 - read-locking of the document added
190
// BTW should only be invoked in EQ - see NbDocument.addAnnotation()
191
readLock();
192         try {
193             // Recreate annotation's position to make sure it's in this doc at a valid offset
194
int docLen = getLength();
195             int offset = startPos.getOffset();
196             offset = Math.min(offset, docLen);
197             try {
198                 startPos = createPosition(offset);
199             } catch (BadLocationException JavaDoc e) {
200                 startPos = null; // should never happen
201
}
202             
203             AnnotationDescDelegate a = (AnnotationDescDelegate)annoMap.get(annotation);
204             if (a != null) { // already added before
205
// #39718 hotfix - remove the original annotation descriptor and put the annotation on the black list
206
a.detachListeners();
207                 getAnnotations().removeAnnotation(a);
208                 annoMap.remove(annotation);
209                 annoBlackList.put(annotation, new Integer JavaDoc(count != null ? count.intValue() + 1 : 1));
210             }
211             if (annotation.getAnnotationType() != null) {
212                 a = new AnnotationDescDelegate(this, startPos, length, annotation);
213                 annoMap.put(annotation, a);
214                 getAnnotations().addAnnotation(a);
215             }
216         } finally {
217             readUnlock();
218         }
219     }
220
221     /** Removal of added annotation.
222      * @param annotation annotation which is going to be removed */

223     public void removeAnnotation(Annotation annotation) {
224         if (annotation == null) { // issue 14803
225
return; // can't do more as the rest of stacktrace is in openide and ant
226
}
227
228         Integer JavaDoc count = (Integer JavaDoc)annoBlackList.get(annotation);
229         if (count != null) {
230             // #39718 hotfix - test whether the annotation was already removed; if so, just remove it from the black list and return
231
if (count.intValue() == 1) {
232                 annoBlackList.remove(annotation);
233                 return;
234             } else if (count.intValue() > 1) {
235                 annoBlackList.put(annotation, new Integer JavaDoc(count.intValue() - 1));
236                 return;
237             }
238         }
239         // partial fix of #33165 - read-locking of the document added
240
// BTW should only be invoked in EQ - see NbDocument.removeAnnotation()
241
readLock();
242         try {
243             if (annotation.getAnnotationType() != null) {
244                 AnnotationDescDelegate a = (AnnotationDescDelegate)annoMap.get(annotation);
245                 if (a == null) { // not added yet
246
// #39718 hotfix - put the annotation on the black list and return
247
annoBlackList.put(annotation, new Integer JavaDoc(count != null ? count.intValue() - 1 : -1));
248                     return;
249                 }
250                 a.detachListeners();
251                 getAnnotations().removeAnnotation(a);
252                 annoMap.remove(annotation);
253             }
254         } finally {
255             readUnlock();
256         }
257     }
258     
259     Map JavaDoc getAnnoMap(){
260         return annoMap;
261     }
262
263     void addStreamDescriptionChangeListener(ChangeListener JavaDoc l) {
264         listenerList.add(ChangeListener JavaDoc.class, l);
265     }
266     
267     void removeStreamDescriptionChangeListener(ChangeListener JavaDoc l) {
268         listenerList.remove(ChangeListener JavaDoc.class, l);
269     }
270     
271     private void fireStreamDescriptionChange() {
272         ChangeEvent evt = new ChangeEvent(this);
273         Object JavaDoc[] listeners = listenerList.getListenerList();
274         for (int i = listeners.length - 2; i >= 0; i -= 2) {
275             if (listeners[i] == ChangeListener JavaDoc.class) {
276                 ((ChangeListener JavaDoc)listeners[i + 1]).stateChanged(evt);
277             }
278         }
279     }
280
281     protected Dictionary JavaDoc createDocumentProperties(Dictionary JavaDoc origDocumentProperties) {
282         return new LazyPropertyMap(origDocumentProperties) {
283             public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
284                 Object JavaDoc origValue = super.put(key, value);
285                 if (Document.StreamDescriptionProperty.equals(key)) {
286                     if (origValue == null || !origValue.equals(value)) {
287                         fireStreamDescriptionChange();
288                     }
289                 }
290                 
291                 return origValue;
292             }
293         };
294     }
295
296     /** Implementation of AnnotationDesc, which delegate to Annotation instance
297      * defined in org.openide.text package.
298      */

299     static class AnnotationDescDelegate extends AnnotationDesc {
300         
301         private Annotation delegate;
302         private PropertyChangeListener JavaDoc l;
303         private Position JavaDoc pos;
304         private BaseDocument doc;
305         
306         AnnotationDescDelegate(BaseDocument doc, Position JavaDoc pos, int length, Annotation anno) {
307             super(pos.getOffset(),length);
308             this.pos = pos;
309             this.delegate = anno;
310             this.doc = doc;
311             
312             // update AnnotationDesc.type member
313
updateAnnotationType();
314             
315             // forward property changes to AnnotationDesc property changes
316
l = new PropertyChangeListener JavaDoc() {
317                 public void propertyChange (PropertyChangeEvent JavaDoc evt) {
318                     if (evt.getPropertyName() == Annotation.PROP_SHORT_DESCRIPTION)
319                         firePropertyChange(AnnotationDesc.PROP_SHORT_DESCRIPTION, null, null);
320                     if (evt.getPropertyName() == Annotation.PROP_MOVE_TO_FRONT)
321                         firePropertyChange(AnnotationDesc.PROP_MOVE_TO_FRONT, null, null);
322                     if (evt.getPropertyName() == Annotation.PROP_ANNOTATION_TYPE) {
323                         updateAnnotationType();
324                         firePropertyChange(AnnotationDesc.PROP_ANNOTATION_TYPE, null, null);
325                     }
326                 }
327             };
328             delegate.addPropertyChangeListener(l);
329         }
330         
331         public String JavaDoc getAnnotationType() {
332             return delegate.getAnnotationType();
333         }
334         
335         public String JavaDoc getShortDescription() {
336             return delegate.getShortDescription();
337         }
338         
339         void detachListeners() {
340             delegate.removePropertyChangeListener(l);
341         }
342
343         public int getOffset() {
344             return pos.getOffset();
345         }
346         
347         public int getLine() {
348             try {
349                 return Utilities.getLineOffset(doc, pos.getOffset());
350             } catch (BadLocationException JavaDoc e) {
351                 return 0;
352             }
353         }
354         
355     }
356     
357     
358     class NbPrintContainer extends AttributedCharacters implements PrintContainer {
359
360         ArrayList JavaDoc acl = new ArrayList JavaDoc();
361
362         AttributedCharacters a;
363
364         NbPrintContainer() {
365             a = new AttributedCharacters();
366         }
367
368         public void add(char[] chars, Font JavaDoc font, Color JavaDoc foreColor, Color JavaDoc backColor) {
369             a.append(chars, font, foreColor);
370         }
371
372         public void eol() {
373             acl.add(a);
374             a = new AttributedCharacters();
375         }
376
377         public boolean initEmptyLines() {
378             return true;
379         }
380
381         public AttributedCharacterIterator JavaDoc[] getIterators() {
382             int cnt = acl.size();
383             AttributedCharacterIterator JavaDoc[] acis = new AttributedCharacterIterator JavaDoc[cnt];
384             for (int i = 0; i < cnt; i++) {
385                 AttributedCharacters ac = (AttributedCharacters)acl.get(i);
386                 acis[i] = ac.iterator();
387             }
388             return acis;
389         }
390
391     }
392
393 }
394
Popular Tags