/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company 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:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.extests.uiAttributes;
import static com.rcpcompany.test.utils.ui.UITestUtils.*;
import static org.junit.Assert.*;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.jface.util.Util;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.junit.After;
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 com.rcpcompany.uibindings.DecorationPosition;
import com.rcpcompany.uibindings.IManager;
import com.rcpcompany.uibindings.IUIAttribute;
import com.rcpcompany.uibindings.IUIAttributeImageDecoration;
import com.rcpcompany.uibindings.UIBindingsUtils;
import com.rcpcompany.uibindings.tests.utils.BaseUIBTestUtils;
import com.rcpcompany.uibindings.tests.utils.views.UIBTestView;
import com.rcpcompany.uibindings.uiAttributes.SimpleUIAttribute;
import com.rcpcompany.uibindings.utils.IPaintDecoration;
/**
* Test of image decorations.
*
* @author Tonny Madsen, The RCP Company
*/
@RunWith(Parameterized.class)
public class UIAttributeImageDecorationTest<T extends Control> {
private final Class<T> myWidgetClass;
private final Point mySizes;
private final boolean myOutside;
private final DecorationPosition myPosition;
private final int myX;
private final int myY;
private final float myAddWidthFactor;
private final float myAddHeightFactor;
private final int myBorderWidth;
private final String what;
@Parameters
public static Collection<Object[]> data() {
final List<Object[]> filtered = new ArrayList<Object[]>();
final List<Object[]> c = Arrays.asList(new Object[][] {
/*
* widgetClass, sizes (Point), outside, xLeft, xRight, yTop, yCenter, yBottom,
* borderWidth, isEnabled
*/
// Text
{ Text.class, null, false, 0, 0, 0, 0, 0, 0, true },
{ Text.class, null, true, 0, 0, 0, 0, 0, 0, Util.isMac() },
{ Text.class, null, true, 6, -6, 1, 0, -1, 0, Util.isWindows() },
// Combo
/*
* INNER on Windows: does not seem to work!
*/
{ Combo.class, null, false, 1, -21, 2, -1, -5, 0, Util.isMac() },
{ Combo.class, null, true, 0, 0, 2, -1, -5, 0, Util.isMac() },
{ Combo.class, null, true, 0, 0, 0, 0, 0, 0, Util.isWindows() },
// CCombo
/*
* INNER NOT POSSIBLE due to the way the inner controls are protected, so we cannot
* add a paint listener
*/
// { CCombo.class, null, false, 0, 0, 0, 0, 0, 0, true },
{ CCombo.class, null, true, 0, 0, 0, -1, -2, 0, Util.isMac() },
{ CCombo.class, null, true, 2, 2, 1, 0, -2, 0, Util.isWindows() },
// StyledText
{ StyledText.class, null, false, 0, -3, 0, -1, -2, 0, Util.isMac() },
{ StyledText.class, null, false, 0, 0, 0, 0, 0, 0, Util.isWindows() },
{ StyledText.class, null, true, 0, 0, 0, -1, -2, 0, Util.isMac() },
{ StyledText.class, null, true, 2, -2, 1, 0, -1, 0, Util.isWindows() },
// Button
{ Button.class, null, false, 14, -14, 5, -2, -9, 0, Util.isMac() },
{ Button.class, null, false, 4, -4, 2, -1, -5, 0, Util.isWindows() },
{ Button.class, null, true, 5, -5, 5, -2, -9, 0, Util.isMac() },
{ Button.class, null, true, 0, 0, 3, -1, -6, 0, Util.isWindows() },
// Composite (small)
{ Composite.class, new Point(100, 30), false, 0, 0, 0, 0, 0, 0, Util.isMac() },
{ Composite.class, new Point(100, 30), false, 0, -1, 0, 0, 0, 0, Util.isWindows() },
{ Composite.class, new Point(100, 30), true, 0, 4, 0, 1, 2, 0, Util.isMac() },
{ Composite.class, new Point(100, 30), true, 2, 10, 1, 3, 5, 0, Util.isWindows() },
// Composite (big)
{ Composite.class, new Point(100, 50), false, 0, 0, 0, -15, -30, 0, Util.isMac() },
{ Composite.class, new Point(100, 50), false, 0, -1, 0, -15, -30, 0, Util.isWindows() },
{ Composite.class, new Point(100, 50), true, 0, 4, 0, -14, -28, 0, Util.isMac() },
{ Composite.class, new Point(100, 50), true, 2, 10, 1, -12, -25, 0, Util.isWindows() },
// Table
/*
* INSIDE: does not make sense
*/
{ Table.class, new Point(100, 50), true, 0, 19, 0, -17, -33, 0, Util.isMac() },
{ Table.class, new Point(100, 50), true, 2, 27, 1, -12, -25, 0, Util.isWindows() },
// Tree
/*
* INSIDE: does not make sense
*/
{ Tree.class, new Point(100, 50), true, 0, 19, 0, -17, -33, 0, Util.isMac() },
{ Tree.class, new Point(100, 50), true, 2, 27, -21, -34, -47, 0, Util.isWindows() },
});
for (final Object[] e : c) {
if (e[9] == Boolean.FALSE) {
continue;
}
final Class<?> widgetClass = (Class<?>) e[0];
final Point sizes = (Point) e[1];
final boolean outside = (Boolean) e[2];
final int xLeft = (Integer) e[3];
final int xRight = (Integer) e[4];
final int yTop = (Integer) e[5];
final int yCenter = (Integer) e[6];
final int yBottom = (Integer) e[7];
final int borderWidth = (Integer) e[8];
if (sizes == null) {
if (!outside) {
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_LEFT, outside, xLeft - 0,
yTop, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_RIGHT, outside,
-SQUARE_SIZE + xRight + 0, yTop, 1.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_LEFT, outside, xLeft - 0,
-SQUARE_SIZE / 2 + yCenter, 0.0f, 0.5f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_RIGHT, outside,
-SQUARE_SIZE + xRight + 0, -SQUARE_SIZE / 2 + yCenter, 1.0f, 0.5f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_LEFT, outside, xLeft - 0,
-SQUARE_SIZE + yBottom, 0.0f, 1.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_RIGHT, outside,
-SQUARE_SIZE + xRight + 0, -SQUARE_SIZE + yBottom, 1.0f, 1.0f, borderWidth, true });
} else {
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH, yTop, 0.0f, 0.0f,
borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH, yTop, 1.0f, 0.0f, borderWidth,
true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH,
-SQUARE_SIZE / 2 + yCenter, 0.0f, 0.5f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH, -SQUARE_SIZE / 2 + yCenter, 1.0f,
0.5f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH,
-SQUARE_SIZE + yBottom, 0.0f, 1.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH, -SQUARE_SIZE + yBottom, 1.0f,
1.0f, borderWidth, true });
}
} else {
if (!outside) {
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_LEFT, outside, xLeft - 0,
yTop, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_RIGHT, outside,
-SQUARE_SIZE + xRight + 0 + sizes.x, yTop, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_LEFT, outside, xLeft - 0,
-SQUARE_SIZE / 2 + yCenter + sizes.y / 2, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_RIGHT, outside,
-SQUARE_SIZE + xRight + 0 + sizes.x, -SQUARE_SIZE / 2 + yCenter + sizes.y / 2, 0.0f, 0.0f,
borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_LEFT, outside, xLeft - 0,
-SQUARE_SIZE + yBottom + sizes.y, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_RIGHT, outside,
-SQUARE_SIZE + xRight + 0 + sizes.x, -SQUARE_SIZE + yBottom + sizes.y, 0.0f, 0.0f,
borderWidth, true });
} else {
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH, yTop, 0.0f, 0.0f,
borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.TOP_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH + sizes.x, yTop, 0.0f, 0.0f,
borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH,
-SQUARE_SIZE / 2 + yCenter + sizes.y / 2, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.CENTER_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH + sizes.x,
-SQUARE_SIZE / 2 + yCenter + sizes.y / 2, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_LEFT, outside,
xLeft - SQUARE_SIZE - IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH,
-SQUARE_SIZE + yBottom + sizes.y, 0.0f, 0.0f, borderWidth, true });
filtered.add(new Object[] { widgetClass, sizes, DecorationPosition.BOTTOM_RIGHT, outside,
xRight + IUIAttributeImageDecoration.OUTER_MARGIN_WIDTH + sizes.x,
-SQUARE_SIZE + yBottom + sizes.y, 0.0f, 0.0f, borderWidth, true });
}
}
}
final List<Object[]> l = Arrays.asList(new Object[][] {
/*
* widgetClass (Class<T>), sizes (Point), position, outside, x, y, addWidthFactor,
* addHeightFactor, borderWidth, isEnabled
*/
});
for (final Object[] e : l) {
if (e[8] == Boolean.FALSE) {
continue;
}
filtered.add(e);
}
return filtered;
}
public UIAttributeImageDecorationTest(Class<T> widgetClass, final Point sizes, final DecorationPosition position,
final boolean outside, final int x, final int y, final float addWidth, final float addHeight,
final int borderWidth, boolean isEnabled) {
myWidgetClass = widgetClass;
mySizes = sizes;
myPosition = position;
myOutside = outside;
myX = x;
myY = y;
myAddWidthFactor = addWidth;
myAddHeightFactor = addHeight;
myBorderWidth = borderWidth;
what = myWidgetClass.getSimpleName() + ": p=" + myPosition + " outside=" + myOutside + " [" + myX + ";" + myY
+ "] bw=" + myBorderWidth + (mySizes == null ? "" : ", size=" + mySizes);
// LogUtils.debug(this, "========== " + what);
}
private static final int SQUARE_SIZE = 8;
@Before
public void before() {
BaseUIBTestUtils.resetAll();
IManager.Factory.getManager().setEditCellSingleClick(false);
createView();
yield();
myOV = WritableValue.withValueType(String.class);
myAttribute = new SimpleUIAttribute(myWidget, null, myOV);
myView.getSite().getPage().activate(myView);
}
private UIBTestView myView;
private Composite myBody;
private T myWidget;
private WritableValue myOV;
private IUIAttribute myAttribute;
/**
* Creates the view
*/
public void createView() {
myView = BaseUIBTestUtils.createUIBTestView(this);
myBody = myView.getBody();
try {
final Constructor<T> constructor = myWidgetClass.getConstructor(Composite.class, Integer.TYPE);
assertNotNull(what, constructor);
myWidget = constructor.newInstance(myBody, SWT.BORDER);
/*
* A little configuration of some widget types
*/
if (myWidgetClass == Table.class) {
final Table t = (Table) myWidget;
final TableColumn column = new TableColumn(t, SWT.NONE);
column.setWidth(100);
column.setText("Hello");
t.setHeaderVisible(true);
}
if (myWidgetClass == Tree.class) {
final Tree t = (Tree) myWidget;
final TreeColumn column = new TreeColumn(t, SWT.NONE);
column.setWidth(100);
column.setText("Hello");
t.setHeaderVisible(true);
}
final GridData ld = new GridData(SWT.CENTER, SWT.CENTER, true, true);
if (mySizes != null) {
ld.widthHint = mySizes.x;
ld.heightHint = mySizes.y;
} else {
ld.widthHint = 100;
// ld.heightHint = 20;
}
myWidget.setLayoutData(ld);
myBody.layout();
} catch (final Exception ex) {
fail(ex.getMessage());
}
}
@After
public void disposeView() {
if (myView != null) {
myView.getSite().getPage().hideView(myView);
}
}
protected final RGB white = new RGB(255, 255, 255);
protected final RGB rgb1 = new RGB(90, 100, 110);
protected final RGB rgb2 = new RGB(190, 100, 110);
protected final Image myImage1 = UIBindingsUtils.getSquareImage(rgb1, SQUARE_SIZE);
protected final Image myImage2 = UIBindingsUtils.getSquareImage(rgb2, SQUARE_SIZE);
@Test
public void testOneImage() {
int x = myX;
int y = myY;
final Point size = myWidget.getSize();
final int bw = myWidget.getBorderWidth();
// LogUtils.debug(myWidget, myAttribute + ": s=" + size + ", trim=" + bw + ", ca="
// + (myWidget instanceof Scrollable ? ((Scrollable) myWidget).getClientArea() : null));
if (myOutside) {
if (myWidget instanceof Scrollable) {
final Scrollable s = (Scrollable) myWidget;
final Rectangle r = s.computeTrim(0, 0, size.x, size.y);
x += r.x;
if ((myWidget instanceof Table) || (myWidget instanceof Tree)) {
/*
* For Table and Tree, we must adjust for the header line
*/
y += r.y;
}
size.x = r.width;
}
size.y += 2;
x -= bw;
y -= bw + 1;
} else {
size.x -= 2 * bw;
size.y -= 2 * bw;
}
x += myAddWidthFactor * size.x;
y += myAddHeightFactor * size.y;
final Display display = myWidget.getDisplay();
final Rectangle r2 = new Rectangle(x - 1, y - 1, SQUARE_SIZE + 1, SQUARE_SIZE + 1);
IPaintDecoration.Factory.paintRectangle(myWidget, r2, display.getSystemColor(SWT.COLOR_DARK_RED));
testImage(myPosition, myOutside, x, y);
}
public void testImage(DecorationPosition position, boolean outside, int x, int y) {
final IUIAttributeImageDecoration decoration = myAttribute.getImageDecoration(position, outside);
assertNotNull(decoration);
decoration.getImageValue().setValue(myImage1);
sleep(100);
testSquare(x, y, rgb1);
decoration.getImageValue().setValue(myImage2);
sleep(100);
testSquare(x, y, rgb2);
}
/**
* @param x
* @param y
* @param rgb TODO
*/
private void testSquare(final int x, final int y, RGB rgb) {
yield();
/*
* Test that the background color is white - the top-left corner
*/
assertPixelColor(what + " - body", myBody, 0, 0, white);
/*
* Test that the complete square is visible
*/
for (int dx = 0; dx < SQUARE_SIZE; dx++) {
for (int dy = 0; dy < SQUARE_SIZE; dy++) {
assertTranslatedPixel(x + dx, y + dy, rgb);
}
}
}
/**
* @param x
* @param y
* @param rgb
*/
private void assertTranslatedPixel(final int x, final int y, RGB rgb) {
final Point p = myWidget.getDisplay().map(myWidget, myBody, x, y);
assertPixelColor(what + " - inner", myBody, p.x, p.y, rgb);
}
}