<?xml version="1.0" encoding="UTF-8" ?>
<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Project><name>z3ext.skintool</name>
<shortdesc>Tool for merging skin layers at runtime</shortdesc>
<description>Detailed Documentation
======================


=========
Skin tool
=========

Skin tool allow configure skin at runtime for each ISite object.

  &gt;&gt;&gt; from z3ext.skintool import interfaces, zcml
  &gt;&gt;&gt; from z3ext.skintool.tool import skinToolModified

  &gt;&gt;&gt; from zope import interface, component, schema

We need site object and request

  &gt;&gt;&gt; from zope.app.component.hooks import getSite
  &gt;&gt;&gt; site = getSite()

  &gt;&gt;&gt; from zope.publisher.browser import TestRequest
  &gt;&gt;&gt; request = TestRequest()

Now let's define layer and skin

  &gt;&gt;&gt; from zope import interface
  &gt;&gt;&gt; class IMySkin(interface.Interface):
  ...     pass
  &gt;&gt;&gt; class IMyLayer(interface.Interface):
  ...     pass

Before we can use IMySkin and IMyLayer we should register it in local registry

  &gt;&gt;&gt; zcml.skinDirective(IMySkin, u'myskin', u'My skin', '', ())
  &gt;&gt;&gt; zcml.layerDirective(IMyLayer, u'mylayer', u'My layer', '')

Now skin and layer should be listed in vocabulary.

  &gt;&gt;&gt; from z3ext.skintool.vocabulary import SkinsVocabulary
  &gt;&gt;&gt; voc = SkinsVocabulary()(site)
  &gt;&gt;&gt; term = voc.getTerm(IMySkin)
  &gt;&gt;&gt; term.value == u'myskin'
  True
  &gt;&gt;&gt; term.title == 'My skin'
  True
  &gt;&gt;&gt; term.token == u'myskin'
  True

  &gt;&gt;&gt; from z3ext.skintool.vocabulary import LayersVocabulary
  &gt;&gt;&gt; voc = LayersVocabulary()(site)
  &gt;&gt;&gt; term = voc.getTerm(IMyLayer)
  &gt;&gt;&gt; term.value == u'mylayer'
  True
  &gt;&gt;&gt; term.title == 'My layer'
  True
  &gt;&gt;&gt; term.token == u'mylayer'
  True

All layers applied in IBeforeTraverseEvent event for ISite object. We will
use handler directly.

  &gt;&gt;&gt; from z3ext.skintool.subscribers import threadServiceSubscriber
  &gt;&gt;&gt; from zope.app.publication.interfaces import BeforeTraverseEvent

Let's check layer for our request.

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))

  &gt;&gt;&gt; IMySkin.providedBy(request)
  False

  &gt;&gt;&gt; IMyLayer.providedBy(request)
  False

This is because we should configure skin tool to use our layer and
site object should implement ISkinable interface.

  &gt;&gt;&gt; interface.directlyProvides(site, interfaces.ISkinable)

Let's configure skin tool

  &gt;&gt;&gt; tool = component.getUtility(interfaces.ISkinTool)
  &gt;&gt;&gt; tool.skin = u'myskin'
  &gt;&gt;&gt; tool.layers = [u'mylayer']
  &gt;&gt;&gt; skinToolModified()

Let's try again

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMySkin.providedBy(request)
  True
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  True

Change layers config

  &gt;&gt;&gt; tool.layers = []
  &gt;&gt;&gt; skinToolModified()

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  False


Skin can depends on other layers

  &gt;&gt;&gt; class IMySkin2(interface.Interface):
  ...     pass

  &gt;&gt;&gt; zcml.skinDirective(IMySkin2, u'myskin2', u'My skin2', '', (IMyLayer,))
  &gt;&gt;&gt; tool.skin = u'myskin2'
  &gt;&gt;&gt; skinToolModified()

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMySkin2.providedBy(request)
  True
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  True

