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

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

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

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

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

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

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

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

  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.
