Author: jmorliaguet
Date: Thu Jun 15 15:47:51 2006
New Revision: 3416

Added:
   cpsskins/branches/paris-sprint-2006/doc/portlets.txt   (contents, props 
changed)
Removed:
   cpsskins/branches/paris-sprint-2006/doc/architecture.txt
   cpsskins/branches/paris-sprint-2006/doc/canvas-rendering.txt
   cpsskins/branches/paris-sprint-2006/doc/draft-rendering-pipelines.txt
   cpsskins/branches/paris-sprint-2006/doc/draft-styles.txt
   cpsskins/branches/paris-sprint-2006/doc/layout-model.png
   cpsskins/branches/paris-sprint-2006/doc/local-portlets.txt
   cpsskins/branches/paris-sprint-2006/doc/mockup-style-editor.png
   cpsskins/branches/paris-sprint-2006/doc/portlet-modes.txt
   cpsskins/branches/paris-sprint-2006/doc/portlet-ordering.txt
   cpsskins/branches/paris-sprint-2006/doc/portlet-rendering.png
   cpsskins/branches/paris-sprint-2006/doc/portlet-rendering.txt
   cpsskins/branches/paris-sprint-2006/doc/setup.txt
   cpsskins/branches/paris-sprint-2006/doc/site-designer.txt
   cpsskins/branches/paris-sprint-2006/doc/theme-layout-model.png
   cpsskins/branches/paris-sprint-2006/doc/ui-portlet-edit-form.png
Modified:
   cpsskins/branches/paris-sprint-2006/doc/theme-structure.txt
   cpsskins/branches/paris-sprint-2006/ftests/test_portlet.py
   cpsskins/branches/paris-sprint-2006/tests/test_renderers.py

Log:

- removed old cruft (drafts, outdated documentation, mockups )

- moved all portlet documentation and doctests to doc/portlets.txt



