[Zope3-dev] Re: ObjectHub/Event service: who sends those events anyway?
Steve Alexander
steve@cat-box.net
Thu, 17 Oct 2002 12:30:42 +0000
> PROPOSAL:
>
> For copy and paste, it seems to me that we can shuffle off the cookie or
> session tracking mechanism to the view code, so that the container
> itself might only need something like this:
>
> class ICopyPasteContainer(IContainer):
> def moveTo(key, destination):
> "move the item specified by key to the destination"
>
> def duplicateTo(key, destination):
> "copy the item specified by key to the destination"
How can a container know how to duplicate things?
Does duplication happen at the ZODB level, or at the application level,
or either, depending on some adapter?
> I also want a "link" in there but I won't scope creep here. ;-)
>
> Then we would need the following modification for a folder that sends
> events:
>
> class IVocalContainer(ICopyPasteContainer):
> def setObject(key, object):
> """sets object and sends an IObjectAdded event"""
>
> def silentSetObject(key, object):
> """does not send an event; used by moveTo and duplicateTo"""
>
> def __delitem__(key):
> """deletes object and sends an IObjectRemoved event"""
>
> def silentDel(key):
> """does not send an event; used by moveTo"""
>
> def moveTo(key, destination, newkey=None):
> "moves and sends an IObjectMoved event"""
>
> def duplicateTo(key, destination):
> "duplicates and sends an IObjectDuplicated event"
>
> Notice that's a new event type--IObjectDuplicated. Presumably it would
> need a hub event parallel as well.
>
> Then the folder handles all of the events for the contained objects
> except for IModified. I think one possible ObjectHub subscriber might
> reject any moves that tried to move a registered object into a
> non-IVocalContainer, for instance.
Not really.
Containers don't need to know about events. Content classes don't need
to know about events.
There is a separate class of components, which you might call
"Management Components", that mediate between something that wants to
manipulate a component, and the component itself.
For example, consider a glass of water:
class IViewGlassOfWater(Interface):
def getVolumeOfWater():
'returns the volume of water in the glass in ml'
class IChangeGlassOfWater(Interface):
def drink(volume):
'drinks the given volume of water'
def fill(volume):
'adds the volume of water to the glass'
class IGlassOfWater(IViewGlassOfWater, IChangeGlassOfWater):
pass
I would have a Content Component that implements IGlassOfWater:
class GlassOfWater(Persistent):
__implements__ = IGlassOfWater
def __init__(self):
self.__volume = 0
def getVolumeOfWater(self):
return self.__volume
def drink(self, volume):
if volume > self.__volume or volume < 0:
raise ValueError, volume
self.__volume -= volume
def fill(self, volume):
if volume < 0:
raise ValueError, volume
self.__volume += volume
Then, I would also have an interface for managing an IGlassOfWater:
class IManageGlassOfWater(IChangeGlassOfWater):
pass
I write this class, and register is as an adapter of IGlassOfWater:
class ManageGlassOfWater:
__implements__ = IManageGlassOfWater
__used_for__ = IChangeGlassOfWater
def __init__(self, glassOfWater):
self.__glassOfWater = glassOfWater
def drink(self, volume):
# send out an IAboutToDrinkEvent
self.__glassOfWater.drink(volume)
def fill(self, volume):
self.__glassOfWater.fill(volume)
# send out an IJustFilledAGlassWithSomeWater event
When I have an IGlassOfWater, and I want to drink or fill it, I don't
call the methods directly on the instance. Instead, I call them on
getAdapter(myGlass).
I might have some details a bit wrong here, but I think the general idea
is sound. I believe Jim was working on a step of the Tutorial with
something like this in it.
--
Steve Alexander