#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Event and EventDispatcher classes
# -----------------------------------------------------------------------------
class Event( object ):
"""
Generic event to use with EventDispatcher.
"""
def __init__(self, event_type, data=None):
"""
The constructor accepts an event type as string and a custom data
"""
self._type = event_type
self._data = data
@property
def type(self):
"""
Returns the event type
"""
return self._type
@property
def data(self):
"""
Returns the data associated to the event
"""
return self._data
class EventDispatcher( object ):
"""
Generic event dispatcher which listen and dispatch events
"""
def __init__(self):
self._events = dict()
def __del__(self):
"""
Remove all listener references at destruction time
"""
self._events = None
def has_listener(self, event_type, listener):
"""
Return true if listener is register to event_type
"""
# Check for event type and for the listener
if event_type in self._events.keys():
return listener in self._events[ event_type ]
else:
return False
def dispatch_event(self, event):
"""
Dispatch an instance of Event class
"""
# Dispatch the event to all the associated listeners
if event.type in self._events.keys():
listeners = self._events[ event.type ]
for listener in listeners:
listener( event )
def add_event_listener(self, event_type, listener):
"""
Add an event listener for an event type
"""
# Add listener to the event type
if not self.has_listener( event_type, listener ):
listeners = self._events.get( event_type, [] )
listeners.append( listener )
self._events[ event_type ] = listeners
def remove_event_listener(self, event_type, listener):
"""
Remove event listener.
"""
# Remove the listener from the event type
if self.has_listener( event_type, listener ):
listeners = self._events[ event_type ]
if len( listeners ) == 1:
# Only this listener remains so remove the key
del self._events[ event_type ]
else:
# Update listeners chain
listeners.remove( listener )
self._events[ event_type ] = listeners
# ------------------------------------------------------------------------------
# Events and Dispatcher example
#
# In this example we create a simple event MyEvent with only two event types,
# ASK and RESPOND, and two classes: WhoAsk, which send AKS event and listen for
# the RESPOND event, and WhoRespond, which listen for ASK events and send back
# a RESPOND event
# -----------------------------------------------------------------------------
class MyEvent( Event ):
"""
When subclassing Event class the only thing you must do is to define
a list of class level constants which defines the event types and the
string associated to them
"""
ASK = "askMyEvent"
RESPOND = "respondMyEvent"
class WhoAsk( object ):
"""
First class which ask who is listening to it
"""
def __init__(self, event_dispatcher):
# Save a reference to the event dispatch
self.event_dispatcher = event_dispatcher
# Listen for the RESPOND event type
self.event_dispatcher.add_event_listener(
MyEvent.RESPOND, self.on_answer_event
)
def ask(self):
"""
Dispatch the ask event
"""
print ">>> I'm instance {0}. Who are listening to me ?".format( self )
self.event_dispatcher.dispatch_event(
MyEvent( MyEvent.ASK, self )
)
def on_answer_event(self, event):
"""
Event handler for the RESPOND event type
"""
print "<<< Thank you instance {0}".format( event.data )
class WhoRespond( object ):
"""
Second class who respond to ASK events
"""
def __init__(self, event_dispatcher):
# Save event dispatcher reference
self.event_dispatcher = event_dispatcher
# Listen for ASK event type
self.event_dispatcher.add_event_listener(
MyEvent.ASK, self.on_ask_event
)
def on_ask_event(self, event):
"""
Event handler for ASK event type
"""
self.event_dispatcher.dispatch_event(
MyEvent ( MyEvent.RESPOND, self )
)
if __name__ == "__main__":
# Create and instance of event dispatcher
dispatcher = EventDispatcher()
# Create an instance of WhoAsk class and two instance of WhoRespond class
who_ask = WhoAsk( dispatcher )
who_responde1 = WhoRespond( dispatcher )
who_responde2 = WhoRespond( dispatcher )
# WhoAsk ask :-)
who_ask.ask()