Author: jmorliaguet
Date: Sun Oct 23 17:34:42 2005
New Revision: 28553

Modified:
   z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py
   z3lab/cpsskins/branches/jmo-perspectives/browser/elements/configure.zcml
   z3lab/cpsskins/branches/jmo-perspectives/browser/negociation/__init__.py
   z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/engine.py
   z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/interfaces.py
   z3lab/cpsskins/branches/jmo-perspectives/browser/skin/template.pt
   
z3lab/cpsskins/branches/jmo-perspectives/configuration/renderers/metaconfigure.py
Log:

- refactoring of the rendering engine:

  - added a IViewer adapter for elements where we:
    - create global context information
    - render the element.

    TODO: create a DOM tree structure and update the nodes before doing the
          rendering

  - optimization: global context info variables are moved to IViewer

  - IRenderer creates a local copy of the context info data structure



Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py      
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py      
Sun Oct 23 17:34:42 2005
@@ -39,7 +39,7 @@
 from cpsskins.browser.elements.interfaces import INodeAdding, INodeRemoving
 from cpsskins.browser.elements.interfaces import INodeMoving, INodeOrdering
 from cpsskins.browser.elements.interfaces import INodeDuplicating
-from cpsskins.browser.rendering.interfaces import IRenderer
+from cpsskins.browser.rendering.interfaces import IViewer
 from cpsskins.thememanager import getThemeManager
 
 class Authoring(BrowserView):
@@ -54,13 +54,8 @@
     def draw(self, **kw):
         """Draws a the canvas element in edit mode
         """
-        context = self.context
-        request = self.request
-        tmutil = getThemeManager()
-
-        renderer = queryMultiAdapter((context, request), IRenderer, '', None)
-        if renderer is not None:
-            return renderer(tmutil=tmutil, **kw)
+        viewer = getMultiAdapter((self.context, self.request), IViewer)
+        return viewer(**kw)
 
     def getCanvasMode(self):
         """Get the canvas view mode
@@ -83,19 +78,22 @@
             session['canvas_mode'] = mode
         self._redirect()
 
-    def setPerspective(self, perspective=None):
+    def setPerspective(self, perspective=''):
         """Set the perspective
         """
         pkg_id = 'cpsskins'
         session = ISession(self.request)[pkg_id]
-        tmutil = getThemeManager()
-        theme = tmutil.getEffectiveTheme(self.context)
-        perspective = theme.getPerspectiveById(perspective)
 
-        # remove the security proxy before storing the object in the session
-        if perspective is not None:
+        if perspective == '':
+            del session['perspective']
+        else:
+            tmutil = getThemeManager()
+            theme = tmutil.getEffectiveTheme(self.context)
+            perspective = theme.getPerspectiveById(perspective)
+
+            # remove the security proxy before storing the object in the 
session
             perspective = removeSecurityProxy(perspective)
-        session['perspective'] = perspective
+            session['perspective'] = perspective
         self._redirect()
 
     def clonePresentation(self, perspective=None):
@@ -195,9 +193,8 @@
         request = self.request
 
         tmutil = getThemeManager()
-        renderer = getMultiAdapter((element, request), IRenderer)
-        return renderer(tmutil=tmutil,
-            location=element, engine=engine, canvas_mode=canvas_mode)
+        viewer = getMultiAdapter((element, request), IViewer)
+        return viewer(location=element, engine=engine, canvas_mode=canvas_mode)
 
     def editElement(self, id, name, value):
         """Edit the element: assign a value to an attribute (name).

Modified: 
z3lab/cpsskins/branches/jmo-perspectives/browser/elements/configure.zcml
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/elements/configure.zcml    
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/elements/configure.zcml    
Sun Oct 23 17:34:42 2005
@@ -4,6 +4,15 @@
     i18n_domain="cpsskins"
     >
 
