comparison dwtx/jface/text/source/AnnotationPainter.d @ 162:1a5b8f8129df

...
author Frank Benoit <benoit@tionex.de>
date Mon, 08 Sep 2008 00:51:37 +0200
parents 7926b636c282
children
comparison
equal deleted inserted replaced
161:f8d52b926852 162:1a5b8f8129df
72 import dwtx.jface.text.source.ISourceViewerExtension4; // packageimport 72 import dwtx.jface.text.source.ISourceViewerExtension4; // packageimport
73 import dwtx.jface.text.source.IAnnotationHoverExtension2; // packageimport 73 import dwtx.jface.text.source.IAnnotationHoverExtension2; // packageimport
74 import dwtx.jface.text.source.OverviewRuler; // packageimport 74 import dwtx.jface.text.source.OverviewRuler; // packageimport
75 import dwtx.jface.text.source.OverviewRulerHoverManager; // packageimport 75 import dwtx.jface.text.source.OverviewRulerHoverManager; // packageimport
76 76
77
78 import dwt.dwthelper.utils; 77 import dwt.dwthelper.utils;
79
80
81 import dwtx.dwtxhelper.Collection; 78 import dwtx.dwtxhelper.Collection;
82 79 import tango.text.convert.Format;
83 80 import tango.io.Stdout;
84
85
86
87
88
89
90
91 81
92 import dwt.DWT; 82 import dwt.DWT;
93 import dwt.DWTException; 83 import dwt.DWTException;
94 import dwt.custom.StyleRange; 84 import dwt.custom.StyleRange;
95 import dwt.custom.StyledText; 85 import dwt.custom.StyledText;
220 peaks= 1; 210 peaks= 1;
221 211
222 int leftX= left.x; 212 int leftX= left.x;
223 213
224 // compute (number of point) * 2 214 // compute (number of point) * 2
225 int length= ((2 * peaks) + 1) * 2; 215 int length_= ((2 * peaks) + 1) * 2;
226 if (length < 0) 216 if (length_ < 0)
227 return new int[0]; 217 return new int[0];
228 218
229 int[] coordinates= new int[length]; 219 int[] coordinates= new int[length_];
230 220
231 // cache peeks' y-coordinates 221 // cache peeks' y-coordinates
232 int top= left.y + Math.min(baseline + 1, lineHeight - HEIGHT - 1); 222 int top= left.y + Math.min(baseline + 1, lineHeight - HEIGHT - 1);
233 int bottom= top + HEIGHT; 223 int bottom= top + HEIGHT;
234 224
240 coordinates[index+2]= coordinates[index] + WIDTH/2; 230 coordinates[index+2]= coordinates[index] + WIDTH/2;
241 coordinates[index+3]= top; 231 coordinates[index+3]= top;
242 } 232 }
243 233
244 // the last down flank is missing 234 // the last down flank is missing
245 coordinates[length-2]= Math.min(Math.max(0, right.x - 1), left.x + (WIDTH * peaks)); 235 coordinates[length_-2]= Math.min(Math.max(0, right.x - 1), left.x + (WIDTH * peaks));
246 coordinates[length-1]= bottom; 236 coordinates[length_-1]= bottom;
247 237
248 return coordinates; 238 return coordinates;
249 } 239 }
250 } 240 }
251 241
340 330
341 /** 331 /**
342 * Implementation of <code>IRegion</code> that can be reused 332 * Implementation of <code>IRegion</code> that can be reused
343 * by setting the offset and the length. 333 * by setting the offset and the length.
344 */ 334 */
345 private static class ReusableRegion : Position , IRegion {} 335 private static class ReusableRegion : Position , IRegion {
336 public override int getOffset(){
337 return super.getOffset();
338 }
339 public override int getLength(){
340 return super.getLength();
341 }
342 }
346 343
347 /** 344 /**
348 * Tells whether this class is in debug mode. 345 * Tells whether this class is in debug mode.
349 * @since 3.0 346 * @since 3.0
350 */ 347 */
360 357
361 /** 358 /**
362 * The squiggly painter strategy. 359 * The squiggly painter strategy.
363 * @since 3.0 360 * @since 3.0
364 */ 361 */
365 private static const IDrawingStrategy SQUIGGLES_STRATEGY= new SquigglesStrategy(); 362 private static IDrawingStrategy SQUIGGLES_STRATEGY_;
363 private static IDrawingStrategy SQUIGGLES_STRATEGY(){
364 if( SQUIGGLES_STRATEGY_ is null ){
365 synchronized( AnnotationPainter.classinfo ){
366 if( SQUIGGLES_STRATEGY_ is null ){
367 SQUIGGLES_STRATEGY_ = new SquigglesStrategy();
368 }
369 }
370 }
371 return SQUIGGLES_STRATEGY_;
372 }
373
366 374
367 /** 375 /**
368 * This strategy is used to mark the <code>null</code> value in the chache 376 * This strategy is used to mark the <code>null</code> value in the chache
369 * maps. 377 * maps.
370 * 378 *
371 * @since 3.4 379 * @since 3.4
372 */ 380 */
373 private static const IDrawingStrategy NULL_STRATEGY= new NullStrategy(); 381 private static IDrawingStrategy NULL_STRATEGY_;
382 private static IDrawingStrategy NULL_STRATEGY(){
383 if( NULL_STRATEGY_ is null ){
384 synchronized( AnnotationPainter.classinfo ){
385 if( NULL_STRATEGY_ is null ){
386 NULL_STRATEGY_= new NullStrategy();
387 }
388 }
389 }
390 return NULL_STRATEGY_;
391 }
374 /** 392 /**
375 * The squiggles painter id. 393 * The squiggles painter id.
376 * @since 3.0 394 * @since 3.0
377 */ 395 */
378 private static const Object SQUIGGLES= new Object(); 396 private static Object SQUIGGLES_;
397 private static Object SQUIGGLES(){
398 if( SQUIGGLES_ is null ){
399 synchronized( AnnotationPainter.classinfo ){
400 if( SQUIGGLES_ is null ){
401 SQUIGGLES_= new Object();
402 }
403 }
404 }
405 return SQUIGGLES_;
406 }
379 /** 407 /**
380 * The squiggly painter strategy. 408 * The squiggly painter strategy.
381 * 409 *
382 * @since 3.4 410 * @since 3.4
383 */ 411 */
384 private static const ITextStyleStrategy HIGHLIGHTING_STRATEGY= new HighlightingStrategy(); 412 private static ITextStyleStrategy HIGHLIGHTING_STRATEGY_;
413 private static ITextStyleStrategy HIGHLIGHTING_STRATEGY(){
414 if( HIGHLIGHTING_STRATEGY_ is null ){
415 synchronized( AnnotationPainter.classinfo ){
416 if( HIGHLIGHTING_STRATEGY_ is null ){
417 HIGHLIGHTING_STRATEGY_= new HighlightingStrategy();
418 }
419 }
420 }
421 return HIGHLIGHTING_STRATEGY_;
422 }
385 423
386 /** 424 /**
387 * The highlighting text style strategy id. 425 * The highlighting text style strategy id.
388 * 426 *
389 * @since 3.4 427 * @since 3.4
390 */ 428 */
391 private static const Object HIGHLIGHTING= new Object(); 429 private static Object HIGHLIGHTING_;
430 private static Object HIGHLIGHTING(){
431 if( HIGHLIGHTING_ is null ){
432 synchronized( AnnotationPainter.classinfo ){
433 if( HIGHLIGHTING_ is null ){
434 HIGHLIGHTING_= new Object();
435 }
436 }
437 }
438 return HIGHLIGHTING_;
439 }
392 440
393 /** 441 /**
394 * The presentation information (decoration) for an annotation. Each such 442 * The presentation information (decoration) for an annotation. Each such
395 * object represents one decoration drawn on the text area, such as squiggly lines 443 * object represents one decoration drawn on the text area, such as squiggly lines
396 * and underlines. 444 * and underlines.
429 private IAnnotationAccess fAnnotationAccess; 477 private IAnnotationAccess fAnnotationAccess;
430 /** 478 /**
431 * The map with decorations 479 * The map with decorations
432 * @since 3.0 480 * @since 3.0
433 */ 481 */
434 private Map fDecorationsMap= new HashMap(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767 482 private Map fDecorationsMap; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767
435 /** 483 /**
436 * The map with of highlighted decorations. 484 * The map with of highlighted decorations.
437 * @since 3.0 485 * @since 3.0
438 */ 486 */
439 private Map fHighlightedDecorationsMap= new HashMap(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767 487 private Map fHighlightedDecorationsMap;
440 /** 488 /**
441 * Mutex for highlighted decorations map. 489 * Mutex for highlighted decorations map.
442 * @since 3.0 490 * @since 3.0
443 */ 491 */
444 private Object fDecorationMapLock= new Object(); 492 private Object fDecorationMapLock;
445 /** 493 /**
446 * Mutex for for decorations map. 494 * Mutex for for decorations map.
447 * @since 3.0 495 * @since 3.0
448 */ 496 */
449 private Object fHighlightedDecorationsMapLock= new Object(); 497 private Object fHighlightedDecorationsMapLock;
450 /** 498 /**
451 * Maps an annotation type to its registered color. 499 * Maps an annotation type to its registered color.
452 * 500 *
453 * @see #setAnnotationTypeColor(Object, Color) 501 * @see #setAnnotationTypeColor(Object, Color)
454 */ 502 */
455 private Map fAnnotationType2Color= new HashMap(); 503 private Map fAnnotationType2Color;
456 504
457 /** 505 /**
458 * Cache that maps the annotation type to its color. 506 * Cache that maps the annotation type to its color.
459 * @since 3.4 507 * @since 3.4
460 */ 508 */
461 private Map fCachedAnnotationType2Color= new HashMap(); 509 private Map fCachedAnnotationType2Color;
462 /** 510 /**
463 * The range in which the current highlight annotations can be found. 511 * The range in which the current highlight annotations can be found.
464 * @since 3.0 512 * @since 3.0
465 */ 513 */
466 private Position fCurrentHighlightAnnotationRange= null; 514 private Position fCurrentHighlightAnnotationRange= null;
495 * Maps annotation types to painting strategy identifiers. 543 * Maps annotation types to painting strategy identifiers.
496 * 544 *
497 * @see #addAnnotationType(Object, Object) 545 * @see #addAnnotationType(Object, Object)
498 * @since 3.0 546 * @since 3.0
499 */ 547 */
500 private Map fAnnotationType2PaintingStrategyId= new HashMap(); 548 private Map fAnnotationType2PaintingStrategyId;
501 /** 549 /**
502 * Maps annotation types to painting strategy identifiers. 550 * Maps annotation types to painting strategy identifiers.
503 * @since 3.4 551 * @since 3.4
504 */ 552 */
505 private Map fCachedAnnotationType2PaintingStrategy= new HashMap(); 553 private Map fCachedAnnotationType2PaintingStrategy;
506 554
507 /** 555 /**
508 * Maps painting strategy identifiers to painting strategies. 556 * Maps painting strategy identifiers to painting strategies.
509 * 557 *
510 * @since 3.0 558 * @since 3.0
511 */ 559 */
512 private Map fPaintingStrategyId2PaintingStrategy= new HashMap(); 560 private Map fPaintingStrategyId2PaintingStrategy;
513 561
514 /** 562 /**
515 * Reuse this region for performance reasons. 563 * Reuse this region for performance reasons.
516 * @since 3.3 564 * @since 3.3
517 */ 565 */
518 private ReusableRegion fReusableRegion= new ReusableRegion(); 566 private ReusableRegion fReusableRegion;
519 567
520 /** 568 /**
521 * Creates a new annotation painter for the given source viewer and with the 569 * Creates a new annotation painter for the given source viewer and with the
522 * given annotation access. The painter is not initialized, i.e. no 570 * given annotation access. The painter is not initialized, i.e. no
523 * annotation types are configured to be painted. 571 * annotation types are configured to be painted.
524 * 572 *
525 * @param sourceViewer the source viewer for this painter 573 * @param sourceViewer the source viewer for this painter
526 * @param access the annotation access for this painter 574 * @param access the annotation access for this painter
527 */ 575 */
528 public this(ISourceViewer sourceViewer, IAnnotationAccess access) { 576 public this(ISourceViewer sourceViewer, IAnnotationAccess access) {
577 fDecorationsMap= new HashMap(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767
578 fHighlightedDecorationsMap= new HashMap(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767
579 fDecorationMapLock= new Object();
580 fHighlightedDecorationsMapLock= new Object();
581 fAnnotationType2Color= new HashMap();
582 fCachedAnnotationType2Color= new HashMap();
583 fReusableRegion= new ReusableRegion();
584 fAnnotationType2PaintingStrategyId= new HashMap();
585 fCachedAnnotationType2PaintingStrategy= new HashMap();
586 fPaintingStrategyId2PaintingStrategy= new HashMap();
587
529 fSourceViewer= sourceViewer; 588 fSourceViewer= sourceViewer;
530 fAnnotationAccess= access; 589 fAnnotationAccess= access;
531 fTextWidget= sourceViewer.getTextWidget(); 590 fTextWidget= sourceViewer.getTextWidget();
532 591
533 // default drawing strategies: squiggles were the only decoration style before version 3.0 592 // default drawing strategies: squiggles were the only decoration style before version 3.0
534 fPaintingStrategyId2PaintingStrategy.put(SQUIGGLES, SQUIGGLES_STRATEGY); 593 fPaintingStrategyId2PaintingStrategy.put(SQUIGGLES, cast(Object)SQUIGGLES_STRATEGY);
535 fPaintingStrategyId2PaintingStrategy.put(HIGHLIGHTING, HIGHLIGHTING_STRATEGY); 594 fPaintingStrategyId2PaintingStrategy.put(HIGHLIGHTING, cast(Object)HIGHLIGHTING_STRATEGY);
536 } 595 }
537 596
538 /** 597 /**
539 * Returns whether this painter has to draw any squiggles. 598 * Returns whether this painter has to draw any squiggles.
540 * 599 *
907 966
908 Object paintingStrategy= getPaintingStrategy(type); 967 Object paintingStrategy= getPaintingStrategy(type);
909 if (paintingStrategy is null || cast(NullStrategy)paintingStrategy ) 968 if (paintingStrategy is null || cast(NullStrategy)paintingStrategy )
910 return null; 969 return null;
911 970
912 Color color= getColor(type); 971 Color color= getColor(stringcast(type));
913 if (color is null) 972 if (color is null)
914 return null; 973 return null;
915 974
916 Position position= fModel.getPosition(annotation); 975 Position position= fModel.getPosition(annotation);
917 if (position is null || position.isDeleted()) 976 if (position is null || position.isDeleted())
952 return strategy; 1011 return strategy;
953 } 1012 }
954 1013
955 if ( cast(IAnnotationAccessExtension)fAnnotationAccess ) { 1014 if ( cast(IAnnotationAccessExtension)fAnnotationAccess ) {
956 IAnnotationAccessExtension ext = cast(IAnnotationAccessExtension) fAnnotationAccess; 1015 IAnnotationAccessExtension ext = cast(IAnnotationAccessExtension) fAnnotationAccess;
957 Object[] sts = ext.getSupertypes(type); 1016 Object[] sts = ext.getSupertypes(stringcast(type));
958 for (int i= 0; i < sts.length; i++) { 1017 for (int i= 0; i < sts.length; i++) {
959 strategy= fPaintingStrategyId2PaintingStrategy.get(fAnnotationType2PaintingStrategyId.get(sts[i])); 1018 strategy= fPaintingStrategyId2PaintingStrategy.get(fAnnotationType2PaintingStrategyId.get(sts[i]));
960 if (strategy !is null) { 1019 if (strategy !is null) {
961 fCachedAnnotationType2PaintingStrategy.put(type, strategy); 1020 fCachedAnnotationType2PaintingStrategy.put(type, strategy);
962 return strategy; 1021 return strategy;
963 } 1022 }
964 } 1023 }
965 } 1024 }
966 1025
967 fCachedAnnotationType2PaintingStrategy.put(type, NULL_STRATEGY); 1026 fCachedAnnotationType2PaintingStrategy.put(type, cast(Object)NULL_STRATEGY);
968 return null; 1027 return null;
969 1028
970 } 1029 }
971 1030
972 /** 1031 /**
1030 if (r is null) 1089 if (r is null)
1031 return; 1090 return;
1032 1091
1033 if ( cast(ITextViewerExtension2)fSourceViewer ) { 1092 if ( cast(ITextViewerExtension2)fSourceViewer ) {
1034 if (DEBUG) 1093 if (DEBUG)
1035 System.out_.println("AP: invalidating offset: " + r.getOffset() + ", length= " + r.getLength()); //$NON-NLS-1$ //$NON-NLS-2$ 1094 System.out_.println(Format("AP: invalidating offset: {}, length= {}", r.getOffset(), r.getLength())); //$NON-NLS-1$ //$NON-NLS-2$
1036 1095
1037 (cast(ITextViewerExtension2)fSourceViewer).invalidateTextPresentation(r.getOffset(), r.getLength()); 1096 (cast(ITextViewerExtension2)fSourceViewer).invalidateTextPresentation(r.getOffset(), r.getLength());
1038 1097
1039 } else { 1098 } else {
1040 fSourceViewer.invalidateTextPresentation(); 1099 fSourceViewer.invalidateTextPresentation();
1056 } 1115 }
1057 1116
1058 IRegion region= tp.getExtent(); 1117 IRegion region= tp.getExtent();
1059 1118
1060 if (DEBUG) 1119 if (DEBUG)
1061 System.out_.println("AP: applying text presentation offset: " + region.getOffset() + ", length= " + region.getLength()); //$NON-NLS-1$ //$NON-NLS-2$ 1120 System.out_.println(Format("AP: applying text presentation offset: {}, length= {}", region.getOffset(), region.getLength())); //$NON-NLS-1$ //$NON-NLS-2$
1062 1121
1063 for (int layer= 0, maxLayer= 1; layer < maxLayer; layer++) { 1122 for (int layer= 0, maxLayer= 1; layer < maxLayer; layer++) {
1064 1123
1065 for (Iterator iter= decorations.iterator(); iter.hasNext();) { 1124 for (Iterator iter= decorations.iterator(); iter.hasNext();) {
1066 Map.Entry entry= cast(Map.Entry)iter.next(); 1125 Map.Entry entry= cast(Map.Entry)iter.next();
1144 // XXX: posting here is a problem for annotations that are being 1203 // XXX: posting here is a problem for annotations that are being
1145 // removed and the positions of which are not updated to document 1204 // removed and the positions of which are not updated to document
1146 // changes any more. If the document gets modified between 1205 // changes any more. If the document gets modified between
1147 // now and running the posted runnable, the position information 1206 // now and running the posted runnable, the position information
1148 // is not accurate any longer. 1207 // is not accurate any longer.
1149 textWidgetDisplay.asyncExec( dgRunnable( (Event event_){ 1208 textWidgetDisplay.asyncExec( dgRunnable( (AnnotationModelEvent event_){
1150 if (fTextWidget !is null && !fTextWidget.isDisposed()) 1209 if (fTextWidget !is null && !fTextWidget.isDisposed())
1151 updatePainting(event_); 1210 updatePainting(event_);
1152 }, event )); 1211 }, event ));
1153 } 1212 }
1154 } 1213 }
1225 */ 1284 */
1226 public void addDrawingStrategy(Object id, IDrawingStrategy strategy) { 1285 public void addDrawingStrategy(Object id, IDrawingStrategy strategy) {
1227 // don't permit null as null is used to signal that an annotation type is not 1286 // don't permit null as null is used to signal that an annotation type is not
1228 // registered with a specific strategy, and that its annotation hierarchy should be searched 1287 // registered with a specific strategy, and that its annotation hierarchy should be searched
1229 if (id is null) 1288 if (id is null)
1230 throw new IllegalArgumentException(); 1289 throw new IllegalArgumentException(null);
1231 fPaintingStrategyId2PaintingStrategy.put(id, strategy); 1290 fPaintingStrategyId2PaintingStrategy.put(id, cast(Object)strategy);
1232 fCachedAnnotationType2PaintingStrategy.clear(); 1291 fCachedAnnotationType2PaintingStrategy.clear();
1233 } 1292 }
1234 1293
1235 /** 1294 /**
1236 * Registers a new drawing strategy under the given ID. If there is already 1295 * Registers a new drawing strategy under the given ID. If there is already
1247 */ 1306 */
1248 public void addTextStyleStrategy(Object id, ITextStyleStrategy strategy) { 1307 public void addTextStyleStrategy(Object id, ITextStyleStrategy strategy) {
1249 // don't permit null as null is used to signal that an annotation type is not 1308 // don't permit null as null is used to signal that an annotation type is not
1250 // registered with a specific strategy, and that its annotation hierarchy should be searched 1309 // registered with a specific strategy, and that its annotation hierarchy should be searched
1251 if (id is null) 1310 if (id is null)
1252 throw new IllegalArgumentException(); 1311 throw new IllegalArgumentException(null);
1253 fPaintingStrategyId2PaintingStrategy.put(id, strategy); 1312 fPaintingStrategyId2PaintingStrategy.put(id, cast(Object)strategy);
1254 fCachedAnnotationType2PaintingStrategy.clear(); 1313 fCachedAnnotationType2PaintingStrategy.clear();
1255 } 1314 }
1256 1315
1257 /** 1316 /**
1258 * Adds the given annotation type to the list of annotation types whose 1317 * Adds the given annotation type to the list of annotation types whose
1448 // prune any annotation that is not drawable or does not need drawing 1507 // prune any annotation that is not drawable or does not need drawing
1449 if (!(a.isMarkedDeleted() || skip(a) || !pp.fPosition.overlapsWith(vOffset, vLength))) { 1508 if (!(a.isMarkedDeleted() || skip(a) || !pp.fPosition.overlapsWith(vOffset, vLength))) {
1450 // ensure sized appropriately 1509 // ensure sized appropriately
1451 for (int i= toBeDrawn.size(); i <= pp.fLayer; i++) 1510 for (int i= toBeDrawn.size(); i <= pp.fLayer; i++)
1452 toBeDrawn.add(new LinkedList()); 1511 toBeDrawn.add(new LinkedList());
1453 (cast(List) toBeDrawn.get(pp.fLayer)).add(entry); 1512 (cast(List) toBeDrawn.get(pp.fLayer)).add(cast(Object)entry);
1454 } 1513 }
1455 } 1514 }
1456 IDocument document= fSourceViewer.getDocument(); 1515 IDocument document= fSourceViewer.getDocument();
1457 for (Iterator it= toBeDrawn.iterator(); it.hasNext();) { 1516 for (Iterator it= toBeDrawn.iterator(); it.hasNext();) {
1458 List layer= cast(List) it.next(); 1517 List layer= cast(List) it.next();