finished new-style skin template structure with main.pt and body.pt

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1303 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-08-17 16:55:45 +00:00
parent dbd3b7b792
commit 173fe3bd0c
9 changed files with 217 additions and 16 deletions

View file

@ -5,7 +5,7 @@ We first set up a test and working environment:
>>> 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
@ -26,17 +26,16 @@ because this already provides some predefined stuff:
Before creating a controller we have to set up a context object and
a view:
>>> class SomeObject(object): pass
>>> obj = SomeObject()
>>> class View(object):
... def __init__(self, context, request):
... self.context = context
... self.request = request
>>> from cybertools.browser.view import GenericView
>>> class View(GenericView):
... pass
>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
>>> view = View(obj, request)
>>> controller = Controller(view, request)
>>> controller.view is view
True
@ -44,6 +43,8 @@ a view:
True
>>> controller.request is request
True
>>> request.annotations['cybertools.browser']['controller'] == controller
True
The controller registers itself with the view:

View file

@ -6,6 +6,24 @@
i18n_domain="zope"
>
<page for="*"
name="main.html"
template="main.pt"
class="cybertools.browser.view.GenericView"
permission="zope.Public"
/>
<page for="*"
name="cybertools.body_macros"
template="liquid/body.pt"
permission="zope.Public"
/>
<page for="*"
name="body.html"
class="cybertools.browser.view.GenericView"
permission="zope.View"/>
<page name="controller"
for="zope.app.publisher.interfaces.browser.IBrowserView"
class="cybertools.browser.controller.Controller"

View file

@ -32,12 +32,14 @@ from cybertools.browser.configurator import IViewConfigurator, IMacroViewPropert
class Controller(object):
def __init__(self, context, request):
self.view = context # the controller is adapted to a view
self.view = view = context # the controller is adapted to a view
self.context = context.context
self.request = request
self.skin = None # may be overwritten by the view
self.configure()
context.controller = self # notify the view
#self.view.setupController()
self.view.controller = self # notify the view
skin = None # may be overwritten by the view
@Lazy
def macros(self):
@ -63,13 +65,21 @@ class Controller(object):
class Macros(dict):
# TODO: move to namedTemplate
standardTemplate = ViewPageTemplateFile('base_macros.pt')
def __init__(self, controller):
self.controller = controller
self['css'] = []
self['js'] = []
self.identifiers = set()
def register(self, slot, template=None, name=None, position=None, **kw):
def register(self, slot, template=None, name=None, position=None,
identifier=None, **kw):
if identifier:
# make sure a certain resource is only registered once
if identifier in self.identifiers:
return
self.identifiers.add(identifier)
if template is None:
template = self.standardTemplate
if name is None:

54
browser/liquid/body.pt Normal file
View file

@ -0,0 +1,54 @@
<div metal:define-macro="body"
tal:define="controller nocall:view/controller;
resourceBase controller/resourceBase;">
<div id="global" metal:define-macro="global">
<div class="top" metal:define-slot="top">
<a href="#" name="top" metal:define-slot="logo"
tal:attributes="href string:${request/URL/1}"><img class="logo"
src="logo.gif" border="0" alt="Home"
tal:attributes="src string:${resourceBase}logo.gif" /></a>
</div>
</div>
<div id="menu">
<metal:menu define-macro="navigators">
<div class="box">
<h4>Navigation</h4>
<tal:menu define="item nocall:view/menu;
level level|python: 1"
condition="nocall:item">
<div class="body">
<metal:menu use-macro="views/node_macros/menu" />
</div>
</tal:menu>
</div>
</metal:menu>
</div>
<div id="content" define-macro="content">
<div metal:define-slot="actions"></div>
<div metal:define-slot="message"></div>
<metal:content define-slot="content">
<tal:content define="item nocall:view/item;
level level|python: 1;
macro item/macro;"
condition="macro">
<metal:block use-macro="macro" />
</tal:content>
</metal:content>
</div>
<div id="sub-section" define-macro="sub-section">
<metal:sub define-slot="sub-section">
</metal:sub>
</div>
<div id="footer" class="footer" define-macro="footer">
<metal:footer define-slot="footer">
Powered by <b><a href="http://www.python.org">Python</a></b> &middot;
<b><a href="http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/FrontPage">Zope 3</a></b>
</metal:footer>
</div>
</div>

