Author: jmorliaguet
Date: Thu Jun 15 23:10:24 2006
New Revision: 3420

Modified:
   cpsskins/branches/paris-sprint-2006/browser/tree/slot.py
   cpsskins/branches/paris-sprint-2006/doc/portlets.txt
   cpsskins/branches/paris-sprint-2006/elements/configure.zcml
   cpsskins/branches/paris-sprint-2006/setup/io/README.txt
   cpsskins/branches/paris-sprint-2006/setup/io/utils.py
   cpsskins/branches/paris-sprint-2006/standard/displays/boxgroup.py
   cpsskins/branches/paris-sprint-2006/standard/formats/configure.zcml

Log:

- added an 'order' format to the slot's display that stores information
  about how portlets are ordered inside the slot. The information used to
  be stored inside the display element itself which meant that a new display
  had to be created to store the portlets of a same slot in different orders.

- test / doc updates



Modified: cpsskins/branches/paris-sprint-2006/browser/tree/slot.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/browser/tree/slot.py    (original)
+++ cpsskins/branches/paris-sprint-2006/browser/tree/slot.py    Thu Jun 15 
23:10:24 2006
@@ -29,7 +29,7 @@
 from cpsskins.browser.tree.interfaces import INodeDuplicating, INodeTraversing
 from cpsskins.elements.display import IGNORE_PERSPECTIVES
 from cpsskins.elements.display import USE_CURRENT_PERSPECTIVE
-from cpsskins.elements.interfaces import IPortlet, IDisplayable
+from cpsskins.elements.interfaces import IPortlet, IDisplayable, IFormattable
 from cpsskins.ontology import hasPortlet, hasPortletFromPerspective
 from cpsskins.relations import DyadicRelation, TriadicRelation
 from cpsskins.utils import getThemeManager, getRelationStorage
@@ -46,22 +46,22 @@
         context = self.context
         relations = getRelationStorage(context)
 
+        # TODO: refactor using relations
         if perspective is None or display.mode == IGNORE_PERSPECTIVES:
             portlets = relations.getSeconds(predicate=hasPortlet, 
first=context)
         elif display.mode == USE_CURRENT_PERSPECTIVE:
             portlets = 
relations.getSeconds(predicate=hasPortletFromPerspective,
                                           first=context, third=perspective)
 
-        # the portlet order is obtained from the display, if the display is
-        # iterable otherwise the portlets are sorted by their identifier.
-        def cmp_by_order(a, b):
-           if a in display and b in display:
-               index = display.index
-               return cmp(index(a), index(b))
-           return cmp(a.identifier, b.identifier)
+        display = IDisplayable(context).getEffectiveDisplay(perspective)
+        order = IFormattable(display).getFormat(u'order')
 
-        # sort the portlets
-        #portlets.sort(cmp_by_order)
+        if order is not None:
+            def cmp_by_order(a, b):
+                index = order.index
+                return cmp(index(a.identifier), index(b.identifier))
+
+        portlets.sort(cmp_by_order)
         return portlets
 
 class SlotAdding(Adding):
@@ -86,18 +86,12 @@
         portlets.add(content)
 
         if perspective is None:
-            relation = DyadicRelation(
-                predicate=hasPortlet,
-                first=container,
-                second=content,
-                )
+            relation = DyadicRelation(predicate=hasPortlet, first=container,
+                                      second=content)
         else:
-            relation = TriadicRelation(
-                predicate=hasPortletFromPerspective,
-                first=container,
-                second=content,
-                third=perspective,
-                )
+            relation = TriadicRelation(predicate=hasPortletFromPerspective,
+                                       first=container, second=content,
+                                       third=perspective)
 
         relations = getThemeManager(container).getRelationStorage()
         relations.add(relation)
@@ -106,7 +100,9 @@
 
         # store the portlet's order in the slot's "BoxGroup" display
         display = IDisplayable(container).getEffectiveDisplay(perspective)
-        display.append(content)
+        order = IFormattable(display).getFormat(u'order')
+        if order is not None:
+            order.append(content.identifier)
 
         return content
 
@@ -116,9 +112,9 @@
     implements(INodeMoving)
 
     def move(self, content):
+        request = self.request
         src_container = getParent(content)
         dest_container = self.context
-        request = self.request
         if dest_container == src_container:
             return content
 
@@ -180,20 +176,21 @@
             ids = relations.search(predicate=hasPortletFromPerspective,
                                    first=container, second=content,
                                    third=perspective)
-
         relations.remove(ids)
         del portlets[getName(content)]
 
         # store the portlet's order in the slot's "BoxGroup" display
         display = IDisplayable(container).getEffectiveDisplay(perspective)
-        display.remove(content)
+        order = IFormattable(display).getFormat(u'order')
+        if order is not None:
+            order.remove(content.identifier)
 
 class SlotOrdering(BrowserView):
     """A view for reordering elements in slots
     """
     implements(INodeOrdering)
 
-    def setOrder(self, content, order):
+    def setOrder(self, content, position):
         """Set the element's order in the container.
         """
         container = self.context
@@ -208,10 +205,12 @@
                          ).getPerspective()
 
         display = IDisplayable(container).getEffectiveDisplay(perspective)
-
-        if content in display:
-            display.remove(content)
-        display.insert(order, content)
+        order = IFormattable(display).getFormat(u'order')
+        if order is not None:
+            id = content.identifier
+            if id in order:
+                order.remove(id)
+            order.insert(position, id)
 
     def getOrder(self, content):
         """Get the element's order in the container.
@@ -226,7 +225,9 @@
                          ).getPerspective()
 
         display = IDisplayable(container).getEffectiveDisplay(perspective)
-        return display.index(content)
+        order = IFormattable(display).getFormat(u'order')
+        if order is not None:
+            return order.index(content.identifier)
 
 class SlotDuplicating(BrowserView):
     """A view for duplicating elements in nodes
@@ -256,7 +257,10 @@
         perspective = len(rel) == 3 and rel.third or None
 
         display = IDisplayable(container).getEffectiveDisplay(perspective)
-        display.insert(0, duplicated)
+        order = IFormattable(display).getFormat(u'order')
+        if order is not None:
+            position = order.index(content.identifier)
+            order.insert(position, duplicated.identifier)
 
         # set the dest_slot -> portlet relation
         if perspective is None:
@@ -268,5 +272,5 @@
                                        third=perspective)
         relations.add(relation)
         duplicated.__parent__ = container
-        return duplicated.identifier
+        return duplicated
 

Modified: cpsskins/branches/paris-sprint-2006/doc/portlets.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/doc/portlets.txt        (original)
+++ cpsskins/branches/paris-sprint-2006/doc/portlets.txt        Thu Jun 15 
23:10:24 2006
@@ -438,24 +438,23 @@
     []
 
 
-
 Finally we clear the storage:
 
     >>> relations.clear()
 
 
 
-PORTLET ORDERING
-================
+PORTLET MANIPULATION
+====================
 
-The portlets displayed in slots need to be ordered. The order information is
-stored in the slot's display.
+Portlets can be manipulated, i.e added, duplicated, removed, reordered inside a
+same slot or be moved between different slots.
 
-We set up some test environment:
+We set up a 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'):
@@ -469,7 +468,7 @@
     >>> 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
+The slots A and B have their own display:
 
     >>> from cpsskins.elements.interfaces import IDisplayable
     >>> from cpsskins.standard.displays.boxgroup import BoxGroup
@@ -486,6 +485,102 @@
     >>> display_slot_A is not display_slot_B
     True
 
