f95a828a610da05d620a73f56879a976bfed0662
[minwii.git] / src / app / eventutils.py
1 # -*- coding: utf-8 -*-
2 """
3 Décorateur, métaclasse et classe mixin pour faciliter
4 l'implémentation des gestionnaires d'événements pygame.
5
6 Utilisation :
7 - hériter de EventHandlerMixin
8 - décorer les méthodes gestionnaires d'événements avec le décorateur 'event_handler'
9 en passant en paramètre un ou plusieurs codes d'événement pygame
10
11 Il n'existe aucune contrainte sur le nommage de la méthode décorée.
12 La méthode gestionnaire d'événement reçoit l'événement pygame comme unique paramètre.
13
14 par exemple :
15
16 import pygame
17 class Machin(pygame.sprite.Sprite, EventHandlerMixin) :
18
19 # .../...
20
21 @event_handler(pygame.KEYDOWN)
22 def handleKeyDown(self, event) :
23 pass
24
25
26 $Id$
27 $URL$
28 """
29 import types
30 import pygame
31 from StringIO import StringIO
32 from logging import getLogger, basicConfig, DEBUG
33 import sys
34 from events import TIMEOUT, COLOVER, eventNames
35 basicConfig(level=DEBUG, stream = sys.stdout)
36 console = getLogger('minwii')
37 eventLog = getLogger('minwii.events')
38
39 hiddenEvents = {pygame.MOUSEMOTION:True,
40 TIMEOUT:True,
41 #COLOVER:True,
42 }
43 from event_pprinters import pprinters
44
45 class _EventDispatcher :
46 def __init__(self) :
47 self.registry = {}
48
49 def addEventListener(self, eventType, listener) :
50 if self.registry.has_key(eventType) :
51 self.registry[eventType][listener] = True
52 else :
53 self.registry[eventType] = {listener:True}
54
55 def removeEventListener(self, eventType, listener) :
56 try :
57 del self.registry[eventType][listener]
58 except KeyError :
59 console.warn("no listener to remove")
60
61 def dispatchEvents(self) :
62 events = pygame.event.get()
63 for event in events :
64 listeners = self.registry.get(event.type, {})
65 if not hiddenEvents.has_key(event.type):
66 #if listeners and not hiddenEvents.has_key(event.type) :
67 eventLog.info(pprinters[event.type](event))
68 for listener in listeners.keys() :
69 listener(event)
70
71 def reset(self) :
72 self.registry = {}
73
74 def __repr__(self) :
75 out = StringIO()
76 keys = self.registry.keys()
77 keys.sort()
78 for k in keys :
79 print >> out, "event", k
80 for listener in self.registry[k].keys() :
81 print >> out, listener.__name__
82 out.seek(0)
83 return out.read()
84
85
86 EventDispatcher = _EventDispatcher()
87
88 def event_handler(*eventTypes) :
89 def markFunctionAsListener(m) :
90 m.__islistener__ = True
91 m.__eventtypes__ = eventTypes
92 return m
93 return markFunctionAsListener
94
95
96 class EventInitializer(type):
97
98 def __init__(cls, name, bases, dict) :
99 def init_listeners(self) :
100 for k, v in dict.items() :
101 if isinstance(v, types.FunctionType) and hasattr(v, '__islistener__') :
102 listener = getattr(self, k)
103 for eventType in v.__eventtypes__ :
104 EventDispatcher.addEventListener(eventType, listener)
105
106 def ctor(self, *args, **kw) :
107 default_ctor = dict.get('__init__')
108 if not default_ctor :
109 super(cls, self).__init__(*args, **kw)
110 else :
111 default_ctor(self, *args, **kw)
112 init_listeners(self)
113
114 cls.__init__ = ctor
115
116
117 class EventHandlerMixin(object) :
118 __metaclass__ = EventInitializer