package abbot.editor.recorder;
import java.awt.AWTEvent;
import java.awt.event.*;
import java.util.ArrayList;
import abbot.*;
import abbot.finder.ComponentFinder;
import abbot.script.*;
import abbot.script.Resolver;
/**
* Template for recording AWTEvents and converting them into an appropriate
* semantic event. The EventRecorder class decides which SemanticRecorder to
* use and handles cancel/termination. Implementations should be named
* AbstractButtonRecorder, JTableRecorder, etc. The semantic recorders will
* be dynamically loaded based on the component receiving a given event
* (compare to ComponentTester).<p>
* See EventRecorder for implementation details.
*/
public abstract class SemanticRecorder implements SemanticEvents {
private ActionListener al;
private Resolver resolver;
protected ArrayList events = new ArrayList();
private int recordingType = SE_NONE;
private volatile boolean isFinished;
private Step step = null;
private BugReport bug;
/** Create a SemanticRecorder for use in capturing the semantics of a GUI
* action.
*/
public SemanticRecorder(Resolver resolver) {
this.resolver = resolver;
}
/** Supports at most one listener. */
public void addActionListener(ActionListener al) {
this.al = al;
}
public int getRecordingType() {
return recordingType;
}
protected void setRecordingType(int type) {
recordingType = type;
}
protected void init(int recordingType) {
events.clear();
step = null;
bug = null;
setFinished(false);
setRecordingType(recordingType);
}
/** Returns whether this SemanticRecorder wishes to accept the given event
* and subsequent events.
*/
public abstract boolean accept(AWTEvent event);
/**
* Handle an event. Returns whether the event was consumed.
*/
final public boolean record(java.awt.AWTEvent event) {
if (!isFinished()) {
try {
if (parse(event)) {
// Maintain a list of all events parsed for future
// reference
events.add(event);
return true;
}
}
catch(BugReport br) {
setFinished(true);
bug = br;
}
}
return false;
}
/** Handle an event. Return true if the event has been consumed.
* Returning false usually means that isFinished() will return true.
*/
public abstract boolean parse(AWTEvent event);
/** Return the Resolver to be used by this recorder. */
protected Resolver getResolver() { return resolver; }
/** Returns the script step generated from the events recorded so far. If
* no real action resulted, may return null (for example, a mouse press on
* a button which releases outside the button).
*/
public synchronized Step getStep() throws BugReport {
if (bug != null)
throw bug;
if (step == null) {
step = createStep();
}
return step;
}
/** Create a step based on the events received thus far. Returns null if
* no semantic event or an imcomplete event has been detected. */
protected abstract Step createStep();
/**
* Add the given step. Should be used when the recorder detects a
* complete semantic event sequence. After this point, the recorder will
* no longer accept events.
*/
protected synchronized void setStep(Step newStep) {
events.clear();
step = newStep;
}
/** Return whether this recorder has finished recording the current
* semantic event.
*/
public synchronized boolean isFinished() { return isFinished; }
/** Invoke when end of the semantic event has been seen. */
protected synchronized void setFinished(boolean state) {
isFinished = state;
}
/** Indicate the current recording state, so that the status may be
* displayed elsewhere.
*/
protected void setStatus(String msg) {
if (al != null) {
ActionEvent event =
new ActionEvent(this, ActionEvent.ACTION_PERFORMED, msg);
al.actionPerformed(event);
}
}
/*
public String toString() {
return getClass().toString();
}
*/
}