/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.internal.swing;
import java.lang.reflect.*;
import java.awt.Component;
import java.awt.Point;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JTable;
import abbot.tester.ActionFailedException;
import abbot.tester.ComponentMissingException;
import abbot.util.AWT;
import com.windowtester.internal.runtime.Platform;
import com.windowtester.internal.runtime.RuntimePlugin;
import com.windowtester.internal.runtime.preferences.PlaybackSettings;
public class DelayUIDriverSwing extends UIDriverSwing {
private static boolean printMessage = false;
/**
* Create an instance (using the default settings).
*/
public DelayUIDriverSwing() {
//this(RuntimePlugin.getDefault().getPlaybackSettings());
try {
if (Platform.isRunning())
_settings = RuntimePlugin.getDefault().getPlaybackSettings();
} catch (Throwable t) {
//ignore: if an exception occurs we will properly setup settings below
//TODO: this is NOT a clean way to do this! wee _should_ clean it up!
}
if (_settings == null)
_settings = PlaybackSettings.loadFromFile();
// pc = getPresentationContext();
// pc.setDefaultShowNoteDuration(5000);
}
/**
* Create an instance.
* @param settings
*/
public DelayUIDriverSwing(PlaybackSettings settings) {
_settings = settings;
// pc = getPresentationContext();
}
public Component click(Component owner, String labelOrPath) throws ComponentMissingException, ActionFailedException {
Component c = super.click(owner, labelOrPath);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component click(int clickCount, Component w, int x, int y, int mask) {
//first move the mouse to the point of interest:
mouseMove(w);
Component c = super.click(clickCount, w, x, y, mask);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component clickComboBox(JComboBox owner, String labelOrPath, int clickCount) throws ActionFailedException {
//first move the mouse to the point of interest:
mouseMove(owner);
Component c = super.clickComboBox(owner, labelOrPath, clickCount);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component clickListItem(int clickCount, JList owner, String labelOrPath, int mask) throws ActionFailedException {
//first move the mouse to the point of interest:
mouseMove(owner);
Component c = super.clickListItem(clickCount, owner, labelOrPath, mask);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component clickMenuItem(JMenuItem owner) {
Component c = super.clickMenuItem(owner);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component clickTable(int clickCount, JTable owner, int row, int col, int mask) {
mouseMove(owner);
Component c = super.clickTable(clickCount, owner, row, col, mask);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public Component clickTreeItem(int clickCount, Component owner, String path, int mask) {
Component c = super.clickTreeItem(clickCount, owner, path, mask);
//pause
if (_settings.getDelayOn())
pause(_settings.getWidgetClickDelay());
return c;
}
public void keyClick(char key) {
super.keyClick(key);
pause(_settings.getKeyClickDelay());
}
public void keyClick(int ctrl, char c) {
super.keyClick(ctrl, c);
pause(_settings.getKeyClickDelay());
}
public void keyClick(int key) {
super.keyClick(key);
pause(_settings.getKeyClickDelay());
}
private Point pointT;
private Point cursorT;
public void mouseMove(Component w, int x, int y) {
int delay = _settings.getMouseMoveDelay();
if (!_settings.getDelayOn() || delay == 0) {
super.mouseMove(w, x, y);
return;
}
// get location of the widget
pointT = AWT.getLocationOnScreen(w);
// get current location of the cursor/mouse for jre 1.5 and above
// PointerInfo info = MouseInfo.getPointerInfo();
// cursorT = info.getLocation();
// since build system is 1.4, use reflection to make calls
try {
Class c = Class.forName("java.awt.MouseInfo");
Method m = c.getMethod("getPointerInfo",null);
Object o = m.invoke(null,null);
Class cPointer = Class.forName("java.awt.PointerInfo");
Method method = cPointer.getMethod("getLocation",null);
cursorT = (Point)method.invoke(o,null);
}
catch (Throwable e) {
if (!printMessage){
System.out.println("Mouse Delay not supported, turn off Mouse Delay in Window->Preferences->WindowTester->Playback");
printMessage = true;
}
return;
}
Point cursorLocation = cursorT;
Point target = new Point(pointT.x+x,pointT.y+y);
Point[] path = getPath(cursorLocation, target);
for (int i = 0; i < path.length; i++) {
super.mouseMove(path[i].x, path[i].y);
pause(delay);
}
}
public void enterText(String txt) throws ActionFailedException {
if (!_settings.getDelayOn() || _settings.getKeyClickDelay() == 0) {
super.enterText(txt);
return;
}
//enter text one char at a time, pausing as we go
for (int i=0; i <= txt.length()-1; ++i) {
keyClick(txt.charAt(i));
}
}
//////////////////////////////////////////////////////////////////////
//
//
// Utility methods
//
//
/////////////////////////////////////////////////////////////////////
public static Point[] getPath(Point p1, Point p2) {
int numSteps = getNumSteps(p1, p2);
return getPath(p1, p2, numSteps+3);
}
private static int getNumSteps(Point p1, Point p2) {
int dx = Math.abs(p1.x - p2.x);
int dy = Math.abs(p1.y - p2.y);
int numSteps = Math.max(dx, dy);
return numSteps;
}
public static Point[] getPath(Point p1, Point p2, int numSteps) {
int[] xsteps = getSteps(p1.x, p2.x, numSteps);
int[] ysteps = getSteps(p1.y, p2.y, numSteps);
Point[] points = new Point[xsteps.length];
for (int i=0; i < xsteps.length; ++i)
points[i] = new Point(xsteps[i], ysteps[i]);
return points;
}
static int[] getSteps(int start, int stop, int numOfSteps) {
float[] fsteps = new float[numOfSteps];
int[] steps = new int[numOfSteps];
float delta = stop - start;
float increment = delta/numOfSteps;
fsteps[0] = start;
for (int i=1; i < numOfSteps; ++i) {
fsteps[i] = fsteps[i-1] + increment;
}
for (int i = 0; i < numOfSteps; ++i) {
steps[i] = Math.round(fsteps[i]);
}
//sanity check last coord:
steps[numOfSteps-1] = stop;
return steps;
}
}