1 11 12 package org.eclipse.jface.text.presentation; 13 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.Map ; 17 18 import org.eclipse.swt.custom.StyleRange; 19 20 import org.eclipse.core.runtime.Assert; 21 22 import org.eclipse.jface.text.BadLocationException; 23 import org.eclipse.jface.text.BadPositionCategoryException; 24 import org.eclipse.jface.text.DefaultPositionUpdater; 25 import org.eclipse.jface.text.DocumentEvent; 26 import org.eclipse.jface.text.DocumentPartitioningChangedEvent; 27 import org.eclipse.jface.text.IDocument; 28 import org.eclipse.jface.text.IDocumentExtension3; 29 import org.eclipse.jface.text.IDocumentListener; 30 import org.eclipse.jface.text.IDocumentPartitioningListener; 31 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension; 32 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2; 33 import org.eclipse.jface.text.IPositionUpdater; 34 import org.eclipse.jface.text.IRegion; 35 import org.eclipse.jface.text.ITextInputListener; 36 import org.eclipse.jface.text.ITextListener; 37 import org.eclipse.jface.text.ITextViewer; 38 import org.eclipse.jface.text.ITextViewerExtension5; 39 import org.eclipse.jface.text.ITypedRegion; 40 import org.eclipse.jface.text.Region; 41 import org.eclipse.jface.text.TextEvent; 42 import org.eclipse.jface.text.TextPresentation; 43 import org.eclipse.jface.text.TextUtilities; 44 import org.eclipse.jface.text.TypedPosition; 45 46 47 48 59 public class PresentationReconciler implements IPresentationReconciler, IPresentationReconcilerExtension { 60 61 62 protected final static String TRACKED_PARTITION= "__reconciler_tracked_partition"; 64 65 68 class InternalListener implements 69 ITextInputListener, IDocumentListener, ITextListener, 70 IDocumentPartitioningListener, IDocumentPartitioningListenerExtension, IDocumentPartitioningListenerExtension2 { 71 72 73 private boolean fDocumentChanging= false; 74 78 private boolean fCachedRedrawState= true; 79 80 83 public void inputDocumentAboutToBeChanged(IDocument oldDocument, IDocument newDocument) { 84 if (oldDocument != null) { 85 try { 86 87 fViewer.removeTextListener(this); 88 oldDocument.removeDocumentListener(this); 89 oldDocument.removeDocumentPartitioningListener(this); 90 91 oldDocument.removePositionUpdater(fPositionUpdater); 92 oldDocument.removePositionCategory(fPositionCategory); 93 94 } catch (BadPositionCategoryException x) { 95 } 97 } 98 } 99 100 103 public void inputDocumentChanged(IDocument oldDocument, IDocument newDocument) { 104 105 fDocumentChanging= false; 106 fCachedRedrawState= true; 107 108 if (newDocument != null) { 109 110 newDocument.addPositionCategory(fPositionCategory); 111 newDocument.addPositionUpdater(fPositionUpdater); 112 113 newDocument.addDocumentPartitioningListener(this); 114 newDocument.addDocumentListener(this); 115 fViewer.addTextListener(this); 116 117 setDocumentToDamagers(newDocument); 118 setDocumentToRepairers(newDocument); 119 processDamage(new Region(0, newDocument.getLength()), newDocument); 120 } 121 } 122 123 126 public void documentPartitioningChanged(IDocument document) { 127 if (!fDocumentChanging && fCachedRedrawState) 128 processDamage(new Region(0, document.getLength()), document); 129 else 130 fDocumentPartitioningChanged= true; 131 } 132 133 137 public void documentPartitioningChanged(IDocument document, IRegion changedRegion) { 138 if (!fDocumentChanging && fCachedRedrawState) { 139 processDamage(new Region(changedRegion.getOffset(), changedRegion.getLength()), document); 140 } else { 141 fDocumentPartitioningChanged= true; 142 fChangedDocumentPartitions= changedRegion; 143 } 144 } 145 146 150 public void documentPartitioningChanged(DocumentPartitioningChangedEvent event) { 151 IRegion changedRegion= event.getChangedRegion(getDocumentPartitioning()); 152 if (changedRegion != null) 153 documentPartitioningChanged(event.getDocument(), changedRegion); 154 } 155 156 159 public void documentAboutToBeChanged(DocumentEvent e) { 160 161 fDocumentChanging= true; 162 if (fCachedRedrawState) { 163 try { 164 int offset= e.getOffset() + e.getLength(); 165 ITypedRegion region= getPartition(e.getDocument(), offset); 166 fRememberedPosition= new TypedPosition(region); 167 e.getDocument().addPosition(fPositionCategory, fRememberedPosition); 168 } catch (BadLocationException x) { 169 } catch (BadPositionCategoryException x) { 171 } 173 } 174 } 175 176 179 public void documentChanged(DocumentEvent e) { 180 if (fCachedRedrawState) { 181 try { 182 e.getDocument().removePosition(fPositionCategory, fRememberedPosition); 183 } catch (BadPositionCategoryException x) { 184 } 186 } 187 fDocumentChanging= false; 188 } 189 190 193 public void textChanged(TextEvent e) { 194 195 fCachedRedrawState= e.getViewerRedrawState(); 196 if (!fCachedRedrawState) 197 return; 198 199 IRegion damage= null; 200 IDocument document= null; 201 202 if (e.getDocumentEvent() == null) { 203 document= fViewer.getDocument(); 204 if (document != null) { 205 if (e.getOffset() == 0 && e.getLength() == 0 && e.getText() == null) { 206 damage= new Region(0, document.getLength()); 208 } else { 209 IRegion region= widgetRegion2ModelRegion(e); 210 try { 211 String text= document.get(region.getOffset(), region.getLength()); 212 DocumentEvent de= new DocumentEvent(document, region.getOffset(), region.getLength(), text); 213 damage= getDamage(de, false); 214 } catch (BadLocationException x) { 215 } 216 } 217 } 218 } else { 219 DocumentEvent de= e.getDocumentEvent(); 220 document= de.getDocument(); 221 damage= getDamage(de, true); 222 } 223 224 if (damage != null && document != null) 225 processDamage(damage, document); 226 227 fDocumentPartitioningChanged= false; 228 fChangedDocumentPartitions= null; 229 } 230 231 238 protected IRegion widgetRegion2ModelRegion(TextEvent e) { 239 240 String text= e.getText(); 241 int length= text == null ? 0 : text.length(); 242 243 if (fViewer instanceof ITextViewerExtension5) { 244 ITextViewerExtension5 extension= (ITextViewerExtension5) fViewer; 245 return extension.widgetRange2ModelRange(new Region(e.getOffset(), length)); 246 } 247 248 IRegion visible= fViewer.getVisibleRegion(); 249 IRegion region= new Region(e.getOffset() + visible.getOffset(), length); 250 return region; 251 } 252 } 253 254 255 private Map fDamagers; 256 257 private Map fRepairers; 258 259 private ITextViewer fViewer; 260 261 private InternalListener fInternalListener= new InternalListener(); 262 263 private String fPositionCategory; 264 265 private IPositionUpdater fPositionUpdater; 266 267 private TypedPosition fRememberedPosition; 268 269 private boolean fDocumentPartitioningChanged= false; 270 271 private IRegion fChangedDocumentPartitions= null; 272 276 private String fPartitioning; 277 278 283 public PresentationReconciler() { 284 super(); 285 fPartitioning= IDocumentExtension3.DEFAULT_PARTITIONING; 286 fPositionCategory= TRACKED_PARTITION + hashCode(); 287 fPositionUpdater= new DefaultPositionUpdater(fPositionCategory); 288 } 289 290 296 public void setDocumentPartitioning(String partitioning) { 297 Assert.isNotNull(partitioning); 298 fPartitioning= partitioning; 299 } 300 301 305 public String getDocumentPartitioning() { 306 return fPartitioning; 307 } 308 309 317 public void setDamager(IPresentationDamager damager, String contentType) { 318 319 Assert.isNotNull(contentType); 320 321 if (fDamagers == null) 322 fDamagers= new HashMap (); 323 324 if (damager == null) 325 fDamagers.remove(contentType); 326 else 327 fDamagers.put(contentType, damager); 328 } 329 330 338 public void setRepairer(IPresentationRepairer repairer, String contentType) { 339 340 Assert.isNotNull(contentType); 341 342 if (fRepairers == null) 343 fRepairers= new HashMap (); 344 345 if (repairer == null) 346 fRepairers.remove(contentType); 347 else 348 fRepairers.put(contentType, repairer); 349 } 350 351 354 public void install(ITextViewer viewer) { 355 Assert.isNotNull(viewer); 356 357 fViewer= viewer; 358 fViewer.addTextInputListener(fInternalListener); 359 360 IDocument document= viewer.getDocument(); 361 if (document != null) 362 fInternalListener.inputDocumentChanged(null, document); 363 } 364 365 368 public void uninstall() { 369 fViewer.removeTextInputListener(fInternalListener); 370 371 fInternalListener.inputDocumentAboutToBeChanged(fViewer.getDocument(), null); 373 } 374 375 378 public IPresentationDamager getDamager(String contentType) { 379 380 if (fDamagers == null) 381 return null; 382 383 return (IPresentationDamager) fDamagers.get(contentType); 384 } 385 386 389 public IPresentationRepairer getRepairer(String contentType) { 390 391 if (fRepairers == null) 392 return null; 393 394 return (IPresentationRepairer) fRepairers.get(contentType); 395 } 396 397 402 protected void setDocumentToDamagers(IDocument document) { 403 if (fDamagers != null) { 404 Iterator e= fDamagers.values().iterator(); 405 while (e.hasNext()) { 406 IPresentationDamager damager= (IPresentationDamager) e.next(); 407 damager.setDocument(document); 408 } 409 } 410 } 411 412 417 protected void setDocumentToRepairers(IDocument document) { 418 if (fRepairers != null) { 419 Iterator e= fRepairers.values().iterator(); 420 while (e.hasNext()) { 421 IPresentationRepairer repairer= (IPresentationRepairer) e.next(); 422 repairer.setDocument(document); 423 } 424 } 425 } 426 427 438 protected TextPresentation createPresentation(IRegion damage, IDocument document) { 439 try { 440 if (fRepairers == null || fRepairers.isEmpty()) { 441 TextPresentation presentation= new TextPresentation(damage, 1); 442 presentation.setDefaultStyleRange(new StyleRange(damage.getOffset(), damage.getLength(), null, null)); 443 return presentation; 444 } 445 446 TextPresentation presentation= new TextPresentation(damage, 1000); 447 448 ITypedRegion[] partitioning= TextUtilities.computePartitioning(document, getDocumentPartitioning(), damage.getOffset(), damage.getLength(), false); 449 for (int i= 0; i < partitioning.length; i++) { 450 ITypedRegion r= partitioning[i]; 451 IPresentationRepairer repairer= getRepairer(r.getType()); 452 if (repairer != null) 453 repairer.createPresentation(presentation, r); 454 } 455 456 return presentation; 457 458 } catch (BadLocationException x) { 459 } 460 461 return null; 462 } 463 464 465 478 private IRegion getDamage(DocumentEvent e, boolean optimize) { 479 int length= e.getText() == null ? 0 : e.getText().length(); 480 481 if (fDamagers == null || fDamagers.isEmpty()) { 482 length= Math.max(e.getLength(), length); 483 length= Math.min(e.getDocument().getLength() - e.getOffset(), length); 484 return new Region(e.getOffset(), length); 485 } 486 487 boolean isDeletion= length == 0; 488 IRegion damage= null; 489 try { 490 int offset= e.getOffset(); 491 if (isDeletion) 492 offset= Math.max(0, offset - 1); 493 ITypedRegion partition= getPartition(e.getDocument(), offset); 494 IPresentationDamager damager= getDamager(partition.getType()); 495 if (damager == null) 496 return null; 497 498 IRegion r= damager.getDamageRegion(partition, e, fDocumentPartitioningChanged); 499 500 if (!fDocumentPartitioningChanged && optimize && !isDeletion) { 501 damage= r; 502 } else { 503 504 int damageEnd= getDamageEndOffset(e); 505 506 int parititionDamageEnd= -1; 507 if (fChangedDocumentPartitions != null) 508 parititionDamageEnd= fChangedDocumentPartitions.getOffset() + fChangedDocumentPartitions.getLength(); 509 510 int end= Math.max(damageEnd, parititionDamageEnd); 511 512 damage= end == -1 ? r : new Region(r.getOffset(), end - r.getOffset()); 513 } 514 515 } catch (BadLocationException x) { 516 } 517 518 return damage; 519 } 520 521 531 private int getDamageEndOffset(DocumentEvent e) throws BadLocationException { 532 533 IDocument d= e.getDocument(); 534 535 int length= 0; 536 if (e.getText() != null) { 537 length= e.getText().length(); 538 if (length > 0) 539 -- length; 540 } 541 542 ITypedRegion partition= getPartition(d, e.getOffset() + length); 543 int endOffset= partition.getOffset() + partition.getLength(); 544 if (endOffset == e.getOffset()) 545 return -1; 546 547 int end= fRememberedPosition == null ? -1 : fRememberedPosition.getOffset() + fRememberedPosition.getLength(); 548 if (endOffset < end && end < d.getLength()) 549 partition= getPartition(d, end); 550 551 IPresentationDamager damager= getDamager(partition.getType()); 552 if (damager == null) 553 return -1; 554 555 IRegion r= damager.getDamageRegion(partition, e, fDocumentPartitioningChanged); 556 557 return r.getOffset() + r.getLength(); 558 } 559 560 565 private void processDamage(IRegion damage, IDocument document) { 566 if (damage != null && damage.getLength() > 0) { 567 TextPresentation p= createPresentation(damage, document); 568 if (p != null) 569 applyTextRegionCollection(p); 570 } 571 } 572 573 579 private void applyTextRegionCollection(TextPresentation presentation) { 580 fViewer.changeTextPresentation(presentation, false); 581 } 582 583 592 private ITypedRegion getPartition(IDocument document, int offset) throws BadLocationException { 593 return TextUtilities.getPartition(document, getDocumentPartitioning(), offset, false); 594 } 595 } 596 | Popular Tags |