Chapter 3. Appearance

Soon after you install and run Plone for the first time, you will probably want to change the appearance. The effort needed to do so varies, and depends largely on your goals. If you are not picky, adding a new theme to Plone can be as simple as adding a package to your buildout.cfg file, running Buildout, and restarting Plone.

However, if you want a high quality, unique, and a professional-looking theme for your site, it could take several days, weeks, or even months to achieve the desired result.

In this chapter, we will cover the spectrum from easy and small changes with a high impact to more complex changes that require more effort. However, keep in mind that this is not a comprehensive coverage, help is just enough to rather a site administrator gain speed quickly. If you want to learn theming in depth, see the book "Plone 3 Theming", Veda Williams, Packt Publishing.

In this chapter, you will learn:

  • Installing themes with Buildout

  • Examining themes with Omelette and Python

  • Overview of theme package files

  • Creating a theme package with ZopeSkel

  • Examining themes in the ZMI

  • Making changes through the Web

Installing themes with Buildout

For a lot of website projects, a theme downloaded from plone.org (http://plone.org/products) or the Python Package Index (http://pypi.python.org) is enough to launch a professional-looking site. If your project falls into this category, or if you just want to experiment, follow the steps in this chapter.

Searching for themes on plone.org

We will need to find a theme we like. We can do that by browsing to http://plone.org. Next, click on Downloads | Add-on Product Releases | Themes.

You should see (result similar to):

Searching for themes on plone.org

Click on a theme to view a screenshot and select one you like, for example beyondskins.ploneday.site2010, and add the package to your buildout.cfg file.

Adding themes with Buildout

In 03-appearance-wpd2010.cfg, we extend the last known working configuration file from Chapter 2, that is 02-site-basics-blog.cfg.

It looks like this:

[buildout]
extends = 02-site-basics-blog.cfg
[instance]
eggs += beyondskins.ploneday.site2010
zcml += beyondskins.ploneday.site2010

In addition to adding the package name to the eggs parameter, we must add it to the zcml parameter as well.

Refer to Chapter 2, Site Basics, for a detailed explanation of why this is necessary.

Now stop Plone (with Ctrl + C or Ctrl +Z/Enter) and run:

$ bin/buildout -c 03-appearance.cfg
Updating zope2.
Updating fake eggs
Updating instance.
Getting distribution for 'beyondskins.ploneday.site2010'.
Got beyondskins.ploneday.site2010 1.0.3.

Now start Plone:

$ bin/instance fg

Installing themes in Plone

Browse to http://localhost:8080/Plone. Now, click on Site Setup | Add/Remove Products and you should see:

Installing themes in Plone

Check the box next to WorldPloneDay: Theme for 2010 edition 1.0.3 and click on Install.

Now browse to http://localhost:8080/Plone and you should see:

Installing themes in Plone

Note

This theme is the courtesy of Simples Consultoria (http://www.simplesconsultoria.com.br/). Thank you!

You can examine the anonymous view (what everyone else sees) by loading http://127.0.0.1:8080/Plone in your browser (that is. by using the IP address instead of the hostname). You can also load either of these URLs (http://127.0.0.1:8080/Plone or http://localhost:8080/Plone) from another web browser (besides the one you are currently using) to see the anonymous view (for example, Safari or Internet Explorer, instead of Firefox).

Installing themes in Plone

To display the blog entry we created in Chapter 2 to the public, we have transitioned the other objects in the site root to the private state.

If you are unfamiliar with how to transition objects from the public state to the private state, please see Chapter 9 of "Practical Plone 3", Veda Williams, Packt Publishing.

Examining themes with Omelette and Python

Simply put, a theme is a collection of templates, images, CSS, JavaScript, and other files (such as Python scripts) that control the appearance of your site.

Typically these files are packaged into a Python package, installed in your Plone site with the help of Buildout, and installed in Plone via the Add/Remove Products configlet in Site Setup.

Once installed, certain elements of the theme can be edited through the Web using the ZMI. However, these changes only exist in the site's database. Currently there is no easy way to transfer changes made through the Web from the database to the filesystem; so there is a trade-off for performing such customizations through the Web. If you lose your database, you lose your customizations.

Depending on your goals, it may not be entirely undesirable to store customizations in your database. But nowadays, most folks choose to separate their site's logical elements (for example themes, add-on functionality, and so on) from their site's content (that is data).

Creating a filesystem theme and resisting the urge to customize it through the Web accomplishes this goal. Otherwise, if you are going to customize your theme through the Web, consider these changes volatile, and subject to loss.

Installing and using Omelette

A great way to examine files on the filesystem is to add Omelette (http://pypi.python.org/pypi/collective.recipe.omelette) to your buildout.cfg and examine the files in the parts/omelette directory.

Omelette is a Buildout recipe that creates (UNIX filesystem) symbolic links from all the Zope 2, Plone, and add-on installation files to one convenient location. This makes the job of examining files on the filesystem much easier.

To install Omelette, in 03-appearance-omelette.cfg, we have this:

[buildout]
extends = 03-appearance-wpd2010.cfg
parts +=
omelette
[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
packages = ${zope2:location}/lib/python

In this configuration file, we extend the sections and parameters in 03-appearance-wpd2010.cfg, and add a new section called omelette to the parts parameter (in the buildout section).

Remember that using the += syntax adds the new value to the current value, so the parts list becomes:

parts = zope2 instance plonesite omelette

(We can examine the current state of the buildout by looking in the .installed.cfg file in the root directory of the buildout.)

We also tell Omelette what files to link in the eggs and packages parameters:

  • ${instance:eggs}: Refers to the packages in the eggs directory.

  • ${zope2:location}/lib/python: Refers to the modules in the parts/zope2/lib/python/ directory.

You can read more about how to configure Omelette here: http://pypi.python.org/pypi/collective.recipe.omelette.

Now stop Plone (with Ctrl + C or Ctrl +Z/Enter) and run:

$ bin/buildout -c 03-appearance-omelette.cfg

You should see:

$ bin/buildout -c 03-appearance-omelette.cfg
Getting distribution for 'collective.recipe.omelette'.
Got collective.recipe.omelette 0.9.
Uninstalling plonesite.
Updating zope2.
Updating fake eggs
Updating instance.
Installing plonesite.
/Users/aclark/Developer/plone-site-admin/buildout/parts/zope2/lib/python/zope/configuration/xmlconfig.py:323: DeprecationWarning: zope.app.annotation has moved to zope.annotation. Import of zope.app.annotation will become unsupported in Zope 3.5
__import__(arguments[0])
Retrieved the admin user
A Plone Site already exists and will not be replaced
Installing omelette.

Note

Omelette in Windows

As of version 0.5, Windows supports Omelette if you have the Junction program installed (and configured in your path). Junction is easy to install, and available here: http://www.microsoft.com/technet/sysinternals/fileanddisk/junction.mspx.

Now that Omelette has been installed, take a look in the parts/omelette directory. You should see:

$ ls -1 parts/omelette
Products/
archetypes/
beyondskins/
borg/
collective/
easy_install.py@
elementtree@
feedparser.py@
five/
kss/
markdown.py@
mdx_footnotes.py@
mdx_rss.py@
openid@
pkg_resources.py@
plone/
setuptools@
simplejson@
site.py@
webcouturier/
wicked/
z3c/
zc/

Exploring modules with zopepy

These files correspond directly to the modules available in Python when Plone is running. To demonstrate this, let us configure a Python interpreter with the modules added to the sys.path.

In 03-appearance-zopepy.cfg, we have this:

[buildout]
extends = 03-appearance-omelette.cfg
parts +=
zopepy
[zopepy]
recipe = zc.recipe.egg
eggs = ${instance:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy

We extend the last working configuration in 03-appearance-omelette.cfg and add a new section called zopepy (short for "Zope Python").

Now stop Plone (with Ctrl + C or Ctrl +Z/Enter) and run Buildout:

$ bin/buildout -c 03-appearance-zopepy.cfg

You should see:

$ bin/buildout -c 03-appearance-zopepy.cfg
Uninstalling plonesite.
Updating zope2.
Updating fake eggs
Updating instance.
Installing plonesite.
/Users/aclark/Developer/plone-site-admin/buildout/parts/zope2/lib/python/zope/configuration/xmlconfig.py:323: DeprecationWarning: zope.app.annotation has moved to zope.annotation. Import of zope.app.annotation will become unsupported in Zope 3.5
__import__(arguments[0])
Retrieved the admin user
A Plone Site already exists and will not be replaced
Updating omelette.
The recipe for omelette doesn't define an update method. Using its install method.
Installing zopepy.
Generated interpreter '/Users/aclark/Developer/plone-site-admin/buildout/bin/zopepy'.

This creates a script that invokes the Python interpreter with the Plone modules added to the sys.path. Now if you run bin/zopepy, you can explore modules in Python.

For example, you can import the beyondskins module (from the top-level namespace):

$ bin/zopepy
>>> import beyondskins
>>>

Python will try to evaluate any statement you input. For example, type beyondskins and hit Enter:

>>> beyondskins
<module 'beyondskins' from '/Users/aclark/Developer/plone-site-admin/buildout/eggs/beyondskins.ploneday.site2010-1.0.3-py2.4.egg/beyondskins/__init__.pyc'>

Python will tell you that beyondskins is a module. You can also try to call beyondskins (as if it were a function or class method):

>>> beyondskins()
Traceback (most recent call last):
File "<console>", line 1, in ?
TypeError: 'module' object is not callable

Python will now tell you that module objects are not callable. You can use the built-in dir function to view the attributes of the beyondskins module:

>>> dir(beyondskins)
['__builtins__', '__doc__', '__file__', '__name__', '__path__', 'ploneday']

Now, Python will tell you its attributes. You can inquire about a specific attribute such as __path__:

>>> beyondskins.__path__
['/Users/aclark/Developer/plone-site-admin/buildout/eggs/beyondskins.ploneday.site2010-1.0.3-py2.4.egg/beyondskins']
>>>

Python will return its value. Just for fun, you can inquire about any attribute of any module:

>>> Products.__path__
['/Users/aclark/Developer/plone-site-admin/buildout/eggs/Plone-3.3.5-py2.4.egg/Products',
…

The value of Products.__path__ is too long to print here. It contains a list of all packages that contain a Products module. All of this code ends up in the Products namespace in Python, handy!

We could spend the rest of the book learning Python, but let's return to theming instead.

Overview of theme package files

You will notice a beyondskins directory in parts/omelette that contains two files:

  • __init__.py

  • ploneday

The __init__.py file tells Python to treat this directory as a module, and that ploneday is another directory.

Plone packages typically do not make use of the top-level or mid-level namespaces, so let us look inside (the third-level module) beyondskins/ploneday/site2010 instead:

$ ls -H -1 parts/omelette/beyondskins/ploneday/site2010
README.txt
__init__.py
__init__.pyc
__init__.pyo
browser/
configure.zcml
doc/
locales/
profiles/
profiles.zcml
setuphandlers.py
setuphandlers.pyc
setuphandlers.pyo
skins/
skins.zcml
tests.py
tests.pyc
tests.pyo
updateTranslations.sh
version.txt

Here is an overview of (most of) these files and directories:

  • __init__.py: This file tells Python the directory is a module; see http://docs.python.org/tutorial/modules.html for more information.

  • __init.__pyc: This file contains compiled byte code; see http://docs.python.org/tutorial/modules.html for more information.

  • __init__.pyo: This file contains optimized and compiled byte code; see http://docs.python.org/tutorial/modules.html for more information.

  • browser/: This directory contains new-style customization code (that is, code that makes use of the Zope Component Architecture), such as browser views, portlets, viewlets, and resources like image, CSS, and JavaScript files. Visit: http://plone.org/documentation/kb/customization-for-developers/zope-3-browser-views for more information.

  • configure.zcml: This file contains ZCML code used to load components defined in your package. It is also responsible for loading other ZCML files within a package:

    <include package=".browser" />
    <include file="skins.zcml" />
    <include file="profiles.zcml" />
    
  • locales/: This directory contains translations for multilingual sites. Visit http://plone.org/documentation/manual/developer-manual/internationalization-i18n-and-localization-l10n for more information.

  • profiles/: This directory contains GenericSetup (http://plone.org/documentation/kb/genericsetup) code typically in the default directory, to indicate the default profile. GenericSetup can be used to configure all manner of settings in Plone. If you are not familiar with it, try the following:

    • Navigate to Site Setup | Zope Management Interface | portal_setup | Export

    • Scroll to the bottom and click on Export all steps

  • You will get a compressed, archived file that contains many XML files containing various settings. You can add these files to the profiles/default/ directory of your add-on package, then edit them to customize the settings.

  • setuphandlers.py: While many settings can be configured using GenericSetup, some cannot. This file holds ad hoc Python code used to configure various settings that cannot be configured elsewhere (that is, using GenericSetup). For more information about setuphandlers.py, see Chapter 6 of "Professional Plone Development", Martin Aspeli, Packt Publishing.

  • skins/: This directory contains Zope 2 File System Directory Views (FSDV) that contain Content Management Framework (CMF) skin layers that contain templates, images, CSS/JavaScript files, and Python scripts.

  • skins.zcml/: This file contains ZCML code that registers FSDVs used by the CMF to facilitate skin layers.

    <configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:cmf="http://namespaces.zope.org/cmf"
    i18n_domain="beyondskins.ploneday.site2010">
    <!-- File System Directory Views registration -->
    <cmf:registerDirectory
    name="beyondskins_ploneday_site2010_images"/>
    <cmf:registerDirectory
    name="beyondskins_ploneday_site2010_templates"/>
    <cmf:registerDirectory
    name="beyondskins_ploneday_site2010_styles"/>
    <!-- Note: This could also be done for all folders at once
    by replacing the previous lines with this one:
    <cmf:registerDirectory name="skins" directory="skins" recursive="True" />
    -->
    </configure>
    
  • tests.py: This file (or directory) typically contains unit tests (and doctests) for the package. See http://plone.org/documentation/kb/testing for more information.

Creating a theme package with ZopeSkel

Now that we have examined someone else's theme, let us try creating our own.

Remember, we will not cover theme creation in depth; this is only a sample for site administrators (who may or may not be required to develop themes, in addition to managing their site).

For more information about creating themes, Visit: http://plone.org/documentation/kb/how-to-create-a-plone-3-theme-product-on-the-filesystem, or Chapter 4 of "Plone 3 Theming", Veda Williams, Packt Publishing.

To create a theme, we will use the ZopeSkel tool (http://pypi.python.org/pypi/ZopeSkel) to generate some of the boilerplate code. ZopeSkel uses PasteScript (http://pypi.python.org/pypi/PasteScript) to facilitate package generation using a set of templates.

Other options include:

  • Write everything by hand from memory

  • Copy the contents of another theme package

  • Use another tool such as ArchGenXML to generate boilerplate code (http://plone.org/products/archgenxml)

Adding ZopeSkel to a buildout

Now let's add ZopeSkel to our buildout.

In 03-appearance-zopeskel.cfg, we have this:

[buildout]
extends = 03-appearance-zopepy.cfg
parts +=
zopeskel
[zopeskel]
recipe = zc.recipe.egg
dependent-scripts = true

We extend the previous working configuration file, and add a new section called zopeskel.

This section uses the zc.recipe.egg recipe (http://pypi.python.org/pypi/zc.recipe.egg) to download ZopeSkel from the Python Package Index (zc.recipe.egg will search the Python Package Index for packages that match the section name zopeskel).

We set dependent-scripts to true, to tell Buildout to generate Python scripts for ZopeSkel's dependencies such as PasteScript, which includes the paster script.

Now stop Plone (with Ctrl + C or Ctrl + Z/Enter) and run Buildout:

$ bin/buildout -c 03-appearance-zopeskel.cfg

You should see:

$ bin/buildout -c 03-appearance-zopeskel.cfg
Uninstalling plonesite.
Updating zope2.
Updating fake eggs
Updating instance.
Installing plonesite.
…
Updating zopepy.
Installing zopeskel.
Getting distribution for 'zopeskel'.
Got ZopeSkel 2.16.
Getting distribution for 'Cheetah>1.0,<=2.2.1'.
…
Got Cheetah 2.2.1.
Getting distribution for 'PasteScript'.
Got PasteScript 1.7.3.
Getting distribution for 'PasteDeploy'.
…
Got PasteDeploy 1.3.3.
Getting distribution for 'Paste>=1.3'.
…
Got Paste 1.7.3.1.
Generated script '/Users/aclark/Developer/plone-site-admin/buildout/bin/zopeskel'.
Generated script '/Users/aclark/Developer/plone-site-admin/buildout/bin/paster'.
Generated script '/Users/aclark/Developer/plone-site-admin/buildout/bin/easy_install'.
Generated script '/Users/aclark/Developer/plone-site-admin/buildout/bin/easy_install-2.4'.

You will notice that in addition to bin/zopeskel, Buildout also installed the "dependent scripts" bin/paster and bin/easy_install (the latter of which we do not really need in this case).

Running ZopeSkel

Now try running ZopeSkel with the command:

$ bin/zopeskel

You should see:

Usage:
zopeskel <template> <output-name> [var1=value] ... [varN=value]
zopeskel --help Full help
zopeskel --list List template verbosely, with details
zopeskel --make-config-file Output .zopeskel prefs file
…

This tells us we need to pick a template and output-name.

ZopeSkel goes on to list the available templates. They are:

archetype: A Plone project that uses Archetypes content types
kss_plugin: A project for a KSS plugin
plone: A project for Plone products
plone2_theme: A theme for Plone 2.1
plone3_portlet: A Plone 3 portlet
plone_app: A project for Plone products with a nested namespace
plone_pas: A project for a Plone PAS plugin
plone2.5_theme: A theme for Plone 2.5
plone3_theme: A theme for Plone 3
plone2.5_buildout: A buildout for Plone 2.5 projects
plone3_buildout: A buildout for Plone 3 installation
plone_hosting: Plone hosting: buildout with ZEO and Plone
recipe: A recipe project for zc.buildout
silva_buildout: A buildout for Silva projects
basic_namespace: A basic Python project with a namespace package
nested_namespace: A basic Python project with a nested
basic_zope: A Zope project

In our case, we will choose plone3_theme.

The output-name is the name of the package we want to create for example, my.theme.

Since we are creating a new package, let us change directories to the src directory and run ZopeSkel from there, like this:

$ cd src
$ ../bin/zopeskel plone3_theme my.theme

You should see:

$ ../bin/zopeskel plone3_theme my.theme
plone3_theme: A theme for Plone 3
This creates a project for a theme for Plone 3.
…

This will be followed by a series of questions, which you can answer based on these suggestions:

  • Mode: Easy: This mode asks the least number of questions it needs to do its job.

  • Skin name: My Theme: This name will show up in various places, including Site Setup | Add/Remove Products.

  • Empty styles: False: This means we want our theme to look like the Plone Default theme. If you answer True, you will get an unstyled theme instead.

  • Include documentation: True: This means our code will be generated with helpful comments included inline.

  • Version: 1.0: This means our theme is ready for production use! Feel free to adjust this value if you like.

  • Description: An installable theme for Plone 3: You can change this to whatever you like.

Running Paster

Next, when ZopeSkel completes, it tells us about the additional commands we can run to generate more boilerplate code.

We do not need to do it now, but if you are curious, try this:

$ cd my.theme
$ ../../bin/paster addcontent --list-all

You should see the following templates available (to generate more boilerplate code):

anonymous_user_factory_plugin: A Plone PAS AnonymousUserFactory Plugin
atschema: A handy AT schema builder
authentication_plugin: A Plone PAS Authentication Plugin
challenge_plugin: A Plone PAS Challenge Plugin
contenttype: A content type skeleton
credentials_reset_plugin: A Plone PAS CredentialsReset Plugin
extraction_plugin: A Plone PAS Extraction Plugin
form: A form skeleton
formfield: Schema field for a form
group_enumeration_plugin: A Plone PAS GroupEnumeration Plugin
groups_plugin: A Plone PAS Groups Plugin
i18nlocale: An i18n locale directory structure
portlet: A Plone 3 portlet
properties_plugin: A Plone PAS Properties Plugin
role_assigner_plugin: A Plone PAS RoleAssigner Plugin
role_enumeration_plugin: A Plone PAS RoleEnumeration Plugin
roles_plugin: A Plone PAS Roles Plugin
update_plugin: A Plone PAS Update Plugin
user_adder_plugin: A Plone PAS UserAdder Plugin
user_enumeration_plugin: A Plone PAS UserEnumeration Plugin
user_factory_plugin: A Plone PAS UserFactory Plugin
validation_plugin: A Plone PAS Validation Plugin
view: A browser view skeleton
zcmlmeta: A ZCML meta directive skeleton

Some of these which apply to themes are:

  • i18nlocale

  • portlet

  • view

To add a portlet (little boxes on the left and right side of your site) to your theme, try this:

$ ../../bin/paster addcontent portlet

We could go on, but let's come back to basics now.

We now have a new theme package, but we do not have a new theme package in our buildout or in Plone. Let us now add our package to the buildout and to Plone.

The easiest way to do this is to tell Buildout we are developing a new package, by setting the value of the develop parameter in the buildout section to our package name (and relative filesystem path, in this case src/my.theme).

In addition to making Plone aware of this package, we must list it in the eggs parameter of the instance section.

In 03-appearance-develop.cfg, we have:

[buildout]
extends = 03-appearance-zopeskel.cfg
develop = src/my.theme
[instance]
eggs += my.theme

Now stop Plone (with Ctrl + C or Ctrl + Z/Enter) and run Buildout:

$ bin/buildout -c 03-appearance-develop.cfg

You should see:

$ bin/buildout -c 03-appearance-develop.cfg
Develop: '/Users/aclark/Developer/plone-site-admin/buildout/src/my.theme'
Uninstalling plonesite.
Updating zope2.
Updating fake eggs
Updating instance.
Installing plonesite.
…

The first line indicates that Buildout has recognized our new package. You may encounter an error during the Buildout run, when the collective.recipe.plonesite recipe tries to start Plone and add a Plone site. Ignore that for now. In fact when Buildout finishes and you restart Zope, you may see an (obnoxiously long) error like this:

$ bin/instance fg
/Users/aclark/Developer/plone-site-admin/buildout/parts/instance/bin/runzope -X debug-mode=on
2010-05-02 11:38:08 INFO ZServer HTTP server started at Sun May 2 11:38:08 2010
…
OSError: [Errno 2] No such file or directory: '/Users/aclark/Developer/plone-site-admin/buildout/my.theme/my/theme/locales'

But this error is good; it means we have succeeded in adding our package to Buildout and Plone.

To fix this error (if you get it), create a locales directory where Plone says one is needed (ZopeSkel forgot to do this for us; a future release that is a release newer than ZopeSkel 2.16 should address the problem.):

$ mkdir src/my.theme/my/theme/locales

Now start Plone and you should see:

$ bin/instance fg
/Users/aclark/Developer/plone-site-admin/buildout/parts/instance/bin/runzope -X debug-mode=on
2010-05-02 11:44:28 INFO ZServer HTTP server started at Sun May 2 11:44:28 2010
Hostname: 0.0.0.0
Port: 8080
…
2010-05-02 11:44:40 INFO Application New disk product detected, determining if we need to fix up any ZClasses.
2010-05-02 11:44:40 INFO Zope Ready to handle requests

The second to last line indicates that Zope 2 has found our package!

Next, browse to http://localhost:8080/Plone. Now, click on Site Setup | Add/Remove Products and look for our package in the Quick Installer:

Running Paster

Check the box next to My Theme 1.0 and click Install.

You will notice the beyondskins.ploneday.site2010 theme has disappeared, and the Plone Default theme has returned (because My Theme 1.0 is based on Plone Default).

Now that our theme is installed, we can try to make a simple customization, like changing the logo.

To do that, we are going to copy a file with the same name as the default logo to our custom images directory: src/my/theme/skins/my_theme_custom_images.

But how do we know the logo image filename? One easy way to find it is to use the Firefox web browser with the Firebug add-on installed (http://getfirebug.com/):

Running Paster

The next step is to add a file of the same name to the custom images folder in our theme package.

You can use any image, but we will use plone-logo-128-white-bg.png from the Plone logo pack on plone.org (http://plone.org/foundation/logo/the-plone-logo/).

For adding the file just mentioned:

$ cp ~/Desktop/plone-logo-128-white-bg.png my.theme/my/theme/skins/my_theme_custom_images/logo.jpg

Now without restarting Plone (assuming you are running it in the foreground with bin/instance fg), reload the front page and you should see:

Running Paster

This is a simple example of customizing Plone with a filesystem theme package. We can customize many aspects of Plone's appearance using this technique.

Note

Why did this work?

You may wonder why we copied plone-logo-128-white-bg.png to logo.jpg. The short answer is because it works, and the file extension does not matter.

The medium length answer is that we have registered a new filesystem directory view and it is higher in the skin resolution order than Plone's filesystem directory view. Both contain an object called logo.jpg, but ours is discovered first.

The long answer is that there is a feature in Zope 2 called Acquisition that makes this customization possible (http://docs.zope.org/zope2/zope2book/Acquisition.html). In addition to the (core) Acquisition feature, there is a powerful add-on called the Content Management Framework (CMF) that Plone uses extensively. Plone registers a filesystem directory view and adds resources to it; then we customize a resource by ensuring it is acquired before Plone's resource is acquired.

Examining themes in the Zope Management Interface

Now that we have seen in part how themes work, let us take a closer look at their representation in Zope Object Database (ZODB).

Browse to http://localhost:8080/Plone. Click on Site Setup | Zope Management Interface and you should see:

Examining themes in the Zope Management Interface

This is a Through the Web (TTW) representation of all the objects in the database at the Plone site level (the application root is one level above).

The most frequently used theme-related objects here are:

  • portal_css

  • portal_javascripts

  • portal_skins

  • portal_view_customizations

Of these, portal_css and portal_javascripts are most often used to enable their respective debug modes, wherein the CSS and JavaScript files are not compiled into a single file (not to be confused with Zope 2's debug mode which detects filesystem changes in real time when enabled).

Take a look at your site with Firebug, in particular the style tab.

You should see:

Examining themes in the Zope Management Interface

Now enable debug mode in portal_javascripts and look again. You should see:

Examining themes in the Zope Management Interface

When portal_css debug mode is enabled, we can see (or by viewing the HTML source) that the CSS files are loaded individually in Firebug.

The same applies to portal_javascripts debug mode.

This can be absolutely invaluable when trying to correlate various visual elements with their respective sources.

In addition to debug mode, you can also add CSS/JavaScript files to their respective registries through the Web, which brings us to the next topic.

Making changes through the Web

Let us continue our ZMI walkthrough by examining both portal_skins and portal_view_customizations.

portal_skins

Browse to http://localhost:8080/Plone. Click on Site Setup | Zope Management Interface | portal_skins.

You should see:

portal_skins

If you scroll down and click on my_theme_custom_images you will find the image you added earlier:

portal_skins

If you wanted to upload a new image, you could click the Customize button and upload it, but keep in mind that change will only exist in the database.

Assuming you want to keep the my.theme package up-to-date (in a software repository for example), you may prefer to customize the image on the filesystem (and resist the temptation to customize it through the Web).

If you do customize through the Web, consider the changes only temporary or volatile.

portal_view_customizations

Next up is portal_view_customizations where we will explore yet another way to customize the logo.

Browse to http://localhost:8080/Plone. Click on Site Setup | Zope Management Interface | portal_view_customizations | zope.interface.interface | plone.logo.

You should see:

portal_view_customizations

If you wanted to, you could click the Customize button and change the image tag code:

portal_view_customizations

Since we used the same file (logo.jpg), the site will look exactly the same.

But now you can upload a new image and change the code as you see fit. To demonstrate this, let us now browse to http://localhost:8080/Plone and click on Site Setup | Zope Management Interface | portal_skins | custom and add an image:

portal_view_customizations

You can use any image you like, but we will use Vlogo250.gif from the Zope logo pack: http://www.zope.com/about_us/legal/low_res.zip.

Now return to http://localhost:8080/Plone and click on Site Setup | Zope Management Interface | portal_view_customizations | zope.interface.interface | plone.logo and change the filename to Vlogo250.gif:

<a metal:define-macro="portal_logo"
id="portal-logo"
accesskey="1"
tal:attributes="href view/navigation_root_url"
i18n:domain="plone">
<tal:comment replace="nothing">
<img src="logo.jpg" alt=""
tal:replace="structure view/logo_tag" />
</tal:comment>
<img src="Vlogo250.gif" />
</a>

You should see:

portal_view_customizations

Summary

That's it for this chapter. We have just demonstrated several ways to customize Plone's appearance with (hopefully) simple examples to convey the pros and cons of each method.

You have learned:

  • How to browse for themes on plone.org and install them with Buildout

  • How to use Omelette and Python to examine theme package contents

  • About theme package contents

  • How to create a theme package, and perform a simple customization

  • How to find your way around the ZMI

  • How to customize themes through the Web

See you in Chapter 4, where we will discuss site administration, including user and group management with LDAP.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.142.232