-[...]
+Adding
+------
+Portlets are added into the slots with the INodeAdding view:
+
+    >>> from cpsskins.browser.tree.slot import INodeAdding
+    >>> adding = getMultiAdapter((slot_A, request), INodeAdding)
+
+    >>> portlet1 = Portlet(u'Portlet 1')
+    >>> added = adding.add(portlet1)
+
+Traversing
+----------
+to get the list of portlets inside a slot we use the INodeTraversing view:
+
+    >>> from cpsskins.browser.tree.slot import INodeTraversing
+    >>> traversing = getMultiAdapter((slot_A, request), INodeTraversing)
+    >>> traversing.getChildNodes() == [portlet1]
+    True
+
+Duplicating
+-----------
+to duplicate portlets inside a slot we use INodeDuplicating:
+
+    >>> from cpsskins.browser.tree.slot import INodeDuplicating
+    >>> duplicating = getMultiAdapter((slot_A, request), INodeDuplicating)
+
+    >>> duplicated = duplicating.duplicate(portlet1)
+
+we now have two identical portlets inside the slot:
+
+    >>> traversing.getChildNodes() == [duplicated, added]
+    True
+
+Removing
+--------
+to remove a portlet we use INodeRemoving:
+
+    >>> from cpsskins.browser.tree.slot import INodeRemoving
+    >>> removing = getMultiAdapter((slot_A, request), INodeRemoving)
+    >>> removing.remove(duplicated)
+
+the second portlet is removed:
+
+    >>> traversing.getChildNodes() == [added]
+    True
+
+we also remove the first portlet:
+
+    >>> removing.remove(added)
+    >>> traversing.getChildNodes() == []
+    True
+
+Reordering
+----------
+portlets are ordered in slots if the slot's display has an 'order' format.
+let us add a few portlets:
+
+    >>> portlets = []
+    >>> for i in range(4):
+    ...     portlets.append(adding.add(Portlet(str(i))))
+
+    >>> traversing.getChildNodes()
+    [Portlet('0'), Portlet('1'), Portlet('2'), Portlet('3')]
+
+    >>> from cpsskins.browser.tree.slot import INodeOrdering
+    >>> ordering = getMultiAdapter((slot_A, request), INodeOrdering)
+
+    >>> ordering.getOrder(portlets[1])
+    1
+
+    >>> ordering.getOrder(portlets[2])
+    2
+
+    >>> ordering.setOrder(portlets[2], 3)
+    >>> ordering.getOrder(portlets[2])
+    3
+
+    >>> traversing.getChildNodes()
+    [Portlet('0'), Portlet('1'), Portlet('3'), Portlet('2')]
+
+Moving
+------
+portlets are moved between slots using INodeMoving:
+
+    >>> from cpsskins.browser.tree.slot import INodeMoving
+    >>> moving = getMultiAdapter((slot_B, request), INodeMoving)
+    >>> moving.move(portlets[1])
+
+now Slot B contains one more portlet:
+
+    >>> traversing_B = getMultiAdapter((slot_B, request), INodeTraversing)
+    >>> traversing_B.getChildNodes()
+    [Portlet('1')]
+
+and Slot A contains one portlet less:
 
+    >>> traversing.getChildNodes()
+    [Portlet('0'), Portlet('3'), Portlet('2')]
 

Modified: cpsskins/branches/paris-sprint-2006/elements/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/elements/configure.zcml (original)
+++ cpsskins/branches/paris-sprint-2006/elements/configure.zcml Thu Jun 15 
23:10:24 2006
@@ -430,6 +430,10 @@
     />
 
     <cpsskins:format
+        name="order"
+    />
+
+    <cpsskins:format
         name="effect"
         types="scale"
     />

Modified: cpsskins/branches/paris-sprint-2006/setup/io/README.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/io/README.txt     (original)
+++ cpsskins/branches/paris-sprint-2006/setup/io/README.txt     Thu Jun 15 
23:10:24 2006
@@ -178,7 +178,7 @@
     >>> pageblock[u'cell1'][u'slot'] = slot
 
     >>> print toXML(pageblock, u'elements', (u'title', u'description'),
-    ...             (u'slot',))
+    ...             (u'name',))
     <?xml version="1.0" encoding="utf-8"?>
     <elements>
       <pageblock id="..." title="Some page block">

Modified: cpsskins/branches/paris-sprint-2006/setup/io/utils.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/io/utils.py       (original)
+++ cpsskins/branches/paris-sprint-2006/setup/io/utils.py       Thu Jun 15 
23:10:24 2006
@@ -131,7 +131,7 @@
         exporter.archive = archive
         exporter.document = document
         exporter.fields_as_attributes = u'title', u'description'
