[Checkins] SVN: zope.app.publisher/trunk/ Add possibility to specify custom item class in menuItem directives.

Dan Korostelev nadako at gmail.com
Thu Nov 6 07:31:25 EST 2008


Log message for revision 92812:
  Add possibility to specify custom item class in menuItem directives.
  

Changed:
  U   zope.app.publisher/trunk/CHANGES.txt
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py

-=-
Modified: zope.app.publisher/trunk/CHANGES.txt
===================================================================
--- zope.app.publisher/trunk/CHANGES.txt	2008-11-06 10:26:36 UTC (rev 92811)
+++ zope.app.publisher/trunk/CHANGES.txt	2008-11-06 12:31:23 UTC (rev 92812)
@@ -5,7 +5,8 @@
 3.5.3 (Unreleased)
 ==================
 
-- ...
+- Added possibility to specify custom item class in menuItem, subMenuItem
+  and addMenuItem directives using the ``item_class`` argument (LP #291865).
 
 3.5.2a1 (2008-10-23)
 ====================

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt	2008-11-06 10:26:36 UTC (rev 92811)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt	2008-11-06 12:31:23 UTC (rev 92812)
@@ -587,7 +587,54 @@
     <InterfaceClass __builtin__.TestMenuItemType>,
     'View')]
 
+Custom menu item classes
+~~~~~~~~~~~~~~~~~~~~~~~~
 
+We can register menu items and sub menu items with custom classes instead
+of ones used by default. For that, we need to create an implementation
+of IBrowserMenuItem or IBrowserSubMenuItem.
+
+  >>> context = Context()
+  >>> items = menumeta.menuItemsDirective(context, TestMenuItemType, ITest)
+  >>> context.actions
+  []
+
+Let's create a custom menu item class that inherits standard BrowserMenuItem:
+
+  >>> class MyMenuItem(menu.BrowserMenuItem):
+  ...    pass
+
+  >>> items.menuItem(context, u'view.html', 'View', item_class=MyMenuItem)
+
+Also create a custom sub menu item class inheriting standard BrowserSubMenuItem:
+
+  >>> class MySubMenuItem(menu.BrowserSubMenuItem):
+  ...    pass
+
+  >>> items.subMenuItem(context, SaveOptions, 'Save', item_class=MySubMenuItem)
+
+  >>> actions = sorted(context.actions, key=lambda a:a['discriminator'])
+  >>> factories = [action['args'][1] for action in actions][-2:]
+
+  >>> factories[0].factory is MySubMenuItem
+  True
+
+  >>> factories[1].factory is MyMenuItem
+  True
+
+These directive will fail if you provide an item_class that does not
+implement IBrowserMenuItem/IBrowserSubMenuItem:
+
+  >>> items.menuItem(context, u'fail', 'Failed', item_class=object)
+  Traceback (most recent call last):
+  ...
+  ValueError: Item class (<type 'object'>) must implement IBrowserMenuItem
+
+  >>> items.subMenuItem(context, SaveOptions, 'Failed', item_class=object)
+  Traceback (most recent call last):
+  ...
+  ValueError: Item class (<type 'object'>) must implement IBrowserSubMenuItem
+
 ``ManagementViewSelector``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py	2008-11-06 10:26:36 UTC (rev 92811)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py	2008-11-06 12:31:23 UTC (rev 92812)
@@ -31,6 +31,7 @@
 from zope.app.publisher.browser.menu import BrowserMenuItem, BrowserSubMenuItem
 from zope.app.publisher.interfaces.browser import IBrowserMenu
 from zope.app.publisher.interfaces.browser import IBrowserMenuItem
+from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
 from zope.app.publisher.interfaces.browser import IMenuItemType
 from zope.app.publisher.interfaces.browser import AddMenu
 
