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:
parent
dbd3b7b792
commit
173fe3bd0c
9 changed files with 217 additions and 16 deletions
|
@ -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:
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
54
browser/liquid/body.pt
Normal 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> ·
|
||||
<b><a href="http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/FrontPage">Zope 3</a></b>
|
||||
</metal:footer>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<skin name="Liquid"
|
||||
layers="liquid rotterdam default" />
|
||||
|
||||
|
||||
<page for="*"
|
||||
name="skin_macros" template="view_macros.pt"
|
||||
permission="zope.View"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
31
browser/main.pt
Normal 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
86
browser/view.py
Normal 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
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue