diff options
author | Mickael Istria | 2018-06-25 22:57:21 +0000 |
---|---|---|
committer | Lakshmi Shanmugam | 2018-07-03 06:53:57 +0000 |
commit | d502cb4c54e2f70232c12c94487c9c59164fc133 (patch) | |
tree | 22cd3040e701bff2a7937742226fef9ad1a4bbe7 | |
parent | 2d97bff877801cf8e8caf48f1b7724d28fa4004f (diff) | |
download | eclipse.platform.swt-d502cb4c54e2f70232c12c94487c9c59164fc133.tar.gz eclipse.platform.swt-d502cb4c54e2f70232c12c94487c9c59164fc133.tar.xz eclipse.platform.swt-d502cb4c54e2f70232c12c94487c9c59164fc133.zip |
Bug 536234 - [syntax highlighting] single char update not rendered
Change-Id: Ib8fcfc46e8e7ce2716e742c15da9cbb4338807c8
Signed-off-by: Mickael Istria <mistria@redhat.com>
3 files changed, 80 insertions, 6 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index 651869e8b9..cba08a72c0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -10156,24 +10156,24 @@ private SortedSet<Integer> computeModifiedLines(int[] referenceRanges, StyleRang while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) { int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset - while (referenceRangeIndex < referenceStyles.length && lastRangeOffset(referenceRanges, referenceRangeIndex) < currentOffset) { + while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) { referenceRangeIndex++; } StyleRange referenceStyleAtCurrentOffset = defaultStyle; if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex]; - nextMilestoneOffset = Math.min(nextMilestoneOffset, lastRangeOffset(referenceRanges, referenceRangeIndex) + 1); //just after current range + nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(referenceRanges, referenceRangeIndex)); } else if (referenceRangeIndex + 1 < referenceStyles.length) { // no range, default styling nextMilestoneOffset = referenceRanges[2 * (referenceRangeIndex + 1)]; // beginning of next range } - while (newRangeIndex < newStyles.length && lastRangeOffset(newRanges, newRangeIndex) < currentOffset) { + while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) { newRangeIndex++; } StyleRange newStyleAtCurrentOffset = defaultStyle; if (isInRange(newRanges, newRangeIndex, currentOffset)) { newStyleAtCurrentOffset = newStyles[newRangeIndex]; - nextMilestoneOffset = Math.min(nextMilestoneOffset, lastRangeOffset(newRanges, newRangeIndex) + 1); + nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex)); } else if (newRangeIndex + 1 < newStyles.length) { nextMilestoneOffset = newRanges[2 * (newRangeIndex + 1)]; } @@ -10207,10 +10207,16 @@ private boolean isInRange(int[] ranges, int styleIndex, int offset) { } int start = ranges[2 * styleIndex]; int length = ranges[2 * styleIndex + 1]; - return offset >= start && offset <= start + length; + return offset >= start && offset < start + length; } -private int lastRangeOffset(int[] ranges, int styleIndex) { +/** + * The offset on which the range ends (excluded) + * @param ranges + * @param styleIndex + * @return + */ +private int endRangeOffset(int[] ranges, int styleIndex) { if (styleIndex < 0 || 2 * styleIndex > ranges.length) { throw new IllegalArgumentException(); } diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java index 470204641b..0e159fa396 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java @@ -48,7 +48,10 @@ import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.GlyphMetrics; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; @@ -59,6 +62,7 @@ import org.eclipse.swt.widgets.Caret; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; @@ -5198,6 +5202,53 @@ public void test_insertInBlockSelection() { + System.getProperty("line.separator"))); } +@Test +public void test_setStyleRanges_render() throws InterruptedException { + Assume.assumeFalse("Bug 536588 prevents test to work on Mac", SwtTestUtil.isCocoa); + shell.setVisible(true); + text.setText("abc"); + text.setMargins(0, 0, 0, 0); + text.pack(); + processEvents(1000, () -> hasPixel(text, text.getBackground()) && !hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); + assertTrue(hasPixel(text, text.getBackground())); + assertFalse(hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); + text.setStyleRanges(new StyleRange[] { + new StyleRange(0, 1, null, text.getDisplay().getSystemColor(SWT.COLOR_RED)), + new StyleRange(2, 1, null, text.getDisplay().getSystemColor(SWT.COLOR_RED)), + }); + processEvents(100, () -> + hasPixel(text, text.getBackground()) && + hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); + assertTrue(hasPixel(text, text.getBackground())); + assertTrue(hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); + text.replaceStyleRanges(0, 3, new StyleRange[] { + new StyleRange(0, 3, null, text.getDisplay().getSystemColor(SWT.COLOR_RED)), + }); + processEvents(1000, () -> !hasPixel(text, text.getBackground()) && hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); + assertFalse(hasPixel(text, text.getBackground())); + assertTrue(hasPixel(text, text.getDisplay().getSystemColor(SWT.COLOR_RED))); +} + +private boolean hasPixel(StyledText text, Color expectedColor) { + GC gc = new GC(text); + final Image image = new Image(text.getDisplay(), text.getSize().x, text.getSize().y); + gc.copyArea(image, 0, 0); + gc.dispose(); + ImageData imageData = image.getImageData(); + RGB expectedRGB = expectedColor.getRGB(); + for (int x = 1; x < image.getBounds().width - 1; x++) { // ignore first and last columns + for (int y = 0; y < image.getBounds().height; y++) { + RGB pixelRGB = imageData.palette.getRGB(imageData.getPixel(x, y)); + if (expectedRGB.equals(pixelRGB)) { + image.dispose(); + return true; + } + } + } + image.dispose(); + return false; +} + private String blockSelectionTestText() { StringBuilder buffer = new StringBuilder(); for (int i = 0; i < 20; i++) { diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Widget.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Widget.java index d821a23c86..8c0d9c3fc5 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Widget.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Widget.java @@ -16,6 +16,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.function.BooleanSupplier; + import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.GC; @@ -207,6 +209,21 @@ protected String getClassName() { return clazz; } +protected void processEvents(int timeoutMs, BooleanSupplier condition) throws InterruptedException { + if (condition == null) { + condition = () -> false; + } + long targetTimestamp = System.currentTimeMillis() + timeoutMs; + while (!condition.getAsBoolean()) { + if (!shell.getDisplay().readAndDispatch()) { + if (System.currentTimeMillis() < targetTimestamp) { + Thread.sleep(50); + } else { + return; + } + } + } +} } |