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