package abbot.script;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import abbot.*;
import abbot.finder.*;
import abbot.tester.ComponentTester;
import abbot.util.AWT;
/** Script step to generate a single AWT event to a component. Currently
* used for key down/up and mouse motion.
*/
// TODO: Save mouse motion/enter/leave as relative to containing window/frame,
// in case frame moves
public class Event extends Step {
private static final String USAGE =
"<event type=\"...\" kind=\"...\" [...]/>";
private String componentID = null;
private String type = null;
private String kind = null;
private Map eventAttributes = new HashMap();
public Event(Resolver resolver, Map attributes) {
super(resolver, attributes);
componentID = (String)attributes.get(TAG_COMPONENT);
// can't create events without a component, so creation of the event
// is deferred. we do check for validity, though.
parseEvent(attributes);
}
/** Create one based on the given event. */
public Event(Resolver resolver, String desc, AWTEvent event) {
super(resolver, desc);
int id = event.getID();
type = simpleClassName(event.getClass());
kind = ComponentTester.getEventID(event);
Component comp = ((ComponentEvent)event).getComponent();
if (event instanceof MouseEvent) {
MouseEvent me = (MouseEvent)event;
ComponentReference ref = resolver.addComponent(comp);
componentID = ref.getID();
eventAttributes.put(TAG_X, String.valueOf(me.getX()));
eventAttributes.put(TAG_Y, String.valueOf(me.getY()));
// Convert enter/exit to mouse moved
if (id == MouseEvent.MOUSE_ENTERED
|| id == MouseEvent.MOUSE_EXITED
|| id == MouseEvent.MOUSE_DRAGGED)
kind = "MOUSE_MOVED";
// No need to include modifiers in a captured event; it is assumed
// that the modifiers are captured separately
if (me.isPopupTrigger())
eventAttributes.put(TAG_TRIGGER, "true");
}
else if (event instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)event;
ComponentReference ref = resolver.addComponent(comp);
componentID = ref.getID();
if (ke.getModifiers() != 0) {
eventAttributes.put(TAG_MODIFIERS, AWT.
getModifiers(ke));
}
if (id == KeyEvent.KEY_TYPED) {
// Must encode keychars (e.g. '<')
eventAttributes.put(TAG_KEYCHAR,
String.valueOf(ke.getKeyChar()));
}
else {
eventAttributes.put(TAG_KEYCODE, AWT.
getKeyCode(ke.getKeyCode()));
}
}
else {
throw new IllegalArgumentException("Unimplemented event type "
+ event);
}
}
public String getDefaultDescription() {
String desc = type + "." + kind;
if (type.equals("KeyEvent"))
desc += " (" + eventAttributes.get(TAG_KEYCODE) + ")";
if (componentID != null)
desc += " on ${" + componentID + "}";
return desc;
}
public String getXMLTag() { return TAG_EVENT; }
public String getUsage() { return USAGE; }
public Map getAttributes() {
Map map = super.getAttributes();
map.put(TAG_COMPONENT, componentID);
map.put(TAG_TYPE, type);
if (kind != null)
map.put(TAG_KIND, kind);
map.putAll(eventAttributes);
return map;
}
/** Send our event to the component's event queue. */
public void runStep() throws Throwable {
ComponentTester.getTester(java.awt.Component.class).
sendEvent(createEvent(System.currentTimeMillis()));
}
/** Validate the attributes are sufficient to construct an event. */
private void parseEvent(Map map) {
type = (String)map.get(TAG_TYPE);
componentID = (String)map.get(TAG_COMPONENT);
kind = (String)map.get(TAG_KIND);
if (type == null)
usage("AWT event type missing");
if (type.endsWith("MouseEvent")) {
String modifiers = (String)map.get(TAG_MODIFIERS);
String x = (String)map.get(TAG_X);
String y = (String)map.get(TAG_Y);
String count = (String)map.get(TAG_COUNT);
String trigger = (String)map.get(TAG_TRIGGER);
if (kind == null)
usage("MouseEvent must specify a kind");
if (modifiers != null)
eventAttributes.put(TAG_MODIFIERS, modifiers);
if (x != null)
eventAttributes.put(TAG_X, x);
if (y != null)
eventAttributes.put(TAG_Y, y);
if (count != null)
eventAttributes.put(TAG_COUNT, count);
if (trigger != null)
eventAttributes.put(TAG_TRIGGER, trigger);
if (type.equals("MenuDragMouseEvent")) {
// FIXME
}
}
else if (type.equals("KeyEvent")) {
if (kind == null)
usage("KeyEvent must specify a kind");
String keyCode = (String)map.get(TAG_KEYCODE);
String modifiers = (String)map.get(TAG_MODIFIERS);
// Saved characters might be XML-encoded
String keyChar = (String)map.get(TAG_KEYCHAR);
if (keyCode == null) {
if (!kind.equals("KEY_TYPED"))
usage("KeyPress/Release require a keyCode");
}
else if (!kind.equals("KEY_TYPED"))
eventAttributes.put(TAG_KEYCODE, keyCode);
if (keyChar == null) {
if (kind.equals("KEY_TYPED"))
usage("KeyTyped requires a keyChar");
}
else if (kind.equals("KEY_TYPED")) {
eventAttributes.put(TAG_KEYCHAR, keyChar);
}
if (modifiers != null && !"".equals(modifiers)) {
eventAttributes.put(TAG_MODIFIERS, modifiers);
}
}
// FIXME what others are important? window events?
else {
Log.warn("Unimplemented event type '" + type + "', placeholder");
//usage("Unimplemented event type '" + type + "'");
}
}
/** Resolve the given name into a component. */
protected java.awt.Component resolve(String name)
throws NoSuchReferenceException,
ComponentNotFoundException,
MultipleComponentsFoundException {
ComponentReference ref = getResolver().getComponentReference(name);
if (ref != null) {
return ref.getComponent();
}
throw new NoSuchReferenceException(name);
}
/** Create an event based on the parameters we've collected */
private AWTEvent createEvent(long timestamp)
throws ComponentSearchException, NoSuchReferenceException {
Component comp = null;
if (componentID != null) {
comp = resolve(componentID);
}
long when = timestamp;
if (type.endsWith("MouseEvent")) {
int x = (comp.getSize().width + 1)/2;
int y = (comp.getSize().height + 1)/2;
int count = 1;
boolean trigger = false;
String modifiers = (String)eventAttributes.get(TAG_MODIFIERS);
int mods = modifiers != null
? AWT.getModifiers(modifiers) : 0;
try { x = Integer.parseInt((String)eventAttributes.get(TAG_X)); }
catch(Exception exc) {}
try { y = Integer.parseInt((String)eventAttributes.get(TAG_Y)); }
catch(Exception exc) {}
try { count = Integer.parseInt((String)eventAttributes.get(TAG_COUNT)); }
catch(Exception exc) {}
try { trigger = Boolean.getBoolean((String)eventAttributes.get(TAG_TRIGGER)); }
catch(Exception exc) {}
int id = ComponentTester.getEventID(MouseEvent.class, kind);
return new MouseEvent(comp, id, when, mods, x, y, count, trigger);
}
else if (type.equals("KeyEvent")) {
String modifiers = (String)eventAttributes.get(TAG_MODIFIERS);
int mods = modifiers != null
? AWT.getModifiers(modifiers) : 0;
int code = AWT.getKeyCode((String)eventAttributes.get(TAG_KEYCODE));
String ch = (String)eventAttributes.get(TAG_KEYCHAR);
char keyChar = ch != null ? ch.charAt(0) : (char)code;
int id = ComponentTester.getEventID(KeyEvent.class, kind);
return new KeyEvent(comp, id, when, mods, code, keyChar);
}
throw new IllegalArgumentException("Bad event type " + type);
}
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getKind() { return kind; }
public void setKind(String kind) { this.kind = kind; }
public String getComponentID() { return componentID; }
public void setComponentID(String id) { componentID = id; }
public String getAttribute(String tag) {
return (String)eventAttributes.get(tag);
}
public void setAttribute(String tag, String value) {
eventAttributes.put(tag, value);
}
}