1 '''
2 Defines a class for managing the L{Perk}s loaded for a single instance of an
3 application.
4
5 @author: Peter Parente
6 @author: Pete Brunet
7 @author: Larry Weiss
8 @author: Scott Haeger
9 @organization: IBM Corporation
10 @copyright: Copyright (c) 2005, 2007 IBM Corporation
11 @license: The BSD License
12
13 All rights reserved. This program and the accompanying materials are made
14 available under the terms of the BSD license which accompanies
15 this distribution, and is available at
16 U{http://www.opensource.org/licenses/bsd-license.php}
17 '''
18 import logging, weakref, traceback, sys, os
19 import AEState, AEInput, Perk, Task, AEConstants
20 from POR import POR
21
22 log = logging.getLogger('Tier')
23
25 '''
26 Manages the L{Perk}s for a single instance of a running program (a process).
27 Supports the addition and removal of L{Perk}s from its stack. Executes
28 L{Task}s registered in each L{Perk} in response to L{AEEvent}s. Provides
29 methods to assist L{Perk}s and L{Task}s in finding registered L{Task}s
30 throughout the L{Tier}.
31
32 @ivar perks: List of L{Perk}s treated as a stack (last in, first executed)
33 @type perks: list
34 @ivar wanted_events: Lookup table for what L{AEEvent}s are desired by any
35 L{Task} in any L{Perk} in this L{Tier}. Used to optimize event dispatch and
36 processing. Unwanted events are ignored.
37 @type wanted_events: dictionary
38 @ivar tier_manager: L{TierManager} that created this L{Tier}
39 @type tier_manager: L{TierManager}
40 @ivar pointer_por: Pointer of regard for the user focus
41 @type pointer_por: L{POR}
42 @ivar focus_por: Point of regard for the application focus
43 @type focus_por: L{POR}
44 @ivar name: Name of this L{Tier}
45 @type name: string
46 @ivar aid: ID uniquely identifying this L{Tier} from all other L{Tier}s
47 @type aid: opaque
48 @ivar last_key: Stores the key code, key sym, and modifiers for the last key
49 pressed
50 @type last_key: 3-tuple of integer, string, integer
51 @ivar perk_refs: References to L{Perk}s keyed by task names, commands,
52 identifiers, etc. Many to one mapping. See L{addTaskRef} and
53 L{removeTaskRef}.
54 @type perk_refs: weakref.WeakValueDictionary
55 @ivar chain_refs: References to L{Perk}s keyed by task names. Many to many
56 mapping. See L{addChainRef} and L{removeChainRef}.
57 @type chain_refs: dictionary
58 @ivar chain_stack: Stack of L{Task} and L{Perk} names currently executing in
59 one or more chains before, after, or around one or more anchors
60 @type chain_stack: list
61 @ivar temp_data: Arbitrary name/value pairs stored by L{Task}s executing in
62 this L{Tier} in response to a single event. The data is persistent until
63 the event has been handled by all L{Task}s at which time it is cleared.
64 @type temp_data: dictionary
65 @ivar task_history: Stack of L{Task} and L{Perk} names having already
66 executed in response to an L{AEEvent}, including all chained L{Task}s and
67 all L{Task}s executed from within other L{Task}s
68 @type task_history: list
69 @ivar show: Call show* methods on L{TierManager} to log events? Set by the
70 L{TierManager} based on whether monitors are loaded or not. Optimization.
71 @type show: boolean
72 '''
73 - def __init__(self, tier_manager, name, aid, por):
74 '''
75 Stores a reference to the L{TierManager} that created this L{Tier}. Creates
76 an empty list of L{Perk}s. Initializes the stored focus L{POR} to None and
77 the pointer L{POR} to the application. Creates the weak dictionary for
78 L{Perk} L{Task}s and stores other information about the L{Tier}.
79
80 @param tier_manager: Manager that created this L{Tier}
81 @type tier_manager: L{TierManager}
82 @param name: Name of this L{Tier}
83 @type name: string
84 @param aid: ID uniquely identifying this L{Tier} from all other L{Tier}s
85 @type aid: opaque
86 @param por: First point of regard to the application represented by
87 this L{Tier}. Typically, the top most accessible.
88 @type por: L{POR}
89 '''
90 self.tier_manager = tier_manager
91 self.perks = []
92 self.wanted_events = {}
93 self.name = name
94 self.aid = aid
95 self.perk_refs = weakref.WeakValueDictionary()
96 self.chain_refs = {}
97 self.pointer_por = por
98 self.focus_por = None
99 self.last_key = (None, None, None)
100 self.auto_pointer = True
101
102 self.clearState()
103
105 '''
106 Clears all L{Perk}s and closes them.
107 '''
108 self.clearPerks()
109
111 '''
112 Sets whether show methods should be called on the L{TierManager} when
113 handling events or not based on the presence of L{AEMonitor}s in the
114 manager.
115
116 @param show: Call show methods to notify monitors?
117 @type show: boolean
118 '''
119 self.show = show
120
122 '''
123 Gets the user L{POR} for this L{Tier}.
124
125 @return: Point of regard of user attention
126 @rtype: L{POR}
127 '''
128 return self.pointer_por
129
131 '''
132 Sets the user L{POR} for this L{Tier}.
133
134 @param por: Point of regard of user attention
135 @type por: L{POR}
136 '''
137 self.pointer_por = por
138
140 '''
141 Gets the application focus L{POR} for this L{Tier}.
142
143 @return: Point of regard of application focus
144 @rtype: L{POR}
145 '''
146 return self.focus_por
147
148 - def getHistory(self):
149 '''
150 Gets the entire linear history of L{Task}s that have executed and the
151 L{Perk}s they are in.
152
153 @return: List of L{Task} identities and L{Perk} class names
154 @rtype: list of 2-tuple of string
155 '''
156 return self.task_history
157
159 '''
160 Gets the identity of the L{Task} to which the current L{Task} is chained
161 and its corresponding L{Perk}. If there is no anchor for the executing
162 L{Task}, this method returns None.
163
164 @return: L{Task} identity and L{Perk} class name or None
165 @rtype: 2-tuple of string
166 '''
167 try:
168 return self.chain_stack[-1]
169 except IndexError:
170 return None
171
173 '''
174 Gets the last key code, key sym, and key modifiers. Useful for dealing with
175 applications that do a poor job of synthesizing caret and text events.
176
177 @return: The key code, key sym, and modifiers for the last key pressed
178 @rtype: 3-tuple of integer, string, integer
179 '''
180 return self.last_key
181
183 '''
184 Gets data from L{temp_data}.
185
186 @param name: Name of the stored data
187 @type name: immutable
188 @return: Value stored under the given name
189 @rtype: object
190 @raise KeyError: When no data is stored under the given name
191 '''
192 return self.temp_data[name]
193
195 '''
196 Stores data for the duration of the execution of an L{AEEvent}.
197
198 @param name: Name to associate with the value
199 @type name: immutable
200 @param value: Any value to store
201 @type value: object
202 '''
203 self.temp_data[name] = value
204
206 '''
207 Clears all stored L{temp_data}, the L{chain_stack}, L{task_history}, and
208 the L{show} flag.
209 '''
210 self.temp_data = {}
211 self.task_history = []
212 self.chain_stack = []
213 self.show = False
214
216 '''
217 Adds a weak reference to a L{Perk} as one to check for L{Task}s which are
218 part of a the chain for the target. Optimization for the L{manageChain}
219 method.
220
221 @param target: Name of the L{Task} to link to
222 @type target: string
223 @param perk: Perk have at least one link in the chain for the target
224 @type perk: L{Perk}
225 '''
226 chain = self.chain_refs.setdefault(target, weakref.WeakKeyDictionary())
227 chain[perk] = None
228
230 '''
231 Removes a weak reference to a L{Perk} as one to no longer check for
232 L{Task}s which are part of the chain for the target. Optimization for the
233 L{manageChain} method.
234
235 @param target: Name of the L{Task} to unlink from
236 @type target: string
237 @param perk: Perk have at least one link in the chain for the target
238 @type perk: L{Perk}
239 '''
240 try:
241 chain = self.chain_refs[target]
242 del chain[perk]
243 except (KeyError, ValueError):
244 pass
245
247 '''
248 Adds a key that can be used later to quickly look up a reference to a
249 L{Perk} in this L{Tier}. Optimization for the L{getKeyedTask},
250 L{getCommandTask}, and L{getNamedTask} methods.
251
252 @param key: Key under which to hash the L{Perk}
253 @type key: immutable
254 @param perk: Perk to store in the hash
255 @type perk: L{Perk}
256 '''
257 self.perk_refs[key] = perk
258
260 '''
261 Removes a key used to quickly look up a reference to a L{Perk} in this
262 L{Tier}. Keys are cleaned up automatically when L{Perk}s are destroyed.
263 However, this method may be used to manually remove L{Perk}s at any time.
264
265 @param key: Key under which to hash the L{Perk}
266 @type key: immutable
267 '''
268 try:
269 del self.perk_refs[key]
270 except KeyError:
271 pass
272
274 '''
275 @return: Name of this L{Tier} (i.e. name of the app with which it is
276 associated)
277 @rtype: string
278 '''
279 return self.name
280
282 '''
283 @return: Unique identifier for this L{Tier}
284 @rtype: opaque
285 '''
286 return self.aid
287
289 '''
290 Adds one or more L{Perk}s to the top of the stack. If more than one L{Perk}
291 is specified, the last specified L{Perk} will be at the top of the stack
292 when this method completes. That is, the behavior of pushing more than one
293 L{Perk} at a time is the same as if each L{Perk} were pushed individually.
294
295 @param ae: The AccessEngine context to use for initializing the Perk
296 @type ae: L{AccessEngine}
297 @param perks: L{Perk}s to add
298 @type perks: list of L{Perk}
299 '''
300 self.insertPerk(ae, 0, *perks)
301
303 '''
304 Adds one L{Perk} to the stack at the insertion index. Negative indices are
305 valid per Python list convention.
306
307 @param ae: The AccessEngine context to use for initializing the Perk
308 @type ae: L{AccessEngine}
309 @param index: Index at which the L{Perk} should be inserted in the stack
310 @type index: integer
311 @param perks: L{Perk}s to add
312 @type perks: list of L{Perk}
313 '''
314 for perk in perks:
315
316 self.perks.insert(index, perk)
317
318 perk.preInit(ae, self)
319
320 perk.preExecute(AEConstants.LAYER_FOCUS)
321 try:
322
323 perk.init()
324 except Exception, e:
325
326 self.perks.pop(index)
327
328 try:
329 perk.close()
330 except Exception:
331
332 pass
333 perk.postClose()
334
335 info = traceback.extract_tb(sys.exc_info()[2])
336 log.debug('cannot initialize %s (%s, %d): %s', perk.getClassName(),
337 os.path.basename(info[-1][0]),
338 info[-1][1], str(e))
339
341 '''
342 Removes one or more L{Perk}s from the stack given their indices. Negative
343 indices are valid per Python list convention. Calls L{Perk.Perk.close} on
344 each to ensure they have a chance to persist state.
345
346 @param indices: Indices of L{Perk}s to remove
347 @type indices: list of integer
348 @raise IndexError: When the stack is empty
349 @raise ValueError: When a specific index is out of the bounds of the stack
350 '''
351 indices = list(indices)
352
353 indices.sort(reverse=True)
354 perks = map(self.perks.pop, indices)
355 for perk in perks:
356 try:
357 perk.close()
358 except Exception:
359
360 pass
361 perk.postClose()
362
364 '''
365 Removes all L{Perk}s from the stack. Calls L{Perk.Perk.close} on each to
366 ensure they have a chance to persist state.
367 '''
368 for perk in self.perks:
369 try:
370 perk.close()
371 except Exception:
372
373 pass
374 perk.postClose()
375 self.perks = []
376
378 '''
379 Gets all L{Perk}s pushed onto this L{Tier} in execution order.
380
381 @note: This method does not return a copy of the stack. Modifications will
382 affect this L{Tier}!
383 @return: All L{Perk}s pushed onto this L{Tier}
384 @rtype: list of L{Perk}
385 '''
386 return self.perks
387
389 '''
390 Updates the L{wanted_events} dictionary to indicate that a L{Task} in a
391 L{Perk} in this L{Tier} has been registered for a particular kind of
392 L{AEEvent}. This information is used for optimization purposes such that no
393 processing will occur on the event unless at least one L{Task} is
394 registered that will use it.
395
396 @param kind: Kind of L{AEEvent} of interest to a L{Task}
397 @type kind: L{AEEvent} class
398 @param wants: Does a L{Perk} want an event (i.e. a L{Task} is registering
399 for it or no longer want an event (i.e. a L{Task} is unregistering for
400 it)?
401 @type wants: boolean
402 '''
403 count = self.wanted_events.setdefault(kind, 0)
404 if wants:
405 count += 1
406 else:
407 count -= 1
408 if count <= 0:
409 del self.wanted_events[kind]
410 else:
411 self.wanted_events[kind] = count
412
413 self.tier_manager.setEventInterest(kind, wants)
414
416 '''
417 Gets if this L{Tier} wants a particular kind of L{AEEvent} given that one of
418 its L{Perk}s has a L{Task} that wants to handle it.
419
420 @param event: Event to be tested
421 @type event: L{AEEvent}
422 '''
423 return self.wanted_events.has_key(type(event))
424
426 '''
427 Gets a L{Task} registered under a particular key set to execute in response
428 to events. None is returned if not found.
429
430 @param key: Unique ID for locating a registered L{Task}
431 @type key: integer
432 @return: L{Task} set to execute in response to the event or None
433 @rtype: L{Task}
434 '''
435 try:
436 perk = self.perk_refs[key]
437 except KeyError:
438 return None
439 return perk.getKeyedTask(key)
440
442 '''
443 Gets a L{Task} registered to execute in response to the L{AEInput.Gesture}.
444 None is returned if not found.
445
446 @param gesture_list: Gestures and device expressed as a list of virtual key
447 codes
448 @type gesture_list: L{AEInput.Gesture}
449 @return: Name of the L{Task} to execute in response to the input gesture
450 or None if no L{Task} registered to execute
451 @rtype: string
452 '''
453 try:
454 perk = self.perk_refs[gesture_list]
455 except KeyError:
456 return None
457 return perk.getCommandTask(gesture_list)
458
460 '''
461 Gets a L{Task} with the given name by iterating through the registered
462 L{Perk}s until one is found containing a L{Task} registered under the given
463 name. None is returned if not found.
464
465 @param name: Name of the L{Task} to find
466 @type name: string
467 @return: L{Task} with the given name or None
468 @rtype: L{Task.Base.Task}
469 '''
470 try:
471 perk = self.perk_refs[name]
472 except KeyError:
473 return None
474 return perk.getNamedTask(name)
475
477 '''
478 Gets all L{Task}s registered to handle the given type of event on the
479 given layer by iterating through the registered {Perk}s. The L{Task}s are
480 returned in the order they will be executed both within and across
481 L{Perk}s in this L{Tier}.
482
483 @param event_type: Desired type of L{AEEvent}
484 @type event_type: L{AEEvent} class
485 @param task_layer: Layer on which the desired L{Task}s are registered
486 @type task_layer: integer
487 @return: List of all L{Task}s registered to handle the given type of event
488 on the given layer
489 @rtype: list of L{Task.Base.Task}
490 '''
491 tasks = []
492 map(tasks.extend, [p.getEventTasks(event_type, task_layer) for p in
493 self.perks])
494 return tasks
495
497 '''
498 Gets all L{Task}s linked to the target by iterating through L{Perk}
499 references established by L{addChainRef}. The L{Task}s are returned in the
500 order in which they were registered within a L{Perk}. Ordering is undefined
501 across L{Perk}s within a chain segment.
502
503 @param target: Name of the L{Task} to link to
504 @type target: string
505 @return: L{Task} names for before, around, and after segments
506 @rtype: 3-tuple of list, string, list
507 @raise KeyError: When the target has no chained L{Task}s
508 '''
509 befores = []
510 afters = []
511 perks = self.chain_refs[target].keys()
512 arounds = [p.mergeChain(target, befores, afters) for p in perks]
513 return befores, arounds[0], afters
514
515 - def _executeTask(self, task, perk, por, layer, params, propagate):
516 '''
517 Executes the given L{Task} in response to the given L{AEEvent}.
518
519 @param task: A L{Task} registered to handle the given event
520 @type task: L{Task}
521 @param perk: The L{Perk} containing the L{Task}
522 @type perk: L{Perk}
523 @param por: Point of regard where the event occurred
524 @type por: L{POR}
525 @param propagate: Should this event be propagated to the
526 L{Task.Base.Task.execute} method or should we call
527 L{Task.Base.Task.update} instead for housekeeping?
528 @type propagate: boolean
529 @param layer: Layer on which the L{AEEvent} occurred, one of
530 L{AEConstants.Event.LAYER_FOCUS}, L{AEConstants.Event.LAYER_TIER},
531 L{AEConstants.Event.LAYER_BACKGROUND}
532 @type layer: integer
533 @param params: Keyword arguments to be provided to the L{Task} as
534 parameters
535 @type params: dictionary
536 @return: Should the next registered L{Task} be executed or only updated?
537 @rtype: boolean
538 @raise AssertionError: When the L{Perk} or L{Task} does not preExecute
539 successfully
540 '''
541
542 if not (perk.preExecute(layer, por) and task.preExecute(layer, por)):
543 raise AssertionError
544 try:
545 if propagate:
546
547 rv = task.execute(layer=layer, **params)
548 else:
549
550 task.update(layer=layer, **params)
551 rv = False
552 except Task.ToolsError, ex:
553
554 if self.tier_manager.getState().Trap:
555 task.sayError(text=str(ex))
556 else:
557 log.exception(ex)
558 rv = True
559 except Exception:
560
561 log.exception('%s: %s %s', task.getClassName(), layer, params)
562
563 rv = True
564 if rv is None:
565
566 rv = True
567 elif not rv:
568
569 task.inhibitAutoPointer()
570
571 task.postExecute()
572 return rv
573
574 - def manageChain(self, por, name, task, perk, layer, task_params,
575 propagate, chain):
576 '''
577 Executes all L{Task}s chained the the given L{Task}, recursively if
578 chain=True.
579
580 @note: This method is purposely long because much code that could be
581 refactored into other methods is inlined for performance reasons.
582
583 @param name: Identity of the L{Task} to execute
584 @type name: string
585 @param task: Task to execute
586 @type task: L{Task}
587 @param perk: Perk in which the Task resides
588 @type perk: L{Perk}
589 @param layer: Layer in which to execute the L{Task}, one of
590 L{AEConstants.Event.LAYER_FOCUS}, L{AEConstants.Event.LAYER_TIER},
591 L{AEConstants.Event.LAYER_BACKGROUND}
592 @type layer: integer
593 @param task_params: Keyword data to pass to the L{Task} as parameters on
594 execution or update
595 @type task_params: dictionary
596 @param propagate: Should chained L{Task}s be executed or updated?
597 @type propagate: boolean
598 @param chain: Execute all L{Task}s chained to the one named or not?
599 @type chain: boolean
600 '''
601
602 show = self.show
603
604 p_name = perk.getClassName()
605
606 if not chain:
607
608
609
610 self.task_history.append((name, p_name))
611 if show:
612
613 self.tier_manager.showTask(task, perk)
614 try:
615 propagate = self._executeTask(task, perk, por, layer, task_params,
616 propagate)
617 except AssertionError:
618 pass
619 self.tier_manager.showPropagate(propagate)
620 else:
621
622 try:
623 propagate = self._executeTask(task, perk, por, layer, task_params,
624 propagate)
625 except AssertionError:
626 pass
627
628 else:
629
630 try:
631 befores, around_name, afters = self.getChainedTasks(name)
632 except KeyError:
633
634
635
636 self.task_history.append((name, p_name))
637 if show:
638
639 self.tier_manager.showTask(task, perk)
640 try:
641 propagate = self._executeTask(task, perk, por, layer, task_params,
642 propagate)
643 except AssertionError:
644 pass
645 self.tier_manager.showPropagate(propagate)
646 else:
647
648 try:
649 propagate = self._executeTask(task, perk, por, layer, task_params,
650 propagate)
651 except AssertionError:
652 pass
653
654 else:
655
656 self.chain_stack.append((name, p_name))
657
658
659 for before_name in befores:
660 if show:
661 self.tier_manager.showChain(AEConstants.CHAIN_BEFORE, name)
662
663 task = self.getNamedTask(before_name)
664
665 if task is not None:
666 perk = task.getPerk()
667
668 propagate = self.manageChain(por, before_name, task, perk, layer,
669 task_params, propagate, chain)
670
671
672 if around_name is None:
673
674 cache = self.chain_stack.pop()
675
676
677 self.task_history.append((name, p_name))
678 if show:
679
680 self.tier_manager.showTask(task, perk)
681 try:
682 propagate = self._executeTask(task, perk, por, layer,
683 task_params, propagate)
684 except AssertionError:
685 pass
686 self.tier_manager.showPropagate(propagate)
687 else:
688
689 try:
690 propagate = self._executeTask(task, perk, por, layer,
691 task_params, propagate)
692 except AssertionError:
693 pass
694
695 por = self.getPointer()
696
697 self.chain_stack.append(cache)
698 else:
699 if show:
700 self.tier_manager.showChain(AEConstants.CHAIN_AROUND, name)
701
702 task = self.getNamedTask(around_name)
703
704 if task is not None:
705 perk = task.getPerk()
706
707 propagate = self.manageChain(por, around_name, task, perk, layer,
708 task_params, propagate, chain)
709
710 por = self.getPointer()
711
712
713 for after_name in afters:
714 if show:
715 self.tier_manager.showChain(AEConstants.CHAIN_AFTER, name)
716
717 task = self.getNamedTask(after_name)
718
719 if task is not None:
720 perk = task.getPerk()
721
722 propagate = self.manageChain(por, after_name, task, perk, layer,
723 task_params, propagate, chain)
724
725 self.chain_stack.pop()
726
727 return propagate
728
730 '''
731 Manages an event by iterating through the L{Perk} stack (top to bottom) and
732 checking for registered L{Task}s of the given type. Executes the registered
733 L{Task}s (last registered, first executed) in each L{Perk} until one of the
734 following conditions is met:
735 - All L{Task}s have executed
736 - A L{Task} returns False
737 - A L{Task} raises an exception
738
739 In the latter two cases, no additional L{Task}s in the current L{Perk} or
740 additional L{Perk}s in this L{Tier} are executed. Instead the
741 L{Task.Base.Task.update} methods are called to allow housekeeping
742 operations (e.g updating state) to be performed.
743
744 If a L{Task} returns neither True or False (e.g. it returns None) a
745 warning is logged and the return value is treated as if it were True. This
746 likely means the L{Task} forgot to specify a return value.
747
748 @param event: Event to process
749 @type event: L{AEEvent.Base.AccessEngineEvent}
750 '''
751 try:
752
753 self.focus_por = event.getFocusPOR()
754 except AttributeError:
755 pass
756
757 if not self.wantsEvent(event):
758
759 return
760
761
762 show = self.show
763
764
765 if show:
766 self.tier_manager.showEvent(event, self.name)
767
768
769 event_por = event.getPOR()
770 task_layer = event.getLayer()
771 task_params = event.getDataForTask()
772 event_type = type(event)
773
774
775 propagate = True
776 for perk in self.perks:
777
778 for task in perk.getEventTasks(event_type, task_layer):
779 try:
780 i = task.getIdentity()
781 except ValueError:
782 i = None
783
784
785 self.task_history.append((i, perk.getClassName()))
786
787 if show:
788
789 self.tier_manager.showTask(task, perk)
790 propagate = self.manageChain(event_por, i, task, perk, task_layer,
791 task_params, propagate, True)
792 self.tier_manager.showPropagate(propagate)
793 else:
794
795 propagate = self.manageChain(event_por, i, task, perk, task_layer,
796 task_params, propagate, True)
797
799 '''
800 Manages an event by getting the L{AEInput.Gesture} that triggered it and
801 locating a L{Task} registered to execute in response to it. If a L{Task}
802 could not be found for the given event, the L{Task} registered for invalid
803 gestures is executed instead.
804
805 @param event: Event to process
806 @type event: L{AEEvent.InputGesture}
807 @param count: Number of times this gesture has been issued without
808 interruption
809 @type count: integer
810 '''
811
812 name = self.getCommandTask(event.getTaskKey())
813 if name is None: return
814
815
816 if self.show:
817 self.tier_manager.showEvent(event, self.name)
818
819 layer = event.getLayer()
820 task_params = event.getDataForTask()
821
822 task_params['cycle_count'] = count
823
824 task = self.getNamedTask(name)
825 if task is not None:
826
827 perk = task.getPerk()
828 self.manageChain(None, name, task, perk, layer, task_params, True, True)
829
831 '''
832 Manages an event by locating a L{Task} under a particular key (not keyboard
833 key, but some immutable identifier) registered to execute in response to
834 it.
835
836 @param event: Event to process
837 @type event: L{AEEvent}
838 '''
839
840 task = self.getKeyedTask(event.getTaskKey())
841
842 show = self.show
843
844 if show:
845 self.tier_manager.showEvent(event, self.name)
846 if task is not None:
847 layer = event.getLayer()
848 perk = task.getPerk()
849 task_params = event.getDataForTask()
850 if show:
851
852 self.tier_manager.showTask(task, perk)
853 try:
854 rv = self._executeTask(task, perk, None, layer, task_params, True)
855 except AssertionError:
856 pass
857 self.tier_manager.showPropagate(rv)
858 else:
859
860 try:
861 self._executeTask(task, perk, None, layer, task_params, True)
862 except AssertionError:
863 pass
864
866 '''
867 Pulls private data from an event and stores it in appropriate instance
868 variables. Does not forward the event to L{Perk}s and L{Task}s. Rather,
869 the stored information is made public through L{Task.Tools} methods.
870
871 @param event: Event to process
872 @type event: L{AEEvent}
873 '''
874 data = event.getDataForTask()
875 kind = data['kind']
876 if kind == event.KEY_PRESS:
877
878 self.last_key = data['code'], data['sym'], data['mod']
879