969ad8138654e49d764ce71ee022e72c0eba0e4b
[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 le code 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 basicConfig(level=DEBUG, stream = sys.stdout)
35 console = getLogger('minwii.eventutils')
36
37 class _EventDispatcher :
38 def __init__(self) :
39 self.registry = {}
40
41 def addEventListener(self, eventType, listener) :
42 if self.registry.has_key(eventType) :
43 self.registry[eventType][listener] = True
44 else :
45 self.registry[eventType] = {listener:True}
46
47 def removeEventListener(self, eventType, listener) :
48 try :
49 del self.registry[eventType][listener]
50 except KeyError :
51 console.warn("no listener to remove")
52
53 def dispatchEvents(self) :
54 events = pygame.event.get()
55 for event in events :
56 #if event.type == pygame.MOUSEMOTION :
57 # if hasattr(event, 'wiimoteid') :
58 # console.info(event)
59 # #return
60
61 listeners = self.registry.get(event.type, {})
62 for listener in listeners.keys() :
63 listener(event)
64 def reset(self) :
65 self.registry = {}
66
67 def __repr__(self) :
68 out = StringIO()
69 keys = self.registry.keys()
70 keys.sort()
71 for k in keys :
72 print >> out, "event", k
73 for listener in self.registry[k].keys() :
74 print >> out, listener.__name__
75 out.seek(0)
76 return out.read()
77
78
79 EventDispatcher = _EventDispatcher()
80
81 def event_handler(*eventTypes) :
82 def markFunctionAsListener(m) :
83 m.__islistener__ = True
84 m.__eventtypes__ = eventTypes
85 return m
86 return markFunctionAsListener
87
88
89 class EventInitializer(type):
90
91 def __init__(cls, name, bases, dict) :
92 def init_listeners(self) :
93 for k, v in dict.items() :
94 if isinstance(v, types.FunctionType) and hasattr(v, '__islistener__') :
95 listener = getattr(self, k)
96 for eventType in v.__eventtypes__ :
97 EventDispatcher.addEventListener(eventType, listener)
98
99 def ctor(self, *args, **kw) :
100 default_ctor = dict.get('__init__')
101 if not default_ctor :
102 super(cls, self).__init__(*args, **kw)
103 else :
104 default_ctor(self, *args, **kw)
105 init_listeners(self)
106
107 cls.__init__ = ctor
108
109
110 class EventHandlerMixin(object) :
111 __metaclass__ = EventInitializer
112
113 #def input(self) :
114 # event = pygame.event.wait()
115 # handler = getattr(self, 'eventHandler%s' % event.type, lambda e:None)
116 # handler(event)