[Zope3-checkins] CVS: Zope3/src/zope/app/utilities - configure.zcml:1.3 content.py:1.4

Stephan Richter srichter at cosmos.phy.tufts.edu
Mon Aug 18 15:56:12 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app/utilities
In directory cvs.zope.org:/tmp/cvs-serv26491/utilities

Modified Files:
	configure.zcml content.py 
Log Message:
Beefed up the Content Component Definition component, by supporting 
flexible menu entries, which is very nice. 

I consider my work on schema-driven Content Components done now and 
encourage people to try it out. I think this functionality addresses an 
audience that we have not dealt with much before, i.e. people that stand
somewhere between scripter and TTW developers.


=== Zope3/src/zope/app/utilities/configure.zcml 1.2 => 1.3 ===
--- Zope3/src/zope/app/utilities/configure.zcml:1.2	Fri Aug 15 20:44:21 2003
+++ Zope3/src/zope/app/utilities/configure.zcml	Mon Aug 18 14:55:37 2003
@@ -61,7 +61,6 @@
 
   </content>
 
-
   <content class=".content.ContentComponentDefinitionRegistration">
     <require
       permission="zope.ManageServices"
@@ -71,6 +70,25 @@
       set_schema="zope.app.interfaces.services.utility.IUtilityRegistration"
       />
   </content>
+
+
+<!-- Content Component Menu Item -->
+
+  <content class=".content.ContentComponentDefinitionMenuItem">
+
+    <require
+      permission="zope.ManageServices"
+      interface="
+          zope.app.interfaces.utilities.content.IContentComponentMenuItem"
+      set_schema="
+          zope.app.interfaces.utilities.content.IContentComponentMenuItem" />
+
+  </content>
+
+  <adapter
+     for="zope.app.interfaces.utilities.content.IContentComponentDefinition"
+     provides="zope.app.interfaces.utilities.content.IContentComponentMenuItem"
+     factory=".content.ContentComponentDefinitionMenuItem" />
 
 <!-- Content Component Instance -->
 


=== Zope3/src/zope/app/utilities/content.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/utilities/content.py:1.3	Sun Aug 17 02:08:33 2003
+++ Zope3/src/zope/app/utilities/content.py	Mon Aug 18 14:55:37 2003
@@ -20,61 +20,267 @@
 from persistence import Persistent
 from persistence.dict import PersistentDict
 from zope.app import zapi
+from zope.app.i18n import ZopeMessageIDFactory as _
+from zope.app.interfaces.annotation import IAnnotations
 from zope.app.interfaces.container import IAdding
+from zope.app.interfaces.services.menu import \
+     ILocalBrowserMenu, ILocalBrowserMenuService
+from zope.app.interfaces.services.registration import ActiveStatus
 from zope.app.interfaces.utilities.content import \
-     IContentComponentDefinition, IContentComponentInstance
-from zope.app.services.menu import LocalBrowserMenuItem
+     IContentComponentDefinition, IContentComponentMenuItem
+from zope.app.interfaces.utilities.content import IContentComponentInstance
+from zope.app.services.menu import \
+     LocalBrowserMenuService, LocalBrowserMenu, LocalBrowserMenuItem
+from zope.app.services.service import ServiceRegistration
 from zope.app.services.servicenames import BrowserMenu
 from zope.app.services.utility import UtilityRegistration
-from zope.context import ContextMethod
+from zope.component.exceptions import ComponentLookupError
+from zope.context import ContextMethod, ContextProperty
 from zope.interface import directlyProvides, implements
 from zope.schema import getFields
 from zope.security.checker import CheckerPublic, Checker, defineChecker
 
+MenuItemKey = 'http://www.zope.org/utilities/content/menuitem'
+
 
 class ContentComponentDefinition(Persistent):
 
     implements(IContentComponentDefinition)
 
-    def __init__(self, name=u'', schema=None):
+    def __init__(self, name=u'', schema=None, copySchema=True):
         self.name = name
         self.schema = schema
+        self.copySchema = copySchema
         self.permissions = PersistentDict()