We can define default layer, that will added automaticly

  &gt;&gt;&gt; class IDefaultLayer(interface.Interface):
  ...     pass

We have to register utility IDefaultLayer

  &gt;&gt;&gt; component.provideUtility(IDefaultLayer, interfaces.IDefaultLayer, 'default')
  &gt;&gt;&gt; tool.layers = [u'mylayer']
  &gt;&gt;&gt; skinToolModified()

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  True
  &gt;&gt;&gt; IDefaultLayer.providedBy(request)
  True


z3ext:layer directive
---------------------

We can do same with z3ext:layer directive. We need load zcml file:

  &gt;&gt;&gt; import z3ext.skintool
  &gt;&gt;&gt; from zope.configuration import xmlconfig
  &gt;&gt;&gt; context = xmlconfig.file('meta.zcml', z3ext.skintool)

  &gt;&gt;&gt; context = xmlconfig.string("""
  ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
  ...    xmlns="http://namespaces.zope.org/zope" i18n_domain="z3ext"&gt;
  ...  &lt;z3ext:layer
  ...    name="mylayer3"
  ...    layer="z3ext.skintool.README.IMyLayer"
  ...    title="My zcml layer" /&gt;
  ... &lt;/configure&gt;""", context)

  &gt;&gt;&gt; voc = LayersVocabulary()(site)
  &gt;&gt;&gt; term = voc.getTerm(IMyLayer)
  &gt;&gt;&gt; term.value == u'mylayer3'
  True
  &gt;&gt;&gt; term.title == 'My zcml layer'
  True
  &gt;&gt;&gt; term.token == u'mylayer3'
  True

  &gt;&gt;&gt; tool.user_layers = ['mylayer3']
  &gt;&gt;&gt; skinToolModified()

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  True

  &gt;&gt;&gt; context = xmlconfig.string("""
  ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
  ...    xmlns="http://namespaces.zope.org/zope" i18n_domain="z3ext"&gt;
  ...  &lt;z3ext:skin
  ...    name="myskin4"
  ...    layer="z3ext.skintool.README.IMySkin2"
  ...    title="My zcml skin4"
  ...    require="z3ext.skintool.README.IMyLayer" /&gt;
  ... &lt;/configure&gt;""", context)

  &gt;&gt;&gt; tool.skin = u'myskin4'
  &gt;&gt;&gt; skinToolModified()

  &gt;&gt;&gt; threadServiceSubscriber(site, BeforeTraverseEvent(site, request))
  &gt;&gt;&gt; IMySkin2.providedBy(request)
  True
  &gt;&gt;&gt; IMyLayer.providedBy(request)
  True


=======
CHANGES
=======

1.1.0 (2008-11-21)
------------------

- Added z3ext:skin directive

- API refactored

- Added translations: nl, ru


1.0.2 (2008-08-07)
------------------

- Added INoSkinSwitching for skin that does not allow skin switching


1.0.1 (2008-05-16)
------------------

- Replace 'autoinclude' with 'includeDependendcies'


1.0.0 (2008-03-28)
------------------

- Code cleanup

- Added tests

- Code moved to svn.zope.org


0.13 (2008-02-28)
----------------

- Use z3c.autoinclude

- Do not generate InterfaceClass object, just apply list of layers


0.12 (2008-02-08)
-----------------

- Code cleanup


0.11 (2008-02-06)
------------------

- Added ISkinable marker interface.
  Now object should implement ISkinable implicitly to support skintool


0.10 (2008-02-01)
------------------

- Initial release.</description>
<homepage rdf:resource="http://z3ext.net/" />
<maintainer><foaf:Person><foaf:name>Nikolay Kim</foaf:name>
<foaf:mbox_sha1sum>d2ae7e827893a4b491ceed859306c037152b761c</foaf:mbox_sha1sum></foaf:Person></maintainer>
<release><Version><revision>1.1.0</revision></Version></release>
</Project></rdf:RDF>