#
# Copyright (c) 2004, 2005 Art Haas
#
# This file is part of PythonCAD.
#
# PythonCAD is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PythonCAD is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PythonCAD; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# A base class for objects that send messages
#
import types
import traceback
class Messenger(object):
__messages = {
'connected' : True,
'disconnected' : True
}
def __init__(self):
self.__connections = None
self.__mdict = None
self.__ignore = None
self.__muted = False
def finish(self):
if self.__connections is not None:
print "remaining connections for obj: " + `self`
for _message in self.__connections:
print "message: %s" % _message
for _method in self.__connections[_message]:
_obj = _method.im_self
print "connected to obj: " + `_obj`
def connect(self, message, method):
if not self.sendsMessage(message):
raise ValueError, "Unknown message : %s" % str(message)
if not isinstance(method, types.MethodType):
raise TypeError, "Invalid class method type: " + `type(method)`
if method.im_self is None:
raise ValueError, "Unbound method use invalid: %s" % str(method)
if self.__connections is None:
self.__connections = {}
_methods = self.__connections.setdefault(message, [])
_seen = False
for _m in _methods:
if _m is method:
_seen = True
break
if not _seen:
_methods.append(method)
self.sendMessage('connected', method)
def disconnect(self, obj, message=None):
if self.__connections is not None:
if message is None:
_messages = self.__connections.keys()
for _message in _messages:
_methods = self.__connections[_message]
for _method in _methods[:]:
_obj = _method.im_self
if _obj is obj:
_methods.remove(_method)
self.sendMessage('disconnected', obj)
if len(_methods) == 0:
del self.__connections[_message]
else:
if message in self.__connections:
_methods = self.__connections[message]
for _method in _methods[:]:
_obj = _method.im_self
if _obj is obj:
_methods.remove(_method)
self.sendMessage('disconnected', obj)
break
if len(_methods) == 0:
del self.__connections[message]
if len(self.__connections) == 0:
self.__connections = None
def sendsMessage(self, m):
return m in Messenger.__messages
def sendMessage(self, message, *args):
if not isinstance(message, str):
raise TypeError, "Invalid message type: " + `type(message)`
if not self.__muted and self.__connections is not None:
if self.__mdict is None or message not in self.__mdict:
if message in self.__connections:
_methods = self.__connections[message][:] # make a copy
for _method in _methods:
_obj = _method.im_self
if (isinstance(_obj, Messenger) and
_obj.ignores(message)):
continue
#
# "handle" the exception - notice the quotes ...
#
try:
_method(self, *args)
except:
traceback.print_exc()
def muteMessage(self, message):
if not isinstance(message, str):
raise TypeError, "Invalid message type: " + `type(message)`
if self.__mdict is None:
self.__mdict = {}
if message in self.__mdict:
raise ValueError, "Message '%s' already blocked." % message
self.__mdict[message] = True
def unmuteMessage(self, message):
if not isinstance(message, str):
raise TypeError, "Invalid message type: " + `type(message)`
if self.__mdict is not None:
if message in self.__mdict:
del self.__mdict[message]
if len(self.__mdict) == 0:
self.__mdict = None
def mute(self):
self.__muted = True
def unmute(self):
self.__muted = False
def isMuted(self):
return self.__muted is True
def ignore(self, message):
if not isinstance(message, str):
raise TypeError, "Invalid message type: " + `type(message)`
if self.__ignore is None:
self.__ignore = {}
if message in self.__ignore:
raise RuntimeError, "Message '%s' already ignored." % message
self.__ignore[message] = True
def receive(self, message):
if not isinstance(message, str):
raise TypeError, "Invalid message type: " + `type(message)`
if self.__ignore is not None:
if message in self.__ignore:
del self.__ignore[message]
if len(self.__ignore) == 0:
self.__ignore = None
def ignores(self, message):
return self.__ignore is not None and message in self.__ignore
def receives(self, message):
return self.__ignore is None or message not in self.__ignore