Making a SilvaLayout Products
=============================

This Documentation gives a step by step guide for making Silva layouts
using Silva 1.6 and Silva 2.x.

Making a Silva layout with Silva 1.6 and SilvaLayout 0.5.10

Setup
-----

Before making the layout product download the SilvaLayout 0.5.10 product, 
restart your Zope instance, and then in the "service_extensions" tab of 
the Zope Management Interface (ZMI) install the SilvaLayout product.

Making the layout product
-------------------------

First make a directory with the name of your layout, for this example this
will be called "NameOfLayout" in either the "Products" directory if you are 
using a Silva tarball or svn, or the "products" directory if you are using 
a Silva buildout.

Move into the layout directory and make the following files and directories.

- __init__.py

- configure.zcml

- install.py

- template.pt

- css/

- images/

In this example I am placing two directories in my layout product. It is
not mandatory to have these directories for a layout product.

After creating the files and directories open the __init__.py file and add the
following lines of code:

.. sourcecode:: python

import install
from Products.Silva.ExtensionRegistry import extensionRegistry

import install
from Products.Silva.ExtensionRegistry import extensionRegistry

from Products.Silva.ExtensionRegistry import extensionRegistry
import install

def initialize(context):
    extensionRegistry.register(
        'NameOfLayout',
        'Name Of Layout',
        context, [], install, depends_on='SilvaLayout')

Save the __init__.py file and now open the install.py file and add the following
code:

..sourcecode:: python

from os import path
from Globals import package_home

mapping = {}
installed_attr = '__name_of_layout__installed__'

def is_installed(context):
    return hasattr(context, installed_attr)

def install(context):
    configureMetadata(context)
    setattr(context, installed_attr, 1)

def uninstall(context):
    delattr(context, installed_attr)

def configureMetadata(context):
    product = package_home(globals())
    schema = path.join(product, 'schema')
    collection = context.service_metadata.getCollection()

    for types, setids in mapping.items():
        for setid in setids:
            if not setid in collection.objectIds():
                xmlfile = path.join(schema, setid+'.xml')
                definition = open(xmlfile, 'r')
        context.service_metadata.addTypesMapping(types, setids)

    context.service_metadata.initializeMetadata()

Save and close the install file.

Next open the configure.zcml file and add the following code:

..sourcecode:: xml

<configure
  xmlns="http://namespaces.zope.org/zope"
  xmlns:browser="http://namespaces.zope.org/browser"
  xmlns:five="http://namespaces.zope.org/five"
  xmlns:i18n="http://namespaces.zope.org/i18n"
  >
  
  <include
    package="Products.SilvaLayout"
    />

  <browser:layer name="NameOfLayout" />

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContent"
    class="Products.SilvaLayout.browser.silvaview.Content"
    template="template.pt"
    permission="zope2.View"
    layer="NameOfLayout"
    />

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContainer"
    class="Products.Silva.browser.silvaview.Container"
    template="template.pt"
    permission="zope2.View"
    layer="NameOfLayout"
    />

  <browser:resourceDirectory
    name="css"
    directory="css"
    permission="zope2.View"
    layer="NameOfLayout"
    />

  <browser.resourceDirectory
    name="images"
    directory="images"
    permission="zope2.View"
    layer="NameOfLayout"
    />

  <browser:skin
    name="NameOfLayout"
    layer="NameOfLayout silvadefault default"
    />

</configure>

Save and close the configure.zcml.

Now open the template.pt file. The template file has been reduced to only a
couple of useful bits of code. The template shows how to link to the css
directory using an example stylesheet called main.css. The example also uses
and image coming from the images directory. The template also makes uses of 
the tree.py module in SilvaLayout/browser/tree.py. This is a useful module for
getting access to navigation trees. It comes with built in styles which can be
overridden by users making their own tree css styles. Finally the template calls
content from the view/render method, the method used for getting access to
Silva Documents.

..sourcecode:: xml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
    metal:define-macro="main">
  <head>
    <!-- title -->
    <title tal:content="structure view/title"/>
    <!-- meta data -->
    <meta tal:replace="structure context/@@contenttype" />
    <!-- Injector for content-specific css/js inclusion -->
    <link tal:replace="structure here/head_inject | nothing" />
    <!-- EXAMPLE LINK TAG -->
    <link rel="stylesheet" tal:attributes="href request/resourcebase/++resource++css/main.css"/>
  </head>
  <body>
    <!-- EXAMPLE IMAGE TAG -->
    <img tal:attributes="src request/resourcebase/++resource++images/name_of_image.gif" />
    <!-- EXAMPLE TREE -->
    <div tal:content="structure context/@@treeview/renderHTML">
      <!-- navtree goes here -->
    </div>
    <div id="contents">
      <span tal:content="structure view/render" /><br />
    </div>
  </body>