+        # This will set up the menu item entry.
+        adapter = zapi.getAdapter(self, IContentComponentMenuItem)
+        
+
+
+class ContentComponentDefinitionMenuItem:
+    """An adapter that takes a Content Component Defintion and provides all
+    necessary information to create a menu item for the content component."""
+
+    implements(IContentComponentMenuItem)
+    __used_for__ = IContentComponentDefinition
+
+    def __init__(self, context):
+        self.context = context
+        ann = zapi.getAdapter(context, IAnnotations)
+        if not ann.has_key(MenuItemKey):
+            ann[MenuItemKey] = PersistentDict(
+                {'interface': IAdding,
+                 'title': self.context.name,
+                 'description': '',
+                 'permission': 'zope.ManageContent',
+                 'filter_string': '',
+                 'menuId': 'add_content',
+                 'create': True,
+                 # This is not part of the interface, but we need to store
+                 # that information.
+                 'menuItemId': None,
+                 'menu': None}
+                )
+        self._data = ann[MenuItemKey]
+        self._menu = self._data['menu']
+        if self._menu:
+            self._menuItem = self._data['menu'][self._data['menuItemId']]
+        else:
+            self._menuItem = None
+
+
+    def _createMenuService(self):
+        """Create a browser menu service for the menu item."""
+        # Get the local service manager; not that we know it must exist,
+        # otherwise this object would not be called.
+        sm = zapi.getServiceManager(self.context)
+        # Get the default package and add a menu service called 'Menus-1'
+        default = zapi.traverse(sm, 'default')
+        default.setObject('Menus-1', LocalBrowserMenuService())
+        # Register the service and set it to active
+        path = "%s/default/%s" % (zapi.getPath(sm), 'Menus-1')
+        reg = ServiceRegistration(BrowserMenu, path, sm)
+        key = default.getRegistrationManager().setObject("", reg)
+        reg = zapi.traverse(default.getRegistrationManager(), key)
+        reg.status = ActiveStatus
+        return zapi.traverse(default, 'Menus-1')    
+
+
+    def _createMenu(self):
+        """Create a menu."""
+        # Create a menu and add it to the default package
+        menu = LocalBrowserMenu()
+        sm = zapi.getServiceManager(self.context)
+        default = zapi.traverse(sm, 'default')
+        default.setObject(self.menuId, menu)
+        # Register th emenu as a utility and activate it.
+        path = "%s/default/%s" % (zapi.getPath(sm), self.menuId)
+        reg = UtilityRegistration(self.menuId, ILocalBrowserMenu, path)
+        key = default.getRegistrationManager().setObject("", reg)
+        reg = zapi.traverse(default.getRegistrationManager(), key)
+        reg.status = ActiveStatus
+        return zapi.traverse(default, self.menuId)    
+
+
+    def createMenuItem(self):
+        "See zope.app.interfaces.utilities.content.IContentComponentMenuItem"
+        # If 'create' is set to true, we must generate the necessary objects
+        # locally
+        if self.create:
+            # Get the servicem manager and the default package
+            sm = zapi.getServiceManager(self.context)
+            default = zapi.traverse(sm, 'default')
+            service = sm.queryService(BrowserMenu)
+            # Check whether the service really exists locally; if not, create
+            # one for this service manager
+            if (service is None or
+                not ILocalBrowserMenuService.isImplementedBy(service) or
+                not zapi.name(service) in default):
+
+                service = self._createMenuService()
+
+            # Check whether the menu exists locally; if not create one.
+            menu = service.queryInheritedMenu(self.menuId, True)
+            if (menu is None or
+                not ILocalBrowserMenu.isImplementedBy(menu) or
+                not zapi.name(menu) in default):
+
+                menu = self._createMenu()
+
+        else:
+            # Find a browser menu service and make sure it is a local one.
+            service = zapi.getService(self, BrowserMenu)
+            if not ILocalBrowserMenuService.isImplementedBy(service):
+                raise ComponentLookupError, \
+                      _('No local/peristent Browser Menu Service found.')
+            # Find the browser menu and make sure it is a local one
+            menu = service.queryInheritedMenu(self.menuId, True)
+            if menu is None or not ILocalBrowserMenu.isImplementedBy(menu):
+                error = _('No local Browser Menu called "${name}" found.')
+                error.mapping = {'name': self.menuId}
+                raise ComponentLookupError, error
+            
+        self._data['menu'] = menu
+        # Creating the menu item
+        item = LocalBrowserMenuItem()
+        for name in ('interface', 'action', 'title', 'description',
+                     'permission', 'filter_string'):
+            setattr(item, name, getattr(self, name))
+        self._data['menuItemId'] = menu.setObject('something', item)
+
+    createMenuItem = ContextMethod(createMenuItem)
+
+
+    def removeMenuItem(self):
+        "See zope.app.interfaces.utilities.content.IContentComponentMenuItem"
+        self._data['menu'].__delitem__(self._data['menuItemId'])
+        self._data['menu'] = None
+        self._data['menuItemId'] = None
+    removeMenuItem = ContextMethod(removeMenuItem)
+
+
+    def _setMenuId(self, value):
+        if self._data['menuId'] != value:
+            self._data['menuId'] = value
+            # This is the path of least reistence
+            self.removeMenuItem()
+            self.createMenuItem()
+
+    menuId = ContextProperty(
+        lambda self: self._data['menuId'], _setMenuId)
+
+
+    def _setInterface(self, value):
+        if self._data['interface'] != value:
+            self._data['interface'] = value
+            # If a menu item exists, make sure it gets updated.
+            if self._menuItem is not None:
+                self._menuItem.interface = value
+
+    interface = ContextProperty(
+        lambda self: self._data['interface'], _setInterface)
+
+
+    def _getAction(self):
+        return 'AddContentComponent/' + self.context.name
+    
+    action = property(_getAction)
+
+
+    def _getTitle(self):
+        return self._data['title'] or self.context.name
+
+    def _setTitle(self, value):
+        if self._data['title'] != value:
+            self._data['title'] = value
+            # If a menu item exists, make sure it gets updated.            
+            if self._menuItem is not None:
+                self._menuItem.title = value
+
+    title = ContextProperty(_getTitle, _setTitle)
+
+
+    def _setDescription(self, value):
+        if self._data['description'] != value:
+            self._data['description'] = value
+            # If a menu item exists, make sure it gets updated.
+            if self._menuItem is not None:
+                self._menuItem.description = value
+
+    description = ContextProperty(
+        lambda self: self._data['description'], _setDescription)
+
+    def _setPermission(self, value):
+        if self._data['permission'] != value:
+            self._data['permission'] = value
+            # If a menu item exists, make sure it gets updated.
+            if self._menuItem is not None:
+                self._menuItem.permission = value
+
+    permission = ContextProperty(
+        lambda self: self._data['permission'], _setPermission)
+
+
+    def _setFilterString(self, value):
+        if self._data['filter_string'] != value:
+            self._data['filter_string'] = value
+            # If a menu item exists, make sure it gets updated.
+            if self._menuItem is not None:
+                self._menuItem.filter = value
+
+    filter_string = ContextProperty(
+        lambda self: self._data['filter_string'], _setFilterString)
+
+
+    def _setCreate(self, value):
+        if self._data['create'] != value:
+            self.removeMenuItem()
+            self._data['create'] = value
+            self.createMenuItem()
+
+    create = ContextProperty(
+        lambda self: self._data['create'], _setCreate)
+
 
 
 class ContentComponentDefinitionRegistration(UtilityRegistration):
     """Content Component Registration"""
 