Added: cpsskins/branches/paris-sprint-2006/doc/portlets.txt
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/doc/portlets.txt        Thu Jun 15 
15:47:51 2006
@@ -0,0 +1,475 @@
+=================
+PORTLET RENDERING
+=================
+
+This document describes how portlets are rendered by the rendering engine.
+
+We first set up a test environment:
+
+    >>> from pprint import pprint
+    >>> from zope.app.testing import ztapi
+    >>> from zope.component import getMultiAdapter
+
+    >>> 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 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, 'location': root})
+
+
+Portlets
+========
+
+Portlets are always the first elements in the rendering chain. For that matter
+they are *content providers* with regard to the rendering engine.
+
+They can provide both *unstructured content* (e.g. HTML markup, plain text) and
+*structured content* (i.e. data structures implementing specific data schemas).
+
+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'<span>Dummy text.</span>')
+
+
+To get the HTML output from it, we simply call the portlet by passing the info
+structure as a parameter:
+
+    >>> portlet(info)
+    u'<span>Dummy text.</span>'
+
+In the case of the Dummy Portlet the data structure is left unchanged:
+
+    >>> info.data, 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.
+
+
+Structured content
+------------------
+
+Structured content consists of data structures that implement specific
+schemas.
+
+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
+
+Let us 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:
+
+    >>> info.data
+    <Items>
+
+    >>> isinstance(info.data, MenuItems)
+    True
+
+let us see what the MenuItems structure now contains:
+
+    >>> pprint(info.data())
+    [<Menu item ''>]
+
+    >>> pprint([item() for item in info.data])
+    [{'description': u'',
+      'icon': u'',
+      'selected': False,
+      'title': '',
+      'url': 'http://127.0.0.1'}]
+
+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 1',
+     'url': u'@@url.html'}
+
+    >>> content = MenuItems([item])
+    >>> content()
+    [<Menu item 'Item 1'>]
+
+
+But structured content cannot be rendered directly in a browser.
+
+We will see how structured data gets tranformed into HTML with help of
+*widgets*.
+
+
+Metadata
+--------
+
+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.
+
+
+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 cpsskins.standard.displays.box import Box
+    >>> from cpsskins.elements.interfaces import IDisplay
+    >>> verifyClass(IDisplay, Box)
+    True
+
+A same portlet can be displayed in different Display Elements depending on the
+context.
+
+Provided that the portlet is associated with a given Box, the Box is in turn
+associated with various Format Element (style, effects, ...) whose
+responsibility in the rendering chain is to format elements.
+
+The type of Format that interests us here is the *widget* Format.
+
+    >>> from cpsskins.standard.formats.widget import Widget
+    >>> from cpsskins.elements.interfaces import IFormat
+    >>> verifyClass(IFormat, Widget)
+    True
+
+The job of the widget is to convert structured data into HTML, or to format the
+HTML markup that it receives from the portlet.
+
+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'])
+
+As a last resort the *basic widget view* registered by default for the given
+data type will be used. It will provide a very minimal formatting but it will
+be able to convert the data structure into HTML.
+
+Note that the widget format described 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.
+
+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
+
+    >>> from zope.component import getGlobalSiteManager
+    >>> gsm = getGlobalSiteManager()
+    >>> gsm.registerAdapter(WidgetFilter, (IWidget,), IFilterView)
+
+    >>> def test_render(widget, rendered, info):
+    ...    widget_filter = IFilterView(widget)
+    ...    return widget_filter(rendered, info)
+
+    >>> rendered = u'<h1>Test of HTML</h1>'
+    >>> info.data = None
+
+    >>> test_render(widget, rendered, info)
+    u'<div class="standardPlainHtml"><h1>Test of HTML</h1></div>'
+
+Available widgets:
+==================
+
+Widgets displaying menu items
+-----------------------------
+
+    >>> itemA = MenuItem(title=u'Item A', url=u'@@urlA.html', icon=u'')
+    >>> itemB = MenuItem(title=u'Item B', url=u'@@urlB.html', icon=u'')
+    >>> info.data = MenuItems([itemA, itemB])
+
+    a) vertical menu
+    ----------------
+    >>> widget = Widget([u'standard.vertical_menu'])
+    >>> test_render(widget, rendered, info)
+    u'<ul class="standardVerticalMenu"><li><a href="@@urlA.html">Item 
A</a></li><li><a href="@@urlB.html">Item B</a></li></ul>'
+
+    b) horizontal tabs
+    ------------------
+    >>> widget = Widget([u'standard.horizontal_tabs'])
+    >>> test_render(widget, rendered, info)
+    u'<ul class="standardHorizontalTabs"><li><a href="@@urlA.html">Item 
A</a></li><li><a href="@@urlB.html">Item B</a></li></ul>'
+
+    c) Menu bar
+    -------------------
+    >>> widget = Widget([u'standard.menu_bar'])
+    >>> test_render(widget, rendered, info)
+    u'<div class="standardMenuBar"><a href="@@urlA.html">Item A</a><a 
href="@@urlB.html">Item B</a></div>'
+
+    d) Horizontal trail
+    -------------------
+    >>> widget = Widget([u'standard.horizontal_trail'])
+    >>> test_render(widget, rendered, info)
+    u'<div class="standardHorizontalTrail"><a href="@@urlA.html">Item 
A</a><span class="sep">&gt;</span><a href="@@urlB.html">Item B</a><span 
class="sep">&gt;</span></div>'
+
+    e) Drop-down list
+    -----------------
+    >>> widget = Widget([u'standard.dropdown_list'])
+    >>> test_render(widget, rendered, info)
+    u'<form action="@@cpsskins_redirect" method="post" 
class="standardDropdownList"><select onchange="submit()" name="url"><option 
value="./"></option><option value="@@urlA.html">Item A</option><option 
value="@@urlB.html">Item B</option></select></form>'
+
+
+Widgets displaying HTML markup
+------------------------------
+
+    >>> info.data = None
+    >>> rendered = '<h1>Test of HTML</h1>'
+
+    a) frame box
+    ------------
+    >>> from cpsskins.standard.ds.metadata import MetaData
+    >>> info.metadata = MetaData(title=u'Example frame box')
+    >>> widget = Widget([u'standard.frame_box'])
+    >>> test_render(widget, rendered, info)
+    u'<fieldset class="standardFrameBox"><legend>Example frame 
box</legend><div><h1>Test of HTML</h1></div></fieldset>'
+
+    b) horizontal scrollbar
+    -----------------------
+    >>> widget = Widget([u'standard.horizontal_scrollbar'])
+    >>> test_render(widget, rendered, info)
+    u'<div style="overflow-x:scroll;" 
class="standardHorizontalScrollbar"><h1>Test of HTML</h1></div>'
+
+    c) pageblock frame
+    ------------------
+    >>> widget = Widget([u'standard.pageblock_frame'])
+    >>> test_render(widget, rendered, info)
+    u'<table summary="" class="standardPageblockFrame"><tr><h1>Test of 
HTML</h1></tr></table>'
+
+    d) cell frame
+    -------------
+    >>> widget = Widget([u'standard.cell_frame'])
+    >>> test_render(widget, rendered, info)
+    u'<td style="vertical-align:top;" class="standardCellFrame"><h1>Test of 
HTML</h1></td>'
+
+    e) pageblock frame (tableless rendering)
+    ------------------------------------
+    >>> widget = Widget([u'tableless-standard.pageblock_frame'])
+    >>> test_render(widget, rendered, info)
+    u'<div class="tablelessStandardPageblockFrame"><h1>Test of HTML</h1><br 
style="clear:left"/></div><div style="clear:left"></div>'
+
+    f) cell frame (tableless rendering)
+    ---------------------------------
+    >>> widget = Widget([u'tableless-standard.cell_frame'])
+    >>> test_render(widget, rendered, info)
+    u'<div style="float:left;overflow:hidden" 
class="tablelessStandardCellFrame"><h1>Test of HTML</h1></div>'
+
+
+Widgets displaying images
+-------------------------
+
+    >>> from cpsskins.standard.ds.image import Image
+    >>> info.data = Image(path=u'/some/image.png')
+
+    a) image
+    --------
+    >>> widget = Widget([u'standard.image'])
+    >>> test_render(widget, rendered, info)
+    u'<img src="/some/image.png" alt="" style="border: none" 
class="standardImage" />'
+
+[to finish]
+
+
+PORTLET ORDERING
+================
+
+The portlets displayed in slots need to be ordered. The order information is
+stored in the slot's display.
+
+We set up some test environment:
+
+    >>> from cpsskins.tests.setup import makeSite
+    >>> from cpsskins.tests.setup import addThemeManager, addThemeSkeleton
+    >>> root = getRootFolder()
+    >>> tmutil = addThemeManager(root, makeSite(root))
+
+Let us create a theme with two slots ('slot_A', 'slot_B'):
+
+    >>> from cpsskins.elements.slot import Slot
+    >>> theme = addThemeSkeleton(tmutil)
+
+    >>> slot_A = Slot(slot=u'A')
+    >>> slot_B = Slot(slot=u'B')
+
+    >>> theme[u'page'][u'block'][u'cell'][u'slot_a'] = slot_A
+    >>> theme[u'page'][u'block'][u'cell'][u'slot_b'] = slot_B
+
+The slots A and B have their own display
+
+    >>> from cpsskins.elements.interfaces import IDisplayable
+    >>> from cpsskins.standard.displays.boxgroup import BoxGroup
+
+    >>> display_slot_A = IDisplayable(slot_A).getDisplay()
+    >>> display_slot_B = IDisplayable(slot_B).getDisplay()
+
+    >>> isinstance(display_slot_A, BoxGroup)
+    True
+
+    >>> isinstance(display_slot_B, BoxGroup)
+    True
+
+    >>> display_slot_A is not display_slot_B
+    True
+
+
+LOCAL PORTLETS
+==============
+
+    >>> from cpsskins.elements.slot import Slot
+    >>> from cpsskins.elements.portlet import TestPortlet as Portlet
+    >>> from cpsskins.perspectives import Perspective
+
+Local portlets are displayed in *slots*
+
+    >>> portlet = Portlet('Some portlet')
+    >>> portlet.identifier = 1
+
+Let us create a slot:
+
+    >>> slot = Slot(slot=u'Right')
+    >>> slot.identifier = 2
+
+And a perspective:
+
+    >>> perspective = Perspective('Some perspective')
+    >>> perspective.identifier = 3
+
+Let us create a relation to connect the slots, the portlet and the perspective:
+
+    >>> from cpsskins.ontology import hasPortletFromPerspective
+    >>> from cpsskins.relations import TriadicRelation as Triad
+
+    >>> relation = Triad(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slot,
+    ...     second=portlet,
+    ...     third=perspective
+    ...     )
+
+and add them to the storage:
+
+    >>> from cpsskins.storage.relations import RelationStorage
+    >>> storage = RelationStorage()
+
+    >>> storage[u'some_id'] = relation
+
+We can now find the portlets present in the slot from the given perspective:
+
+    >>> storage.getSeconds(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slot,
+    ...     third=perspective
+    ...     )
+    [Portlet('Some portlet')]
+
+The portlet will not be visible from another perspective:
+
+    >>> other_perspective = Perspective('Some other perspective')
+    >>> other_perspective.identifier = 4
+
+    >>> storage.getSeconds(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slot,
+    ...     third=other_perspective
+    ...     )
+    []
+
+We clear the storage:
+
+    >>> storage.clear()
+
+A slot has:
+
+- a unique identifier that is used internally
+
+    >>> slot.identifier
+    2
+
+- a slot name that is exposed to the user.
+
+    >>> str(slot)
+    'Right'
+
+
+If two *different* slots have the *same slot name*, they will display the same
+portlets:
+
+    >>> slotA = Slot(slot=u'Some slot')
+    >>> slotA.identifier = 5
+    >>> slotB = Slot(slot=u'Some slot')
+    >>> slotB.identifier = 6
+
+    >>> relationA = Triad(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slotA,
+    ...     second=portlet,
+    ...     third=perspective
+    ...     )
+
+    >>> relationB = Triad(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slotB,
+    ...     second=portlet,
+    ...     third=perspective
+    ...     )
+
+    >>> storage[u'A'] = relationA
+    >>> storage[u'B'] = relationB
+
+    >>> storage.getSeconds(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slotA,
+    ...     third=perspective
+    ...     )
+    [Portlet('Some portlet')]
+
+    >>> storage.getSeconds(
+    ...     predicate=hasPortletFromPerspective,
+    ...     first=slotB,
+    ...     third=perspective
+    ...     )
+    [Portlet('Some portlet')]
+
+Finally we clear the storage:
+
+    >>> storage.clear()
+
+

