work in progress: layout management
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2783 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
996846f711
commit
3c3d635493
13 changed files with 345 additions and 10 deletions
|
@ -63,8 +63,8 @@ class IInstance(Interface):
|
|||
|
||||
context = Attribute('Object this instance adapter has been created for')
|
||||
template = Attribute('A template to be used for this instance')
|
||||
aspect = Attribute('A dotted name that helps to store and retrieve the '
|
||||
'template.')
|
||||
aspect = Attribute('Optional: a dotted name that may help to store and '
|
||||
'retrieve the template.')
|
||||
|
||||
def applyTemplate(*args, **kw):
|
||||
""" Apply the template using the instance's context. Note that this
|
||||
|
|
|
@ -4,5 +4,41 @@ Layout Management
|
|||
|
||||
($Id$)
|
||||
|
||||
>>> from cybertools.composer.layout.base import Layout
|
||||
>>> from zope import component
|
||||
>>> from zope.interface import Interface
|
||||
|
||||
>>> from cybertools.composer.layout.base import Layout, LayoutInstance
|
||||
>>> from cybertools.composer.layout.region import Region, regions
|
||||
|
||||
|
||||
Browser Views
|
||||
=============
|
||||
|
||||
>>> from zope.traversing.adapters import DefaultTraversable
|
||||
>>> component.provideAdapter(DefaultTraversable, (Interface,))
|
||||
|
||||
>>> from cybertools.composer.layout.browser.layout import PageLayout
|
||||
>>> pageLayout = PageLayout()
|
||||
>>> pageLayoutInstance = LayoutInstance(pageLayout)
|
||||
|
||||
>>> from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
|
||||
>>> bodyLayout = Layout()
|
||||
>>> bodyLayout.renderer = ViewPageTemplateFile('browser/liquid/body.pt').macros['body']
|
||||
>>> bodyRegion = Region('body')
|
||||
>>> bodyRegion.layouts.append(LayoutInstance(bodyLayout))
|
||||
>>> regions['page.body'] = bodyRegion
|
||||
|
||||
>>> standardRenderers = ViewPageTemplateFile('browser/standard.pt').macros
|
||||
>>> footerLayout = Layout()
|
||||
>>> footerLayout.renderer = standardRenderers['footer']
|
||||
>>> footerRegion = Region('footer')
|
||||
>>> footerRegion.layouts.append(LayoutInstance(footerLayout))
|
||||
>>> regions['body.footer'] = footerRegion
|
||||
|
||||
>>> from cybertools.composer.layout.browser.view import Page
|
||||
>>> from zope.publisher.browser import TestRequest
|
||||
>>> page = Page(pageLayoutInstance, TestRequest())
|
||||
|
||||
>>> page()
|
||||
u'<!DOCTYPE ...>...<html ...>...</html>...
|
||||
|
|
|
@ -26,7 +26,8 @@ from zope.interface import implements
|
|||
|
||||
from cybertools.composer.base import Component, Element, Compound
|
||||
from cybertools.composer.base import Template
|
||||
from cybertools.composer.layout.interfaces import ILayout
|
||||
from cybertools.composer.layout.interfaces import ILayout, ILayoutInstance
|
||||
from cybertools.composer.layout.interfaces import IRegion
|
||||
from cybertools.util.jeep import Jeep
|
||||
|
||||
|
||||
|
@ -36,4 +37,32 @@ class Layout(Template):
|
|||
|
||||
name = u''
|
||||
manager = None
|
||||
renderer = None
|
||||
|
||||
|
||||
class LayoutInstance(object):
|
||||
|
||||
implements(ILayoutInstance)
|
||||
|
||||
def __init__(self, template, context=None):
|
||||
self.template = template
|
||||
self.context = context
|
||||
|
||||
@property
|
||||
def renderer(self):
|
||||
return self.template.renderer
|
||||
|
||||
|
||||
class Region(object):
|
||||
|
||||
implements(IRegion)
|
||||
|
||||
allowedLayoutCategories = None
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
@property
|
||||
def layouts(self):
|
||||
return []
|
||||
|
||||
|
|
3
composer/layout/browser/__init__.py
Normal file
3
composer/layout/browser/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
$Id$
|
||||
"""
|
1
composer/layout/browser/base.pt
Normal file
1
composer/layout/browser/base.pt
Normal file
|
@ -0,0 +1 @@
|
|||
<metal:render use-macro="nocall:view/renderer" />
|
37
composer/layout/browser/layout.py
Normal file
37
composer/layout/browser/layout.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Copyright (c) 2008 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
|
||||
#
|
||||
|
||||
"""
|
||||
Specialized browser layouts.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
|
||||
from cybertools.composer.layout.base import Layout
|
||||
|
||||
|
||||
class PageLayout(Layout):
|
||||
|
||||
name = u'page'
|
||||
|
||||
@property
|
||||
def renderer(self):
|
||||
return ViewPageTemplateFile('main.pt').macros['page']
|
||||
|
3
composer/layout/browser/liquid/__init__.py
Normal file
3
composer/layout/browser/liquid/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
$Id$
|
||||
"""
|
37
composer/layout/browser/liquid/body.pt
Normal file
37
composer/layout/browser/liquid/body.pt
Normal file
|
@ -0,0 +1,37 @@
|
|||
<body class="tundra"
|
||||
metal:define-macro="body">
|
||||
|
||||
<!--<div id="global">
|
||||
<div class="top">
|
||||
<tal:sub repeat="view view/layouts/logo">
|
||||
<metal:sub use-macro="view/renderer" /></tal:sub>
|
||||
<tal:sub repeat="view view/layouts/top_actions">
|
||||
<metal:sub use-macro="view/renderer" /></tal:sub>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<tal:sub repeat="view view/layouts/portlets_left">
|
||||
<metal:sub use-macro="view/renderer" />
|
||||
</tal:sub>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<tal:sub repeat="view view/layouts/content">
|
||||
<metal:sub use-macro="view/renderer" />
|
||||
</tal:sub>
|
||||
</div>
|
||||
|
||||
<div id="sub-section">
|
||||
<tal:sub repeat="view view/layouts/portlets_right">
|
||||
<metal:sub use-macro="view/renderer" />
|
||||
</tal:sub>
|
||||
</div>-->
|
||||
|
||||
<div id="footer" class="footer">
|
||||
<tal:sub repeat="view view/layouts/footer">
|
||||
<metal:sub use-macro="view/renderer" />
|
||||
</tal:sub>
|
||||
</div>
|
||||
|
||||
</body>
|
22
composer/layout/browser/main.pt
Normal file
22
composer/layout/browser/main.pt
Normal file
|
@ -0,0 +1,22 @@
|
|||
<metal:page define-macro="page"><!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"
|
||||
tal:define="body view/body">
|
||||
|
||||
<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 view/resources/css">
|
||||
<metal:css use-macro="macro" />
|
||||
</tal:css>
|
||||
|
||||
<base href="." tal:attributes="href request/URL">
|
||||
</head>
|
||||
<body tal:replace="structure body" />
|
||||
|
||||
</html>
|
||||
|
||||
</metal:page>
|
3
composer/layout/browser/standard.pt
Normal file
3
composer/layout/browser/standard.pt
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div metal:define-macro="footer">
|
||||
Some footer text.
|
||||
</div>
|
97
composer/layout/browser/view.py
Normal file
97
composer/layout/browser/view.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
#
|
||||
# Copyright (c) 2008 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
|
||||
#
|
||||
|
||||
"""
|
||||
Basic view classes for layout-based presentation.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope import component
|
||||
from zope.interface import Interface, implements
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
|
||||
from cybertools.composer.layout.region import regions
|
||||
|
||||
|
||||
class BaseView(object):
|
||||
|
||||
template = ViewPageTemplateFile('base.pt')
|
||||
|
||||
def __init__(self, context, request, name=None):
|
||||
self.context = self.__parent__ = context
|
||||
self.request = request
|
||||
if name is not None:
|
||||
self.name = name
|
||||
|
||||
def update(self):
|
||||
return True
|
||||
|
||||
def __call__(self):
|
||||
return self.template(self)
|
||||
|
||||
|
||||
class LayoutView(BaseView):
|
||||
|
||||
name = 'base'
|
||||
|
||||
@Lazy
|
||||
def renderer(self):
|
||||
return self.context.renderer
|
||||
|
||||
@Lazy
|
||||
def layouts(self):
|
||||
return ViewLayouts(self)
|
||||
|
||||
@Lazy
|
||||
def resources(self):
|
||||
return ViewResources(self)
|
||||
|
||||
def getRegion(self, key):
|
||||
return regions['.'.join((self.name, key))]
|
||||
|
||||
|
||||
class Page(LayoutView):
|
||||
|
||||
name = 'page'
|
||||
|
||||
#@Lazy
|
||||
def body(self):
|
||||
return self.layouts['body'][0]()
|
||||
|
||||
|
||||
class ViewLayouts(object):
|
||||
|
||||
def __init__(self, view):
|
||||
self.view = view
|
||||
|
||||
def __getitem__(self, key):
|
||||
view = self.view
|
||||
region = view.getRegion(key)
|
||||
return [LayoutView(layout, view.request, name=key)
|
||||
for layout in region.layouts]
|
||||
|
||||
|
||||
class ViewResources(object):
|
||||
|
||||
def __init__(self, view):
|
||||
self.view = view
|
||||
|
||||
def __getitem__(self, key):
|
||||
return []
|
|
@ -1,4 +1,4 @@
|
|||
#
|
||||
|
||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -28,7 +28,7 @@ from zope import schema
|
|||
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
|
||||
|
||||
from cybertools.composer.interfaces import ITemplate, IComponent
|
||||
from cybertools.composer.interfaces import IInstance as IBaseInstance
|
||||
from cybertools.composer.interfaces import IInstance
|
||||
|
||||
_ = MessageFactory('cybertools.composer')
|
||||
|
||||
|
@ -37,7 +37,7 @@ class ILayout(ITemplate):
|
|||
""" Represents an ordered sequence of layout elements.
|
||||
"""
|
||||
|
||||
name = schema.ASCII(
|
||||
name = schema.ASCIILine(
|
||||
title=_(u'Layout name'),
|
||||
description=_(u'The internal name of the layout.'),
|
||||
required=True,)
|
||||
|
@ -49,13 +49,20 @@ class ILayout(ITemplate):
|
|||
title=_(u'Description'),
|
||||
description=_(u'A medium-length description.'),
|
||||
required=False,)
|
||||
category = schema.ASCIILine(
|
||||
title=_(u'Layout category'),
|
||||
description=_(u'The name of a layout category this layout '
|
||||
u'belongs to.'),
|
||||
required=False,)
|
||||
|
||||
renderer = Attribute(u'An object responsible for rendering the layout.')
|
||||
|
||||
|
||||
class ILayoutComponent(IComponent):
|
||||
""" May be used for data entry or display.
|
||||
"""
|
||||
|
||||
name = schema.ASCII(
|
||||
name = schema.ASCIILine(
|
||||
title=_(u'Component name'),
|
||||
description=_(u'The internal name of the component'),
|
||||
required=True,)
|
||||
|
@ -73,10 +80,29 @@ class ILayoutComponent(IComponent):
|
|||
u'or a listing, ...')
|
||||
|
||||
|
||||
class ILayoutInstance(IBaseInstance):
|
||||
class ILayoutInstance(IInstance):
|
||||
""" An instance adapter for an arbitrary client object that associates
|
||||
it with a layout.
|
||||
"""
|
||||
|
||||
renderer = Attribute(u'An object responsible for rendering the layout.')
|
||||
|
||||
componentAttributes = Attribute(u'A mapping``{componentName: value, ...}`` '
|
||||
u'specifying the parameter values entered for the components.')
|
||||
u'specifying the parameter values entered for the components. '
|
||||
u'If a component is a layout the value is a corresponding '
|
||||
u'layout instance.')
|
||||
|
||||
|
||||
class IRegion(Interface):
|
||||
""" A part of a layout "canvas" that may be filled with layout objects.
|
||||
"""
|
||||
|
||||
allowedLayoutCategories = schema.List(
|
||||
title=_(u'Allowed layout categories'),
|
||||
description=_(u'A collection of names of layout categories '
|
||||
u'to which layouts may belong that may be placed '
|
||||
u'in this region'),
|
||||
value_type=schema.ASCIILine(),
|
||||
required=False,)
|
||||
|
||||
layouts = Attribute(u'The layout instances currently assigned to this region.')
|
||||
|
|
41
composer/layout/region.py
Normal file
41
composer/layout/region.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# Copyright (c) 2008 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
|
||||
#
|
||||
|
||||
"""
|
||||
Region class(es) + default regions registry.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.interface import implements
|
||||
|
||||
from cybertools.composer.layout.interfaces import IRegion
|
||||
|
||||
|
||||
class Region(object):
|
||||
|
||||
implements(IRegion)
|
||||
|
||||
allowedLayoutCategories = None
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.layouts = []
|
||||
|
||||
|
||||
regions = {}
|
Loading…
Add table
Reference in a new issue