blob: 3cea6ca88e44a64f94f7759381348aa2bb458ed1 [file] [log] [blame]
/*******************************************************************************
* 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.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;
/**
* This test verify that the bounds of the text as returned by StyledText.getTextBounds()
* actually match what's printed on the widget.
*/
@RunWith(Parameterized.class)
public class LineContentBoundsDrawingTest {
@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 LineContentBoundsDrawingTest(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;
}
}
public static final class TestAnnotationPainter extends AnnotationPainter {
private boolean painted;
public 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);
// XXX disabled due bug 549110
// 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 - 3; y++) {
if (!imageData.palette.getRGB(imageData.getPixel(x, y)).equals(backgroundRgb)) {
image.dispose();
return x;
}
}
}
image.dispose();
return -1;
}
}