From 3c3d635493648fc57de3a5081cd8cc20da56be73 Mon Sep 17 00:00:00 2001 From: helmutm Date: Thu, 31 Jul 2008 11:18:28 +0000 Subject: [PATCH] work in progress: layout management git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2783 fd906abe-77d9-0310-91a1-e0d9ade77398 --- composer/interfaces.py | 4 +- composer/layout/README.txt | 38 ++++++++- composer/layout/base.py | 31 ++++++- composer/layout/browser/__init__.py | 3 + composer/layout/browser/base.pt | 1 + composer/layout/browser/layout.py | 37 +++++++++ composer/layout/browser/liquid/__init__.py | 3 + composer/layout/browser/liquid/body.pt | 37 +++++++++ composer/layout/browser/main.pt | 22 +++++ composer/layout/browser/standard.pt | 3 + composer/layout/browser/view.py | 97 ++++++++++++++++++++++ composer/layout/interfaces.py | 38 +++++++-- composer/layout/region.py | 41 +++++++++ 13 files changed, 345 insertions(+), 10 deletions(-) create mode 100644 composer/layout/browser/__init__.py create mode 100644 composer/layout/browser/base.pt create mode 100644 composer/layout/browser/layout.py create mode 100644 composer/layout/browser/liquid/__init__.py create mode 100644 composer/layout/browser/liquid/body.pt create mode 100644 composer/layout/browser/main.pt create mode 100644 composer/layout/browser/standard.pt create mode 100644 composer/layout/browser/view.py create mode 100644 composer/layout/region.py diff --git a/composer/interfaces.py b/composer/interfaces.py index b3297eb..e3a7546 100644 --- a/composer/interfaces.py +++ b/composer/interfaces.py @@ -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 diff --git a/composer/layout/README.txt b/composer/layout/README.txt index 5a15908..ce998f7 100644 --- a/composer/layout/README.txt +++ b/composer/layout/README.txt @@ -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'......... diff --git a/composer/layout/base.py b/composer/layout/base.py index c664bd5..f0d4ca4 100644 --- a/composer/layout/base.py +++ b/composer/layout/base.py @@ -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 [] diff --git a/composer/layout/browser/__init__.py b/composer/layout/browser/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/composer/layout/browser/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/composer/layout/browser/base.pt b/composer/layout/browser/base.pt new file mode 100644 index 0000000..5924365 --- /dev/null +++ b/composer/layout/browser/base.pt @@ -0,0 +1 @@ + diff --git a/composer/layout/browser/layout.py b/composer/layout/browser/layout.py new file mode 100644 index 0000000..fc614f7 --- /dev/null +++ b/composer/layout/browser/layout.py @@ -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'] + diff --git a/composer/layout/browser/liquid/__init__.py b/composer/layout/browser/liquid/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/composer/layout/browser/liquid/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/composer/layout/browser/liquid/body.pt b/composer/layout/browser/liquid/body.pt new file mode 100644 index 0000000..de854d7 --- /dev/null +++ b/composer/layout/browser/liquid/body.pt @@ -0,0 +1,37 @@ + + + + + + + diff --git a/composer/layout/browser/main.pt b/composer/layout/browser/main.pt new file mode 100644 index 0000000..7159ef9 --- /dev/null +++ b/composer/layout/browser/main.pt @@ -0,0 +1,22 @@ + + + + + + Powered by Zope 3 + + + + + + + + + + + + + + diff --git a/composer/layout/browser/standard.pt b/composer/layout/browser/standard.pt new file mode 100644 index 0000000..5497492 --- /dev/null +++ b/composer/layout/browser/standard.pt @@ -0,0 +1,3 @@ +
+ Some footer text. +
diff --git a/composer/layout/browser/view.py b/composer/layout/browser/view.py new file mode 100644 index 0000000..d2c1d3a --- /dev/null +++ b/composer/layout/browser/view.py @@ -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 [] diff --git a/composer/layout/interfaces.py b/composer/layout/interfaces.py index baebe2f..3d96c80 100644 --- a/composer/layout/interfaces.py +++ b/composer/layout/interfaces.py @@ -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.') diff --git a/composer/layout/region.py b/composer/layout/region.py new file mode 100644 index 0000000..0fff39b --- /dev/null +++ b/composer/layout/region.py @@ -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 = {}