</html>

Applying the layout in Silva
----------------------------

Go to the Silva Management Interface (SMI) of your Silva root. Click on the
"properties" tab, and then click on the "settings..." button, at the bottom of
the page you can use the pulldown menu to select the newly built skin.

Making a layout for Silva 2.x trunk and SilvaLayout trunk
---------------------------------------------------------

Follow the "Setup" steps in the previous example only switching the 
products to Silva trunk and SilvaLayout trunk. 

Pointing out some differences
-----------------------------

Without going into too much detail, the main difference between a Silva 1.6
layout and a 2.x layout is the exclusion of initialization code in a single 
__init__.py file. I say "single __init__.py" because this example uses a much 
deeper directory tree, each directory using an __init__.py file to register the
directory with python. Another striking difference is the lack of an install.py
file. In addition to a deeper directory tree each directory comes with its own
configure.zcml. Finally there there is the addition of the "skin.py" file,
which contains a class subclassing a default SilvaLayout interface.

Making the layout product
-------------------------

First make a directory with the name of your layout (NameLayout) in either 
the "Products" directory if you are using a Silva tarball or the "products" 
directory if you are using a Silva buildout.

Move into the layout directory and make the following files and directories

- __init__.py

- configure.zcml

- browser/

Open the __init__.py and add the following:

#

Save and close the file. Then open the configure.zcml file and the following 
directives:

.. sourcecode:: xml

<configure 
  xmlns="http://namespaces.zope.org/zope"
  xmlns:browser="http://namespaces.zope.org/browser"
  xmlns:five="http://namespaces.zope.org/five">

  <!-- make sure SilvaLayout is loaded first -->
  <include 
    package="Products.SilvaLayout"
  />
  
  <!-- include views -->
  <include 
    package=".browser"
  />
  
</configure>

Save and close the configure.zcml. Now enter the browser directory and make the 
following files and directory:

- __init__.py

- configure.zcml

- NameOfLayoutTemplate/

open the __init__.py file and the following code:

#

Save the file and open the configure.zcml file and add:

..sourcecode:: xml

<configure 
  xmlns="http://namespaces.zope.org/zope"
  xmlns:browser="http://namespaces.zope.org/browser"
  xmlns:five="http://namespaces.zope.org/five">
  
  <include 
    package=".NameOfLayoutTemplate"
  />
  
</configure>

Now enter the NameOfLayoutTemplate directory and add the following files and 
directories:

 - __init__.py

- configure.zcml

- skin.py

- template.pt

- css/

- images/

Open __init__.py and add the following code:

#

Save the file and open the configure.zcml and add the following code:

..sourcecode:: xml

<configure 
  xmlns="http://namespaces.zope.org/zope"
  xmlns:browser="http://namespaces.zope.org/browser"
  xmlns:five="http://namespaces.zope.org/five">

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContent"
    class="Products.SilvaLayout.browser.silvaview.Content"
    template="template.pt"
    permission="zope2.View"
    layer=".skin.INameOfLayoutTemplate"
  />

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContainer"
    class="Products.SilvaLayout.browser.silvaview.Container"
    template="template.pt"
    permission="zope2.View"
    layer=".skin.INameOfLayoutTemplate"
  />

  <browser:resourceDirectory
    name="css"
    directory="css"
    permission="zope2.View"
    layer=".skin.INameOfLayoutTemplate"
  />

  <browser:resourceDirectory
    name="images"
    directory="images"
    permission="zope2.View"
    layer=".skin.INameOfLayoutTemplate"
  />

  <interface
    interface=".skin.INameOfLayoutTemplate"
    type="zope.publisher.interfaces.browser.IBrowserSkinType"
    name="NameLayout"
  />

</configure>

Save and close this file. Open the skin.py file and add the following code:

..sourcecode:: python

from Products.SilvaLayout.browser.silvadefault.skin import ISilvaDefault

class INameOfLayoutTemplate(ISilvaDefault):
    """Default skin for SilvaLayout.
    """

Save the skin.py file.

The template.pt remains the same as the previous example.

Applying the layout in Silva
----------------------------

Apply the layout in the same way as the previous example.

Note

This is only one way to make a layout, it is not necessary to follow this tree
structure if you do not wish to.