+  <!-- Element viewer -->
+
+  <adapter
+      for="cpsskins.elements.interfaces.IElement
+           zope.publisher.interfaces.IRequest"
+      factory="cpsskins.browser.rendering.engine.Viewer"
+      provides="cpsskins.browser.rendering.interfaces.IViewer"
+  />
+
   <!-- Theme -->
 
   <adapter

Modified: 
z3lab/cpsskins/branches/jmo-perspectives/browser/negociation/__init__.py
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/negociation/__init__.py    
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/negociation/__init__.py    
Sun Oct 23 17:34:42 2005
@@ -23,7 +23,7 @@
 from zope.component import getUtilitiesFor
 from zope.interface import directlyProvidedBy
 
-from cpsskins.browser.rendering.interfaces import IRenderer
+from cpsskins.browser.rendering.interfaces import IViewer
 from cpsskins.thememanager import getThemeManager
 
 class NegociationView(BrowserView):
@@ -32,14 +32,12 @@
     def getDefaultThemeView(self):
         tmutil = getThemeManager()
         theme = tmutil.getDefaultTheme()
-        theme_renderer = zapi.getMultiAdapter((theme, self.request), IRenderer)
-        return theme_renderer
+        return zapi.getMultiAdapter((theme, self.request), IViewer)
 
     def getDefaultPageView(self):
         tmutil = getThemeManager()
         page = tmutil.getDefaultPage()
-        page_renderer = zapi.getMultiAdapter((page, self.request), IRenderer)
-        return page_renderer
+        return zapi.getMultiAdapter((page, self.request), IViewer)
 
     def getDefaultThemeUrl(self):
         tmutil = getThemeManager()

Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/engine.py
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/engine.py        
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/engine.py        
Sun Oct 23 17:34:42 2005
@@ -17,9 +17,10 @@
 """
 __docformat__ = "reStructuredText"
 
+from zope.app.publisher.browser import BrowserView
 from zope.app.traversing.api import getParent
 from zope.app.zapi import getMultiAdapter, queryMultiAdapter
-from zope.component import adapts, getUtility, adaptedBy
+from zope.component import adapts, getUtility
 from zope.configuration.exceptions import ConfigurationError
 from zope.interface import implements
 from zope.publisher.interfaces import IRequest
@@ -31,7 +32,7 @@
 from cpsskins.relations.interfaces import IPredicate
 from cpsskins.storage.interfaces import IRelationStorage
 from cpsskins.thememanager import getThemeManager
-from interfaces import IRenderer, IFilter, IContextInfo
+from interfaces import IViewer, IRenderer, IFilter, IContextInfo
 
 import logging
 
@@ -73,11 +74,18 @@
     >>> c.contexts
     {'display': 'some other display', 'element': 'some element'}
 
+    >>> c.items()
+
     """
     implements(IContextInfo)
 
-    def __init__(self, contexts):
-        self.contexts = contexts
+    def __init__(self, contexts={}):
+        # to avoid creating a reference, 'contexts' is not set directly.
+        self.contexts = {}
+        self.update(contexts)
+
+    def __getitem__(self, name):
+        return getattr(self, name)
 
     def __setitem__(self, name, value):
         self.contexts[name] = value
@@ -89,24 +97,79 @@
             raise AttributeError(
                 "No such variable '%s' in this context" % name)
 
+    def items(self):
+        return self.contexts.items()
+
     def update(self, map):
         for k, v in map.items():
             self[k] = v
 
+    def __iter__(self):
+        return iter(self.contexts)
+
     def __repr__(self):
         return '<Renderer context info at %s>' % hex(id(self))
 
