plone.app.contentmenu contains the logic that powers Plone's content menu which is part of the toolbar.
It provides the menus items (and its submenues) for
- factories menu (order=10)
- workflows menu (order=20)
- actions menu (order=30)
- display menu (order=40)
- manage portlets menu (order=50)
Note that menu items are ordered by an 'ordered' property. To allow third party products to slot their own sub-menus in between the default menu items, these are registered with gaps.
Custom menus are registered in configure.zcml like so:
<!-- the main menu item -->
<adapter for="* *"
name="plone.contentmenu.my_menu_item"
factory=".menu.MyMainMenuItem"
provides="plone.app.contentmenu.interfaces.IContentMenuItem" />
<!-- the sub menu items - name must match submenuId of MyMainMenuItem class -->
<browser:menu
id="my_fancy_menu"
title="The 'My' menu - allows to do new exciting stuff"
class=".menu.MyMenu"
/>
in menu.py the class looks like so:
from zope.browsermenu.interfaces import IBrowserMenu
from zope.browsermenu.menu import BrowserMenu
from zope.browsermenu.menu import BrowserSubMenuItem
from zope.component import getMultiAdapter
from zope.i18nmessageid import MessageFactory
from zope.interface import implementer
_ = MessageFactory('my.fancy')
class IMyMainMenuItem(IBrowserMenu):
"""The main my menu item.
You may want to place this in interfaces.py
"""
class IMyMenu(IBrowserMenu):
"""The my menu.
You may want to place this in interfaces.py
"""
@implementer(IMyMainMenuItem)
class MyMainMenuItem(BrowserSubMenuItem):
# This is in fact a submenu item of the parent menu, thus the name
# of the inherited class tells it, don't be confused.
title = _(u'label_my_menu', default=u'My')
description = _(u'title_my_menu', default=u'My for the current content item')
submenuId = 'my_fancy_menu'
order = 70 # after the default menus
extra = {
'id': 'my-fancy-menu',
'li_class': 'plonetoolbar-content-my-fancy'
}
@property
def action(self):
# return the url to be loaded if clicked on the link.
# even if a submenu exists it will be active if javascript is disabled
return self.context.absolute_url()
def available(self):
# check if the menu is available and shown or not
return True
def selected(self):
# check if the menu should be shown as selected
return False
@implementer(IMyMenu)
class MyMenu(BrowserMenu):
def getMenuItems(self, context, request):
"""Return menu item entries in a TAL-friendly form."""
results = []
# here a single item is added. do what needed to add several entries
results.append({
'title': 'My item 1',
'description': 'An my item',
'action': '/url/to/action',
'selected': False,
'icon': 'some_icon_class',
'extra': {
'id': 'plone-contentmenu-my-fancy-one',
'separator': None,
'class': 'my-class pat-plone-modal',
'modal': 'width: 400'
},
'submenu': None,
})
return results
Contributors please read the document Process for Plone core's development
Sources are at the Plone code repository hosted at Github.