Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jface.internal.text.codemining.CodeMiningLineHeaderAnnotation;

import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;

Expand Down Expand Up @@ -99,7 +100,7 @@ private Font getAnnotationFont(StyledText textWidget) {
if (annotationFont == null) {
annotationFont = createInlineAnnotationFont(textWidget);
textWidget.setData(INLINE_ANNOTATION_FONT, annotationFont);
textWidget.addDisposeListener(e -> ((Font)textWidget.getData(INLINE_ANNOTATION_FONT)).dispose());
textWidget.addDisposeListener(e -> ((Font) textWidget.getData(INLINE_ANNOTATION_FONT)).dispose());
}
return annotationFont;
}
Expand Down Expand Up @@ -154,7 +155,8 @@ public static void draw(AbstractInlinedAnnotation annotation, GC gc, StyledText
private static void draw(LineHeaderAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
Color color) {
int line= textWidget.getLineAtOffset(offset);
if (isDeleted(annotation)) {
int charCount= textWidget.getCharCount();
if (isDeleted(annotation, charCount)) {
// When annotation is deleted, update metrics to null to remove extra spaces of the line header annotation.
if (textWidget.getLineVerticalIndent(line) > 0)
textWidget.setLineVerticalIndent(line, 0);
Expand All @@ -180,9 +182,16 @@ private static void draw(LineHeaderAnnotation annotation, GC gc, StyledText text
textWidget.setLineVerticalIndent(line, 0);
}
// Compute the location of the annotation
Rectangle bounds= textWidget.getTextBounds(offset, offset);
int x= bounds.x;
int y= bounds.y;
int x, y;
if (offset < charCount) {
Rectangle bounds= textWidget.getTextBounds(offset, offset);
x= bounds.x;
y= bounds.y;
} else {
Point locAtOff= textWidget.getLocationAtOffset(offset);
x= locAtOff.x;
y= locAtOff.y - height;
}
// Draw the line header annotation
gc.setBackground(textWidget.getBackground());
annotation.setLocation(x, y);
Expand All @@ -193,7 +202,16 @@ private static void draw(LineHeaderAnnotation annotation, GC gc, StyledText text
Rectangle client= textWidget.getClientArea();
textWidget.redraw(0, bounds.y, client.width, bounds.height, false);
} else {
textWidget.redrawRange(offset, length, true);
if (offset >= charCount) {
if (charCount > 0) {
textWidget.redrawRange(charCount - 1, 1, true);
} else {
Rectangle client= textWidget.getClientArea();
textWidget.redraw(0, 0, client.width, client.height, false);
}
} else {
textWidget.redrawRange(offset, length, true);
}
}
}

Expand All @@ -212,7 +230,11 @@ private static void draw(LineContentAnnotation annotation, GC gc, StyledText tex
Color color) {
if (annotation instanceof CodeMiningLineContentAnnotation a) {
if (a.isAfterPosition()) {
drawAsLeftOf1stCharacter(annotation, gc, textWidget, widgetOffset, length, color);
if (widgetOffset < textWidget.getCharCount()) {
drawAsLeftOf1stCharacter(annotation, gc, textWidget, widgetOffset, length, color);
} else {
drawAtEndOfDocumentInFirstColumn(annotation, gc, textWidget, widgetOffset, length, color);
}
return;
}
}
Expand All @@ -226,7 +248,7 @@ private static void draw(LineContentAnnotation annotation, GC gc, StyledText tex
}

private static void drawAfterLine(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) {
if (isDeleted(annotation)) {
if (isDeleted(annotation, textWidget.getCharCount())) {
return;
}
if (gc != null) {
Expand All @@ -247,14 +269,43 @@ private static void drawAfterLine(LineContentAnnotation annotation, GC gc, Style
}
}

private static void drawAtEndOfDocumentInFirstColumn(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) {
if (isDeleted(annotation, textWidget.getCharCount())) {
return;
}
if (gc != null) {
Point locAtOff= textWidget.getLocationAtOffset(widgetOffset);
int x= locAtOff.x;
int y= locAtOff.y;
annotation.setLocation(x, y);
annotation.draw(gc, textWidget, widgetOffset, length, color, x, y);
int width= annotation.getWidth();
if (width != 0) {
if (!gc.getClipping().contains(x, y)) {
Rectangle client= textWidget.getClientArea();
int height= textWidget.getLineHeight();
textWidget.redraw(x, y, client.width, height, false);
}
}
} else {
int charCount= textWidget.getCharCount();
if (charCount > 0) {
textWidget.redrawRange(charCount - 1, 1, true);
} else {
Rectangle client= textWidget.getClientArea();
textWidget.redraw(0, 0, client.width, client.height, false);
}
}
}

protected static void drawAsLeftOf1stCharacter(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) {
StyleRange style= null;
try {
style= textWidget.getStyleRangeAtOffset(widgetOffset);
} catch (Exception e) {
return;
}
if (isDeleted(annotation)) {
if (isDeleted(annotation, textWidget.getCharCount())) {
// When annotation is deleted, update metrics to null to remove extra spaces of the line content annotation.
if (style != null && style.metrics != null) {
style.metrics= null;
Expand Down Expand Up @@ -369,7 +420,7 @@ protected static void drawAsRightOfPreviousCharacter(LineContentAnnotation annot
} catch (Exception e) {
return;
}
if (isDeleted(annotation)) {
if (isDeleted(annotation, textWidget.getCharCount())) {
// When annotation is deleted, update metrics to null to remove extra spaces of the line content annotation.
if (style != null && style.metrics != null) {
style.metrics= null;
Expand Down Expand Up @@ -449,7 +500,17 @@ protected static void drawAsRightOfPreviousCharacter(LineContentAnnotation annot
* @param annotation the inlined annotation to check
* @return <code>true</code> if inlined annotation is deleted and <code>false</code> otherwise.
*/
private static boolean isDeleted(AbstractInlinedAnnotation annotation) {
return annotation.isMarkedDeleted() || annotation.getPosition().isDeleted() || annotation.getPosition().getLength() == 0;
private static boolean isDeleted(AbstractInlinedAnnotation annotation,int maxOffset) {
if (annotation.isMarkedDeleted()) {
return true;
}
Position pos= annotation.getPosition();
if (pos.isDeleted()) {
return true;
}
if (pos.getLength() == 0 && pos.getOffset() < maxOffset) {
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
Expand Down Expand Up @@ -250,6 +251,71 @@ protected boolean condition() {
}.waitForCondition(fViewer.getTextWidget().getDisplay(), 1000));
}

@Test
public void testLineHeaderCodeMiningAtEndOfDocumentWithEmptyLine() throws Exception {
String source= "first\nsecond\n";
fViewer.getDocument().set(source);
fViewer.setCodeMiningProviders(new ICodeMiningProvider[] { new ICodeMiningProvider() {
@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) {
List<ICodeMining> minings= new ArrayList<>();
try {
minings.add(new LineHeaderCodeMining(new Position(source.length(), 0), this, null) {
@Override
public String getLabel() {
return "multiline first line\nmultiline second line\nmultiline third line\nmultiline fourth line";
}
});
} catch (BadLocationException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture(minings);
}

@Override
public void dispose() {
}
} });
Assert.assertTrue("Code mining is not visible at end of document", new DisplayHelper() {
@Override
protected boolean condition() {
try {
return hasCodeMiningPrintedAfterTextOnLine(fViewer, 2);
} catch (BadLocationException e) {
e.printStackTrace();
return false;
}
}
}.waitForCondition(fViewer.getTextWidget().getDisplay(), 10_000));
}

@Test
public void testCodeMiningAtEndOfDocumentWithEmptyLine() throws Exception {
String source= "first\nsecond\n";
fViewer.getDocument().set(source);
fViewer.setCodeMiningProviders(new ICodeMiningProvider[] { new ICodeMiningProvider() {
@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) {
return CompletableFuture.completedFuture(Collections.singletonList(new StaticContentLineCodeMining(new Position(source.length(), 0), true, "mining", this)));
}

@Override
public void dispose() {
}
} });
Assert.assertTrue("Code mining is not visible at end of document", new DisplayHelper() {
@Override
protected boolean condition() {
try {
return hasCodeMiningPrintedAfterTextOnLine(fViewer, 2);
} catch (BadLocationException e) {
e.printStackTrace();
return false;
}
}
}.waitForCondition(fViewer.getTextWidget().getDisplay(), 10_000));
}

@Test
public void testCodeMiningEndOfLine() {
fViewer.getDocument().set("a\n");
Expand Down Expand Up @@ -389,7 +455,18 @@ private static boolean hasCodeMiningPrintedAfterTextOnLine(ITextViewer viewer, i
if (lineLength < 0) {
lineLength= 0;
}
Rectangle secondLineBounds= widget.getTextBounds(document.getLineOffset(line), document.getLineOffset(line) + lineLength);
Rectangle secondLineBounds= null;
int lineOffset= document.getLineOffset(line);
if (lineOffset >= document.getLength()) {
int off= document.getLength() - 1;
secondLineBounds= widget.getTextBounds(off, off + lineLength);
Point l= widget.getLocationAtOffset(lineOffset);
int lineVerticalIndent= widget.getLineVerticalIndent(line);
secondLineBounds.x= l.x;
secondLineBounds.y= l.y - lineVerticalIndent;
} else {
secondLineBounds= widget.getTextBounds(lineOffset, lineOffset + lineLength);
}
Image image = new Image(widget.getDisplay(), widget.getSize().x, widget.getSize().y);
GC gc = new GC(widget);
gc.copyArea(image, 0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public StaticContentLineCodeMining(Position position, String message, ICodeMinin
setLabel(message);
}

public StaticContentLineCodeMining(Position position, boolean afterPosition, String message, ICodeMiningProvider provider) {
super(position, afterPosition, provider);
setLabel(message);
}

public StaticContentLineCodeMining(int i, char c, ICodeMiningProvider repeatLettersCodeMiningProvider) {
super(new Position(i, 1), repeatLettersCodeMiningProvider);
setLabel(Character.toString(c));
Expand Down
Loading