+class Viewer(BrowserView):
+    """An element viewer provides a view of an element in two steps:
+
+    a) by creating the tree structure
+
+    b) by updating the entire tree
+
+    c) by rendering the subtree starting from the element's node
+
+    """
+    adapts(IElement, IRequest)
+    implements(IViewer)
+
+    def __init__(self, element, request):
+        self.element = element
+        self.request = request
+
+        theme = getThemeManager().getThemeInContext(element)
+        relations = theme.getStorage(IRelationStorage)
+        perspective = getMultiAdapter((element, request),
+                                       INegociation).getPerspective()
+
+        self.info = ContextInfo({
+            'request': self.request,
+            'relations': relations,
+            'perspective': perspective,
+            })
+
+    def __call__(self, **kw):
+        element = self.element
+        info = self.info
+
+        # update global context info variables pass as keyword parameters
+        info.update({
+            'view': kw.get('view'),
+            'location': kw.get('location'),
+            'template': kw.get('template'),
+            'engine': kw.get('engine', 'default'),
+            })
+
+        # TODO create the tree
+
+        # TODO update the tree
+
+        # render the tree
+        return getMultiAdapter((element, info), IRenderer)(**kw)
+
 class Renderer(object):
     """A renderer is a collection of filters. It provides some rendering
     for elements.
     """
-    adapts(IElement, IRequest)
+    adapts(IElement, IContextInfo)
     implements(IRenderer)
 
-    def __init__(self, context, request):
-        element = context
-        perspective = getMultiAdapter((context, request),
-                                       INegociation).getPerspective()
+    def __init__(self, element, info):
+        self.element = element
+        # create a copy of the global context info structure
+        self.info = ContextInfo(info)
+
+        perspective = info.perspective
 
         displayable = IDisplayable(element)
         display = displayable.getEffectiveDisplay(perspective)
@@ -117,26 +180,68 @@
         if display is None and ISlot.providedBy(parent):
             display = IDisplayable(parent).getEffectiveDisplay(perspective)
 
