/******************************************************************************* * Copyright (c) 2000, 2020 IBM Corporation 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jface.text.tests; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GlyphMetrics; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextPresentation; public class TextPresentationTest { private static final int NORMAL= SWT.NORMAL; private static final int BOLD= SWT.BOLD; private TextPresentation fTextPresentation; private StyleRange[] fAllRanges; private StyleRange[] fNonDefaultRanges; // collect colors for disposal private ArrayList fColors= new ArrayList<>(); private Display fDisplay; @Before public void setUp() { fDisplay= Display.getDefault(); setUpStyleRanges(); setUpTextPresentation(); } private void setUpStyleRanges() { fAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL) }; fNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD) }; } private void setUpTextPresentation() { fTextPresentation= new TextPresentation(); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 140, NORMAL)); for (StyleRange range : fAllRanges) { fTextPresentation.addStyleRange(range); } } @After public void tearDown() { for (Color c : fColors) { if (c != null && !c.isDisposed()) { c.dispose(); } } fColors.clear(); fDisplay.dispose(); } private StyleRange createStyleRange(int start, int end, int style) { return createStyleRange(start, end, style, null, null); } private StyleRange createStyleRange(int start, int end, int style, Color foreground, Color background) { return new StyleRange(start, end - start, foreground, background, style); } private StyleRange createStyleRange(int start, int end, int style, int foreground, int background) { return createStyleRange(start, end, style, createColor(foreground, foreground, foreground), createColor(background, background, background)); } /** * Creates a new color. * * @param red the amount of red in the color * @param green the amount of green in the color * @param blue the amount of blue in the color * @return null if any of the parameters is smaller than 0 or greater than 255 */ private Color createColor(int red, int green, int blue) { if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) return null; Color c= new Color(fDisplay, red, green, blue); fColors.add(c); return c; } /** * Check that the presentation contains the expected style ranges and other presentation methods * return compatible values. * * @param expectedAllRanges all styles expected for the whole presentation * @param expectedNonDefaultRanges all styles which are not the default for the whole * presentation */ protected void checkRegions(StyleRange[] expectedAllRanges, StyleRange[] expectedNonDefaultRanges) { checkRegions(expectedAllRanges, fTextPresentation.getAllStyleRangeIterator(), true); checkRegions(expectedNonDefaultRanges, fTextPresentation.getNonDefaultStyleRangeIterator(), false); // now test the same but remove the default style StyleRange defaultRange= fTextPresentation.getDefaultStyleRange(); fTextPresentation.setDefaultStyleRange(null); checkRegions(expectedAllRanges, fTextPresentation.getAllStyleRangeIterator(), true); checkRegions(expectedAllRanges, fTextPresentation.getNonDefaultStyleRangeIterator(), true); fTextPresentation.setDefaultStyleRange(defaultRange); } /** * Check expected regions against existing regions from presentation. Also validates that * iterator returns ordered and disjoint styles and most other presentation methods. * * @param expectedRanges the expected regions * @param rangeIterator iterator from presentation to get the actual regions * @param withDefaults if true the expected ranges also contains the ranges which * are equal to default style */ private void checkRegions(StyleRange[] expectedRanges, Iterator rangeIterator, boolean withDefaults) { StyleRange defaultRange= fTextPresentation.getDefaultStyleRange(); int start= -1, end= -1; int lastEnd= defaultRange != null ? defaultRange.start : Integer.MIN_VALUE; for (int i= 0; i < expectedRanges.length; i++) { StyleRange expectedRange= expectedRanges[i]; assertTrue("Presentation has less ranges than expected.", rangeIterator.hasNext()); StyleRange actualRange= rangeIterator.next(); assertEquals(expectedRange, actualRange); assertTrue("Unexpected default style.", withDefaults || !actualRange.similarTo(defaultRange)); assertTrue("Overlapping or wrong ordered style.", lastEnd <= actualRange.start); lastEnd= actualRange.start + actualRange.length; // test first and last range methods if (i == 0) { start= actualRange.start; StyleRange first= fTextPresentation.getFirstStyleRange(); if (withDefaults) { assertEquals("getFirstStyleRange() failed", expectedRange, first); } else { assertTrue("getFirstStyleRange() failed", first.equals(expectedRange) || first.similarTo(defaultRange)); } } else if (i == expectedRanges.length - 1) { end= actualRange.start + actualRange.length; StyleRange last= fTextPresentation.getLastStyleRange(); if (withDefaults) { assertEquals("getLastStyleRange() failed", expectedRange, last); } else { assertTrue("getLastStyleRange() failed", last.equals(expectedRange) || last.similarTo(defaultRange)); } } } assertTrue("Presentation has more ranges than expected.", !rangeIterator.hasNext()); if (withDefaults) { assertEquals("getDenumerableRanges() failed", expectedRanges.length, fTextPresentation.getDenumerableRanges()); } assertEquals("isEmpty() failed", Boolean.valueOf(expectedRanges.length == 0 && defaultRange == null), Boolean.valueOf(fTextPresentation.isEmpty())); IRegion expectedCover; if (defaultRange == null) { expectedCover= (start == -1 && end == -1 ? null : new Region(start, end - start)); } else { expectedCover= new Region(defaultRange.start, defaultRange.length); } assertEquals("Wrong coverage", expectedCover, fTextPresentation.getCoverage()); } @Test public void testUnclippedRegions() { checkRegions(fAllRanges, fNonDefaultRanges); } @Test public void testClippedRegions1() { fTextPresentation.setResultWindow(new Region(0, 140)); checkRegions(fAllRanges, fNonDefaultRanges); } @Test public void testClippedRegions2() { fTextPresentation.setResultWindow(new Region(30, 70)); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 17, NORMAL), createStyleRange( 17, 24, BOLD), createStyleRange( 24, 66, NORMAL), createStyleRange( 66, 70, BOLD) }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 17, 24, BOLD), createStyleRange( 66, 70, BOLD) }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at start of first existing range. */ @Test public void testMergeStyleRange1() { StyleRange range= createStyleRange(0, 2, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 2, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 4, 20, BOLD), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at end of last existing range. */ @Test public void testMergeStyleRange2() { StyleRange range= createStyleRange(138, 140, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 138, NORMAL), createStyleRange(138, 140, NORMAL, 1, -1), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), createStyleRange(138, 140, NORMAL, 1, -1), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at start of existing default range. */ @Test public void testMergeStyleRange3() { StyleRange range= createStyleRange(20, 22, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 22, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range within existing default range. */ @Test public void testMergeStyleRange4() { StyleRange range= createStyleRange(22, 24, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL), createStyleRange( 22, 24, NORMAL, 1, -1), createStyleRange( 24, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 22, 24, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at end of existing default range. */ @Test public void testMergeStyleRange5() { StyleRange range= createStyleRange(45, 47, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 45, NORMAL), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at start of existing non-default range. */ @Test public void testMergeStyleRange6() { StyleRange range= createStyleRange(47, 49, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range within existing non-default range. */ @Test public void testMergeStyleRange7() { StyleRange range= createStyleRange(49, 51, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 49, BOLD), createStyleRange( 49, 51, BOLD, 1, -1), createStyleRange( 51, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 49, BOLD), createStyleRange( 49, 51, BOLD, 1, -1), createStyleRange( 51, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range at end of existing non-default range. */ @Test public void testMergeStyleRange8() { StyleRange range= createStyleRange(52, 54, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range from existing default to non-default range. */ @Test public void testMergeStyleRange9() { StyleRange range= createStyleRange(45, 49, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 45, NORMAL), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range from existing non-default to default range. */ @Test public void testMergeStyleRange10() { StyleRange range= createStyleRange(52, 56, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 56, NORMAL, 1, -1), createStyleRange( 56, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 56, NORMAL, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range from existing default over non-default to default range. */ @Test public void testMergeStyleRange11() { StyleRange range= createStyleRange(45, 56, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 45, NORMAL), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 56, NORMAL, 1, -1), createStyleRange( 56, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 56, NORMAL, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range from existing non-default over default to non-default range. */ @Test public void testMergeStyleRange12() { StyleRange range= createStyleRange(52, 98, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL, 1, -1), createStyleRange( 96, 98, BOLD, 1, -1), createStyleRange( 98, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL, 1, -1), createStyleRange( 96, 98, BOLD, 1, -1), createStyleRange( 98, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range over existing default range. */ @Test public void testMergeStyleRange13() { StyleRange range= createStyleRange(20, 47, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range over existing non-default range. */ @Test public void testMergeStyleRange14() { StyleRange range= createStyleRange(47, 54, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range over whole presentation. */ @Test public void testMergeStyleRange15() { StyleRange range= createStyleRange(0, 140, NORMAL, 1, -1); Color expectedColor= createColor(1, 1, 1); StyleRange[] expectedAllRanges= new StyleRange[fAllRanges.length]; for (int i= 0; i < fAllRanges.length; i++) { expectedAllRanges[i]= (StyleRange) fAllRanges[i].clone(); expectedAllRanges[i].foreground= expectedColor; } StyleRange[] expectedNonDefaultRanges= expectedAllRanges; fTextPresentation.mergeStyleRange(range); checkRegions(expectedAllRanges, expectedNonDefaultRanges); range= createStyleRange(-100, 200, BOLD); for (int i= 0; i < expectedAllRanges.length; i++) { expectedAllRanges[i].fontStyle= BOLD; } fTextPresentation.mergeStyleRange(range); checkRegions(expectedAllRanges, expectedNonDefaultRanges); fTextPresentation.setDefaultStyleRange(null); range= createStyleRange(-150, 250, NORMAL, -1, 2); expectedColor= createColor(2, 2, 2); for (int i= 0; i < expectedAllRanges.length; i++) { expectedAllRanges[i].background= expectedColor; } StyleRange[] newExpectedRanges= new StyleRange[expectedAllRanges.length + 2]; System.arraycopy(expectedAllRanges, 0, newExpectedRanges, 1, expectedAllRanges.length); newExpectedRanges[0]= createStyleRange(-150, 0, NORMAL, -1, 2); newExpectedRanges[newExpectedRanges.length - 1]= createStyleRange(140, 250, NORMAL, -1, 2); fTextPresentation.mergeStyleRange(range); checkRegions(newExpectedRanges, newExpectedRanges); } /** * Merge range covering existing default range. */ @Test public void testMergeStyleRange16() { StyleRange range= createStyleRange(20, 47, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range covering existing non-default range. */ @Test public void testMergeStyleRange17() { StyleRange range= createStyleRange(47, 54, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range covering three ranges. */ @Test public void testMergeStyleRange18() { StyleRange range= createStyleRange(20, 96, NORMAL, 1, -1); fTextPresentation.mergeStyleRange(range); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL, 1, -1), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL, 1, -1), createStyleRange( 47, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL, 1, -1), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range starting and ending outside. */ @Test public void testMergeStyleRange22() { StyleRange range= createStyleRange(-5, 145, BOLD, 1, -1); Color expectedColor= createColor(1, 1, 1); StyleRange[] expectedAllRanges= new StyleRange[fAllRanges.length]; for (int i= 0; i < fAllRanges.length; i++) { expectedAllRanges[i]= (StyleRange) fAllRanges[i].clone(); expectedAllRanges[i].fontStyle= BOLD; expectedAllRanges[i].foreground= expectedColor; } StyleRange[] expectedNonDefaultRanges= expectedAllRanges; fTextPresentation.mergeStyleRange(range); checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge range starting and ending outside without default style. */ @Test public void testMergeStyleRange23() { fTextPresentation.setDefaultStyleRange(null); StyleRange range= createStyleRange(-5, 145, BOLD, 1, -1); Color expectedColor= createColor(1, 1, 1); StyleRange[] expectedAllRanges= new StyleRange[fAllRanges.length + 2]; expectedAllRanges[0]= createStyleRange(-5, 0, BOLD, 1, -1); for (int i= 0; i < fAllRanges.length; i++) { expectedAllRanges[i + 1]= (StyleRange) fAllRanges[i].clone(); expectedAllRanges[i + 1].fontStyle= BOLD; expectedAllRanges[i + 1].foreground= expectedColor; } expectedAllRanges[expectedAllRanges.length - 1]= createStyleRange(140, 145, BOLD, 1, -1); StyleRange[] expectedNonDefaultRanges= expectedAllRanges; fTextPresentation.mergeStyleRange(range); checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Merge/replace styles on default only presentation. */ @Test public void testApplyStyleRange1() { fTextPresentation.clear(); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 140, NORMAL)); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.mergeStyleRange(range); } checkRegions(fAllRanges, fNonDefaultRanges); fTextPresentation.clear(); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 140, NORMAL)); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.replaceStyleRange(range); } checkRegions(fAllRanges, fNonDefaultRanges); } /** * Merge/replace styles without default on empty presentation. */ @Test public void testApplyStyleRange2() { fTextPresentation.clear(); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.mergeStyleRange(range); } checkRegions(fAllRanges, fAllRanges); fTextPresentation.clear(); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.replaceStyleRange(range); } checkRegions(fAllRanges, fAllRanges); } /** * Merge/replace styles without default on existing styles. */ @Test public void testApplyStyleRange3() { fTextPresentation.clear(); fTextPresentation.mergeStyleRange(createStyleRange(0, 140, NORMAL)); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.mergeStyleRange(range); } checkRegions(fAllRanges, fAllRanges); fTextPresentation.clear(); fTextPresentation.mergeStyleRange(createStyleRange(0, 140, NORMAL)); for (StyleRange range : deepClone(fAllRanges)) { fTextPresentation.replaceStyleRange(range); } checkRegions(fAllRanges, fAllRanges); } /** * Merge/replace empty range. */ @Test public void testApplyStyleRange4() { StyleRange empty= createStyleRange(0, 0, BOLD); fTextPresentation.mergeStyleRange(empty); checkRegions(fAllRanges, fNonDefaultRanges); fTextPresentation.replaceStyleRange(empty); checkRegions(fAllRanges, fNonDefaultRanges); } /** * Test merge operation involving link styling. */ @Test public void testLinkMerge() { Color linkColor= createColor(0, 0, 255); StyleRange[] ranges= new StyleRange[] { createStyleRange( 4, 20, NORMAL), // default underline createStyleRange( 20, 47, NORMAL), // explicit default underline createStyleRange( 47, 54, NORMAL), // double underline createStyleRange( 96, 102, NORMAL, 1, -1), // set color for later test createStyleRange(102, 140, NORMAL), // link }; ranges[0].underline= true; ranges[1].underline= true; ranges[1].underlineStyle= SWT.UNDERLINE_SINGLE; ranges[2].underline= true; ranges[2].underlineStyle= SWT.UNDERLINE_DOUBLE; ranges[4].underline= true; ranges[4].underlineStyle= SWT.UNDERLINE_LINK; ranges[4].foreground= linkColor; for (StyleRange range : deepClone(ranges)) { fTextPresentation.mergeStyleRange(range); } StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD, 1, -1), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { expectedAllRanges[1], expectedAllRanges[2], expectedAllRanges[3], expectedAllRanges[5], expectedAllRanges[6], }; expectedNonDefaultRanges[0].underline= true; expectedNonDefaultRanges[1].underline= true; expectedNonDefaultRanges[1].underlineStyle= SWT.UNDERLINE_SINGLE; expectedNonDefaultRanges[2].underline= true; expectedNonDefaultRanges[2].underlineStyle= SWT.UNDERLINE_DOUBLE; expectedNonDefaultRanges[4].underline= true; expectedNonDefaultRanges[4].underlineStyle= SWT.UNDERLINE_LINK; expectedNonDefaultRanges[4].foreground= linkColor; checkRegions(expectedAllRanges, expectedNonDefaultRanges); for (int i= 0; i < 3; i++) { ranges[i].underlineStyle= SWT.UNDERLINE_LINK; ranges[i].foreground= linkColor; expectedNonDefaultRanges[i].underlineStyle= SWT.UNDERLINE_LINK; expectedNonDefaultRanges[i].foreground= linkColor; } ranges[3].underlineStyle= SWT.UNDERLINE_LINK; ranges[3].foreground= null; expectedNonDefaultRanges[3].underlineStyle= SWT.UNDERLINE_LINK; expectedNonDefaultRanges[3].foreground= null; // merging underline_link force set the foreground ranges[4].underlineStyle= SWT.UNDERLINE_SQUIGGLE; // expect no change for expectedNonDefaultRanges[4]. underline_link cannot removed using merge for (StyleRange range : ranges) { fTextPresentation.mergeStyleRange(range); } checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Test merge operation with all style parts. */ @Test public void testMergeAll() { StyleRange range= createStyleRange(4, 20, BOLD, 1, 2); range.borderColor= createColor(3, 3, 3); range.borderStyle= SWT.BORDER_DASH; range.font= fDisplay.getSystemFont(); range.metrics= new GlyphMetrics(0, 0, 10); range.strikeout= true; range.strikeoutColor= createColor(4, 4, 4); range.underline= true; range.underlineColor= createColor(5, 5, 5); range.underlineStyle= SWT.UNDERLINE_SQUIGGLE; fTextPresentation.mergeStyleRange((StyleRange) range.clone()); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 4, NORMAL), (StyleRange) range.clone(), createStyleRange( 20, 47, NORMAL), createStyleRange( 47, 54, BOLD), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 140, NORMAL), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { (StyleRange) range.clone(), createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); range.background= null; range.borderColor= null; range.borderStyle= SWT.NONE; range.font= null; range.fontStyle= SWT.NORMAL; range.foreground= null; range.metrics= null; range.strikeout= false; range.strikeoutColor= null; range.underline= false; range.underlineColor= null; range.underlineStyle= SWT.UNDERLINE_SINGLE; fTextPresentation.mergeStyleRange((StyleRange) range.clone()); checkRegions(expectedAllRanges, expectedNonDefaultRanges); fTextPresentation.replaceStyleRange((StyleRange) range.clone()); expectedAllRanges[1]= range; expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 47, 54, BOLD), createStyleRange( 96, 102, BOLD), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } @Test public void testMergeStyleRanges1() { StyleRange[] ranges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), // at start of first existing createStyleRange( 20, 22, NORMAL, 1, -1), // at start of existing default createStyleRange( 24, 26, NORMAL, 1, -1), // within existing default createStyleRange( 45, 47, NORMAL, 1, -1), // at end of existing default createStyleRange( 47, 49, NORMAL, 1, -1), // at start of existing non-default createStyleRange( 50, 51, NORMAL, 1, -1), // within existing non-default createStyleRange( 52, 54, NORMAL, 1, -1), // at end of existing non-default createStyleRange(138, 140, NORMAL, 1, -1), // at end of last existing }; fTextPresentation.mergeStyleRanges(deepClone(ranges)); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 2, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 22, 24, NORMAL), createStyleRange( 24, 26, NORMAL, 1, -1), createStyleRange( 26, 45, NORMAL), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 50, BOLD), createStyleRange( 50, 51, BOLD, 1, -1), createStyleRange( 51, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 138, NORMAL), createStyleRange(138, 140, NORMAL, 1, -1), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 24, 26, NORMAL, 1, -1), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, BOLD, 1, -1), createStyleRange( 49, 50, BOLD), createStyleRange( 50, 51, BOLD, 1, -1), createStyleRange( 51, 52, BOLD), createStyleRange( 52, 54, BOLD, 1, -1), createStyleRange( 96, 102, BOLD), createStyleRange(138, 140, NORMAL, 1, -1), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); // now swap fore- and background colors for an easy additional test for (StyleRange r : ranges) { Color c= r.foreground; r.foreground= r.background; r.background= c; } for (StyleRange[] rs : new StyleRange[][] { expectedAllRanges, expectedNonDefaultRanges }) { for (StyleRange r : rs) { r.background= r.foreground; } } fTextPresentation.mergeStyleRanges(ranges); checkRegions(expectedAllRanges, expectedNonDefaultRanges); } @Test public void testReplaceStyleRanges1() { StyleRange[] ranges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), // at start of first existing createStyleRange( 20, 22, NORMAL, 1, -1), // at start of existing default createStyleRange( 24, 26, NORMAL, 1, -1), // within existing default createStyleRange( 45, 47, NORMAL, 1, -1), // at end of existing default createStyleRange( 47, 49, NORMAL, 1, -1), // at start of existing non-default createStyleRange( 50, 51, NORMAL, 1, -1), // within existing non-default createStyleRange( 52, 54, NORMAL, 1, -1), // at end of existing non-default createStyleRange(138, 140, NORMAL, 1, -1), // at end of last existing }; fTextPresentation.replaceStyleRanges(deepClone(ranges)); StyleRange[] expectedAllRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 2, 4, NORMAL), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 22, 24, NORMAL), createStyleRange( 24, 26, NORMAL, 1, -1), createStyleRange( 26, 45, NORMAL), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, NORMAL, 1, -1), createStyleRange( 49, 50, BOLD), createStyleRange( 50, 51, NORMAL, 1, -1), createStyleRange( 51, 52, BOLD), createStyleRange( 52, 54, NORMAL, 1, -1), createStyleRange( 54, 96, NORMAL), createStyleRange( 96, 102, BOLD), createStyleRange(102, 138, NORMAL), createStyleRange(138, 140, NORMAL, 1, -1), }; StyleRange[] expectedNonDefaultRanges= new StyleRange[] { createStyleRange( 0, 2, NORMAL, 1, -1), createStyleRange( 4, 20, BOLD), createStyleRange( 20, 22, NORMAL, 1, -1), createStyleRange( 24, 26, NORMAL, 1, -1), createStyleRange( 45, 47, NORMAL, 1, -1), createStyleRange( 47, 49, NORMAL, 1, -1), createStyleRange( 49, 50, BOLD), createStyleRange( 50, 51, NORMAL, 1, -1), createStyleRange( 51, 52, BOLD), createStyleRange( 52, 54, NORMAL, 1, -1), createStyleRange( 96, 102, BOLD), createStyleRange(138, 140, NORMAL, 1, -1), }; checkRegions(expectedAllRanges, expectedNonDefaultRanges); // now swap all fore- and background colors for an easy additional test for (StyleRange[] rs : new StyleRange[][] { ranges, expectedAllRanges, expectedNonDefaultRanges }) { for (StyleRange r : rs) { Color c= r.foreground; r.foreground= r.background; r.background= c; } } fTextPresentation.replaceStyleRanges(ranges); checkRegions(expectedAllRanges, expectedNonDefaultRanges); } /** * Replace whole presentation. */ @Test public void testReplaceStyleRange2() { StyleRange range= createStyleRange(0, 140, BOLD, 1, -1); fTextPresentation.replaceStyleRange(range); Color expectedColor= createColor(1, 1, 1); StyleRange[] expectedAllRanges= new StyleRange[fAllRanges.length]; for (int i= 0; i < fAllRanges.length; i++) { expectedAllRanges[i]= (StyleRange) fAllRanges[i].clone(); expectedAllRanges[i].fontStyle= BOLD; expectedAllRanges[i].foreground= expectedColor; } StyleRange[] expectedNonDefaultRanges= expectedAllRanges; checkRegions(expectedAllRanges, expectedNonDefaultRanges); } @Test public void testExtend() { fTextPresentation.setDefaultStyleRange(null); assertEquals(new Region(0, 140), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 150, NORMAL)); assertEquals(new Region(0, 150), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(null); fTextPresentation.setResultWindow(new Region(100, 10)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 150, NORMAL)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); fTextPresentation= new TextPresentation(new Region(0, 160), 10); assertEquals(new Region(0, 160), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 150, NORMAL)); assertEquals(new Region(0, 160), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(null); fTextPresentation.setResultWindow(new Region(100, 10)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); fTextPresentation.setDefaultStyleRange(createStyleRange(0, 150, NORMAL)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); } @Test public void testExtendUndefined() { fTextPresentation= new TextPresentation(new Region(0, 160), 10); fTextPresentation.setResultWindow(new Region(-10, 5)); assertEquals(new Region(10, -5), fTextPresentation.getExtent()); fTextPresentation.setResultWindow(new Region(-10, 30)); assertEquals(new Region(10, 20), fTextPresentation.getExtent()); fTextPresentation.setResultWindow(new Region(150, 30)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); fTextPresentation.setResultWindow(new Region(200, 30)); assertEquals(new Region(0, -40), fTextPresentation.getExtent()); } @Test public void testEmptyPresentation() { fTextPresentation.clear(); checkRegions(new StyleRange[0], new StyleRange[0]); fTextPresentation.setResultWindow(new Region(4, 10)); checkRegions(new StyleRange[0], new StyleRange[0]); fTextPresentation.setResultWindow(null); StyleRange defaultRange= createStyleRange(0, 50, BOLD); fTextPresentation.setDefaultStyleRange(defaultRange); checkRegions(new StyleRange[0], new StyleRange[0]); fTextPresentation.setResultWindow(new Region(4, 10)); checkRegions(new StyleRange[0], new StyleRange[0]); fTextPresentation= new TextPresentation(new Region(0, 100), 1); assertEquals(new Region(0, 100), fTextPresentation.getExtent()); fTextPresentation.setResultWindow(new Region(4, 10)); assertEquals(new Region(0, 10), fTextPresentation.getExtent()); } @Test public void testApplyTextPresentation() { Shell shell= new Shell(fDisplay); try { StyledText text= new StyledText(shell, SWT.NONE); text.setText(String.join("", Collections.nCopies(fTextPresentation.getCoverage().getLength(), "."))); TextPresentation.applyTextPresentation(fTextPresentation, text); assertArrayEquals(fAllRanges, text.getStyleRanges()); } finally { shell.dispose(); } } @Test public void testIterator() { // Test read over iterator end Iterator e= fTextPresentation.getAllStyleRangeIterator(); try { for (int i= 0; i < 1000; i++) { e.next(); } fail("Iterator has no end."); } catch (NoSuchElementException ex) { // expected } e= fTextPresentation.getNonDefaultStyleRangeIterator(); try { for (int i= 0; i < 1000; i++) { e.next(); } fail("Iterator has no end."); } catch (NoSuchElementException ex) { // expected } } // helper method required as long as TextPresentation methods manipulate given arguments private static StyleRange[] deepClone(StyleRange[] original) { StyleRange[] clone= new StyleRange[original.length]; for (int i= 0; i < original.length; i++) { clone[i]= (StyleRange) original[i].clone(); } return clone; } }