001: package abbot.editor.recorder;
002:
003: import java.awt.AWTEvent;
004: import java.awt.event.*;
005: import java.util.ArrayList;
006:
007: import abbot.*;
008: import abbot.script.*;
009: import abbot.script.Resolver;
010:
011: /**
012: * Template for recording AWTEvents and converting them into an appropriate
013: * semantic event. The EventRecorder class decides which SemanticRecorder to
014: * use and handles cancel/termination. Implementations should be named
015: * AbstractButtonRecorder, JTableRecorder, etc. The semantic recorders will
016: * be dynamically loaded based on the component receiving a given event
017: * (compare to ComponentTester).<p>
018: * See EventRecorder for implementation details.
019: */
020: public abstract class SemanticRecorder implements SemanticEvents {
021: private ActionListener al;
022: private Resolver resolver;
023: protected ArrayList events = new ArrayList();
024: private Step step = null;
025: private int recordingType = SE_NONE;
026: private BugReport bug;
027: private volatile boolean isFinished;
028:
029: /** Create a SemanticRecorder for use in capturing the semantics of a GUI
030: * action.
031: */
032: public SemanticRecorder(Resolver resolver) {
033: this .resolver = resolver;
034: }
035:
036: /** Supports at most one listener. */
037: public void addActionListener(ActionListener al) {
038: this .al = al;
039: }
040:
041: public int getRecordingType() {
042: return recordingType;
043: }
044:
045: protected void setRecordingType(int type) {
046: recordingType = type;
047: }
048:
049: protected void init(int recordingType) {
050: events.clear();
051: step = null;
052: bug = null;
053: setFinished(false);
054: setRecordingType(recordingType);
055: }
056:
057: /** Returns whether this SemanticRecorder wishes to accept the given event
058: * and subsequent events.
059: */
060: public abstract boolean accept(AWTEvent event);
061:
062: /**
063: * Handle an event. Returns whether the event was consumed.
064: */
065: final public boolean record(java.awt.AWTEvent event) {
066: if (!isFinished()) {
067: try {
068: if (parse(event)) {
069: // Maintain a list of all events parsed for future
070: // reference
071: events.add(event);
072: return true;
073: }
074: } catch (BugReport br) {
075: setFinished(true);
076: bug = br;
077: }
078: }
079: return false;
080: }
081:
082: /** Handle an event. Return true if the event has been consumed.
083: * Returning false usually means that isFinished() will return true.
084: */
085: public abstract boolean parse(AWTEvent event);
086:
087: /** Return the Resolver to be used by this recorder. */
088: protected Resolver getResolver() {
089: return resolver;
090: }
091:
092: /** Returns the script step generated from the events recorded so far. If
093: * no real action resulted, may return null (for example, a mouse press on
094: * a button which releases outside the button).
095: */
096: public synchronized Step getStep() throws BugReport {
097: if (bug != null)
098: throw bug;
099:
100: if (step == null) {
101: step = createStep();
102: }
103: return step;
104: }
105:
106: /** Create a step based on the events received thus far. Returns null if
107: * no semantic event or an imcomplete event has been detected. */
108: protected abstract Step createStep();
109:
110: /**
111: * Add the given step. Should be used when the recorder detects a
112: * complete semantic event sequence. After this point, the recorder will
113: * no longer accept events.
114: */
115: protected synchronized void setStep(Step newStep) {
116: events.clear();
117: step = newStep;
118: }
119:
120: /** Return whether this recorder has finished recording the current
121: * semantic event.
122: */
123: public synchronized boolean isFinished() {
124: return isFinished;
125: }
126:
127: /** Invoke when end of the semantic event has been seen. */
128: protected synchronized void setFinished(boolean state) {
129: isFinished = state;
130: }
131:
132: /** Indicate the current recording state, so that the status may be
133: * displayed elsewhere.
134: */
135: protected void setStatus(String msg) {
136: if (al != null) {
137: ActionEvent event = new ActionEvent(this ,
138: ActionEvent.ACTION_PERFORMED, msg);
139: al.actionPerformed(event);
140: }
141: }
142:
143: /*
144: public String toString() {
145: return getClass().toString();
146: }
147: */
148: }
|