package org.eclipse.swt.tests; import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextMarginsBugTest { private Display display; private Shell shell; private StyledText textBoxWithMargins; private Composite containerWithMargins; private StyledText textBoxWithoutMargins; private static final String TEXT = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; private Point textPrefSize; private int margin; private int lineHeight; private int twoLineHeight; /** *
	 * SHELL
	 * - root (pref width)
	 * 	- 1) container (right margin)
	 * 		- text
	 * 	- 2) text (right margin)
	 * 
*
    *
  1. the first text control inside container with margin displays correctly
  2. *
  3. the second text control is not laid-out correctly * (second line is correctly wrapped, but is not visible because {@linkplain StyledText#computeSize(int,int)} does not return correct values.
  4. *
*/ @Before public void setUp () { display = Display.getDefault (); shell = new Shell (display, SWT.SHELL_TRIM); shell.setText ("StyledText Margins Layout Bug Tester"); final GridLayout shellLayout = new GridLayout (); shellLayout.marginWidth = 12; shellLayout.marginHeight = 9; shell.setLayout (shellLayout); final Composite root = new Composite(shell, SWT.NONE); final GridLayout rootLayout = new GridLayout (); rootLayout.marginWidth = 0; rootLayout.marginHeight = 0; root.setLayout (rootLayout); containerWithMargins = new Composite (root, SWT.NONE); final GridLayout layoutWithMargin = new GridLayout (); layoutWithMargin.marginWidth = 0; layoutWithMargin.marginHeight = 0; containerWithMargins.setLayout (layoutWithMargin); textBoxWithoutMargins = new StyledText (containerWithMargins, SWT.MULTI | SWT.WRAP); textBoxWithoutMargins.setText (TEXT); textBoxWithMargins = new StyledText (root, SWT.MULTI | SWT.WRAP); textBoxWithMargins.setText (TEXT); textPrefSize = textBoxWithMargins.computeSize (SWT.DEFAULT, SWT.DEFAULT); // Lets set the margin to the third of the preferred width of the text control margin = textPrefSize.x / 3; layoutWithMargin.marginRight = margin; textBoxWithMargins.setRightMargin (margin); // set the root width hint to the text preferred width final GridData rootLD = new GridData (SWT.FILL, SWT.FILL, true, true); rootLD.widthHint = textPrefSize.x; root.setLayoutData (rootLD); // finish the initialization with some common layout data setting... containerWithMargins.setLayoutData (new GridData (SWT.FILL, SWT.TOP, true, false)); textBoxWithMargins.setLayoutData (new GridData (SWT.FILL, SWT.TOP, true, false)); textBoxWithoutMargins.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true)); // and debugging colors containerWithMargins.setBackground (display.getSystemColor (SWT.COLOR_GREEN)); textBoxWithoutMargins.setBackground (display.getSystemColor (SWT.COLOR_BLUE)); textBoxWithMargins.setBackground (display.getSystemColor (SWT.COLOR_RED)); // pack shell (to the size where the bug is most visible -- to the pref. width of the text // (=previous preferred width of the text control without margins) shell.pack (); // shell.setSize (shell.computeSize (textPrefSize.x, SWT.DEFAULT)); // Prepare line height values against which the assertions will be performed final int lineSpacing = textBoxWithoutMargins.getLineSpacing (); lineHeight = textBoxWithoutMargins.getLineHeight (); twoLineHeight = (lineHeight * 2) + lineSpacing; } @After public void tearDown () { if (shell != null && !shell.isDisposed ()) { shell.dispose (); } shell = null; } /** * This is of course ok :) */ @Test public void testComputeSizePreferred () { // PREFERRED SIZE... that is ok :) assertEquals (textPrefSize, textBoxWithoutMargins.computeSize (SWT.DEFAULT, SWT.DEFAULT)); assertEquals (textPrefSize.x + margin, containerWithMargins.computeSize (SWT.DEFAULT, SWT.DEFAULT).x); assertEquals (textPrefSize.x + margin, textBoxWithMargins.computeSize (SWT.DEFAULT, SWT.DEFAULT).x); } @Test public void testMyAssumptions() { // tests my assumption that the pref height of a one line StyledText control is equal to the line height. assertEquals (lineHeight, textPrefSize.y); assertEquals (textPrefSize, textBoxWithoutMargins.computeSize (SWT.DEFAULT, SWT.DEFAULT)); assertEquals (twoLineHeight, textBoxWithoutMargins.computeSize (textPrefSize.x - margin, SWT.DEFAULT).y); // StyledText.getLineCound() currently does not return 2, but if main method is run, // there will be two lines rendered in the correct (blue) StyledText. // assertEquals (2, textBoxWithMargins.getLineCount ()); } /** * Shows how the bug in the {@linkplain StyledText#computeSize(int, int, boolean)} represents itself. */ @Test public void testComputeSizeWithWidthConstraint () { // On my Mac, there is some 1px addition to the calculated width that I can't pinpoint... // so change this small value if it doesn't match exactly. // (the bug will present itself with much greater difference) final int textBoxCalculatedWidthAdditon = 1; // no margin StyledText test assertEquals ("reference test... this is how it looks when no margin is set\n", new Point(textPrefSize.x + textBoxCalculatedWidthAdditon, textPrefSize.y), textBoxWithoutMargins.computeSize (textPrefSize.x, SWT.DEFAULT) ); assertEquals ("reference test... this is how it half width StyledText looks when no margin is set\n", new Point(textPrefSize.x - margin + textBoxCalculatedWidthAdditon, twoLineHeight), textBoxWithoutMargins.computeSize (textPrefSize.x - margin, SWT.DEFAULT) ); // margined Composite test assertEquals ("composite with margins... calculates the size correctly\n", new Point( textPrefSize.x, // the margin is incorporated inside the composite twoLineHeight ), containerWithMargins.computeSize (textPrefSize.x, SWT.DEFAULT) ); // margined StyledText test – will fail if the bug this test describes is still in place assertEquals ("TextBox with margins... calculates the size incorrectly because of this bug!\n", new Point( textPrefSize.x + textBoxCalculatedWidthAdditon, // the margin should be incorporated inside the StyledText twoLineHeight // the text should be 2 lines high, but as this failed test shows, it is only 1 line high! ), textBoxWithMargins.computeSize (textPrefSize.x, SWT.DEFAULT, true) ); /* * We see that the margin is calculated into the size AFTER the dimensions based on the text were done. * But it has to be done in the reverse order: * -- the available space has to be cropped BEFORE the size of the text is calculated. * * Solution is in repairing the {@linkplain StyledText#computeSize(int, int, boolean)} method ;) * (if i knew how to compile the swt library, I would correct it myself) */ } /** * Main */ static public void main(final String... args) { final StyledTextMarginsBugTest test = new StyledTextMarginsBugTest(); test.setUp (); test.shell.open (); while (!test.shell.isDisposed ()) { if (!test.display.readAndDispatch ()) { test.display.sleep (); } } test.tearDown (); } }