[Zope-CVS] CVS: Products/PageDesign - IIndexedSlot.py:1.1.2.2 Slot.py:1.1.2.6 SlotElementClipboardTarget.py:1.1.2.4

Shane Hathaway shane@cvs.zope.org
Fri, 9 Aug 2002 13:55:16 -0400


Update of /cvs-repository/Products/PageDesign
In directory cvs.zope.org:/tmp/cvs-serv29815

Modified Files:
      Tag: page-redesign-branch
	IIndexedSlot.py Slot.py SlotElementClipboardTarget.py 
Log Message:
Corrected element reordering using insertion point trackers, which keep element
indexes up to date.


=== Products/PageDesign/IIndexedSlot.py 1.1.2.1 => 1.1.2.2 ===
--- Products/PageDesign/IIndexedSlot.py:1.1.2.1	Sat Aug  3 15:58:03 2002
+++ Products/PageDesign/IIndexedSlot.py	Fri Aug  9 13:55:15 2002
@@ -18,15 +18,33 @@
 class IIndexedSlot(ISlot):
 
     def getElementCount():
-        """
+        """Returns the number of elements currently in the slot.
         """
 
     def getElement(index):
+        """Returns the IPageElement at the specified index.
         """
+
+    def track(index):
+        """Returns an insertion point tracker.
+
+        The insertion point will be updated as items are added or
+        removed from this slot, ensuring that elements are later inserted
+        where the user expected.
         """
 
-    def insertBefore(before_element, elements):
+    def untrack(ipt):
+        """Disconnects an insertion point tracker, returning its index.
         """
+
+    def insertElements(index, elements):
+        """Inserts IPageElements at the specified index.
+
+        If index is an insertion point tracker (as returned by track()),
+        the tracker will be disconnected and its current value will be
+        used as the index.
+
+        If index is None, the elements will be appended to the end.
         """
 
     def remove(element):


=== Products/PageDesign/Slot.py 1.1.2.5 => 1.1.2.6 ===
--- Products/PageDesign/Slot.py:1.1.2.5	Thu Aug  8 22:58:46 2002
+++ Products/PageDesign/Slot.py	Fri Aug  9 13:55:15 2002
@@ -80,6 +80,7 @@
     element_html = '''<div class="design-element" id="%(clipboard_path)s">
     <div class="design-element-titlebar">%(title)s</div>%(text)s</div>'''
 
+    _trackers = ()
 
     def __init__(self, id):
         self.id = id
@@ -187,27 +188,62 @@
     def beforeChange(self):
         aq_parent(aq_inner(self))._persistSlot(self)
 
-    def insertBefore(self, before_element, elements):
+    def track(self, index):
+        self.beforeChange()
+        ipt = InsertionPointTracker(index)
+        self._trackers = self._trackers + (ipt,)
+        return ipt
+
+    def untrack(self, ipt):
+        self.beforeChange()
+        ipts = list(self._trackers)
+        ipts.remove(ipt)
+        self._trackers = tuple(ipts)
+        return ipt.index
+
+    def insertElements(self, index, elements):
         # Verify none of the elements are already inserted.
         # An element can only be in one place at a time.
+        if isinstance(index, InsertionPointTracker):
+            index = self.untrack(index)
         for e in elements:
             if not IPageElement.isImplementedBy(e):
                 raise ValueError, 'Not a page element'
             if e in self.contents:
                 raise ValueError, 'Already inserted'
         self.beforeChange()
-        if before_element is None:
+        if index is None:
             # append.
             self.contents = self.contents + tuple(elements)
         else:
-            index = list(self.contents).index(before_element)
             self.contents = (self.contents[:index] + tuple(elements)
                              + self.contents[index:])
+        for ipt in self._trackers:
+            ipt.afterInsert(index, len(elements))
 
     def remove(self, element):
-        lst = list(self.contents)
-        lst.remove(element)
         self.beforeChange()
+        lst = list(self.contents)
+        index = lst.index(element)
+        del lst[index]
         self.contents = tuple(lst)
+        for ipt in self._trackers:
+            ipt.afterRemove(index, 1)
 
 Globals.InitializeClass(Slot)
+
+
+
+class InsertionPointTracker:
+
+    def __init__(self, index):
+        self.index = index
+
+    def afterInsert(self, index, count):
+        if self.index >= index:
+            self.index += count
+
+    def afterRemove(self, index, count):
+        if self.index > index:
+            self.index -= count
+


=== Products/PageDesign/SlotElementClipboardTarget.py 1.1.2.3 => 1.1.2.4 ===
--- Products/PageDesign/SlotElementClipboardTarget.py:1.1.2.3	Thu Aug  8 22:58:46 2002
+++ Products/PageDesign/SlotElementClipboardTarget.py	Fri Aug  9 13:55:15 2002
@@ -18,7 +18,6 @@
 from AccessControl import ClassSecurityInfo
 from IClipboardTarget import IClipboardTarget
 from IIndexedSlot import IIndexedSlot
-from IPageElement import IPageElement
 
 # Permission name
 change_page_designs = 'Change Page Designs'
@@ -36,15 +35,13 @@
         index = int(index)
         slot = aq_parent(aq_inner(self))
         assert IIndexedSlot.isImplementedBy(slot), `slot`
-        before_element = aq_base(slot.getElement(index))
-        assert IPageElement.isImplementedBy(before_element), `before_element`
-        self.before_element = before_element
+        self.ipt = slot.track(index)
         return self
 
     security.declareProtected(change_page_designs, 'paste')
     def paste(self, elements):
         slot = aq_parent(aq_inner(self))
-        slot.insertBefore(aq_base(self.before_element), elements)
+        slot.insertElements(self.ipt, elements)
 
 Globals.InitializeClass(SlotElementClipboardTarget)
 
@@ -61,7 +58,7 @@
     def paste(self, elements):
         slot = aq_parent(aq_inner(self))
         assert IIndexedSlot.isImplementedBy(slot), `slot`
-        slot.insertBefore(None, elements)
+        slot.insertElements(None, elements)
 
 Globals.InitializeClass(SlotElementClipboardLastTarget)