Modified: cpsskins/branches/paris-sprint-2006/doc/theme-structure.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/doc/theme-structure.txt (original)
+++ cpsskins/branches/paris-sprint-2006/doc/theme-structure.txt Thu Jun 15 
15:47:51 2006
@@ -1,26 +1,34 @@
 
-Theme structure
----------------
+=======================
+THEME MANAGEMENT FOLDER
+=======================
 
 ::
 
  + themes ( .../++etc++site/defaut/themes )
  |
- +----- Theme A
+ +--- Theme A
+ |  |
+ |  + page a
  |
- +----+ Theme B
-      |
-      + Pages + page a
-      |       |
-      |       + page b
-      |
-      + Displays (areas, boxes)
-      |
-      + Formats (styles, layouts,...)
-      |
-      + Portlets (global)
-      |
-      + Images (backgrounds, images, ...)
+ |
+ +--+ Theme B
+ |  |
+ |  + page a
+ |  |
+ |  + page b
+ |
+ |
+ + Portlets (local)
+ |
+ + Displays (areas, boxes, ...)
+ |
+ + Formats (styles, layouts, ...)
+ |
+ + Images (backgrounds, icons, ...)
+ |
+ + Presets
+ |
+ + Snapshots
 
 
-- images, portlets, formats and displays are shared between pages

