// Module : $RCSfile: DefaultSequenceDetectionRule.java,v $ // Version : $Revision: 0.0 $ $Author: patrick $ $Date: 18.03.2012 $ // Project : TaskTreeCreator // Creation : 2012 by patrick // Copyright : Patrick Harms, 2012 package de.ugoe.cs.quest.tasktrees.temporalrelation; import java.util.ArrayList; import java.util.List; import java.util.Locale; import de.ugoe.cs.quest.eventcore.IEventTarget; import de.ugoe.cs.quest.eventcore.gui.KeyInteraction; import de.ugoe.cs.quest.eventcore.gui.KeyPressed; import de.ugoe.cs.quest.eventcore.gui.KeyReleased; import de.ugoe.cs.quest.eventcore.guimodel.ITextArea; import de.ugoe.cs.quest.eventcore.guimodel.ITextField; import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask; import de.ugoe.cs.quest.tasktrees.treeifc.ISequence; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory; import de.ugoe.cs.quest.tasktrees.treeifc.ITextInputEventTask; import de.ugoe.cs.tasktree.keyboardmaps.KeyboardMap; import de.ugoe.cs.tasktree.keyboardmaps.KeyboardMapFactory; import de.ugoe.cs.tasktree.keyboardmaps.VirtualKey; /** * TODO comment * * @version $Revision: $ $Date: 18.03.2012$ * @author 2012, last modified by $Author: patrick$ */ public class DefaultTextInputReductionRule implements TemporalRelationshipRule { /** */ private KeyboardMap keyboardMap = KeyboardMapFactory.createKeyboardMap(Locale.GERMAN); /* * (non-Javadoc) * * @see TemporalRelationshipRule#apply(TaskTreeNode, TaskTreeBuilder, TaskTreeNodeFactory) */ @Override public RuleApplicationResult apply(ITaskTreeNode parent, ITaskTreeBuilder builder, ITaskTreeNodeFactory nodeFactory, boolean finalize) { if ((!(parent instanceof ISequence)) || (parent instanceof ITextInputEventTask)) { return null; } RuleApplicationResult result = new RuleApplicationResult(); int textEntryStartIndex = -1; IEventTarget currentEventTarget = null; int index = 0; ITaskTreeNode task = null; while (index < parent.getChildren().size()) { task = parent.getChildren().get(index); if (isKeyInteraction(task) && isDataInputEventTarget(((IEventTask) task).getEventTarget())) { if (textEntryStartIndex < 0) { textEntryStartIndex = index; currentEventTarget = ((IEventTask) task).getEventTarget(); } else if (!currentEventTarget.equals(((IEventTask) task).getEventTarget())) { handleTextEntrySequence(parent, textEntryStartIndex, index - 1, currentEventTarget, builder, nodeFactory, result); return result; } } else if (textEntryStartIndex >= 0) { handleTextEntrySequence(parent, textEntryStartIndex, index - 1, currentEventTarget, builder, nodeFactory, result); return result; } index++; } if (textEntryStartIndex >= 0) { if (finalize) { handleTextEntrySequence(parent, textEntryStartIndex, parent.getChildren().size() - 1, currentEventTarget, builder, nodeFactory, result); } else { result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE); } } return result; } /** * TODO: comment * * @param taskTreeNode * @return */ private boolean isKeyInteraction(ITaskTreeNode taskTreeNode) { if ((taskTreeNode instanceof IEventTask)) { return (((IEventTask) taskTreeNode).getEventType() instanceof KeyInteraction); } else { return false; } } /** * TODO: comment * * @param textEntryStartIndex * @param i * @param result * @return */ private void handleTextEntrySequence(ITaskTreeNode parent, int startIndex, int endIndex, IEventTarget eventTarget, ITaskTreeBuilder builder, ITaskTreeNodeFactory nodeFactory, RuleApplicationResult result) { ITextInputEventTask textInput = nodeFactory.createNewTextInputEventTask(eventTarget); for (int i = startIndex; i <= endIndex; i++) { builder.addChild(textInput, parent.getChildren().get(startIndex)); builder.removeChild((ISequence) parent, startIndex); } builder.addChild((ISequence) parent, startIndex, textInput); StringBuffer enteredText = new StringBuffer(); determineEnteredText(textInput, new ArrayList(), enteredText); textInput.setEnteredText(enteredText.toString()); result.addNewlyCreatedParentNode(textInput); result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED); } /** * TODO: comment * * @param eventTarget * @return */ private boolean isDataInputEventTarget(IEventTarget eventTarget) { return ((eventTarget instanceof ITextField) || (eventTarget instanceof ITextArea)); } /** * TODO: comment * * @param sequence * @param enteredText */ private void determineEnteredText(ITaskTreeNode node, List pressedKeys, StringBuffer enteredText) { if ((node instanceof ISequence) || (node instanceof ITextInputEventTask)) { for (ITaskTreeNode child : node.getChildren()) { if (child instanceof IEventTask) { if (((IEventTask) child).getEventType() instanceof KeyPressed) { VirtualKey key = ((KeyPressed) ((IEventTask) child).getEventType()).getKey(); pressedKeys.add(key); if (key == VirtualKey.BACK_SPACE) { if (enteredText.length() > 0) { enteredText.deleteCharAt(enteredText.length() - 1); } } else if (key == VirtualKey.ENTER) { // text fields only contain one line of code. Therefore the return is // ignored. if (!(((IEventTask) child).getEventTarget() instanceof ITextField)) { enteredText.append(getCharacter(key, pressedKeys)); } } else { char theChar = getCharacter(key, pressedKeys); if (theChar != Character.UNASSIGNED) { enteredText.append(theChar); } } } else if (((IEventTask) child).getEventType() instanceof KeyReleased) { pressedKeys.remove (((KeyReleased) ((IEventTask) child).getEventType()).getKey()); } } else { determineEnteredText(child, pressedKeys, enteredText); } } } } /** * TODO: comment * * @param key * @param pressedKeys * @return */ private char getCharacter(VirtualKey key, List pressedKeys) { boolean numlock = false; boolean shift = false; boolean altgr = false; for (VirtualKey pressedKey : pressedKeys) { if (pressedKey.isShiftKey()) { shift = !shift; } else if (pressedKey == VirtualKey.ALT_GRAPH) { altgr = !altgr; } else if (pressedKey == VirtualKey.NUM_LOCK) { numlock = !numlock; } } return keyboardMap.getCharacterFor(key, numlock, shift, altgr, false); } }