source: trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/gui/SortedInteractionEventList.java @ 683

Last change on this file since 683 was 683, checked in by pharms, 12 years ago
  • renamed interaction event list to correctly state, what it is, a list of sorted interaction events
  • Property svn:executable set to *
File size: 7.5 KB
Line 
1package de.ugoe.cs.quest.eventcore.gui;
2
3import java.io.Serializable;
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.List;
7
8import de.ugoe.cs.quest.eventcore.Event;
9
10/**
11 * TODO comment
12 *
13 * @version $Revision: $ $Date: $
14 * @author 2011, last modified by $Author: $
15 */
16public class SortedInteractionEventList extends ArrayList<Event> implements List<Event> {
17   
18    /**  */
19    private static final long serialVersionUID = 1L;
20   
21    /** stores the events to be handled later in the order, they should be processed */
22    private List<KeyEventPair> eventPairs = new ArrayList<KeyEventPair>();
23
24    /**
25     * this method sorts interaction events for pressed keys. The reason is, that sometimes the
26     * release of one key comes after the pressing of the succeeding key. This only makes sense for
27     * shift, ctrl or alt keys, but not for usual characters. So the events are sorted.<br/>
28     * Furthermore, this methods creates key released events in the specific case, where a key is
29     * pressed for a long time. Here, many subsequent key pressed events for the same key can be
30     * observed, for which there are no key released events.
31     */
32    @Override
33    public boolean add(Event event) {
34        if (event.getType() instanceof KeyInteraction) {
35            for (int i = 0; i < eventPairs.size(); i++) {
36                KeyEventPair eventPair = eventPairs.get(i);
37
38                if (eventPair.process(event)) {
39                    // handle all leading and completed event pairs, if any
40                    while ((eventPairs.size() > 0) && (eventPairs.get(0).isComplete())) {
41                        addEventPair(eventPairs.get(0));
42                        eventPairs.remove(0);
43                    }
44                    return true;
45                }
46            }
47
48            eventPairs.add(new KeyEventPair(event));
49            return true;
50        }
51        else {
52            // any other event is simply added
53            return super.add(event);
54        }
55    }
56
57    /*
58     * (non-Javadoc)
59     *
60     * @see java.util.ArrayList#add(int, java.lang.Object)
61     */
62    @Override
63    public void add(int index, Event event) {
64        List<Event> remaining = new ArrayList<Event>();
65
66        while (index < super.size()) {
67            remaining.add(super.remove(index));
68        }
69
70        add(event);
71        addAll(remaining);
72    }
73
74    /*
75     * (non-Javadoc)
76     *
77     * @see java.util.ArrayList#addAll(java.util.Collection)
78     */
79    @Override
80    public boolean addAll(Collection<? extends Event> events) {
81        int initialSize = super.size();
82
83        for (Event event : events) {
84            add(event);
85        }
86
87        return initialSize != super.size();
88    }
89
90    /*
91     * (non-Javadoc)
92     *
93     * @see java.util.ArrayList#addAll(int, java.util.Collection)
94     */
95    @Override
96    public boolean addAll(int index, Collection<? extends Event> events) {
97        int initialSize = super.size();
98
99        List<Event> remaining = new ArrayList<Event>();
100
101        while (index < super.size()) {
102            remaining.add(super.remove(index));
103        }
104
105        addAll(events);
106        addAll(remaining);
107
108        return initialSize != super.size();
109    }
110
111    /**
112     *
113     */
114    private void addEventPair(KeyEventPair eventPair) {
115        super.add(eventPair.first);
116
117        for (KeyEventPair child : eventPair.children) {
118            addEventPair(child);
119        }
120
121        super.add(eventPair.second);
122    }
123
124    /**
125     *
126     */
127    private static class KeyEventPair implements Serializable {
128       
129        /**  */
130        private static final long serialVersionUID = 1L;
131
132        /** the first key interaction event */
133        private Event first;
134
135        /** the second key interaction event */
136        private Event second;
137
138        /** the children, this event pair may have */
139        private List<KeyEventPair> children = new ArrayList<KeyEventPair>();
140
141        /**
142         *
143         */
144        private KeyEventPair(Event first) {
145            if (!(first.getType() instanceof KeyPressed)) {
146                throw new IllegalArgumentException
147                  ("can only handle key pressed interaction events as first element of an" +
148                   "event pair");
149            }
150            this.first = first;
151        }
152
153        /**
154         * sorts the event as the second of the pair or as the closing of this. Returns true, if
155         * this matched, false else
156         */
157        private boolean process(Event event) {
158            if (!(event.getType() instanceof KeyInteraction)) {
159                throw new IllegalArgumentException("can only handle key interaction events");
160            }
161
162            if (this.isComplete()) {
163                // do not process events, if there are no more events expected
164                return false;
165            }
166
167            if ((event.getType() instanceof KeyReleased) &&
168                (((KeyInteraction) first.getType()).getKey() ==
169                 ((KeyInteraction) event.getType()).getKey()) &&
170                (second == null))
171            {
172                // this is the release of the represented key. Store it and notify the processing.
173                second = event;
174                return true;
175            }
176            else if ((event.getType() instanceof KeyPressed) &&
177                     (((KeyInteraction) first.getType()).getKey() ==
178                      ((KeyInteraction) event.getType()).getKey()) &&
179                     (second == null))
180            {
181                // the key was pressed before it was released again. This happens, if the key
182                // stays pressed for a long time. Generate a key released event but do not mark
183                // the new event as processed
184                second = new Event
185                    (new KeyReleased(((KeyInteraction) event.getType()).getKey()),
186                     first.getTarget());
187               
188                return false;
189            }
190            else if (((KeyInteraction) first.getType()).getKey().isCombinationKey() &&
191                     (((KeyInteraction) first.getType()).getKey() !=
192                      ((KeyInteraction) event.getType()).getKey()))
193            {
194                // this pair may have children. Let the event be processed by the children. If this
195                // doesn't work, add the event as a new child pair, if it is a new key pressed
196
197                for (KeyEventPair child : children) {
198                    if (child.process(event)) {
199                        return true;
200                    }
201                }
202
203                if (event.getType() instanceof KeyPressed) {
204                    children.add(new KeyEventPair(event));
205                    return true;
206                }
207                else {
208                    return false;
209                }
210            }
211            else {
212                // this pair may not have children
213                return false;
214            }
215        }
216
217        /**
218         * @return
219         */
220        private boolean isComplete() {
221            if ((first != null) && (second != null)) {
222                for (KeyEventPair child : children) {
223                    if (!child.isComplete()) {
224                        return false;
225                    }
226                }
227
228                return true;
229            }
230            else {
231                return false;
232            }
233        }
234    }
235}
Note: See TracBrowser for help on using the repository browser.