diff options
5 files changed, 173 insertions, 19 deletions
diff --git a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF index a86ce43a0f7..1a42f604259 100644 --- a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF @@ -12,6 +12,7 @@ Export-Package: org.eclipse.jface.text.tests.reconciler, org.eclipse.jface.text.tests.rules, org.eclipse.jface.text.tests.source, + org.eclipse.jface.text.tests.source.inlined, org.eclipse.jface.text.tests.templates.persistence, org.eclipse.jface.text.tests.util Require-Bundle: diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java index d35ff7e74e3..5a492dad97c 100644 --- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java @@ -17,8 +17,8 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; -import org.eclipse.jface.text.tests.codemining.CodeMiningTest; import org.eclipse.jface.text.tests.codemining.CodeMiningProjectionViewerTest; +import org.eclipse.jface.text.tests.codemining.CodeMiningTest; import org.eclipse.jface.text.tests.contentassist.AsyncContentAssistTest; import org.eclipse.jface.text.tests.reconciler.AbstractReconcilerTest; import org.eclipse.jface.text.tests.rules.DefaultPartitionerTest; @@ -27,6 +27,7 @@ import org.eclipse.jface.text.tests.rules.FastPartitionerTest; import org.eclipse.jface.text.tests.rules.ScannerColumnTest; import org.eclipse.jface.text.tests.rules.WordRuleTest; import org.eclipse.jface.text.tests.source.LineNumberRulerColumnTest; +import org.eclipse.jface.text.tests.source.inlined.InlineAnnotationTest; import org.eclipse.jface.text.tests.templates.persistence.TemplatePersistenceDataTest; @@ -57,6 +58,7 @@ import org.eclipse.jface.text.tests.templates.persistence.TemplatePersistenceDat WordRuleTest.class, TemplatePersistenceDataTest.class, + InlineAnnotationTest.class, CodeMiningTest.class, CodeMiningProjectionViewerTest.class }) diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningProjectionViewerTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningProjectionViewerTest.java index 4fbb54ecffc..88bf217ce1b 100644 --- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningProjectionViewerTest.java +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningProjectionViewerTest.java @@ -43,7 +43,6 @@ import org.eclipse.jface.text.Position; import org.eclipse.jface.text.codemining.ICodeMining; import org.eclipse.jface.text.codemining.ICodeMiningProvider; import org.eclipse.jface.text.codemining.LineContentCodeMining; -import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.AnnotationPainter; import org.eclipse.jface.text.source.IAnnotationAccess; import org.eclipse.jface.text.source.ISharedTextColors; @@ -51,6 +50,7 @@ import org.eclipse.jface.text.source.projection.ProjectionAnnotation; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.jface.text.tests.source.inlined.InlineAnnotationTest.AccessAllAnnoations; import org.eclipse.jface.text.tests.util.DisplayHelper; public class CodeMiningProjectionViewerTest { @@ -86,22 +86,7 @@ public class CodeMiningProjectionViewerTest { fParent.setSize(500, 200); fParent.setLayout(new FillLayout()); fViewer= new ProjectionViewer(fParent, null, null, false, SWT.NONE); - IAnnotationAccess annotationAccess = new IAnnotationAccess() { - @Override - public Object getType(Annotation annotation) { - return annotation.getType(); - } - - @Override - public boolean isMultiLine(Annotation annotation) { - return true; - } - - @Override - public boolean isTemporary(Annotation annotation) { - return true; - } - }; + IAnnotationAccess annotationAccess = new AccessAllAnnoations(); // code minings AnnotationPainter painter = new AnnotationPainter(fViewer, annotationAccess); fViewer.addPainter(painter); diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/source/inlined/InlineAnnotationTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/source/inlined/InlineAnnotationTest.java new file mode 100644 index 00000000000..75e924d2811 --- /dev/null +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/source/inlined/InlineAnnotationTest.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2019 Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.jface.text.tests.source.inlined; + +import java.util.Collections; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.ITextViewerExtension2; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.inlined.InlinedAnnotationSupport; +import org.eclipse.jface.text.source.inlined.LineContentAnnotation; +import org.eclipse.jface.text.tests.util.DisplayHelper; + +@RunWith(Parameterized.class) +public class InlineAnnotationTest { + @Parameters(name="{0}") + public static String[] contents() { + return new String[] { + "annotation inside text", + " annotation just after initial space", + "\tannoation just after initial tab" + }; + } + + private String text; + + public InlineAnnotationTest(String text) { + this.text = text; + } + + public static final class AccessAllAnnoations implements IAnnotationAccess { + @Override + public Object getType(Annotation annotation) { + return annotation.getType(); + } + + @Override + public boolean isMultiLine(Annotation annotation) { + return true; + } + + @Override + public boolean isTemporary(Annotation annotation) { + return true; + } + } + + private static final class TestAnnotationPainter extends AnnotationPainter { + private boolean painted; + + private TestAnnotationPainter(ISourceViewer sourceViewer, IAnnotationAccess access) { + super(sourceViewer, access); + } + + @Override + public void paint(int reason) { + this.painted = true; + super.paint(reason); + } + + public boolean wasPainted() { + return this.painted; + } + } + + private Shell fParent; + + @Before + public void setUp() { + fParent= new Shell(); + } + + @After + public void tearDown() { + fParent.dispose(); + fParent = null; + } + + @Test + public void testTextBoundsMatchPaintedArea() { + fParent.setLayout(new FillLayout()); + + // Create source viewer and initialize the content + ISourceViewer sourceViewer = new SourceViewer(fParent,null, + SWT.V_SCROLL | SWT.BORDER); + sourceViewer.setDocument(new Document(this.text), new AnnotationModel()); + + // Initialize inlined annotations support + InlinedAnnotationSupport support = new InlinedAnnotationSupport(); + IAnnotationAccess annotationAccess = new AccessAllAnnoations(); + TestAnnotationPainter painter = new TestAnnotationPainter(sourceViewer, annotationAccess); + ((ITextViewerExtension2) sourceViewer).addPainter(painter); + support.install(sourceViewer, painter); + + // add annotations + LineContentAnnotation annotation= new LineContentAnnotation(new Position(1, 1), sourceViewer); + annotation.setText("longAnnationToDisplayOnTab"); + support.updateAnnotations(Collections.singleton(annotation)); + fParent.open(); + StyledText textWidget= sourceViewer.getTextWidget(); + Assert.assertTrue(new DisplayHelper() { + @Override + protected boolean condition() { + return textWidget.isVisible() && painter.wasPainted(); + } + }.waitForCondition(textWidget.getDisplay(), 2000)); + DisplayHelper.sleep(textWidget.getDisplay(), 1000); + Rectangle textBounds= textWidget.getTextBounds(0, textWidget.getText().length() - 1); + int supposedMostRightPaintedPixel = textBounds.x + textBounds.width - 1; + int mostRightPaintedPixel= getMostRightPaintedPixel(textWidget); + Assert.assertEquals(supposedMostRightPaintedPixel, mostRightPaintedPixel, 1.5); // use double comparison with delta to tolerate variation from a system to the other + } + + public int getMostRightPaintedPixel(StyledText widget) { + Image image = new Image(widget.getDisplay(), widget.getSize().x, widget.getSize().y); + GC gc = new GC(widget); + gc.copyArea(image, 0, 0); + gc.dispose(); + RGB backgroundRgb = widget.getBackground().getRGB(); + ImageData imageData = image.getImageData(); + for (int x = imageData.width - 50 /* magic number to avoid rulers and other */; x >= 0; x--) { + for (int y = 3 /* magic number as well to avoid title bar */; y < imageData.height; y++) { + if (!imageData.palette.getRGB(imageData.getPixel(x, y)).equals(backgroundRgb)) { + image.dispose(); + return x; + } + } + } + image.dispose(); + return -1; + } +} 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 6ec1ca33d2e..6a606360b57 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 @@ -151,7 +151,9 @@ public class LineContentAnnotation extends AbstractInlinedAnnotation { } boolean drawRightToPreviousChar(int widgetOffset) { - return widgetOffset > 0 && getTextWidget().getLineAtOffset(widgetOffset) == getTextWidget().getLineAtOffset(widgetOffset - 1); + return widgetOffset > 0 && + getTextWidget().getLineAtOffset(widgetOffset) == getTextWidget().getLineAtOffset(widgetOffset - 1) && + getTextWidget().getText().charAt(widgetOffset - 1) != '\t'; // \t workaround bug 547532 } } |