Author: jmorliaguet
Date: Thu Apr 13 15:35:35 2006
New Revision: 2832


- doc update

Modified: cpsskins/branches/jmo-perspectives/doc/portlet-rendering.txt
--- cpsskins/branches/jmo-perspectives/doc/portlet-rendering.txt        
+++ cpsskins/branches/jmo-perspectives/doc/portlet-rendering.txt        Thu Apr 
13 15:35:35 2006
@@ -1,6 +1,9 @@
+This document describes how portlets are rendered by the rendering engine.
 We first set up a test environment:
     >>> from pprint import pprint
@@ -10,73 +13,137 @@
     >>> from zope.publisher.browser import TestRequest
     >>> from zope.publisher.interfaces import IRequest
     >>> request = TestRequest()
+    >>> root = getRootFolder()
-Portlets use a context info structure to transmit data further down in the
-rendering chain. This structure is created by the page renderer but since
+Portlets use a *context info* structure to transmit data through the
+rendering chain. This structure is created by the page renderer itself for
+every object that needs to be rendered (such as portlets) but since
 there is no page renderer in this example, we create a fake info structure:
     >>> from cpsskins.browser.rendering.context import ContextInfo
     >>> info = ContextInfo({'data': None, 'metadata': None})
-    >>> info.globals = ContextInfo({'request': request})
+    >>> info.globals = ContextInfo({'request': request, 'location': root})
+Portlets are always the first elements in the rendering chain. For that matter
+they are *content providers* with regard to the rendering engine.
-Portlets are the first elements in the rendering chain, they are content
-providers. They can provide both unstructured data (HTML markup) and
-structured data (data structures implementing specific data schemas).
+They can provide both *unstructured content* (e.g. HTML markup, plain text) and
+*structured content* (i.e. data structures implementing specific data schemas).
-The dummy portlet is an example implementation of a portlet which provides
+Unstructured content
+Unstructured content consists of unicode strings (HTML markup, plain text)
+The Dummy Portlet is an example implementation of a portlet which provides
 HTML markup:
     >>> from cpsskins.standard.portlets.dummy.portlet import Dummy \
     ...                                               as DummyPortlet
     >>> portlet = DummyPortlet(title=u'Example portlet',
-    ...                        text=u'Dummy text.')
+    ...                        text=u'<span>Dummy text.</span>')
-To get HTML markup from the portlet we pass the info structure to it:
+To get the HTML output from it, we simply call the portlet by passing the info
+structure as a parameter:
     >>> portlet(info)
-    u'Dummy text.'
+    u'<span>Dummy text.</span>'
-the portlet can also modify the info structure that it receives, however in
-the case of the Dummy portlet the info structure is left unchanged:
+In the case of the Dummy Portlet the data structure is left unchanged:
     >>>, info.metadata = None, None
+It is the job of the rendering engine to call the portlet, but since we are
+detailing every step, we call the portlet directly to see what it does.
-Rendering steps
-A portlet is rendered in three steps:
-1) a portlet has some data to display, called the 'Display Data'.
-   it corresponds to the model in the Model-View-Controller paradigm.
+Structured content
-   the Display Data can be for instance:
+Structured content consists of data structures that implement specific
-   - a list of menu items
+The Breadcrumbs Portlet provides structured data in the form of menu items.
     >>> from cpsskins.standard.ds.menuitems import MenuItems
     >>> from cpsskins.standard.ds.menuitem import MenuItem
-    >>> item = MenuItem(title=u'Item title', url=u'@@url.html', icon=u'')
+We instanciate a Breadcrumbs Portlet:
+    >>> from cpsskins.standard.portlets.breadcrumbs.portlet import Breadcrumbs
+    >>> portlet = Breadcrumbs()
+The portlet returns no markup:
+    >>> portlet(info) is None
+    True
+but the data structure got updated:
+    >>>
+    <Items>
+    >>> isinstance(, MenuItems)
+    True
+let us see what is inside the MenuItems structure:
+    >>> pprint(
+    [<Menu item ''>]
+    >>> pprint([item() for item in])
+    [{'description': u'',
+      'icon': u'',
+      'selected': False,
+      'title': '',
+      'url': ''}]
+as we see, the Breadcrumbs Portlet provides a list of menu items such as:
+    >>> item = MenuItem(title=u'Item 1', url=u'@@url.html', icon=u'')
     >>> pprint(item())
     {'description': u'',
      'icon': u'',
      'selected': False,
-     'title': u'Item title',
+     'title': u'Item 1',
      'url': u'@@url.html'}
     >>> content = MenuItems([item])
     >>> content()
-    [<Menu item 'Item title'>]
+    [<Menu item 'Item 1'>]
+Structured content cannot be rendered directly in a browser.
+We will see how structured data gets tranformed into HTML with help of
+The 'metadata' present in the context info structure contains data *about* the
+portlet. It implements the IMetaData schema which specifies:
+  - the portlet's title
+  - the portlet's description
+  - a URL associated with the portlet
-   - ...
+None of the information above needs to be displayed on the page, however it
+can be used to provide information on the portlet.
-2) the data is then displayed in a Display Element (here: a box).
+Displaying portlets
+The data provided by portlets is displayed in Display Elements (e.g. a Box),
+which represents the fragment of the page in which the portlet will appear.
     >>> from zope.interface.verify import verifyClass
     >>> from import Box
@@ -84,44 +151,48 @@
     >>> verifyClass(IDisplay, Box)
-    the box and its content is formatted with a *widget*:
+A same portlet can be displayed in different Display Elements depending on the
+The Box and its content is formatted with a *widget* (a Format Element):
     >>> from cpsskins.standard.formats.widget import Widget
     >>> from cpsskins.elements.interfaces import IFormat
     >>> verifyClass(IFormat, Widget)
-    >>> widget = Widget([u'standard.plain_html'])
+The job of the widget is to convert structured data into HTML, or to format the
+HTML markup that it received.
-   A list of widget names can be specified, i.e. if the first type of widget
-   cannot render the data structure, the next widget will be used, etc. until
-   a suitable widget is found.
+A list of widget names can be specified, i.e. if the first widget cannot
+render the data, the next widget will be used, etc. until a suitable widget
+is found.
     >>> widget = Widget([u'standard.special_widget', u'standard.plain_html'])
-   Otherwise a basic widget view registered by default for the data type will
-   be used.
+As a last resort the *basic widget view* registered by default for the given
+data type will be used. It will provide minimal formatting.
-3) The portlet is finally rendered with a widget filter.
+Note that the widget format describe here does not directly produce any HTML
+output it only specifies which widget view to use. Also it is the object that
+the user can interact with.
+The portlet is rendered with a widget view (called a 'filter' in the rendering
+chain). The widget filter attempts to find a named view for the data
+structure, by looking up the different names specified by the widget format.
-   It corresponds to the 'view' in the MVC paradigm.
-   the widget filter attempts to find a named view for the data structure or
-   it falls back to the basic widget view registered for the data structure.
+We create a fake filter view in order to test the various widgets:
     >>> from cpsskins.standard.filters.widget import WidgetFilter
     >>> from cpsskins.standard.formats.widget import IWidget
     >>> from cpsskins.browser.rendering.interfaces import IFilterView
     >>> ztapi.provideAdapter(IWidget, IFilterView, WidgetFilter)
-    >>> rendered = u'<h1>Test of HTML</h1>'
     >>> def test_render(widget, rendered, info):
     ...    widget_filter = IFilterView(widget)
     ...    return widget_filter(rendered, info)
+    >>> rendered = u'<h1>Test of HTML</h1>'
     >>> test_render(widget, rendered, info)
     u'<div><h1>Test of HTML</h1></div>'
@@ -185,29 +256,29 @@
     >>> test_render(widget, rendered, info)
     u'<div style="overflow-x:scroll;"><h1>Test of HTML</h1></div>'
-    c) table frame
+    c) pageblock frame
-    >>> widget = Widget([u'standard.table_frame'])
+    >>> widget = Widget([u'standard.pageblock_frame'])
     >>> test_render(widget, rendered, info)
     u'<table summary=""><tr><h1>Test of HTML</h1></tr></table>'
-    d) table cell
+    d) cell frame
-    >>> widget = Widget([u'standard.table_cell'])
+    >>> widget = Widget([u'standard.cell_frame'])
     >>> test_render(widget, rendered, info)
     u'<td style="vertical-align:top;"><h1>Test of HTML</h1></td>'
-    e) div frame (tableless renderering)
+    e) pageblock frame (tableless rendering)
-    >>> widget = Widget([u'standard.div_frame'])
+    >>> widget = Widget([u'tableless-standard.pageblock_frame'])
     >>> test_render(widget, rendered, info)
     u'<div><h1>Test of HTML</h1><br style="clear:left"/></div><div 
-    f) div cell (tableless rendering)
+    f) cell frame (tableless rendering)
-    >>> widget = Widget([u'standard.div_cell'])
+    >>> widget = Widget([u'tableless-standard.cell_frame'])
     >>> test_render(widget, rendered, info)
-    u'<div style="float:left;overflow-x:hidden"><h1>Test of HTML</h1></div>'
+    u'<div style="float:left;overflow:hidden"><h1>Test of HTML</h1></div>'
 Widgets displaying images
@@ -222,4 +293,4 @@
     >>> test_render(widget, rendered, info)
     u'<img src="/some/image.png" alt="" style="border: none" />'
+[to finish]

Reply via email to