1 19 20 package org.netbeans.editor; 21 22 import java.text.MessageFormat ; 23 import java.util.Hashtable ; 24 import java.util.Enumeration ; 25 import java.awt.Color ; 26 import java.awt.Font ; 27 import javax.swing.text.BadLocationException ; 28 import javax.swing.text.StyledDocument ; 29 import javax.swing.text.Style ; 30 import javax.swing.text.Element ; 31 import javax.swing.text.AttributeSet ; 32 import javax.swing.text.StyleContext ; 33 import javax.swing.event.DocumentEvent ; 34 import javax.swing.text.Position ; 35 import javax.swing.text.SimpleAttributeSet ; 36 import org.openide.util.NbBundle; 37 44 45 public class GuardedDocument extends BaseDocument 46 implements StyledDocument { 47 48 51 public static final String GUARDED_ATTRIBUTE = "guarded"; 53 54 public static final SimpleAttributeSet guardedSet = new SimpleAttributeSet (); 55 56 57 public static final SimpleAttributeSet unguardedSet = new SimpleAttributeSet (); 58 59 private static final boolean debugAtomic = Boolean.getBoolean("netbeans.debug.editor.atomic"); private static final boolean debugAtomicStack = Boolean.getBoolean("netbeans.debug.editor.atomic.stack"); 62 static { 64 guardedSet.addAttribute(GUARDED_ATTRIBUTE, Boolean.TRUE); 65 unguardedSet.addAttribute(GUARDED_ATTRIBUTE, Boolean.FALSE); 66 } 67 68 public static final String FMT_GUARDED_INSERT_LOCALE = "FMT_guarded_insert"; public static final String FMT_GUARDED_REMOVE_LOCALE = "FMT_guarded_remove"; 71 MarkBlockChain guardedBlockChain; 72 73 74 boolean breakGuarded; 75 76 boolean atomicAsUser; 77 78 79 protected StyleContext styles; 80 81 82 protected Hashtable stylesToLayers; 83 84 87 protected String normalStyleName; 88 89 public GuardedDocument(Class kitClass) { 90 this(kitClass, true, new StyleContext ()); 91 } 92 93 99 public GuardedDocument(Class kitClass, boolean addToRegistry, StyleContext styles) { 100 super(kitClass, addToRegistry); 101 this.styles = styles; 102 stylesToLayers = new Hashtable (5); 103 guardedBlockChain = new MarkBlockChain(this) { 104 protected Mark createBlockStartMark() { 105 MarkFactory.ContextMark startMark = new MarkFactory.ContextMark(Position.Bias.Forward, false); 106 return startMark; 107 } 108 109 protected Mark createBlockEndMark() { 110 MarkFactory.ContextMark endMark = new MarkFactory.ContextMark(Position.Bias.Backward, false); 111 return endMark; 112 } 113 }; 114 } 115 116 117 public MarkBlockChain getGuardedBlockChain() { 118 return guardedBlockChain; 119 } 120 121 public boolean isPosGuarded(int pos) { 122 int rel = guardedBlockChain.compareBlock(pos, pos) & MarkBlock.IGNORE_EMPTY; 123 return (rel == MarkBlock.INSIDE_BEGIN || rel == MarkBlock.INNER); 124 } 125 126 133 protected void preInsertCheck(int offset, String text, AttributeSet a) 134 throws BadLocationException { 135 super.preInsertCheck(offset, text, a); 136 137 int rel = guardedBlockChain.compareBlock(offset, offset) & MarkBlock.IGNORE_EMPTY; 138 139 if (debugAtomic) { 140 System.err.println("GuardedDocument.beforeInsertUpdate() atomicAsUser=" + atomicAsUser + ", breakGuarded=" + breakGuarded + ", inserting text='" + EditorDebug.debugString(text) + "' at offset=" + Utilities.debugPosition(this, offset)); if (debugAtomicStack) { 145 Thread.dumpStack(); 146 } 147 } 148 149 if (text.length() > 0 150 && (rel & MarkBlock.OVERLAP) != 0 151 && rel != MarkBlock.INSIDE_END && !(text.charAt(text.length() - 1) == '\n' 153 && rel == MarkBlock.INSIDE_BEGIN) 154 ) { 155 if (!breakGuarded || atomicAsUser) { 156 throw new GuardedException( 157 MessageFormat.format( 158 NbBundle.getBundle(BaseKit.class).getString(FMT_GUARDED_INSERT_LOCALE), 159 new Object [] { 160 new Integer (offset) 161 } 162 ), 163 offset 164 ); 165 } 166 } 167 } 168 169 172 protected void preRemoveCheck(int offset, int len) 173 throws BadLocationException { 174 int rel = guardedBlockChain.compareBlock(offset, offset + len); 175 176 if (debugAtomic) { 177 System.err.println("GuardedDocument.beforeRemoveUpdate() atomicAsUser=" + atomicAsUser + ", breakGuarded=" + breakGuarded + ", removing text='" + EditorDebug.debugChars(getChars(offset, len)) + "'at offset=" + Utilities.debugPosition(this, offset)); if (debugAtomicStack) { 182 Thread.dumpStack(); 183 } 184 } 185 186 if ((rel & MarkBlock.OVERLAP) != 0 187 || (rel == MarkBlock.CONTINUE_BEGIN 188 && !(offset == 0 || getChars(offset - 1, 1)[0] == '\n')) 189 ) { 190 if (!breakGuarded || atomicAsUser) { 191 throw new GuardedException( 193 MessageFormat.format( 194 NbBundle.getBundle(BaseKit.class).getString(FMT_GUARDED_REMOVE_LOCALE), 195 new Object [] { 196 new Integer (offset) 197 } 198 ), 199 offset 200 ); 201 } 202 } 203 } 204 205 public void setCharacterAttributes(int offset, int length, AttributeSet s, 206 boolean replace) { 207 if (((Boolean )s.getAttribute(GUARDED_ATTRIBUTE)).booleanValue() == true) { 208 guardedBlockChain.addBlock(offset, offset + length, false); fireChangedUpdate(createDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE)); 210 } 211 if (((Boolean )s.getAttribute(GUARDED_ATTRIBUTE)).booleanValue() == false) { 212 guardedBlockChain.removeBlock(offset, offset + length); 213 fireChangedUpdate(createDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE)); 214 } 215 } 216 217 public void runAtomic(Runnable r) { 218 if (debugAtomic) { 219 System.out.println("GuardedDocument.runAtomic() called"); if (debugAtomicStack) { 221 Thread.dumpStack(); 222 } 223 } 224 225 boolean completed = false; 226 atomicLock(); 227 boolean origBreakGuarded = breakGuarded; 228 try { 229 breakGuarded = true; 230 r.run(); 231 completed = true; 232 } finally { 233 breakGuarded = origBreakGuarded; 234 try { 235 if (!completed) { 236 breakAtomicLock(); 237 } 238 } finally { 239 atomicUnlock(); 240 } 241 if (debugAtomic) { 242 System.out.println("GuardedDocument.runAtomic() finished"); } 244 } 245 } 246 247 public void runAtomicAsUser(Runnable r) { 248 if (debugAtomic) { 249 System.out.println("GuardedDocument.runAtomicAsUser() called"); if (debugAtomicStack) { 251 Thread.dumpStack(); 252 } 253 } 254 255 boolean completed = false; 256 atomicLock(); 257 boolean origAtomicAsUser = atomicAsUser; 258 try { 259 atomicAsUser = true; 260 r.run(); 261 completed = true; 262 } finally { 263 atomicAsUser = origAtomicAsUser; 264 try { 265 if (!completed) { 266 breakAtomicLock(); 267 } 268 } finally { 269 atomicUnlock(); 270 } 271 if (debugAtomic) { 272 System.out.println("GuardedDocument.runAtomicAsUser() finished"); } 274 } 275 } 276 277 protected BaseDocumentEvent createDocumentEvent(int offset, int length, 278 DocumentEvent.EventType type) { 279 return new GuardedDocumentEvent(this, offset, length, type); 280 } 281 282 283 public Style addStyle(String styleName, Style parent) { 284 String layerName = (String )stylesToLayers.get(styleName); 285 if (layerName == null) { 286 layerName = styleName; addStyleToLayerMapping(styleName, layerName); 288 } 289 290 Style style = styles.addStyle(styleName, parent); 291 if (findLayer(layerName) == null) { try { 293 extWriteLock(); 294 addStyledLayer(layerName, style); 295 } finally { 296 extWriteUnlock(); 297 } 298 } 299 return style; 300 } 301 302 public void addStyleToLayerMapping(String styleName, String layerName) { 303 stylesToLayers.put(styleName, layerName); 304 } 305 306 307 public void removeStyle(String styleName) { 308 styles.removeStyle(styleName); 309 } 310 311 312 public Style getStyle(String styleName) { 313 return styles.getStyle(styleName); 314 } 315 316 319 public void setNormalStyleName(String normalStyleName) { 320 this.normalStyleName = normalStyleName; 321 } 322 323 324 public Enumeration getStyleNames() { 325 return styles.getStyleNames(); 326 } 327 328 329 public void setParagraphAttributes(int offset, int length, AttributeSet s, 330 boolean replace) { 331 } 333 334 345 public void setLogicalStyle(int pos, Style s) { 346 try { 347 extWriteLock(); 348 pos = Utilities.getRowStart(this, pos); 349 String layerName = (String )stylesToLayers.get(s.getName()); 350 DrawLayer[] layerArray = getDrawLayerList().currentLayers(); 352 for (int i = 0; i < layerArray.length; i++) { 353 if (layerArray[i] instanceof DrawLayerFactory.StyleLayer) { 354 ((DrawLayerFactory.StyleLayer)layerArray[i]).markChain.removeMark(pos); 355 } 356 } 357 DrawLayerFactory.StyleLayer styleLayer 359 = (DrawLayerFactory.StyleLayer)findLayer(layerName); 360 if (styleLayer != null) { 361 styleLayer.markChain.addMark(pos); 362 } 363 fireChangedUpdate(createDocumentEvent(pos, 0, 364 DocumentEvent.EventType.CHANGE)); } catch (BadLocationException e) { 366 } finally { 368 extWriteUnlock(); 369 } 370 } 371 372 373 public Style getLogicalStyle(int pos) { 374 try { 375 pos = Utilities.getRowStart(this, pos); 376 DrawLayer[] layerArray = getDrawLayerList().currentLayers(); 377 for (int i = 0; i < layerArray.length; i++) { 378 DrawLayer layer = layerArray[i]; 379 if (layer instanceof DrawLayerFactory.StyleLayer) { 380 if (((DrawLayerFactory.StyleLayer)layer).markChain.isMark(pos)) { 381 return ((DrawLayerFactory.StyleLayer)layer).style; 382 } 383 } 384 } 385 return getStyle(normalStyleName); } catch (BadLocationException e) { 387 return null; 388 } 389 } 390 391 398 public Element getCharacterElement(int pos) { 399 return getParagraphElement(pos); 400 } 401 402 403 411 public Color getForeground(AttributeSet attr) { 412 return null; } 414 415 423 public Color getBackground(AttributeSet attr) { 424 return null; } 426 427 436 public Font getFont(AttributeSet attr) { 437 return new Font ("Default",Font.BOLD,12); } 439 440 446 protected DrawLayer addStyledLayer(String layerName, Style style) { 447 if (layerName != null) { 448 try { 449 int indColon = layerName.indexOf(':'); 450 int layerVisibility = Integer.parseInt(layerName.substring(indColon + 1)); 451 DrawLayer layer = new DrawLayerFactory.StyleLayer(layerName, this, style); 452 453 addLayer(layer, layerVisibility); 454 return layer; 455 456 } catch (NumberFormatException e) { 457 } 459 } 460 return null; 461 } 462 463 public String toStringDetail() { 464 return super.toStringDetail() 465 + getDrawLayerList() 466 + ",\nGUARDED blocks:\n" + guardedBlockChain; } 468 469 } 470 | Popular Tags |