-        exporter.ignored_fields = u'slot',
+        exporter.ignored_fields = u'name',
         exporter.save()
 
     archive[u'themes.xml'] = document.toprettyxml(indent=u'  ',

Modified: cpsskins/branches/paris-sprint-2006/standard/displays/boxgroup.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/displays/boxgroup.py   
(original)
+++ cpsskins/branches/paris-sprint-2006/standard/displays/boxgroup.py   Thu Jun 
15 23:10:24 2006
@@ -42,106 +42,18 @@
         vocabulary="Display Modes",
         required=True)
 
-    def insert(i, item):
-        """ """
-
-    def remove(item):
-        """ """
-
-    def __contains__(value):
-        """Return whether the value is contained in the box group"""
-
-    def index(value):
-        """Return the position of a value in the box group"""
-
 class BoxGroup(Persistent, Display):
     """A Box Group is used to display a group of portlets.
-
-    >>> from zope.component import getGlobalSiteManager
-    >>> from cpsskins.thememanager import ThemeManagementFolder
-    >>> from cpsskins.thememanager import IThemeManagementFolder
-
-    >>> gsm = getGlobalSiteManager()
-    >>> gsm.registerUtility(ThemeManagementFolder(), IThemeManagementFolder,
-    ...                     name=u'themes')
-
-    >>> from cpsskins.elements.portlet import TestPortlet as Portlet
-    >>> portlet1, portlet2 = (Portlet('portlet1'), Portlet('portlet2'))
-    >>> portlet1.identifier = 1
-    >>> portlet2.identifier = 2
-
-    >>> boxgroup = BoxGroup()
-    >>> boxgroup.identifier = 12345
-    >>> boxgroup
-    <BoxGroup: 12345>
-
-    >>> boxgroup.insert(0, portlet1)
-    >>> boxgroup.insert(1, portlet2)
-    >>> portlet1 in boxgroup and portlet2 in boxgroup
-    True
-
-    >>> list(boxgroup)
-    [1, 2]
-
-    >>> boxgroup.remove(portlet1)
-    >>> list(boxgroup)
-    [2]
-
-    >>> portlet1 in boxgroup
-    False
-
-    >>> portlet2 in boxgroup
-    True
-
-    >>> boxgroup.append(portlet1)
-    >>> list(boxgroup)
-    [2, 1]
-
     """
     implements(IBoxGroup)
 
     def __init__(self, **kw):
         super(BoxGroup, self).__init__(**kw)
-        self._order = PersistentList()
         self.mode = USE_CURRENT_PERSPECTIVE
 
     def __repr__(self):
         return "<BoxGroup: %s>" % self.identifier
 
-    def insert(self, order, item):
-        """Insert an element at the specified 'order' position
-        """
-        self._order.insert(order, item.identifier)
-        self._p_changed = True
-        logger.debug("Inserted %s in %s at position %s", repr(item), 
repr(self),
-                     order)
-
-    def remove(self, item):
-        """Remove an element
-        """
-        self._order.remove(item.identifier)
-        self._p_changed = True
-        logger.debug("Removed %s from %s", repr(item), repr(self))
-
-    def append(self, item):
-        """Add an element in the last position.
-        """
-        self._order.append(item.identifier)
-        self._p_changed = True
-        logger.debug("Appended %s to %s", repr(item), repr(self))
-
-    def __len__(self):
-        return len(self._order)
-
-    def index(self, item):
-        return self._order.index(item.identifier)
-
-    def __contains__(self, item):
-        return item.identifier in self._order
-
-    def __iter__(self):
-        return iter(self._order)
-
 # List of display modes
 
 def DisplayModes(context):

Modified: cpsskins/branches/paris-sprint-2006/standard/formats/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/formats/configure.zcml 
(original)
+++ cpsskins/branches/paris-sprint-2006/standard/formats/configure.zcml Thu Jun 
15 23:10:24 2006
@@ -41,4 +41,12 @@
       predicate=".effect.hasEffect"
   />
 
+  <!-- Order -->
+  <cpsskins:format
+      name="order"
+      schema=".order.IOrder"
+      class=".order.Order"
+      predicate=".order.hasOrder"
+  />
+
 </configure>
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to