/*******************************************************************************
* Breakout Cave Survey Visualizer
*
* Copyright (C) 2014 James Edwards
*
* jedwards8 at fastmail dot fm
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*******************************************************************************/
package org.andork.ui.test;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
/**
* A {@link Ghost} wrapper that automatically delays between events (introduces
* the same auto-delay behavior as in {@link Robot} to the {@link Ghost}
* paradigm).
*
* @author andy.edwards
*/
public class SlowGhost implements Ghost {
private static final int MAX_DELAY = 60000;
Ghost wrapped;
private boolean isAutoWaitForIdle = false;
private int autoDelay = 0;
public SlowGhost(Ghost wrapped, boolean isAutoWaitForIdle, int autoDelay) {
super();
this.wrapped = wrapped;
this.isAutoWaitForIdle = isAutoWaitForIdle;
this.autoDelay = autoDelay;
}
/*
* Called after an event is generated
*/
private void afterEvent() {
autoWaitForIdle();
autoDelay();
}
/*
* Automatically sleeps for the specified interval after event generated.
*/
private void autoDelay() {
delay(autoDelay);
}
/*
* Calls waitForIdle after every event if so desired.
*/
private void autoWaitForIdle() {
if (isAutoWaitForIdle) {
AutomatedTesting.flushEDT();
}
}
private void checkDelayArgument(int ms) {
if (ms < 0 || ms > MAX_DELAY) {
throw new IllegalArgumentException("Delay must be to 0 to 60,000ms");
}
}
/**
* Sleeps for the specified time. To catch any
* <code>InterruptedException</code>s that occur,
* <code>Thread.sleep()</code> may be used instead.
*
* @param ms
* time to sleep in milliseconds
* @throws IllegalArgumentException
* if <code>ms</code> is not between 0 and 60,000 milliseconds
* inclusive
* @see java.lang.Thread#sleep
*/
public void delay(int ms) {
checkDelayArgument(ms);
try {
Thread.sleep(ms);
} catch (InterruptedException ite) {
ite.printStackTrace();
}
}
/**
* Returns the number of milliseconds this SlowGhost sleeps after generating
* an event.
*/
public synchronized int getAutoDelay() {
return autoDelay;
}
/**
* Returns whether this SlowGhost automatically invokes
* <code>waitForIdle</code> after generating an event.
*
* @return Whether <code>waitForIdle</code> is automatically called
*/
public synchronized boolean isAutoWaitForIdle() {
return isAutoWaitForIdle;
}
@Override
public InputBuilder on(Component c) {
return new InputBuilder(c) {
InputBuilder wrapped = SlowGhost.this.wrapped.on(comp);
@Override
public InputBuilder alt() {
wrapped.alt();
return this;
}
@Override
public InputBuilder at(Point mouseLocation) {
wrapped.at(mouseLocation);
afterEvent();
return this;
}
@Override
public InputBuilder backspace() {
wrapped.backspace();
afterEvent();
return this;
}
@Override
public InputBuilder click(int button, int clickCount) {
wrapped.click(button, clickCount);
afterEvent();
return this;
}
@Override
public InputBuilder ctrl() {
wrapped.ctrl();
return this;
}
@Override
public InputBuilder delete() {
wrapped.delete();
afterEvent();
return this;
}
@Override
public InputBuilder enter() {
wrapped.enter();
afterEvent();
return this;
}
@Override
public InputBuilder leftClick() {
wrapped.leftClick();
afterEvent();
return this;
}
@Override
public InputBuilder middleClick() {
wrapped.middleClick();
afterEvent();
return this;
}
@Override
public InputBuilder press(int keyCode) {
wrapped.press(keyCode);
afterEvent();
return this;
}
@Override
public InputBuilder release(int keyCode) {
wrapped.release(keyCode);
afterEvent();
return this;
}
@Override
public InputBuilder rightClick() {
wrapped.rightClick();
afterEvent();
return this;
}
@Override
public InputBuilder shift() {
wrapped.shift();
return this;
}
@Override
public InputBuilder type(int keyCode) {
wrapped.type(keyCode);
afterEvent();
return this;
}
};
}
@Override
public synchronized void scroll(Component c, Rectangle toBounds) {
wrapped.scroll(c, toBounds);
afterEvent();
}
/**
* Sets the number of milliseconds this SlowGhost sleeps after generating an
* event.
*
* @throws IllegalArgumentException
* If <code>ms</code> is not between 0 and 60,000 milliseconds
* inclusive
*/
public synchronized void setAutoDelay(int ms) {
checkDelayArgument(ms);
autoDelay = ms;
}
/**
* Sets whether this SlowGhost automatically invokes
* <code>waitForIdle</code> after generating an event.
*
* @param isOn
* Whether <code>waitForIdle</code> is automatically invoked
*/
public synchronized void setAutoWaitForIdle(boolean isOn) {
isAutoWaitForIdle = isOn;
}
@Override
public synchronized void type(Component c, String text) {
wrapped.type(c, text);
afterEvent();
}
}