1 '''
2 Defines a class representing an input L{Gesture}, one or more device specific
3 input actions (e.g. keyboard key press, Braille button press, speech input
4 command, camera tracked gesture, etc.) performed simultaneously.
5
6 @author: Peter Parente
7 @organization: IBM Corporation
8 @copyright: Copyright (c) 2005, 2007 IBM Corporation
9 @license: The BSD License
10
11 All rights reserved. This program and the accompanying materials are made
12 available under the terms of the BSD license which accompanies
13 this distribution, and is available at
14 U{http://www.opensource.org/licenses/bsd-license.php}
15 '''
16
18 '''
19 Represents one or more device specific input actions. Maintains a list of
20 action codes specific to a L{AEInput} device as well as a reference to the
21 device itself. Maintains a separate list of the action codes sorted according
22 to the order specified by the L{AEInput} device owning this L{Gesture} in
23 order to speed comparisons of two L{Gesture}s. Maintains a hash value computed
24 by XORing the sorted action codes in order to support the deterministic
25 hashing of L{Gesture}s with the same action codes to the same bin in a
26 dictionary. Both the cached sorted list and the hash code are reset on each
27 successful call to L{Gesture.addActionCode}.
28
29 @ivar device: Input device on which the L{Gesture} is performed
30 @type device: L{AEInput.AEInput}
31 @ivar sorted_codes: Cached action codes sorted by the device owning this
32 L{Gesture}
33 @type sorted_codes: list of integer
34 @ivar hash: Cached copy of the hash value of the L{Gesture}
35 @type hash: integer
36 @ivar action_codes: Codes for the actions performed on the device forming this
37 L{Gesture}
38 @type action_codes: list of integer
39 '''
40 - def __init__(self, device, action_codes=None, gesture=None):
41 '''
42 Stores a reference to the input device. Stores a copy of the the provided
43 action codes or gets a copy of the action codes from the provided
44 L{Gesture}. If neither is specified, creates an empty action code list.
45
46 @param device: Input device on which this L{Gesture} is pressed
47 @type device: L{AEInput.AEInput}
48 @param action_codes: Action codes used to initialize the action code list
49 @type action_codes: list of integer
50 @param gesture: L{Gesture} object that this L{Gesture} should copy
51 @type gesture: L{Gesture}
52 '''
53 self.device = device
54 self.sorted_codes = None
55 self.hash = None
56
57 if action_codes is not None:
58
59 self.action_codes = []
60 for code in action_codes:
61 self.addActionCode(code)
62 elif gesture is not None:
63
64 self.action_codes = gesture.getActionCodes()
65 else:
66
67 self.action_codes = []
68
70 '''
71 Gets a human readable representation of the L{Gesture} as a string from
72 L{asString}.
73
74 @return: Text describing the gesture
75 @rtype: string
76 '''
77 return self.asString()
78
80 '''
81 Compares this L{Gesture} to the one provided. The comparison is performed
82 independent of the order of the actions forming the gesture by using
83 L{Gesture.getSortedActionCodes}.
84
85 @param other: L{Gesture} to compare to this one
86 @type other: L{Gesture}
87 @return: Is this L{Gesture} equal to the one provided?
88 @rtype: boolean
89 '''
90
91
92
93 return self.getSortedActionCodes() == other.getSortedActionCodes()
94
96 '''
97 Gets an iterator over the action codes in this L{Gesture}.
98
99 @return: Iterator over all action codes in this L{Gesture}
100 @rtype: iterator
101 '''
102 return iter(self.action_codes)
103
105 '''
106 Gets if this L{Gesture} contains the given action code.
107
108 @return: Is the action code in this L{Gesture}?
109 @rtype: boolean
110 '''
111 return action_code in self.action_codes
112
114 '''
115 Builds a hash code for this L{Gesture} based on its action code contents by
116 XORing them together. The hash code is used by a L{GestureList} in building
117 its hash code. The action codes are sorted in device dependent order using
118 L{Gesture.getSortedActionCodes} before XORing to ensure two L{Gesture}s with
119 the same actions hash to the same value.
120
121 @return: Hash code for this L{Gesture}
122 @rtype: integer
123 '''
124 if self.hash is None:
125 self.hash = 0
126 for code in self.getSortedActionCodes():
127 self.hash = self.hash^code
128 return self.hash
129
131 '''
132 Gets the number of codes in the current gesture.
133
134 @return: Number of codes
135 @rtype: integer
136 '''
137 return len(self.action_codes)
138
140 '''
141 Gets the device on which this L{Gesture} is performed.
142
143 @return: Device on which this L{Gesture} is performed
144 @rtype: L{AEInput.AEInput}
145 '''
146 return self.device
147
149 '''
150 Adds the given action code to this L{Gesture}. If the L{Gesture} is full
151 (i.e. it has the maximum number of action as determined by its device), a
152 ValueError is raised. If the L{Gesture} is not full, the new action code is
153 added to the end of L{action_codes}. If the action code was already in the
154 L{Gesture}, the action code is moved to the end of L{action_codes}.
155
156 @param code: Action code to add to this L{Gesture}
157 @type code: integer
158 @raise ValueError: When the L{Gesture} is full according to
159 L{AEInput.Base.AEInput.getMaxActions}
160 '''
161
162 if len(self.action_codes) == self.device.getMaxActions():
163 raise ValueError('Maximum action codes reached for this device')
164 try:
165
166 self.action_codes.remove(code)
167 except ValueError:
168
169 pass
170
171 self.action_codes.append(code)
172
173 self.sorted_codes = None
174 self.hash = None
175
177 '''
178 Deletes an action code from this L{Gesture}.
179
180 @param code: Action code to remove from this L{Gesture}
181 @type code: integer
182 @raise ValueError: When the action code does not exist in the L{Gesture}
183 '''
184 self.action_codes.remove(code)
185 self.sorted_codes = None
186 self.hash = None
187
189 '''
190 Deletes all action codes from this L{Gesture}.
191 '''
192 self.action_codes = []
193 self.sorted_codes = None
194 self.hash = None
195
197 '''
198 Gets a copy of all the action codes in this L{Gesture}. Makes a fast copy by taking
199 a slice using the start and end slice defaults.
200
201 @return: Copy of all the action codes in this L{Gesture}
202 @rtype: list of integer
203 '''
204 return self.action_codes[:]
205
207 '''
208 Gets a reference to the list of action codes in this L{Gesture}. The reference to
209 the list should be used for read-only access even though protections against
210 modification are not used. This method exists solely to offset the time
211 cost incurred by making a copy of actions using L{getActionCodes}.
212 '''
213 return self.action_codes
214
216 '''
217 Gets a copy of all the action codes in this L{Gesture} in a sort order
218 determined by the L{AEInput} device on which the actions are performed.
219
220 @return: Copy of all the action codes in device dependent sort order
221 @rtype: list of integer
222 '''
223 if self.sorted_codes is None:
224 self.sorted_codes = self.device.sortGesture(self)
225 return self.sorted_codes
226
228 '''
229 Gets the number of action codes stored in this L{Gesture}.
230
231 @return: Number of action codes bounded by
232 L{AEInput.Base.AEInput.getMaxActions}
233 @rtype: integer
234 '''
235 return len(self.action_codes)
236
238 '''
239 Gets a human readable representation of the action codes in this L{Gesture}
240 determined by the L{AEInput} device on which the actions were performed.
241
242 @return: Text representation of the actions in this L{Gesture}
243 @rtype: string
244 '''
245 return self.device.asString(self)
246