View file

@ -11,7 +11,7 @@
<skin name="Liquid"
layers="liquid rotterdam default" />
<page for="*"
name="skin_macros" template="view_macros.pt"
permission="zope.View"

View file

@ -28,9 +28,9 @@ from cybertools.browser.controller import Controller as BaseController
class Controller(BaseController):
def __init__(self, context, request):
super(Controller, self).__init__(context, request)
self.setupCss()
self.setupJs()
super(Controller, self).__init__(context, request)
def setupCss(self):
macros = self.macros

View file

@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="zope"
tal:define="controller nocall:view/@@controller;
resourceBase controller/resourceBase">
resourceBase controller/resourceBase;">
<metal:block metal:define-slot="settings" />
@ -29,7 +29,8 @@
tal:attributes="href string:${resourceBase}favicon.png" />
</head>
<body tal:attributes="onload body_onload | nothing">
<body tal:attributes="onload body_onload | nothing"
metal:define-macro="body">
<div id="global">
<div class="top" metal:define-slot="top">

31
browser/main.pt Normal file
View file

@ -0,0 +1,31 @@
<metal:block define-macro="page"><metal:block define-slot="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></metal:block>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="zope"
tal:define="controller nocall:view/@@controller;
resourceBase controller/resourceBase;
body view/pageBody">
<head metal:define-macro="head">
<title metal:define-macro="title"
tal:content="options/title|view/headTitle|context/title|default">
Powered by Zope 3
</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<tal:css repeat="macro controller/macros/css">
<metal:css use-macro="macro" />
</tal:css>
<tal:js repeat="macro controller/macros/js">
<metal:js use-macro="macro" />
</tal:js>
<link rel="icon" type="image/png"
tal:attributes="href string:${resourceBase}favicon.png" />
</head>
<body tal:content="structure body"/>
</html>
</metal:block>

86
browser/view.py Normal file
View file

@ -0,0 +1,86 @@
#
# 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 generic view class.
$Id$
"""
from zope import component
from zope.interface import Interface, implements
from zope.cachedescriptors.property import Lazy
from zope.publisher.interfaces.browser import ISkin
from zope.app.pagetemplate import ViewPageTemplateFile
class UnboundTemplateFile(ViewPageTemplateFile):
def __get__(self, instance, type):
return self
class GenericView(object):
index = ViewPageTemplateFile('main.pt')
bodyTemplate = UnboundTemplateFile('liquid/body.pt')
menu = macro = skin = None
def setController(self, controller):
# make the (one and only controller) available via the request
viewAnnotations = self.request.annotations.setdefault('cybertools.browser', {})
viewAnnotations['controller'] = controller
if getattr(controller, 'skinName', None):
self.setSkin(controller.skinName.value)
controller.skin = self.skin
# this is the place to register special macros with the controller:
self.setupController()
def getController(self):
viewAnnotations = self.request.annotations.setdefault('cybertools.browser', {})
return viewAnnotations.get('controller', None)
controller = property(getController, setController)
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self, *args, **kw):
return self.index(*args, **kw)
def setupController(self):
pass
def pageBody(self):
template = component.getMultiAdapter((self.context, self.request),
name='body.html').bodyTemplate
return template(self)
def setSkin(self, skinName):
skin = None
if skinName:
skin = component.queryUtility(ISkin, skinName)
if skin:
applySkin(self.request, skin)
self.skin = skin
@Lazy
def item(self):
return self