@@ -106,21 +107,21 @@
 def menuItemDirective(_context, menu, for_,
                       action, title, description=u'', icon=None, filter=None,
                       permission=None, layer=IDefaultBrowserLayer, extra=None,
-                      order=0):
+                      order=0, item_class=None):
     """Register a single menu item."""
     return menuItemsDirective(_context, menu, for_, layer).menuItem(
         _context, action, title, description, icon, filter,
-        permission, extra, order)
+        permission, extra, order, item_class)
 
 
 def subMenuItemDirective(_context, menu, for_, title, submenu,
                          action=u'', description=u'', icon=None, filter=None,
                          permission=None, layer=IDefaultBrowserLayer,
-                         extra=None, order=0):
+                         extra=None, order=0, item_class=None):
     """Register a single sub-menu menu item."""
     return menuItemsDirective(_context, menu, for_, layer).subMenuItem(
         _context, submenu, title, description, action, icon, filter,
-        permission, extra, order)
+        permission, extra, order, item_class)
 
 
 class MenuItemFactory(object):
@@ -159,7 +160,8 @@
         self.permission = permission
 
     def menuItem(self, _context, action, title, description=u'',
-                 icon=None, filter=None, permission=None, extra=None, order=0):
+                 icon=None, filter=None, permission=None, extra=None,
+                 order=0, item_class=None):
 
         if filter is not None:
             filter = Engine.compile(filter)
@@ -171,8 +173,14 @@
             order = _order_counter.get(self.for_, 1)
             _order_counter[self.for_] = order + 1
 
+        if item_class is None:
+            item_class = self.menuItemClass
+
+        if not IBrowserMenuItem.implementedBy(item_class):
+            raise ValueError("Item class (%s) must implement IBrowserMenuItem" % item_class)
+
         factory = MenuItemFactory(
-            self.menuItemClass,
+            item_class,
             title=title, description=description, icon=icon, action=action,
             filter=filter, permission=permission, extra=extra, order=order,
             _for=self.for_)
@@ -181,7 +189,7 @@
 
     def subMenuItem(self, _context, submenu, title, description=u'',
                     action=u'', icon=None, filter=None, permission=None,
-                    extra=None, order=0):
+                    extra=None, order=0, item_class=None):
 
         if filter is not None:
             filter = Engine.compile(filter)
@@ -193,8 +201,14 @@
             order = _order_counter.get(self.for_, 1)
             _order_counter[self.for_] = order + 1
 
+        if item_class is None:
+            item_class = self.subMenuItemClass
+
+        if not IBrowserSubMenuItem.implementedBy(item_class):
+            raise ValueError("Item class (%s) must implement IBrowserSubMenuItem" % item_class)
+
         factory = MenuItemFactory(
-            self.subMenuItemClass,
+            item_class,
             title=title, description=description, icon=icon, action=action,
             filter=filter, permission=permission, extra=extra, order=order,
             _for=self.for_, submenuId=submenu)
@@ -230,7 +244,7 @@
 def addMenuItem(_context, title, description='', menu=None, for_=None,
                 class_=None, factory=None, view=None, icon=None, filter=None,
                 permission=None, layer=IDefaultBrowserLayer, extra=None,
-                order=0):
+                order=0, item_class=None):
     """Create an add menu item for a given class or factory
 
     As a convenience, a class can be provided, in which case, a
@@ -288,4 +302,4 @@
 
     return menuItemsDirective(_context, menu, for_, layer=layer).menuItem(
         _context, action, title, description, icon, filter,
-        permission, extra, order)
+        permission, extra, order, item_class)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py	2008-11-06 10:26:36 UTC (rev 92811)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py	2008-11-06 12:31:23 UTC (rev 92812)
@@ -494,6 +494,13 @@
         default=0
         )
 
+    item_class = GlobalObject(
+        title=u"Menu item class",
+        description=u"""
+        A class to be used as a factory for creating menu item""",
+        required=False
+        )
+
 class IMenuItemSubdirective(IMenuItem):
     """Define a menu item within a group of menu items"""
 



More information about the Checkins mailing list