-        self.info = ContextInfo(
-            {'request': request,
-             'element': element,
+        # set local context info variables
+        self.info.update(
+            {'element': element,
              'display': display,
              'actual_display': actual_display,
-             'perspective': perspective,
              'data': None,
              'metadata': None,
             })
 
-    def _getFilters(self, iface, engine, theme):
+    def __call__(self, **kw):
+        """Do the actual rendering by applying all filters.
+        """
+        info = self.info
+        element, request = info.element, info.request
+
+        rendered = []
+        if ILeaf.providedBy(element):
+            # do the actual rendering
+            display_data = getMultiAdapter((element, info), IDisplayData)
+            if callable(display_data):
+                rendered.append(display_data(**kw))
+        else:
+            for node in element.getChildNodes(info=info):
+                renderer = getMultiAdapter((node, info), IRenderer)
+                rendered.append(renderer(**kw))
+        rendered = ''.join(rendered)
+
+        engine = info.engine
+
+        # look for renderers associated to the element's content type
+        iface = element.getContentType()
+        if (iface, engine) not in renderer_registry:
+            # fall back to the element type
+            iface = element.getElementType()
+
+        if (iface, engine) not in renderer_registry:
+            logger.log(INFO,
+                "The element '%s' cannot be rendered by the '%s' engine."
+                % (repr(element), engine)
+                )
+            return rendered
+
+        # apply all filters
+        for f in self._getFilters(iface):
+            rendered = f(rendered, info, **kw)
+
+        # Filter output
+        return rendered
+
+    def _getFilters(self, iface):
         """Get the list of filters
         """
         info = self.info
-        element, display, request = info.element, info.display, info.request
+        element, request = info.element, info.request
+
+        display = info.display
 
         if display is None:
             return []
 
-        relations = theme.getStorage(IRelationStorage)
+        engine = info.engine
+        relations = info.relations
 
         filters = []
         for filter_name in renderer_registry.get((iface, engine), []):
@@ -184,59 +289,3 @@
             filters.append(filter)
         return filters
 
-    def __call__(self, rendered='', **kw):
-        """Do the actual rendering by applying all filters.
-        """
-        info = self.info
-
-        # set global parameters
-        info.update({
-            'view': kw.get('view'),
-            'location': kw.get('location'),
-            'template': kw.get('template'),
-            'engine': kw.get('engine', 'default'),
-            })
-
-        # these have been set in __init__()
-        element, request = (info.element, info.request)
-
-        # TODO this can be cached.
-        theme = getThemeManager().getThemeInContext(element)
-
-        if ILeaf.providedBy(element):
-            # update leaf elements before rendering them
-            update_data = queryMultiAdapter((element, info), IUpdateData)
-            if update_data is not None:
-                update_data(**kw)
-            # do the actual rendering
-            display_data = getMultiAdapter((element, info), IDisplayData)
-            if callable(display_data):
-                rendered = display_data(**kw)
-        else:
-            rendered = []
-            for node in element.getChildNodes(info=info):
-                renderer = getMultiAdapter((node, request), IRenderer)
-                rendered.append(renderer(**kw))
-            rendered = ''.join(rendered)
-
-        engine = info.engine
-
-        # look for renderers associated to the element's content type
-        iface = element.getContentType()
-        if (iface, engine) not in renderer_registry:
-            # fall back to the element type
-            iface = element.getElementType()
-
-        if (iface, engine) not in renderer_registry:
-            logger.log(INFO,
-                "The element '%s' cannot be rendered by the '%s' engine."
-                % (repr(element), engine)
-                )
-            return rendered
-
-        # apply all filters
-        for f in self._getFilters(iface, engine, theme):
-            rendered = f(rendered, info, **kw)
-
-        # Filter output
-        return rendered

Modified: 
z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/interfaces.py
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/interfaces.py    
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/rendering/interfaces.py    
Sun Oct 23 17:34:42 2005
@@ -21,6 +21,9 @@
 
 # Rendering
 
+class IViewer(Interface):
+    """Elements that can be viewed should implement this."""
+
 class IRenderer(Interface):
     """Renderers should implement this"""
 
@@ -30,6 +33,9 @@
 class IContextInfo(Interface):
     """Some information about the element being rendered"""
 
+    def items():
+        """Return the context's items"""
+
     def update(map):
         """Update map entries."""
 

Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/skin/template.pt
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/browser/skin/template.pt   
(original)
+++ z3lab/cpsskins/branches/jmo-perspectives/browser/skin/template.pt   Sun Oct 
23 17:34:42 2005
@@ -4,8 +4,7 @@
         "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"
-  tal:define="tmutil context/@@getThemeManager;
-              pageview context/@@getDefaultPageView;
+  tal:define="pageview context/@@getDefaultPageView;
               engine context/@@getEffectiveEngine">
     <head>
       <title metal:define-slot="title">CPSSkins for Zope3</title>
@@ -16,7 +15,6 @@
       tal:content="string:@import url(./renderCSS);"></style>
     </head>
     <tal:block content="structure python:pageview(
-      tmutil=tmutil,
       location=context,
       view=view,
       template=template,

Modified: 
z3lab/cpsskins/branches/jmo-perspectives/configuration/renderers/metaconfigure.py
==============================================================================
--- 
z3lab/cpsskins/branches/jmo-perspectives/configuration/renderers/metaconfigure.py
   (original)
+++ 
z3lab/cpsskins/branches/jmo-perspectives/configuration/renderers/metaconfigure.py
   Sun Oct 23 17:34:42 2005
@@ -23,6 +23,7 @@
 from zope.i18nmessageid import MessageFactory
 from zope.publisher.interfaces.browser import IBrowserRequest
 
+from cpsskins.interfaces import IContextInfo
 from cpsskins.configuration.interfaces import IRegistry
 from cpsskins.browser.rendering.engine import Renderer as RenderingEngine
 from cpsskins.browser.rendering.interfaces import IRenderer
@@ -67,7 +68,7 @@
         adapter(_context=_context,
                 factory=(RenderingEngine,),
                 provides=IRenderer,
-                for_=(iface, IBrowserRequest),
+                for_=(iface, IContextInfo),
                )
         registered_adapters.append(iface)
 
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to