Modified: cpsskins/branches/paris-sprint-2006/ftests/test_portlet.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/ftests/test_portlet.py  (original)
+++ cpsskins/branches/paris-sprint-2006/ftests/test_portlet.py  Thu Jun 15 
15:47:51 2006
@@ -25,9 +25,7 @@
 
 def test_suite():
     return unittest.TestSuite((
-        FunctionalDocFileSuite('../doc/local-portlets.txt', setUp=setUp),
-        FunctionalDocFileSuite('../doc/portlet-rendering.txt', setUp=setUp),
-        FunctionalDocFileSuite('../doc/portlet-ordering.txt', setUp=setUp),
+        FunctionalDocFileSuite('../doc/portlets.txt', setUp=setUp),
         ))
 
 if __name__ == '__main__':

Modified: cpsskins/branches/paris-sprint-2006/tests/test_renderers.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/tests/test_renderers.py (original)
+++ cpsskins/branches/paris-sprint-2006/tests/test_renderers.py Thu Jun 15 
15:47:51 2006
@@ -26,8 +26,6 @@
         DocTestSuite('cpsskins.browser.rendering.renderer'),
         DocTestSuite('cpsskins.browser.rendering.context'),
         DocTestSuite('cpsskins.browser.rendering.viewer'),
-        DocFileSuite('../doc/canvas-rendering.txt'),
-        DocFileSuite('../doc/draft-rendering-pipelines.txt'),
         ))
 
 if __name__ == '__main__':
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to