Bug 531957 - [CodeMining] Line content annotation doesn't take the
expected space

Change-Id: I62d89d7ba74a0409cb13dbce4844e8e14a6ee4ea
Signed-off-by: angelozerr <angelo.zerr@gmail.com>
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java
index 42be750..dbbe395 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java
@@ -15,8 +15,10 @@
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.GlyphMetrics;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 
+import org.eclipse.jface.text.Position;
 import org.eclipse.jface.text.source.Annotation;
 import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
 
@@ -160,36 +162,33 @@
 			int x= bounds.x;
 			int y= bounds.y;
 
+			// Get size of the character where GlyphMetrics width is added
+			String s= textWidget.getText(offset, offset);
+			Point charBounds= gc.stringExtent(s);
+			int charWidth= charBounds.x;
+
 			// Draw the line content annotation
 			annotation.draw(gc, textWidget, offset, length, color, x, y);
 			int width= annotation.getWidth();
 			if (width != 0) {
+				// FIXME: remove this code when we need not redraw the character (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=531769)
+				// START TO REMOVE
+				annotation.setRedrawnCharacterWidth(charWidth);
+				// END TO REMOVE
+
 				// Annotation takes place, add GlyphMetrics width to the style
-				GlyphMetrics metrics= style != null ? style.metrics : null;
-				if (metrics == null || metrics.width != width) {
-					// The annotation drawn width is not the same than metrics width, update it.
-					if (metrics == null) {
-						metrics= new GlyphMetrics(0, 0, width);
-					} else {
-						metrics.width= width;
-					}
-					if (style == null) {
-						style= new StyleRange();
-						style.start= offset;
-						style.length= 1;
-						style.background= textWidget.getBackground();
-						style.foreground= textWidget.getForeground();
-					}
-					style.metrics= metrics;
-					textWidget.setStyleRange(style);
+				StyleRange newStyle= updateStyle(annotation, style);
+				if (newStyle != null) {
+					textWidget.setStyleRange(newStyle);
 					return;
 				}
+
+				// FIXME: remove this code when we need not redraw the character (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=531769)
+				// START TO REMOVE
 				// The inline annotation replaces one character by taking a place width
 				// GlyphMetrics
 				// Here we need to redraw this first character because GlyphMetrics clip this
 				// character.
-				String s= textWidget.getText(offset, offset);
-				int charWidth= gc.stringExtent(s).x;
 				int charX= x + bounds.width - charWidth;
 				int charY= y;
 				if (style != null) {
@@ -199,13 +198,52 @@
 					}
 					if (style.foreground != null) {
 						gc.setForeground(style.foreground);
+					} else {
+						gc.setForeground(textWidget.getForeground());
 					}
 					gc.setFont(annotation.getFont(style.fontStyle));
 				}
 				gc.drawString(s, charX, charY, true);
+				// END TO REMOVE
 			}
 		} else {
 			textWidget.redrawRange(offset, length, true);
 		}
 	}
+
+	/**
+	 * Returns the style to apply with GlyphMetrics width only if needed.
+	 *
+	 * @param annotation the line content annotation
+	 * @param style the current style and null otherwise.
+	 * @return the style to apply with GlyphMetrics width only if needed.
+	 */
+	static StyleRange updateStyle(LineContentAnnotation annotation, StyleRange style) {
+		int width= annotation.getWidth();
+		if (width == 0) {
+			return null;
+		}
+		int fullWidth= width + annotation.getRedrawnCharacterWidth();
+		if (style == null) {
+			style= new StyleRange();
+			Position position= annotation.getPosition();
+			style.start= position.getOffset();
+			style.length= 1;
+		}
+		GlyphMetrics metrics= style.metrics;
+		if (!annotation.isMarkedDeleted()) {
+			if (metrics == null) {
+				metrics= new GlyphMetrics(0, 0, fullWidth);
+			} else {
+				if (metrics.width == fullWidth) {
+					return null;
+				}
+				metrics.width= fullWidth;
+			}
+		} else {
+			metrics= null;
+		}
+		style.metrics= metrics;
+		return style;
+	}
 }
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java
index 7ab62bc..a590467 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java
@@ -16,8 +16,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.function.Consumer;
 
 import org.eclipse.swt.SWT;
@@ -53,11 +53,11 @@
 import org.eclipse.jface.text.TextPresentation;
 import org.eclipse.jface.text.source.Annotation;
 import org.eclipse.jface.text.source.AnnotationPainter;
+import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
 import org.eclipse.jface.text.source.IAnnotationModel;
 import org.eclipse.jface.text.source.IAnnotationModelExtension;
 import org.eclipse.jface.text.source.IAnnotationModelExtension2;
 import org.eclipse.jface.text.source.ISourceViewer;
-import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
 
 /**
  * Support to draw inlined annotations:
@@ -106,18 +106,9 @@
 					.forEachRemaining(annotation -> {
 						if (annotation instanceof LineContentAnnotation) {
 							LineContentAnnotation ann= (LineContentAnnotation) annotation;
-							Position position= ann.getPosition();
-							if (position != null) {
-								int width= ann.getWidth();
-								if (width != 0) {
-									StyleRange s= new StyleRange();
-									s.start= position.getOffset();
-									s.length= 1;
-									s.metrics= ann.isMarkedDeleted()
-											? null
-											: new GlyphMetrics(0, 0, width);
-									textPresentation.mergeStyleRange(s);
-								}
+							StyleRange style= InlinedAnnotationDrawingStrategy.updateStyle(ann, null);
+							if (style != null) {
+								textPresentation.mergeStyleRange(style);
 							}
 						}
 					});
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java
index 7b136c7..dacc71b 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java
@@ -30,6 +30,8 @@
 	 */

 	private int width;

 

+	private int redrawnCharacterWidth;

+

 	/**

 	 * Line content annotation constructor.

 	 *

@@ -78,4 +80,12 @@
 		super.draw(gc, textWidget, offset, length, color, x, y);

 		return gc.stringExtent(getText()).x + 2 * gc.getFontMetrics().getAverageCharWidth();

 	}

+

+	int getRedrawnCharacterWidth() {

+		return redrawnCharacterWidth;

+	}

+

+	void setRedrawnCharacterWidth(int redrawnCharacterWidth) {

+		this.redrawnCharacterWidth= redrawnCharacterWidth;

+	}

 }