Plone 3 skinning and other atrocities
So, head mistress Helga from the local bordello is off-duty and you need some other means of satisfying your masochistic tendencies. Someone on your local S&M forum suggests creating a Plone 3 theme, and you decide to give it a go.
BUT, you don't want to jump in front of the Plone train and get trampled, you just want to feel some "good" pain, like mistress Helga usually gives.
Cue some tips and pointers I have picked up (and I only want to hear 1 click!):
- Create a theme via paster, the same paster that you used to create a buildout of your zope/plone instance.
francois@ubuntu:~/paster create -t plone3_theme
Things to note regarding the paster prompts:
- Name your project something like "mytheme.theme".
- Name your namespace package something like "mytheme".
- Name the package "theme". This is very important otherwise Plone won't install the theme correctly.
- Name your skinname something like "My Theme".
I placed my new theme in my src/ directory and added the following to my buildout.cfg:
Under # Add additional eggs here: added "mytheme.theme" to the list ie eggs=elementtree Products.ATVocabularyManager mytheme.theme Under develop added "mytheme.theme" to the list ie develop = src/mytheme.theme -
Changing the main layout of the site:
Copy main_template.pt from your instance's CMFPlone/skins/plone_templates/ directory to your skin's custom template directory ie mytheme/theme/skins/mytheme_theme_custom_templates and change as needed
Proceed to move stuff around/yank stuff out/add stuff at own discretion
-
Change the look and feel of the site:
Copy public.css.dtml, portlets.css.dtml and base.css.dtml from CMFPlone/skins/plone_styles to your skin's custom style directory ie mytheme/theme/skins/mytheme_theme_styles
-
Manage which viewlets must be activated on the main template's portlets
First you want to find out which viewlet is shown where: Where is What in Plone 3
Create a viewlets.xml in your theme's profiles/default/ directory. Add the following to viewlets.xml to hide the SearchBox and logo:
<?xml version="1.0"?> <object> <hidden manager="plone.portalheader" skinname="My Theme"> <viewlet name="plone.searchbox" /> <viewlet name="plone.logo" /> </hidden> </object>Restart zope and reinstall the theme for any of these changes to come into effectTo unhide something previously hidden: <viewlet name="plone.global_sections" remove="True" />
-
Manage your portlets from code:
Create a portlets.xml in your theme's profiles/default/ directory. Say you want to remove the calendar and navigation portlets that are added by default when creating a Plone site, add the following to portlets.xml
<?xml version="1.0"?> <portlets xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="plone"> <assignment remove="true" name="calendar" category="context" ket="/" manager="plone.rightcolumn" type="portlets.Calendar" /> <assignment remove="true" name="navigation" category="context" ket="/" manager="plone.leftcolumn" type="portlets.Navigation" /> </portlets> -
Set initial site properties when using your theme.
Copy propertiestool.xml from CMFPlone/profiles/default/ to your skin's profiles/default directory and edit with care!
For instance: I wanted to prevent the objects in my site's root directory from appearing as portal tabs:
<property name="disable_nonfolderish_sections" type="boolean">True</property>
-
Show custom tabs for portal tabs
Create an actions.xml file in your theme's profiles/default/ directory. Here is some example entries:
<?xml version="1.0"?> <object name="portal_actions" meta_type="Plone Actions Tool"> <object name="portal_tabs" meta_type="CMF Action Category"> <object name="index_html" meta_type="CMF Action" > <property name="title" >Home</property> <property name="description"></property> <property name="url_expr">string:${globals_view/navigationRootUrl}</property> <property name="icon_expr"></property> <property name="available_expr"></property> <property name="permissions"> <element value="View"/> </property> <property name="visible">True</property> </object> <object name="example" meta_type="CMF Action"> <property name="title" >example</property> <property name="description" /> <property name="url_expr">string:${globals_view/navigationRootUrl}/example</property> <property name="available_expr"></property> <property name="permissions"> <element value="View"/> </property> <property name="visible">True</property> </object> </object> </object> -
Want more? Well, you haven't said the "safe" word yet, so, on we go...
Customize a viewlet which doesn't have a class definitionAn easy example of this is the footer viewlet.
Copy footer.pt from plone.app.layout*.egg/plone/app/layout/viewlets/ to your theme's browser directory and apply your changes.
In your browser directory's configure.zcml add the following: <!-- The footer viewlet --> <browser:viewlet name="plone.footer" for="*" manager="plone.app.layout.viewlets.interfaces.IPortalFooter" layer=".interfaces.IThemeSpecific" template="footer.pt" permission="zope2.Public" /> -
Customize a viewlet which does have a class definition
Let's do the personal bar in the top part of the site.
Copy personal_bar.pt from plone.app.layout*.egg/plone/app/layout/viewlets/ to your theme's browser directory and apply your changes.
In your browser directory's configure.zcml add the following: <!-- The personal bar --> <browser:viewlet name="plone.personal_bar" manager="plone.app.layout.viewlets.interfaces.IPortalTop" class=".viewlets.PersonalBarViewlet" layer=".interfaces.IThemeSpecific" permission="zope2.View" /> Add the following to your browser/viewlets.py from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from plone.app.layout.viewlets.common import ViewletBase from plone.app.layout.viewlets.common import PersonalBarViewlet class PersonalBarViewlet(PersonalBarViewlet): """ Custom Personal bar """ index = ViewPageTemplateFile('personal_bar.pt') -
Custom views for your archetypes
If you've got custom archetype content types and you want custom views for their view/edits etc, you can do this by creating specific files in your theme's *custom_templates/ directory.
Say you've got a content type named "MyContentType" with attributes Title, Description and CustomText. If you want to override the default view of this content type, you'll have to create a file called mycontenttype_view.pt and add at least the following:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="here/main_template/macros/master" i18n:domain="plone"> <body> <metal:fill metal:fill-slot="main"> <metal:folder define-macro="folderlisting"/> <metal:header define-macro="header"/> <metal:footer define-macro="footer"/> <metal:main_macro define-macro="body"> </metal:main_macro> </metal:fill> </body> </html> To show attributes of the object of type MyContentType: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="here/main_template/macros/master" i18n:domain="plone"> <body> <metal:fill metal:fill-slot="main"> <metal:folder define-macro="folderlisting"/> <metal:header define-macro="header"/> <metal:footer define-macro="footer"/> <metal:main_macro define-macro="body"> <table> <tr> <th>Title</th> <td tal:content="context/Title"></td> </tr> <tr> <th>Description</th> <td tal:content="context/getDescription"></td> </tr> <tr> <th>CustomText</th> <td tal:content="context/getCustomText"></td> </tr> </table> </metal:main_macro> </metal:fill> </body> </html>
Of course, there is plenty more where that came from, and even more from other places where that didn't come from. Here is some more resources:






