platypus: add * as shortcircuit template cycle notation
authorrgbecker
Wed, 19 Jul 2006 11:25:24 +0000
changeset 2661 e179247ffea3
parent 2660 c147aff8edae
child 2662 0a5217162c3f
platypus: add * as shortcircuit template cycle notation
reportlab/platypus/doctemplate.py
reportlab/test/test_platypus_leftright.py
--- a/reportlab/platypus/doctemplate.py	Fri Jul 14 09:25:10 2006 +0000
+++ b/reportlab/platypus/doctemplate.py	Wed Jul 19 11:25:24 2006 +0000
@@ -48,6 +48,18 @@
     "Dummy callback for onPage"
     pass
 
+class PTCycle(list):
+    def __init__(self):
+        self._restart = 0
+        self._idx = 0
+        list.__init__(self)
+
+    def cyclicIterator(self):
+        while 1:
+            yield self[self._idx]
+            self._idx += 1
+            if self._idx>=len(self):
+                self._idx = self._restart
 
 class IndexingFlowable(Flowable):
     """Abstract interface definition for flowables which might
@@ -437,11 +449,7 @@
 
             if hasattr(self,'_nextPageTemplateCycle'):
                 #they are cycling through pages'; we keep the index
-                cyc = self._nextPageTemplateCycle
-                idx = self._nextPageTemplateIndex
-                self.pageTemplate = cyc[idx]  #which is one of the ones in the list anyway
-                #bump up by 1
-                self._nextPageTemplateIndex = (idx + 1) % len(cyc)
+                self.pageTemplate = self._nextPageTemplateCycle.next()
             elif hasattr(self,'_nextPageTemplateIndex'):
                 self.pageTemplate = self.pageTemplates[self._nextPageTemplateIndex]
                 del self._nextPageTemplateIndex
@@ -504,21 +512,25 @@
         elif type(pt) in (ListType, TupleType):
             #used for alternating left/right pages
             #collect the refs to the template objects, complain if any are bad
-            cycle = []
-            for templateName in pt:
+            c = PTCycle()
+            for ptn in pt:
                 found = 0
+                if ptn=='*':    #special case name used to short circuit the iteration
+                    c._restart = len(c)
+                    continue
                 for t in self.pageTemplates:
-                    if t.id == templateName:
-                        cycle.append(t)
+                    if t.id == ptn:
+                        c.append(t)
                         found = 1
                 if not found:
                     raise ValueError("Cannot find page template called %s" % templateName)
-            #double-check all of them are there...
-            
-            first = cycle[0]
+            if not c:
+                raise ValueError("No valid page templates in cycle")
+            elif c._restart>len(c):
+                raise ValueError("Invalid cycle restart position")
+
             #ensure we start on the first one
-            self._nextPageTemplateCycle = cycle
-            self._nextPageTemplateIndex = 0  #indexes into the cycle
+            self._nextPageTemplateCycle = c.cyclicIterator()
         else:
             raise TypeError, "argument pt should be string or integer or list"
 
--- a/reportlab/test/test_platypus_leftright.py	Fri Jul 14 09:25:10 2006 +0000
+++ b/reportlab/test/test_platypus_leftright.py	Wed Jul 19 11:25:24 2006 +0000
@@ -34,8 +34,6 @@
     canvas.drawString(10*cm, cm, str(pageNumber))
     canvas.restoreState()
 
-
-
 class LeftPageTemplate(PageTemplate):
     def __init__(self):
         #allow a bigger margin on the right for the staples
@@ -119,35 +117,37 @@
 
         story.append(NextPageTemplate(['left','right']))
 
-
         story.append(Paragraph("""
             One can specify a list of templates instead of a single one in
             order to sequence through them.""",style=bt))
-        for i in range(10):
-            story.append(Paragraph('Heading 1 always starts a new page (%d)' % len(story), h1))
-            for j in range(3):
-                story.append(Paragraph('Heading1 paragraphs should always'
-                                'have a page break before.  Heading 2 on the other hand'
-                                'should always have a FRAME break before (%d)' % len(story), bt))
-                story.append(Paragraph('Heading 2 always starts a new frame (%d)' % len(story), h2))
-                story.append(Paragraph('Heading1 paragraphs should always'
-                                'have a page break before.  Heading 2 on the other hand'
-                                'should always have a FRAME break before (%d)' % len(story), bt))
+        def doSome():
+            for i in range(10):
+                story.append(Paragraph('Heading 1 always starts a new page (%d)' % len(story), h1))
                 for j in range(3):
-                    story.append(Paragraph(randomText(theme=PYTHON, sentences=2)+' (%d)' % len(story), bt))
-                    story.append(Paragraph('I should never be at the bottom of a frame (%d)' % len(story), h3))
-                    story.append(Paragraph(randomText(theme=PYTHON, sentences=1)+' (%d)' % len(story), bt))
+                    story.append(Paragraph('Heading1 paragraphs should always'
+                                    'have a page break before.  Heading 2 on the other hand'
+                                    'should always have a FRAME break before (%d)' % len(story), bt))
+                    story.append(Paragraph('Heading 2 always starts a new frame (%d)' % len(story), h2))
+                    story.append(Paragraph('Heading1 paragraphs should always'
+                                    'have a page break before.  Heading 2 on the other hand'
+                                    'should always have a FRAME break before (%d)' % len(story), bt))
+                    for j in range(3):
+                        story.append(Paragraph(randomText(theme=PYTHON, sentences=2)+' (%d)' % len(story), bt))
+                        story.append(Paragraph('I should never be at the bottom of a frame (%d)' % len(story), h3))
+                        story.append(Paragraph(randomText(theme=PYTHON, sentences=1)+' (%d)' % len(story), bt))
 
+        doSome()
         story.append(NextPageTemplate('plain'))
         story.append(Paragraph('Back to plain old page template',h1))
         story.append(Paragraph('Back to plain old formatting', bt))
-
+        story.append(Paragraph("""use a template name of * to indicate where the iteration should restart""",style=bt))
+        story.append(NextPageTemplate(['left','*','right']))
+        doSome()
 
         #doc = MyDocTemplate(outputfile('test_platypus_leftright.pdf'))
         doc = MyDocTemplate(outputfile('test_platypus_leftright.pdf'))
         doc.multiBuild(story)
 
-
 def makeSuite():
     return makeSuiteForClasses(LeftRightTestCase)