-    menuitem_id = None
-    menu = None
-
     def activated(self):
         """Once activated, we have to register the new Content Object with the
         appropriate menu.
         """
-        service = zapi.getService(self, BrowserMenu)
-        # XXX: Should use queryInheritedMenu()
-        self.menu = service.queryLocalMenu('add_content')
-        # Creating the menu item
-        # XXX: Should be configurable
-        item = LocalBrowserMenuItem()
-        item.interface = IAdding
-        item.action = 'AddContentComponent/' + self.name
-        item.title = self.name
-        item.permission = 'zope.ManageContent'
-        self.menuitem_id = self.menu.setObject('something', item)
         component = self.getComponent()
         component.name = self.name
+        zapi.getAdapter(component, IContentComponentMenuItem).createMenuItem()
     activated = ContextMethod(activated)
 
     def deactivated(self):
         """Once activated, we have to unregister the new Content Object with
         the appropriate menu."""
-        self.menu.__delitem__(self.menuitem_id)
-        self.menu = None
-        self.menuitem_id = None
         component = self.getComponent()
-        component.name = '<component not activated>'
+        component.name = None
+        zapi.getAdapter(component, IContentComponentMenuItem).removeMenuItem()
     deactivated = ContextMethod(deactivated)
 
 
@@ -125,21 +331,21 @@
         if is_schema_field:
             super(ContentComponentInstance, self).__setattr__(key, value)
         else:
-            raise AttributeError, 'Attribute not available'
+            raise AttributeError, 'Attribute "%s" not available' %key
 
 
     def getSchema(self):
         return self.__schema
 
+
     def __repr__(self):
         return '<ContentComponentInstance called %s>' %self.__name__
 
 
+
 def ContentComponentInstanceChecker(instance):
     """A function that can be registered as a Checker in defineChecker()"""
     return Checker(instance.__checker_getattr.get,
                    instance.__checker_setattr.get)
 
 defineChecker(ContentComponentInstance, ContentComponentInstanceChecker)
-
-




More information about the Zope3-Checkins mailing list