package org.eclipse.nebula.cwt.test;
import java.awt.Robot;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.eclipse.nebula.cwt.v.VControl;
import org.eclipse.nebula.cwt.v.VNative;
import org.eclipse.nebula.cwt.v.VPanel;
import org.eclipse.nebula.cwt.v.VTracker;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
public abstract class AbstractVTestCase extends TestCase {
private Thread t = new Thread("Test - " + getName()) {
@Override
public void run() {
try {
runTest();
} catch (Throwable e) {
if (exception == null) {
exception = e;
}
} finally {
testing = false;
if (display != null && !display.isDisposed()) {
display.wake();
}
}
}
};
private Point defaultSize;
private int delay = 100;
private Throwable exception = null;
private int stateMask = 0;
private Shell shell;
private Display display;
private String capturePath;
private int captureFormat = SWT.IMAGE_PNG;
private Object tmpObj;
private Set<Character> keyDownChars = new HashSet<Character>();
private Set<Integer> keyDownMods = new HashSet<Integer>();
private Set<Integer> mouseDowns = new HashSet<Integer>();
boolean testing = false;
protected void assertUserConfirm(final String message) {
syncExec(new Runnable() {
public void run() {
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.NO);
mb.setMessage(message);
mb.setText("User Confirmation");
tmpObj = mb.open();
}
});
assertTrue(message, tmpObj.equals(SWT.YES));
}
public void asyncExec(Runnable runnable) {
display.asyncExec(runnable);
}
public void capture(Control control) {
capture(control, null);
}
public void capture(final Control control, final String suffix) {
syncExec(new Runnable() {
public void run() {
Point location = control.getParent().toDisplay(control.getLocation());
Point size = control.getSize();
capture(new Rectangle(location.x, location.y, size.x, size.y), suffix);
}
});
}
public void capture(int x, int y, int width, int height) {
capture(x, y, width, height, null);
}
public void capture(int x, int y, int width, int height, String suffix) {
capture(new Rectangle(x, y, width, height), suffix);
}
private void capture(Rectangle bounds, String suffix) {
GC gc = new GC(display);
Image image = new Image(display, bounds);
gc.copyArea(image, bounds.x, bounds.y);
gc.dispose();
ImageData[] da = new ImageData[] { image.getImageData() };
image.dispose();
ImageLoader il = new ImageLoader();
il.data = da;
StringBuilder sb = new StringBuilder();
if (capturePath != null && capturePath.length() > 0) {
sb.append(capturePath);
} else {
sb.append(System.getProperty("user.home"));
}
File path = new File(sb.toString());
if (!path.exists()) {
path.mkdirs();
}
sb.append(File.separator);
sb.append(getName());
if (suffix != null && suffix.length() > 0) {
sb.append("-").append(suffix);
}
switch (captureFormat) {
case SWT.IMAGE_BMP:
sb.append(".bmp");
break;
case SWT.IMAGE_GIF:
sb.append(".gif");
break;
case SWT.IMAGE_ICO:
sb.append(".ico");
break;
case SWT.IMAGE_JPEG:
sb.append(".jpg");
break;
case SWT.IMAGE_PNG:
sb.append(".png");
break;
case SWT.IMAGE_TIFF:
sb.append(".tiff");
break;
default:
captureFormat = SWT.IMAGE_PNG;
sb.append(".png");
break;
}
il.save(sb.toString(), captureFormat);
}
public void capture(final VControl control) {
capture(control, null);
}
public void capture(final VControl control, final String suffix) {
syncExec(new Runnable() {
public void run() {
Point location = control.toDisplay(control.getLocation());
Point size = control.getSize();
capture(new Rectangle(location.x, location.y, size.x, size.y), suffix);
}
});
}
public void captureScreen() {
captureScreen(null);
}
public void captureScreen(final String suffix) {
syncExec(new Runnable() {
public void run() {
capture(display.getBounds(), suffix);
}
});
}
public void captureShell() {
captureShell(null);
}
public void captureShell(final String suffix) {
syncExec(new Runnable() {
public void run() {
capture(shell.getBounds(), suffix);
}
});
}
public void click() {
click(1);
}
public void click(Control control) {
click(control, 1);
}
public void click(Control control, int button) {
moveTo(control);
click(button);
}
public void click(int button) {
final int oldDelay = delay;
delay = 0;
mouseDown(button);
delay = oldDelay;
processEvents();
mouseUp(button);
processEvents();
}
public void click(VControl control) {
click(control, 1);
}
public void click(VControl control, int button) {
moveTo(control);
click(button);
}
public void doubleClick() {
click();
pause(display.getDoubleClickTime() / 2);
click();
}
public void doubleClick(VControl control) {
moveTo(control);
doubleClick();
}
public int getDelay() {
return delay;
}
public Display getDisplay() {
return display;
}
public Control getFocusControl() {
synchronized (this) {
syncExec(new Runnable() {
public void run() {
tmpObj = display.getFocusControl();
}
});
return (Control) tmpObj;
}
}
public VPanel getPanel(final Control control) {
final ArrayList<VPanel> result = new ArrayList<VPanel>();
syncExec(new Runnable() {
public void run() {
Object o = control.getData("cwt_vcontrol");
if (o instanceof VPanel)
result.add((VPanel) o);
else
result.add(null);
}
});
return result.get(0);
}
public Composite getComposite(final VPanel panel) {
final ArrayList<Composite> result = new ArrayList<Composite>();
syncExec(new Runnable() {
public void run() {
result.add(panel.getComposite());
}
});
return result.get(0);
}
protected Shell getShell() {
return shell;
}
public boolean hasFocus(Control control) {
synchronized (this) {
processEvents();
syncExec(new Runnable() {
public void run() {
tmpObj = display.getFocusControl();
}
});
return tmpObj == control;
}
}
public boolean hasFocus(VControl control) {
processEvents();
return control == VTracker.getFocusControl();
}
public boolean hasFocus(VNative<? extends Control> vnative) {
return hasFocus(vnative.getControl());
}
public void keyDown(char character) {
keyDownChars.add(character);
Event event = new Event();
event.type = SWT.KeyDown;
event.character = character;
display.post(event);
pause(delay);
}
public void keyDown(int keyCode) {
keyDownMods.add(keyCode);
Event event = new Event();
event.type = SWT.KeyDown;
event.keyCode = keyCode;
display.post(event);
pause(delay);
}
public void keyPress(char character) {
final int oldDelay = delay;
delay = 0;
keyDown(character);
delay = oldDelay;
processEvents();
keyUp(character);
processEvents();
}
public void keyPress(int keyCode) {
final int oldDelay = delay;
delay = 0;
keyDown(keyCode);
delay = oldDelay;
processEvents();
keyUp(keyCode);
processEvents();
}
public void keyPress(char character, int... keyCodes) {
for (int keyCode : keyCodes) {
keyDown(keyCode);
}
keyDown(character);
keyUp(character);
for (int keyCode : keyCodes) {
keyUp(keyCode);
}
}
public void keyUp(char character) {
keyDownChars.remove(character);
Event event = new Event();
event.type = SWT.KeyUp;
event.character = character;
display.post(event);
pause(delay);
}
public void keyUp(int keyCode) {
keyDownMods.remove(keyCode);
Event event = new Event();
event.type = SWT.KeyUp;
event.keyCode = keyCode;
display.post(event);
pause(delay);
}
public void layoutShell() {
syncExec(new Runnable() {
public void run() {
if (defaultSize != null) {
shell.setSize(defaultSize);
} else if (shell.getChildren().length > 0) {
shell.pack();
}
Point size = shell.getSize();
Rectangle screen = display.getMonitors()[0].getBounds();
shell.setBounds((screen.width - size.x) / 2, (screen.height - size.y) / 2, size.x, size.y);
}
});
}
public void mouseDown() {
mouseDown(1);
}
public void mouseDown(Control control) {
mouseDown(control, 1);
}
public void mouseDown(Control control, int button) {
moveTo(control);
mouseDown(control);
}
public void mouseDown(int button) {
mouseDowns.add(button);
Event event = new Event();
event.type = SWT.MouseDown;
event.button = button;
// event.stateMask = stateMask;
// event.data = VTracker.getActiveControl();
display.post(event);
pause(delay);
}
public void mouseDown(VControl control) {
mouseDown(control, 1);
}
public void mouseDown(VControl control, int button) {
moveTo(control);
mouseDown(button);
}
public void mouseUp() {
mouseUp(1);
}
public void mouseUp(int button) {
mouseDowns.remove(button);
Event event = new Event();
event.type = SWT.MouseUp;
event.button = button;
// event.stateMask = stateMask;
// event.data = VTracker.getActiveControl();
display.post(event);
pause(delay);
}
public void mouseWheel(int count) {
// Event event = new Event();
// event.type = SWT.MouseWheel;
// event.data = VTracker.getActiveControl();
// event.detail = SWT.SCROLL_LINE;
// event.x = x;
// event.y = y;
// event.count = count;
// display.post(event);
try {
Robot robot = new Robot();
robot.mouseWheel(count);
} catch (Exception e) {
e.printStackTrace();
}
pause(delay);
}
public void move(final int x, final int y) {
display.syncExec(new Runnable() {
public void run() {
Point point = display.getCursorLocation();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = point.x + x;
event.y = point.y + y;
display.post(event);
event.x += 1;
display.post(event);
}
});
pause(delay);
}
public void moveTo(final Control control) {
syncExec(new Runnable() {
public void run() {
Point location = control.getParent().toDisplay(control.getLocation());
Point size = control.getSize();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = location.x + (size.x / 2) - 1;
event.y = location.y + (size.y / 2);
display.post(event);
event.x += 1;
display.post(event);
}
});
pause(delay);
}
public void moveTo(final int x, final int y) {
display.syncExec(new Runnable() {
public void run() {
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = x;
event.y = y;
display.post(event);
event.x += 1;
display.post(event);
}
});
pause(delay);
}
public void moveX(final int x) {
display.syncExec(new Runnable() {
public void run() {
Point location = getDisplay().getCursorLocation();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = location.x + x;
event.y = location.y;
display.post(event);
event.x += 1;
display.post(event);
}
});
pause(delay);
}
public void moveY(final int y) {
display.syncExec(new Runnable() {
public void run() {
Point location = getDisplay().getCursorLocation();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = location.x;
event.y = location.y + y;
display.post(event);
event.x += 1;
display.post(event);
}
});
pause(delay);
}
public void moveTo(final VControl control) {
syncExec(new Runnable() {
public void run() {
Point location = control.toDisplay(control.getLocation());
Point size = control.getSize();
int multiplier = (control.getShell().getStyle() & SWT.LEFT_TO_RIGHT) == SWT.LEFT_TO_RIGHT ? 1 : -1;
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = location.x + ((size.x / 2) * multiplier) - 1;
event.y = location.y + (size.y / 2);
display.post(event);
processEvents();
event.x += 1;
display.post(event);
}
});
processEvents();
pause(delay);
}
public void moveToEdge(final Control control, final int edge) {
syncExec(new Runnable() {
public void run() {
Point location = control.toDisplay(control.getLocation());
Point size = control.getSize();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
if ((edge & SWT.LEFT) != 0) {
event.x = location.x;
} else if ((edge & SWT.RIGHT) != 0) {
event.x = location.x + size.x - 1;
} else {
event.x = location.x + (size.x / 2) - 1;
}
if ((edge & SWT.TOP) != 0) {
event.y = location.y;
} else if ((edge & SWT.BOTTOM) != 0) {
event.y = location.y + size.y - 1;
} else {
event.y = location.y + (size.y / 2) - 1;
}
display.post(event);
processEvents();
event.x += 1;
display.post(event);
}
});
processEvents();
pause(delay);
}
public void moveToEdge(final VControl control, final int edge) {
syncExec(new Runnable() {
public void run() {
Point location = control.toDisplay(control.getLocation());
Point size = control.getSize();
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
if ((edge & SWT.LEFT) != 0) {
event.x = location.x;
} else if ((edge & SWT.RIGHT) != 0) {
event.x = location.x + size.x - 1;
} else {
event.x = location.x + (size.x / 2) - 1;
}
if ((edge & SWT.TOP) != 0) {
event.y = location.y;
} else if ((edge & SWT.BOTTOM) != 0) {
event.y = location.y + size.y - 1;
} else {
event.y = location.y + (size.y / 2) - 1;
}
display.post(event);
processEvents();
event.x += 1;
display.post(event);
}
});
processEvents();
pause(delay);
}
public void moveTo(final VControl control, final int step) {
syncExec(new Runnable() {
public void run() {
Point location = control.toDisplay(control.getLocation());
Point size = control.getSize();
Point start = display.getCursorLocation();
Point end = new Point(location.x + (size.x / 2), location.y + (size.y / 2));
int x = start.x;
int y = start.y;
while (x < end.x || y < end.y) {
if (x < end.x) {
x += step;
}
if (y < end.y) {
y += step;
}
Event event = new Event();
event.type = SWT.MouseMove;
event.stateMask = stateMask;
event.x = x;
event.y = y;
display.post(event);
processEvents();
pause(10);
}
}
});
pause(delay);
}
public void pause(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
}
public void processEvents() {
syncExec(new Runnable() {
public void run() {
while (display.readAndDispatch()) {
}
}
});
}
public void redraw() {
redraw(shell);
}
public void redraw(final Control control) {
syncExec(new Runnable() {
public void run() {
control.redraw();
}
});
}
public void releaseAllEvents() {
processEvents();
delay = 0;
for (Integer button : mouseDowns) {
mouseUp(button);
}
for (Integer keyCode : keyDownMods) {
keyUp(keyCode);
}
for (Character character : keyDownChars) {
keyUp(character);
}
processEvents();
}
public void runBare() throws Throwable {
final String name = getName();
display = Display.getDefault();
display.syncExec(new Runnable() {
public void run() {
shell = createShell();
shell.setText(name);
shell.setLayout(new FillLayout());
try {
setUp();
} catch (Exception e) {
exception = e;
}
layoutShell();
shell.open();
pause(500);
processEvents();
testing = true;
if (name.endsWith("_Sync")) {
t.run();
} else {
t.start();
}
while (testing && !shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
try {
tearDown();
} catch (Exception e) {
exception = e;
}
display.dispose();
display = null;
}
});
if (exception != null) {
throw exception;
}
}
/**
* Creates the {@link Shell}, override for a special shell.
*
* @return
*/
public Shell createShell() {
return new Shell(display);
}
public void setCaptureFormat(int format) {
switch (captureFormat) {
case SWT.IMAGE_BMP:
case SWT.IMAGE_GIF:
case SWT.IMAGE_ICO:
case SWT.IMAGE_JPEG:
case SWT.IMAGE_PNG:
case SWT.IMAGE_TIFF:
captureFormat = format;
break;
default:
captureFormat = SWT.IMAGE_PNG;
}
}
public void setCapturePath(String path) {
capturePath = path;
}
public void setDefaultShellSize(Point size) {
defaultSize = size;
}
public void setDelay(int delay) {
this.delay = delay;
}
@Override
protected void setUp() throws Exception {
String name = getName();
Method method = null;
// TODO: pick a format and stick to it :)
try {
String setup = "setup" + name.substring(4);
method = getClass().getMethod(setup, new Class[0]);
} catch (NoSuchMethodException e) {
// nothing to do
}
if (method == null) {
try {
String setup = Character.toLowerCase(name.charAt(4)) + name.substring(5) + "Setup";
method = getClass().getMethod(setup, new Class[0]);
} catch (NoSuchMethodException e) {
// nothing to do
}
}
if (method == null) {
try {
String[] sa = name.split("_");
String s = sa[sa.length - 1];
method = getClass().getMethod("setUp" + Integer.valueOf(s), new Class[0]);
} catch (NoSuchMethodException e) {
// nothing to do
} catch (NumberFormatException e) {
// nothing to do
}
}
if (method != null) {
method.invoke(this, new Object[0]);
}
}
public void syncExec(Runnable runnable) {
display.syncExec(runnable);
}
@Override
protected void tearDown() throws Exception {
releaseAllEvents();
super.tearDown();
}
}