basic set up for view configurator stuff

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1200 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-05-07 11:56:47 +00:00
parent d8de666f2f
commit cbc15a5a2d
7 changed files with 195 additions and 15 deletions

View file

@ -3,8 +3,12 @@ Browser View Tools
We first set up a test and working environment:
>>> from zope.app import zapi
>>> from zope.app.testing import ztapi
>>> from zope.app import zapi
>>> from zope.app.testing import ztapi
>>> from zope import component, interface
>>> from zope.publisher.browser import TestRequest
>>> from zope.publisher.interfaces.browser import IBrowserRequest
The View Controller
-------------------
@ -91,3 +95,43 @@ The pre-set collection of macros for a certain slot may be extended:
>>> print m5.name, m5.media, m5.resourceName
css all node.css
The View Configurator
---------------------
A view configurator is a multiadapter for a content object that provides
a set of properties to be used for setting up special presentation
characteristics of a page. Typical examples for such characteristics are
- the skin to be used
- the logo to show in the corner of the page
The default configurator uses attribute annotations for retrieving view
properties; that means that there could be form somewhere to edit those
properties and store them in the content object's annotations.
The configurator is called automatically from the controller if there is
an appropriate adapter:
>>> from cybertools.browser.configurator import IViewConfigurator
>>> from cybertools.browser.configurator import ViewConfigurator
>>> component.provideAdapter(ViewConfigurator, (SomeObject, IBrowserRequest),
... IViewConfigurator)
>>> controller = Controller(view, request)
But this does not have any effect as long as there aren't any properties
stored in the attribute annotations. So let's set a 'skinName' attribute:
>>> from zope.app.annotation.interfaces import IAttributeAnnotatable, IAnnotations
>>> from zope.app.annotation.attribute import AttributeAnnotations
>>> interface.classImplements(SomeObject, IAttributeAnnotatable)
>>> component.provideAdapter(AttributeAnnotations, (SomeObject,), IAnnotations)
>>> ann = IAnnotations(obj)
>>> setting = {'skinName': {'value': 'SuperSkin'}}
>>> from cybertools.browser.configurator import ANNOTATION_KEY
>>> ann[ANNOTATION_KEY] = setting
>>> controller = Controller(view, request)
>>> controller.skinName.value
'SuperSkin'

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2005 Helmut Merz helmutm@cy55.de
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -21,13 +21,3 @@ cybertools browser package.
$Id$
"""
from zope.viewlet.interfaces import IViewletManager
class ILeft(IViewletManager):
""" Left slot.
"""
class IBody(IViewletManager):
""" Body (main) content slot.
"""

View file

@ -1,3 +1,13 @@
<metal:logo define-macro="logo">
<a href="#" name="logo" title="Home"
tal:attributes="href macro/href;
title macro/title"><img
src="logo.gif" border="0" alt="Home"
tal:attributes="src string:${resourceBase}${macro/resourceName};
alt macro/alt" /></a>
</metal:logo>
<metal:css define-macro="css">
<style type="text/css" media="all"
tal:attributes="media macro/media"

118
browser/configurator.py Normal file
View file

@ -0,0 +1,118 @@
#
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
A view configurator provides configuration data for a view controller.
$Id$
"""
from zope.app import zapi
from zope.app.annotation.interfaces import IAttributeAnnotatable
from zope.app.annotation.attribute import AttributeAnnotations
from zope.cachedescriptors.property import Lazy
from zope.interface import Interface, Attribute, implements
from zope.component import adapts
# interfaces
class IViewConfigurator(Interface):
""" Usually implemented by an adapter (e.g. to IAnnotatable);
provides a set of properties that govern the appearance of a
page, e.g. the name of the logo, CSS file(s), or portlets.
"""
viewProperties = Attribute('A sequence of IViewProperty objects')
class IViewProperty(Interface):
slot = Attribute('The property slot to fill')
name = Attribute('The name of the object to fill the slot')
class IMacroViewProperty(IViewProperty):
slot = Attribute('The property slot to fill')
name = Attribute('The name of the macro to use; may be None, '
'meaning that the slot name will be used')
template = Attribute('The template providing the macro')
params = Attribute('A mapping with parameters (key/value pairs) '
'to be handed over to the macro')
#default implementations
ANNOTATION_KEY = 'cybertools.browser.configurator.ViewConfigurator'
class ViewConfigurator(AttributeAnnotations):
""" Simple/basic default adapter using attribute annotations as storage
for view properties.
"""
implements(IViewConfigurator)
def __init__(self, context, request):
AttributeAnnotations.__init__(self, context)
self.context = context
self.request = request
@property
def viewProperties(self):
propDefs = self.get(ANNOTATION_KEY, [])
result = []
for prop in propDefs:
vp = zapi.queryMultiAdapter((self.context, self.request),
IViewProperty, name=prop)
if vp is None:
vp = ViewProperty(self.context, self.request)
vp.slot = prop
vp.setParams(propDefs[prop])
result.append(vp)
return result
class ViewProperty(object):
implements(IViewProperty)
def __init__(self, context, request):
self.context = context
self.request = request
self.slot = None
self.name = None
self.value = None
self.params = {}
def setParams(self, params):
self.name = params.pop('name', '')
self.value = params.pop('value', None)
self.params = params
class MacroViewProperty(object):
implements(IMacroViewProperty)
template = None
def setParams(self, params):
self.name = params.pop('name', '')
self.template = params.pop('template', None)
self.params = params

View file

@ -26,6 +26,8 @@ from zope.app import zapi
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from cybertools.browser.configurator import IViewConfigurator, IMacroViewProperty
class Controller(object):
@ -34,6 +36,7 @@ class Controller(object):
self.context = context.context
self.request = request
self.skin = None # may be overwritten by the view
self.configure()
context.controller = self # notify the view
@Lazy
@ -46,6 +49,17 @@ class Controller(object):
# TODO: put '/@@' etc after path to site instead of directly after URL0
return self.request.URL[0] + skinSetter + '/@@/'
def configure(self):
configurator = zapi.queryMultiAdapter((self.context, self.request),
IViewConfigurator)
if configurator is not None:
for item in configurator.viewProperties:
if IMacroViewProperty.providedBy(item):
self.macros.register(item.slot, item.template, item.name,
**item.params)
else:
setattr(self, item.slot, item)
class Macros(dict):

View file

@ -33,6 +33,10 @@ body {
border-left: none;
}
div.box h4 {
height: auto;
}
.footer {
text-align: center;
border-top: 1px solid #ccc;

View file

@ -296,7 +296,7 @@ pre {
}
div#action {
height: 16px;
height: 1.35em;
/*width: 100%;*/
background-color: #c8c4ff;
border-left: 1px solid #6478b0;
@ -368,7 +368,7 @@ div.box h4 {
color: #606060;
padding: 0px 5px;
display: block;
height: 18px;
/* height: 18px; */
}
.box div.body {