// Module : $RCSfile: InteractionEventList.java,v $ // Version : $Revision: 0.0 $ $Author: Patrick $ $Date: 04.12.2011 10:20:14 $ // Project : TaskTreePerformanceTest // Creation : 2011 by Patrick // Copyright : Patrick Harms, 2011 package de.ugoe.cs.quest.eventcore.gui; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import de.ugoe.cs.quest.eventcore.Event; /** * TODO comment * * @version $Revision: $ $Date: $ * @author 2011, last modified by $Author: $ */ public class InteractionEventList extends ArrayList implements List { /** */ private static final long serialVersionUID = 1L; /** stores the events to be handled later in the order, they should be processed */ private List eventPairs = new ArrayList(); /** * this method sorts interaction events for pressed keys. The reason is, that sometimes the * release of one key comes after the pressing of the succeeding key. This only makes sense for * shift, ctrl or alt keys, but not for usual characters. So the events are sorted.
* Furthermore, this methods creates key released events in the specific case, where a key is * pressed for a long time. Here, many subsequent key pressed events for the same key can be * observed, for which there are no key released events. */ @Override public boolean add(Event event) { if (event.getType() instanceof KeyInteraction) { for (int i = 0; i < eventPairs.size(); i++) { KeyEventPair eventPair = eventPairs.get(i); if (eventPair.process(event)) { // handle all leading and completed event pairs, if any while ((eventPairs.size() > 0) && (eventPairs.get(0).isComplete())) { addEventPair(eventPairs.get(0)); eventPairs.remove(0); } return true; } } eventPairs.add(new KeyEventPair(event)); return true; } else { // any other event is simply added return super.add(event); } } /* * (non-Javadoc) * * @see java.util.ArrayList#add(int, java.lang.Object) */ @Override public void add(int index, Event event) { List remaining = new ArrayList(); while (index < super.size()) { remaining.add(super.remove(index)); } add(event); addAll(remaining); } /* * (non-Javadoc) * * @see java.util.ArrayList#addAll(java.util.Collection) */ @Override public boolean addAll(Collection events) { int initialSize = super.size(); for (Event event : events) { add(event); } return initialSize != super.size(); } /* * (non-Javadoc) * * @see java.util.ArrayList#addAll(int, java.util.Collection) */ @Override public boolean addAll(int index, Collection events) { int initialSize = super.size(); List remaining = new ArrayList(); while (index < super.size()) { remaining.add(super.remove(index)); } addAll(events); addAll(remaining); return initialSize != super.size(); } /** * */ private void addEventPair(KeyEventPair eventPair) { super.add(eventPair.first); for (KeyEventPair child : eventPair.children) { addEventPair(child); } super.add(eventPair.second); } /** * */ private static class KeyEventPair implements Serializable { /** */ private static final long serialVersionUID = 1L; /** the first key interaction event */ private Event first; /** the second key interaction event */ private Event second; /** the children, this event pair may have */ private List children = new ArrayList(); /** * */ private KeyEventPair(Event first) { if (!(first.getType() instanceof KeyPressed)) { throw new IllegalArgumentException ("can only handle key pressed interaction events as first element of an" + "event pair"); } this.first = first; } /** * sorts the event as the second of the pair or as the closing of this. Returns true, if * this matched, false else */ private boolean process(Event event) { if (!(event.getType() instanceof KeyInteraction)) { throw new IllegalArgumentException("can only handle key interaction events"); } if (this.isComplete()) { // do not process events, if there are no more events expected return false; } if ((event.getType() instanceof KeyReleased) && (((KeyInteraction) first.getType()).getKey() == ((KeyInteraction) event.getType()).getKey()) && (second == null)) { // this is the release of the represented key. Store it and notify the processing. second = event; return true; } else if ((event.getType() instanceof KeyPressed) && (((KeyInteraction) first.getType()).getKey() == ((KeyInteraction) event.getType()).getKey()) && (second == null)) { // the key was pressed before it was released again. This happens, if the key // stays pressed for a long time. Generate a key released event but do not mark // the new event as processed second = new Event (new KeyReleased(((KeyInteraction) event.getType()).getKey()), first.getTarget()); return false; } else if (((KeyInteraction) first.getType()).getKey().isCombinationKey() && (((KeyInteraction) first.getType()).getKey() != ((KeyInteraction) event.getType()).getKey())) { // this pair may have children. Let the event be processed by the children. If this // doesn't work, add the event as a new child pair, if it is a new key pressed for (KeyEventPair child : children) { if (child.process(event)) { return true; } } if (event.getType() instanceof KeyPressed) { children.add(new KeyEventPair(event)); return true; } else { return false; } } else { // this pair may not have children return false; } } /** * @return */ private boolean isComplete() { if ((first != null) && (second != null)) { for (KeyEventPair child : children) { if (!child.isComplete()) { return false; } } return true; } else { return false; } } } }