001: /*
002: * Jacareto Copyright (c) 2002-2005
003: * Applied Computer Science Research Group, Darmstadt University of
004: * Technology, Institute of Mathematics & Computer Science,
005: * Ludwigsburg University of Education, and Computer Based
006: * Learning Research Group, Aachen University. All rights reserved.
007: *
008: * Jacareto is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * Jacareto is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public
019: * License along with Jacareto; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: *
022: */
023:
024: package jacareto.struct;
025:
026: import jacareto.parse.RecordTokenizer;
027: import jacareto.parse.RecordTokenizerState;
028: import jacareto.record.MouseEventRecordable;
029: import jacareto.system.Environment;
030:
031: import java.util.Vector;
032:
033: /**
034: * This structure element stands for double, triple, ... mouse clicks. A structure element can
035: * parse a part of a record.
036: *
037: * @author <a href="mailto:cspannagel@web.de">Christian Spannagel</a>
038: * @version 1.01
039: */
040: public class MultipleMouseClick extends StructureElement {
041: /** The indices of the mouse clicks in the children array. */
042: public MouseClick[] mouseClicks;
043:
044: /** The click count. */
045: public int clickCount;
046:
047: /**
048: * Creates a new "multiple mouse click" structure element.
049: *
050: * @param env the environment
051: * @param children the child structure elements
052: */
053: public MultipleMouseClick(Environment env,
054: StructureElement[] children) {
055: super (env, children);
056:
057: StructureElement[] filteredChildren = getChildren("jacareto.struct.MouseClick");
058: mouseClicks = new MouseClick[filteredChildren.length];
059:
060: for (int i = 0; i < mouseClicks.length; i++) {
061: mouseClicks[i] = (MouseClick) filteredChildren[i];
062: }
063:
064: this .clickCount = mouseClicks.length;
065: }
066:
067: /**
068: * Creates a new "multiple mouse click" structure element.
069: *
070: * @param env the environment
071: * @param children the child structure elements
072: * @param mouseClicks the children which are mouse clicks.
073: * @param clickCount the click count (must NOT be the length of <code>mouseClicks</code>
074: */
075: public MultipleMouseClick(Environment env,
076: StructureElement[] children, MouseClick[] mouseClicks,
077: int clickCount) {
078: super (env, children);
079: this .mouseClicks = mouseClicks;
080: this .clickCount = clickCount;
081: }
082:
083: /**
084: * Parses a record which is tokenized by the given record tokenizer.
085: *
086: * @param env DOCUMENT ME!
087: * @param recordTokenizer the record tokenizer
088: *
089: * @return a structure element, or <code>null</code> if this class cannot parse the record at
090: * the current position
091: */
092: public static StructureElement parse(Environment env,
093: RecordTokenizer recordTokenizer) {
094: StructureElement result = null;
095: Vector addedChildren = null;
096: Vector addedMouseClicks = null;
097: StructureElement firstElement = null;
098: MouseClick mouseClick = null;
099: int clickCount = 0;
100:
101: RecordTokenizerState rtState = new RecordTokenizerState(env,
102: recordTokenizer);
103: RecordTokenizerState stateAfterLastClick = null;
104:
105: // the first element of a multiple mouse click can be a single mouse click,
106: // a short mouseDrag or a focus change which contains the first mouse click
107: firstElement = MouseClick.parse(env, recordTokenizer);
108:
109: if (firstElement != null) {
110: mouseClick = (MouseClick) firstElement;
111: } else {
112: firstElement = FocusChange.parse(env, recordTokenizer);
113:
114: if (firstElement != null) {
115: mouseClick = ((FocusChange) firstElement)
116: .getMouseClick();
117: } else {
118: firstElement = MouseDrag.parse(env, recordTokenizer);
119: }
120: }
121:
122: if (firstElement != null) {
123: //could be a multiple mouse click
124: try {
125: addedMouseClicks = new Vector(3, 3);
126:
127: if (mouseClick != null) {
128: clickCount = mouseClick.getClickCount();
129:
130: if (clickCount != 1) {
131: throw new Exception();
132: }
133:
134: addedMouseClicks.add(mouseClick);
135: } else {
136: // first element is short mouse drag
137: clickCount = ((MouseDrag) firstElement)
138: .getMouseReleased().getClickCount();
139:
140: if (clickCount != 1) {
141: throw new Exception();
142: }
143: }
144:
145: addedChildren = new Vector(5, 5);
146: addedChildren.add(firstElement);
147:
148: while (recordTokenizer.hasMore()) {
149: mouseClick = (MouseClick) MouseClick.parse(env,
150: recordTokenizer);
151:
152: if (mouseClick != null) {
153: if (mouseClick.getClickCount() == (clickCount + 1)) {
154: // next mouse click found
155: clickCount++;
156: addedChildren.add(mouseClick);
157: addedMouseClicks.add(mouseClick);
158: stateAfterLastClick = new RecordTokenizerState(
159: env, recordTokenizer);
160: } else {
161: // the mouse click found does not belong to the multiple mouse click
162: break;
163: }
164: } else {
165: // There may be small mouse motions or other elements
166: // between the mouse clicks
167: StructureElement inbetween = null;
168: inbetween = MouseMotion.parse(env,
169: recordTokenizer);
170:
171: if (inbetween == null) {
172: inbetween = MouseDrag.parse(env,
173: recordTokenizer);
174:
175: if (inbetween != null) {
176: MouseEventRecordable mouseReleased = ((MouseDrag) inbetween)
177: .getMouseReleased();
178:
179: if (mouseReleased.getClickCount() == (clickCount + 1)) {
180: clickCount++;
181: }
182: }
183: }
184:
185: if (inbetween != null) {
186: addedChildren.add(inbetween);
187: } else {
188: break;
189: }
190: }
191: }
192: } catch (Throwable t) {
193: recordTokenizer.restoreState(rtState);
194: clickCount = 0;
195: }
196: }
197:
198: if ((clickCount > 1) && (addedMouseClicks.size() > 0)
199: && (stateAfterLastClick != null)) {
200: MouseClick[] mouseClicks = new MouseClick[addedMouseClicks
201: .size()];
202:
203: for (int i = 0; i < mouseClicks.length; i++) {
204: mouseClicks[i] = (MouseClick) addedMouseClicks.get(i);
205: }
206:
207: int lastClickIndex = addedChildren
208: .indexOf(mouseClicks[mouseClicks.length - 1]);
209: StructureElement[] children = new StructureElement[lastClickIndex + 1];
210:
211: for (int i = 0; i <= lastClickIndex; i++) {
212: children[i] = (StructureElement) addedChildren.get(i);
213: }
214:
215: recordTokenizer.restoreState(stateAfterLastClick);
216: result = new MultipleMouseClick(env, children, mouseClicks,
217: clickCount);
218: } else {
219: recordTokenizer.restoreState(rtState);
220: }
221:
222: return result;
223: }
224:
225: /**
226: * Returns the click count.
227: *
228: * @return DOCUMENT ME!
229: */
230: public int getClickCount() {
231: return clickCount;
232: }
233:
234: /**
235: * Returns all mouse clicks contained in this element.
236: *
237: * @return DOCUMENT ME!
238: */
239: public MouseClick[] getMouseClicks() {
240: return mouseClicks;
241: }
242:
243: /**
244: * Returns the name of the element.
245: *
246: * @return the name
247: */
248: public String getElementName() {
249: return language.getString("Structures.MultipleMouseClick.Name");
250: }
251:
252: /**
253: * Returns a description of the element.
254: *
255: * @return the description
256: */
257: public String getElementDescription() {
258: return language
259: .getString("Structures.MultipleMouseClick.Description");
260: }
261:
262: /**
263: * Returns a String which describes the content of the element shortly.
264: *
265: * @return a string with a short description of the element
266: */
267: public String toShortString() {
268: return getElementName() + " (" + clickCount + ")";
269: }
270:
271: /**
272: * Clones the element.
273: *
274: * @return DOCUMENT ME!
275: */
276: public Object clone() {
277: StructureElement[] clonedChildren = getClonedChildren();
278: MouseClick[] clonedMouseClicks = new MouseClick[mouseClicks.length];
279: StructureElement[] children = getChildren();
280:
281: for (int i = 0; i < mouseClicks.length; i++) {
282: MouseClick click = mouseClicks[i];
283:
284: for (int j = 0; j < children.length; j++) {
285: if (children[j] == click) {
286: clonedMouseClicks[i] = (MouseClick) clonedChildren[j];
287:
288: break;
289: }
290: }
291: }
292:
293: return new MultipleMouseClick(env, clonedChildren,
294: clonedMouseClicks, clickCount);
295: }
296: }
|