1 19 20 package org.netbeans.modules.editor; 21 22 import java.awt.Font ; 23 import java.awt.Color ; 24 import java.awt.Component ; 25 import java.util.ArrayList ; 26 import java.util.HashMap ; 27 import java.text.AttributedCharacterIterator ; 28 import javax.swing.text.AttributeSet ; 29 import javax.swing.JEditorPane ; 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 ; 40 import org.openide.text.Annotation; 41 import java.beans.PropertyChangeListener ; 42 import java.beans.PropertyChangeEvent ; 43 import java.util.Dictionary ; 44 import java.util.Map ; 45 import java.util.WeakHashMap ; 46 import javax.swing.JToolBar ; 47 import javax.swing.event.ChangeEvent ; 48 import javax.swing.event.ChangeListener ; 49 import org.netbeans.editor.BaseDocument; 50 import javax.swing.text.BadLocationException ; 51 import javax.swing.text.Document ; 52 import org.netbeans.editor.AnnotationDesc; 53 54 60 61 public class NbEditorDocument extends GuardedDocument 62 implements NbDocument.PositionBiasable, NbDocument.WriteLockable, 63 NbDocument.Printable, NbDocument.CustomEditor, NbDocument.CustomToolbar, NbDocument.Annotatable { 64 65 66 public static final String FORMATTER = "formatter"; 68 71 public static final String MIME_TYPE_PROP = "mimeType"; 73 74 public static final String INDENT_ENGINE = "indentEngine"; 76 77 private Formatter formatter; 78 79 80 private HashMap annoMap; 81 82 private WeakHashMap annoBlackList; 84 85 public NbEditorDocument(Class kitClass) { 86 super(kitClass); 87 addStyleToLayerMapping(NbDocument.BREAKPOINT_STYLE_NAME, 88 NbDocument.BREAKPOINT_STYLE_NAME + "Layer:10"); addStyleToLayerMapping(NbDocument.ERROR_STYLE_NAME, 90 NbDocument.ERROR_STYLE_NAME + "Layer:20"); addStyleToLayerMapping(NbDocument.CURRENT_STYLE_NAME, 92 NbDocument.CURRENT_STYLE_NAME + "Layer:30"); setNormalStyleName(NbDocument.NORMAL_STYLE_NAME); 94 95 annoMap = new HashMap (20); 96 annoBlackList = new WeakHashMap (); 97 } 98 99 public void settingsChange(SettingsChangeEvent evt) { 100 super.settingsChange(evt); 101 102 Object o = getProperty(MIME_TYPE_PROP); 104 if (!(o instanceof String )) { 105 BaseKit kit = BaseKit.getKit(getKitClass()); 106 putProperty(MIME_TYPE_PROP, kit.getContentType()); 107 } 108 109 putProperty(INDENT_ENGINE, 111 new BaseDocument.PropertyEvaluator() { 112 113 private Object cached; 114 115 public Object getValue() { 116 if (cached == null) { 117 cached = Settings.getValue(getKitClass(), INDENT_ENGINE); 118 } 119 120 return cached; 121 } 122 } 123 ); 124 125 formatter = null; 127 128 } 129 130 public void setCharacterAttributes(int offset, int length, AttributeSet s, 131 boolean replace) { 132 if (s != null) { 133 Object val = s.getAttribute(NbDocument.GUARDED); 134 if (val != null && val instanceof Boolean ) { 135 if (((Boolean )val).booleanValue() == true) { super.setCharacterAttributes(offset, length, guardedSet, replace); 137 } else { super.setCharacterAttributes(offset, length, unguardedSet, replace); 139 } 140 } else { super.setCharacterAttributes(offset, length, s, replace); 142 } 143 } 144 } 145 146 public java.text.AttributedCharacterIterator [] createPrintIterators() { 147 NbPrintContainer npc = new NbPrintContainer(); 148 print(npc); 149 return npc.getIterators(); 150 } 151 152 public Component createEditor(JEditorPane j) { 153 return Utilities.getEditorUI(j).getExtComponent(); 154 } 155 156 public JToolBar createToolbar(JEditorPane 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 177 public void addAnnotation(Position startPos, int length, Annotation annotation) { 178 Integer count = (Integer )annoBlackList.get(annotation); 179 if (count != null) { 180 if (count.intValue() == -1) { 182 annoBlackList.remove(annotation); 183 return; 184 } else if (count.intValue() < -1) { 185 annoBlackList.put(annotation, new Integer (count.intValue() + 1)); 186 return; 187 } 188 } 189 readLock(); 192 try { 193 int docLen = getLength(); 195 int offset = startPos.getOffset(); 196 offset = Math.min(offset, docLen); 197 try { 198 startPos = createPosition(offset); 199 } catch (BadLocationException e) { 200 startPos = null; } 202 203 AnnotationDescDelegate a = (AnnotationDescDelegate)annoMap.get(annotation); 204 if (a != null) { a.detachListeners(); 207 getAnnotations().removeAnnotation(a); 208 annoMap.remove(annotation); 209 annoBlackList.put(annotation, new Integer (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 223 public void removeAnnotation(Annotation annotation) { 224 if (annotation == null) { return; } 227 228 Integer count = (Integer )annoBlackList.get(annotation); 229 if (count != null) { 230 if (count.intValue() == 1) { 232 annoBlackList.remove(annotation); 233 return; 234 } else if (count.intValue() > 1) { 235 annoBlackList.put(annotation, new Integer (count.intValue() - 1)); 236 return; 237 } 238 } 239 readLock(); 242 try { 243 if (annotation.getAnnotationType() != null) { 244 AnnotationDescDelegate a = (AnnotationDescDelegate)annoMap.get(annotation); 245 if (a == null) { annoBlackList.put(annotation, new Integer (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 getAnnoMap(){ 260 return annoMap; 261 } 262 263 void addStreamDescriptionChangeListener(ChangeListener l) { 264 listenerList.add(ChangeListener .class, l); 265 } 266 267 void removeStreamDescriptionChangeListener(ChangeListener l) { 268 listenerList.remove(ChangeListener .class, l); 269 } 270 271 private void fireStreamDescriptionChange() { 272 ChangeEvent evt = new ChangeEvent(this); 273 Object [] listeners = listenerList.getListenerList(); 274 for (int i = listeners.length - 2; i >= 0; i -= 2) { 275 if (listeners[i] == ChangeListener .class) { 276 ((ChangeListener )listeners[i + 1]).stateChanged(evt); 277 } 278 } 279 } 280 281 protected Dictionary createDocumentProperties(Dictionary origDocumentProperties) { 282 return new LazyPropertyMap(origDocumentProperties) { 283 public Object put(Object key, Object value) { 284 Object 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 299 static class AnnotationDescDelegate extends AnnotationDesc { 300 301 private Annotation delegate; 302 private PropertyChangeListener l; 303 private Position pos; 304 private BaseDocument doc; 305 306 AnnotationDescDelegate(BaseDocument doc, Position pos, int length, Annotation anno) { 307 super(pos.getOffset(),length); 308 this.pos = pos; 309 this.delegate = anno; 310 this.doc = doc; 311 312 updateAnnotationType(); 314 315 l = new PropertyChangeListener () { 317 public void propertyChange (PropertyChangeEvent 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 getAnnotationType() { 332 return delegate.getAnnotationType(); 333 } 334 335 public String 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 e) { 351 return 0; 352 } 353 } 354 355 } 356 357 358 class NbPrintContainer extends AttributedCharacters implements PrintContainer { 359 360 ArrayList acl = new ArrayList (); 361 362 AttributedCharacters a; 363 364 NbPrintContainer() { 365 a = new AttributedCharacters(); 366 } 367 368 public void add(char[] chars, Font font, Color foreColor, Color 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 [] getIterators() { 382 int cnt = acl.size(); 383 AttributedCharacterIterator [] acis = new AttributedCharacterIterator [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 |