/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.tests.forms.widgets;
import static org.junit.Assert.assertEquals;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.SizeCache;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class SizeCacheTest {
private static Display display;
private Shell shell;
private static final String SHORT_TEXT = "Hedgehog";
private static final String LONG_TEXT = "A hedgehog is any of the spiny mammals of the subfamily Erinaceinae, in the order Erinaceomorpha. " //$NON-NLS-1$
+ "There are seventeen species of hedgehog in five genera, found through parts of Europe, Asia, Africa and New Zealand. " //$NON-NLS-1$
;
private Font font;
// change this to true if you want to see test is slow motion
private boolean humanWatching = Boolean.valueOf(System.getProperty("junit.human.watching"));
private SizeCache sizeCache;
private Control control;
private Point expectedSize;
static {
try {
display = PlatformUI.getWorkbench().getDisplay();
} catch (Throwable e) {
// this is to run without eclipse
display = new Display();
}
}
@Before
public void setUp() throws Exception {
font = new Font(display, "Arial", 12, SWT.NORMAL);
shell = new Shell(display);
shell.setSize(600, 400);
shell.setLayout(GridLayoutFactory.fillDefaults().create());
shell.setFont(font);
shell.open();
}
@After
public void tearDown() throws Exception {
if (humanWatching)
dispatch(1000);
shell.dispose();
font.dispose();
}
private static void dispatch0() {
while (display.readAndDispatch()) {
}
}
private static void dispatch(int msec) {
long cur = System.currentTimeMillis();
do {
dispatch0();
long pass = System.currentTimeMillis() - cur;
if (pass < msec) {
// not doing display.sleep() because its automated tests,
// nothing will cause any display events
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
} else
break;
} while (true);
}
private Label createLabel(Composite comp, String text, int style) {
Label l = new Label(comp, style);
l.setText(text);
l.setFont(comp.getFont());
return l;
}
private Button createButton(Composite comp, String text, int style) {
Button l = new Button(comp, style);
l.setText(text);
l.setFont(comp.getFont());
return l;
}
/**
* This does automatic check to make sure that cached size of control is the
* same as calculated size. It also return current calulated size if needs
* to be used for further testing.
*/
private Point checkSizeEquals(int whint, int hhint) {
expectedSize = controlComputeSize(whint, hhint);
// this is just for show if somebody is watching
control.setSize(expectedSize);
dispatch();
checkDoubleCall(whint, hhint);
checkPreferedThenOther(whint, hhint);
return expectedSize;
}
private Point controlComputeSize(int wHint, int hHint) {
Point adjusted = computeHintOffset();
int adjustedWidthHint = wHint;
if (adjustedWidthHint != SWT.DEFAULT) {
adjustedWidthHint = Math.max(0, wHint - adjusted.x);
}
int adjustedHeightHint = hHint;
if (adjustedHeightHint != SWT.DEFAULT) {
adjustedHeightHint = Math.max(0, hHint - adjusted.y);
}
Point result = control.computeSize(adjustedWidthHint, adjustedHeightHint, true);
// Ignore any component if the hint was something other than SWT.DEFAULT.
// There's no way to measure hints smaller than the adjustment value and
// somecontrols have buggy computeSize methods that don't return non-default
// hints verbatim. The purpose of this test is to verify SizeCache, not the
// controls, and we don't want such quirks to create failures, so we correct the
// result here if necessary.
if (wHint != SWT.DEFAULT) {
result.x = wHint;
}
if (hHint != SWT.DEFAULT) {
result.y = hHint;
}
return result;
}
private Point checkAlterate(int whint, int hhint) {
Point expectedSize1 = controlComputeSize(-1, hhint);
Point expectedSize2 = controlComputeSize(whint, -1);
resetCache();
checkCacheComputeSize(expectedSize1, -1, hhint);
checkCacheComputeSize(expectedSize1, -1, hhint);
// switch
checkCacheComputeSize(expectedSize2, whint, -1);
checkCacheComputeSize(expectedSize2, whint, -1);
return expectedSize1;
}
private Point computeHintOffset() {
Point size = new Point(0, 0);
if (control instanceof Scrollable) {
// For scrollables, subtract off the trim size
Scrollable scrollable = (Scrollable) control;
Rectangle trim = scrollable.computeTrim(0, 0, 0, 0);
size.x = trim.width;
size.y = trim.height;
} else {
// For non-composites, subtract off 2 * the border size
size.x = control.getBorderWidth() * 2;
size.y = size.x;
}
return size;
}
private void checkPreferedThenOther(int whint, int hhint) {
resetCache();
sizeCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
checkCacheComputeSize(expectedSize, whint, hhint);
}
private void checkDoubleCall(int whint, int hhint) {
resetCache();
checkCacheComputeSize(expectedSize, whint, hhint);
// calling this again should return same value
checkCacheComputeSize(expectedSize, whint, hhint);
}
private void resetCache() {
sizeCache = new SizeCache(control);
}
private void checkCacheComputeSize(Point calcSize, int whint, int hhint) {
Point cachedSize = sizeCache.computeSize(whint, hhint);
assertEquals(calcSize, cachedSize);
}
private void update() {
shell.layout(true, true);
dispatch();
}
private void dispatch() {
if (humanWatching)
dispatch(200);
else
dispatch0();
}
private Composite createComposite(Composite parent, int flags) {
Composite comp = new Composite(parent, flags);
comp.setFont(parent.getFont());
comp.setBackground(comp.getDisplay().getSystemColor(SWT.COLOR_MAGENTA));
return comp;
}
private Composite createFillComp(Composite parent, int flags) {
Composite comp = createComposite(parent, flags);
GridLayoutFactory.fillDefaults().applyTo(comp);
Label l = createLabel(comp, LONG_TEXT, SWT.WRAP);
GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(l);
return comp;
}
private Composite createFixedComp(Composite parent, int flags) {
Composite comp = createComposite(parent, flags);
GridLayoutFactory.fillDefaults().applyTo(comp);
Label l = createLabel(comp, SHORT_TEXT, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.BEGINNING).applyTo(l);
return comp;
}
/**
* This does automatic test to make sure that cached size of control is the
* same as calculated size with different given hints
*
* @param inner
*/
private void checkCacheSize(Control inner) {
update();
control = inner;
Point size = controlComputeSize(SWT.DEFAULT, SWT.DEFAULT);
int w = size.x;
int h = size.y;
checkSizeEquals(SWT.DEFAULT, SWT.DEFAULT);
checkSizeEquals(w, SWT.DEFAULT); // preferred width
checkSizeEquals(w / 2, SWT.DEFAULT); // half of preferred width
checkSizeEquals(w * 2, SWT.DEFAULT); // bigger then preferred with
checkSizeEquals(SWT.DEFAULT, h);
checkSizeEquals(SWT.DEFAULT, h / 2);
checkSizeEquals(SWT.DEFAULT, h * 2);
checkSizeEquals(w, h);
checkSizeEquals(w / 2, h * 2);
checkSizeEquals(w * 2, h * 2);
checkSizeEquals(1, SWT.DEFAULT);
checkSizeEquals(SWT.DEFAULT, 1);
checkSizeEquals(0, 0);
checkAlterate(w, h);
checkAlterate(w * 2, h * 2);
checkAlterate(w / 2, h / 2);
}
@Test
public void testFixedLabel() {
checkCacheSize(createLabel(shell, SHORT_TEXT, SWT.NONE));
}
@Test
public void testWrapLabel() {
checkCacheSize(createLabel(shell, SHORT_TEXT, SWT.WRAP));
}
@Test
public void testFixedComp() {
checkCacheSize(createFixedComp(shell, SWT.NONE));
}
@Test
public void testFixedCompWithWrapFlag() {
checkCacheSize(createFixedComp(shell, SWT.WRAP));
}
@Test
public void testFillComp() {
checkCacheSize(createFillComp(shell, SWT.NONE));
}
@Test
public void testFillCompWithWrapFlag() {
checkCacheSize(createFillComp(shell, SWT.WRAP));
}
@Test
public void testFillCompWithBorder() {
checkCacheSize(createFillComp(shell, SWT.BORDER));
}
@Test
public void testWrapCompNonWrapLabels() {
Composite inner = createComposite(shell, SWT.NONE);
inner.setLayout(new TableWrapLayout());
createLabel(inner, SHORT_TEXT, SWT.NONE);
createLabel(inner, LONG_TEXT, SWT.NONE);
checkCacheSize(inner);
}
@Test
public void testWrapCompWrapLabels() {
Composite inner = createComposite(shell, SWT.NONE);
inner.setLayout(new TableWrapLayout());
createLabel(inner, SHORT_TEXT, SWT.WRAP);
createLabel(inner, LONG_TEXT, SWT.WRAP);
checkCacheSize(inner);
}
@Test
public void testFixedLabelLong() {
checkCacheSize(createLabel(shell, LONG_TEXT, SWT.NONE));
}
@Test
public void testWrapLabelLong() {
checkCacheSize(createLabel(shell, LONG_TEXT, SWT.WRAP));
}
@Test
public void testHyperlink() {
Hyperlink link = new Hyperlink(shell, SWT.NONE);
link.setText(LONG_TEXT);
link.setFont(shell.getFont());
checkCacheSize(link);
}
@Test
public void testHyperlinkWithBorder() {
Hyperlink link = new Hyperlink(shell, SWT.BORDER);
link.setText(LONG_TEXT);
link.setFont(shell.getFont());
checkCacheSize(link);
}
public void suppressed_testWrapHyperlink() {
Hyperlink link = new Hyperlink(shell, SWT.WRAP);
link.setText(LONG_TEXT);
link.setFont(shell.getFont());
checkCacheSize(link);
}
public void suppressed_testButton() {
checkCacheSize(createButton(shell, LONG_TEXT, SWT.PUSH));
}
@Test
public void testCheckButton() {
checkCacheSize(createButton(shell, LONG_TEXT, SWT.CHECK));
}
@Test
public void testWrapCompButtonsWrap() {
Composite inner = createComposite(shell, SWT.NONE);
inner.setLayout(new TableWrapLayout());
createButton(inner, SHORT_TEXT, SWT.WRAP | SWT.CHECK);
createButton(inner, LONG_TEXT, SWT.WRAP | SWT.CHECK);
checkCacheSize(inner);
}
@Test
public void testWrapCompWrapLabels3() {
Composite inner = createComposite(shell, SWT.NONE);
TableWrapLayout layout = new TableWrapLayout();
layout.numColumns = 3;
inner.setLayout(layout);
createLabel(inner, SHORT_TEXT, SWT.WRAP);
createLabel(inner, LONG_TEXT, SWT.WRAP);
checkCacheSize(inner);
}
@Test
public void testGripWrap3() {
Composite inner = createComposite(shell, SWT.BORDER);
GridLayoutFactory.fillDefaults().numColumns(3).applyTo(inner);
GridDataFactory gdf = GridDataFactory.fillDefaults();
createLabel(inner, SHORT_TEXT, SWT.WRAP).setLayoutData(gdf.create());
createLabel(inner, LONG_TEXT, SWT.WRAP).setLayoutData(gdf.create());
createLabel(inner, SHORT_TEXT, SWT.NONE).setLayoutData(gdf.create());
checkCacheSize(inner);
}
}