Home Company Services Portfolio Contact us nav spacer

Plone 3 skinning and other atrocities

by francois posted on Apr 06, 2009 11:40 PM last modified Jul 07, 2009 12:46 PM

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!):

  1. 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
    

     

  2. 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

  3. 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

  4. 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 effect
    To unhide something previously hidden:
    
      <viewlet name="plone.global_sections" remove="True" />
    
    
  5. 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>
    
    
  6. 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>
    
    
  7. 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>
    
    
  8. Want more? Well, you haven't said the "safe" word yet, so, on we go...
    Customize a viewlet which doesn't have a class definition

    An 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" 
            />
    
    
  9. 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')
    
    
    
  10. 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: