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

Last change on this file since 765 was 765, checked in by sherbold, 12 years ago
  • complete rewrite of keyboard interaction sorting. As a result, the command cleanupKeyInteractions is deprecated.
  • Property svn:mime-type set to text/plain
File size: 7.7 KB
Line 
1
2package de.ugoe.cs.quest.eventcore.gui;
3
4import java.util.HashSet;
5import java.util.LinkedList;
6import java.util.List;
7import java.util.ListIterator;
8import java.util.Set;
9import java.util.logging.Level;
10
11import de.ugoe.cs.quest.eventcore.Event;
12import de.ugoe.cs.tasktree.keyboardmaps.VirtualKey;
13import de.ugoe.cs.util.console.Console;
14
15/**
16 *
17 * <p>
18 * TODO comment
19 * </p>
20 *
21 * @version $Revision: $ $Date: Sep 4, 2012$
22 * @author 2012, last modified by $Author: sherbold$
23 */
24public class KeyInteractionSorter {
25
26    /**
27     * <p>
28     * Describes the clean-up mode.
29     * </p>
30     *
31     * @version $Revision: $ $Date: Sep 3, 2012$
32     * @author 2012, last modified by $Author: sherbold$
33     */
34    public static enum CleanupMode {
35        REMOVAL, ADDITION
36    };
37
38    private final CleanupMode mode;
39
40    public KeyInteractionSorter() {
41        this(CleanupMode.ADDITION);
42    }
43
44    public KeyInteractionSorter(CleanupMode mode) {
45        this.mode = mode;
46    }
47
48    public List<Event> sortKeyInteractions(final List<Event> sequence) {
49        List<Event> sortedSequence = new LinkedList<Event>(sequence);
50
51        handleIncompleteKeyPairs(sortedSequence);
52        sortCombinationKeyPairs(sortedSequence);
53
54        return sortedSequence;
55    }
56
57    private void sortCombinationKeyPairs(List<Event> sequence) {
58        LinkedList<VirtualKey> pressedCombinationKeys = new LinkedList<VirtualKey>();
59
60        for (int i = 0; i < sequence.size(); i++) {
61            Event event = sequence.get(i);
62            if (event.getType() instanceof KeyPressed) {
63                final VirtualKey key = ((KeyPressed) event.getType()).getKey();
64                if (key.isCombinationKey()) {
65                    pressedCombinationKeys.add(key);
66                }
67            }
68            if (event.getType() instanceof KeyReleased) {
69                final VirtualKey key = ((KeyReleased) event.getType()).getKey();
70                if (key.isCombinationKey()) {
71                    /*
72                     * if( pressedCombinationKeys.isEmpty() ) { Console.traceln(Level.INFO, "" + i);
73                     * for( int j=i-30 ; j<=i ; j++ ) { Console.traceln(Level.INFO,
74                     * sequence.get(i).toString()); } }
75                     */
76                    if (key.equals(pressedCombinationKeys.getLast())) {
77                        pressedCombinationKeys.removeLast();
78                    }
79                    else {
80                        // look-ahead to find new position
81                        int offset;
82                        for (offset = 1; offset + i < sequence.size(); offset++) {
83                            Event lookaheadEvent = sequence.get(i + offset);
84                            if (lookaheadEvent.getType() instanceof KeyReleased) {
85                                if (((KeyReleased) lookaheadEvent.getType()).getKey()
86                                    .equals(pressedCombinationKeys.getLast()))
87                                {
88                                    break;
89                                }
90                            }
91                        }
92                        sequence.add(i + offset + 1, event);
93                        sequence.remove(i);
94                        i--;
95                    }
96                }
97            }
98        }
99    }
100
101    private void handleIncompleteKeyPairs(List<Event> sequence) {
102        Set<VirtualKey> pressedKeys = new HashSet<VirtualKey>();
103        int firstPressedIndex = -1;
104
105        Set<VirtualKey> pressedCombinationKeysSession = new HashSet<VirtualKey>();
106
107        for (int i = 0; i < sequence.size(); i++) {
108            Event event = sequence.get(i);
109            if (event.getType() instanceof KeyboardFocusChange) {
110                if (firstPressedIndex != -1) {
111                    sequence.remove(i);
112                    sequence.add(firstPressedIndex, event);
113                }
114            }
115
116            if (event.getType() instanceof KeyPressed) {
117                if (pressedKeys.isEmpty()) {
118                    firstPressedIndex = i;
119                }
120                VirtualKey key = ((KeyPressed) event.getType()).getKey();
121                if (!key.isCombinationKey()) {
122                    ListIterator<Event> iter = sequence.listIterator(i);
123                    iter.next();
124                    iter.set(new Event(new KeyTyped(key), event.getTarget()));
125                }
126                else {
127                    pressedCombinationKeysSession.add(key);
128                    if (pressedKeys.contains(key)) {
129                        sequence.remove(i);
130                        i--;
131                    }
132                }
133                pressedKeys.add(key);
134            }
135            if (event.getType() instanceof KeyReleased) {
136                VirtualKey key = ((KeyReleased) event.getType()).getKey();
137                if (!key.isCombinationKey()) {
138                    if (pressedKeys.contains(key)) {
139                        sequence.remove(i);
140                        i--;
141                    }
142                    else {
143                        // found KeyReleased event without KeyPressed
144                        switch (mode)
145                        {
146                            case REMOVAL:
147                                sequence.remove(i);
148                                i--;
149                                break;
150                            case ADDITION:
151                                ListIterator<Event> iter = sequence.listIterator(i);
152                                iter.next();
153                                iter.set(new Event(new KeyTyped(key), event.getTarget()));
154                                break;
155                            default:
156                                throw new AssertionError(
157                                                         "reached source code that should be unreachable");
158                        }
159                    }
160                }
161                else {
162                    if (!pressedKeys.contains(key)) {
163                        if (pressedCombinationKeysSession.contains(key)) {
164                            Console.traceln(Level.SEVERE, "Found a " + key +
165                                " KeyReleased event without a KeyPressed event." +
166                                "The event will be dropped and the session is possibly faulty.");
167                            sequence.remove(i);
168                            i--;
169                        }
170                        else {
171                            Console
172                                .traceln(Level.SEVERE,
173                                         "Found a " +
174                                             key +
175                                             " KeyReleased event without a KeyPressed event." +
176                                             "Since no KeyPressed of key " +
177                                             key +
178                                             " has been part of the session " +
179                                             "till now, we assume that the key has been pressed since the beginning " +
180                                             "of the session and add a KeyPressed event for " +
181                                             key + " to the start " + "of the session.");
182                            sequence.add(0, new Event(new KeyPressed(key), event.getTarget()));
183                            i++;
184                        }
185                    }
186                }
187                pressedKeys.remove(key);
188                if (pressedKeys.isEmpty()) {
189                    firstPressedIndex = -1;
190                }
191            }
192        }
193        if (!pressedKeys.isEmpty()) {
194            Console
195                .traceln(Level.WARNING,
196                         "There was probably a failure during the handling of incomplete key event pairs.");
197        }
198    }
199}
Note: See TracBrowser for help on using the repository browser.