tables.py: slightly better spanned row height calcs
authorrgbecker
Sat, 27 Oct 2007 13:51:47 +0000
changeset 2879 0ba5481218bd
parent 2878 a7af19b6f9fb
child 2880 70c6ad230fea
tables.py: slightly better spanned row height calcs
reportlab/platypus/tables.py
reportlab/test/test_platypus_tables.py
--- a/reportlab/platypus/tables.py	Fri Oct 26 16:16:38 2007 +0000
+++ b/reportlab/platypus/tables.py	Sat Oct 27 13:51:47 2007 +0000
@@ -203,11 +203,24 @@
     except:
         return 0
 
-def _spanConsCmp(a,b):
-    r = cmp(b[1]-b[0],a[1]-a[0])
-    if not r:
-        r = cmp(a,b)
-    return r
+def spanFixDim(V0,V,spanCons,FUZZ=rl_config._FUZZ):
+    print 'V0=',V0
+    print 'V=',V
+    print 'spanCons=',spanCons
+    #assign required space to variable rows equally to existing calculated values
+    M = {}
+    for (x0,x1),v in spanCons.iteritems():
+        t = sum([V[x]+M.get(x,0) for x in xrange(x0,x1+1)])
+        if t>=v-FUZZ: continue      #already good enough
+        X = [x for x in xrange(x0,x1+1) if V0[x] is None]   #variable candidates
+        if not X: continue          #something wrong here mate
+        v -= t
+        v /= float(len(X))
+        for x in X:
+            M[x] = max(M.get(x,v),v)
+    for x,v in M.iteritems():
+        V[x] += v
+    print 'V-->',V
 
 class Table(Flowable):
     def __init__(self, data, colWidths=None, rowHeights=None, style=None,
@@ -384,7 +397,6 @@
                 colSpanCells = ()
                 spanRanges = {}
             spanCons = {}
-            FUZZ = rl_config._FUZZ
             if W is self._argW:
                 W0 = W
                 W = W[:]
@@ -421,18 +433,7 @@
                 W[j] = w
 
             if spanCons:
-                spanConsX = spanCons.keys()     #try to ensure span constraints are satisfied
-                spanConsX.sort(_spanConsCmp)    #assign required space to variable rows
-                for c0,c1 in spanConsX:         #equally to existing calculated values
-                    w = spanCons[c0,c1]
-                    t = sum(W[c0:c1+1])
-                    if t>=w-FUZZ: continue      #already good enough
-                    X = [x for x in xrange(c0,c1+1) if W0[x] is None]   #variable candidates
-                    if not X: continue          #something wrong here mate
-                    w -= t
-                    w /= float(len(X))
-                    for x in X:
-                        W[x] += w
+                spanFixDim(W0,W,spanCons)
 
         self._colWidths = W
         width = 0
@@ -541,18 +542,7 @@
             if None not in H: hmax = lim
 
             if spanCons:
-                spanConsX = spanCons.keys()     #try to ensure span constraints are satisfied
-                spanConsX.sort(_spanConsCmp)    #assign required space to variable rows
-                for r0,r1 in spanConsX:         #equally to existing calculated values
-                    h = spanCons[r0,r1]
-                    t = sum(H[r0:r1+1])
-                    if t>=h-FUZZ: continue      #already good enough
-                    X = [x for x in xrange(r0,r1+1) if H0[x] is None]   #variable candidates
-                    if not X: continue          #something wrong here mate
-                    h -= t
-                    h /= float(len(X))
-                    for x in X:
-                        H[x] += h
+                spanFixDim(H0,H,spanCons)
 
         height = self._height = reduce(operator.add, H[:hmax], 0)
         self._rowpositions = [height]    # index 0 is actually topline; we skip when processing cells
--- a/reportlab/test/test_platypus_tables.py	Fri Oct 26 16:16:38 2007 +0000
+++ b/reportlab/test/test_platypus_tables.py	Sat Oct 27 13:51:47 2007 +0000
@@ -706,43 +706,63 @@
 
     lst.append(t)
 
-    #Volker Haas' example
-    sty=[
-        ('TOPPADDING',(0,0),(-1,-1),0),
-        ('BOTTOMPADDING',(0,0),(-1,-1),0),
-        ('RIGHTPADDING',(0,0),(-1,-1),0),
-        ('LEFTPADDING',(0,0),(-1,-1),0),
-        ('GRID',(0,0),(-1,-1),0.5,colors.grey),
-        ('BACKGROUND', (0, 0), (0, 1), colors.pink),
-        ('SPAN',(0,0),(0,1)),
-        ('BACKGROUND', (2, 2), (2, 3), colors.orange),
-        ('SPAN',(2,2),(2,3)),
-        ('SPAN',(3,1),(4,1)),
-        ]
-
+    #Volker Haas' example extended
+    #the optimal row heights are the solution of an LP similar to
+    #
+    #Objective function
+    #   min: 3*h0+3*h1+3*h2+2*h3;
+    #
+    #constraints
+    #   h0>=12;
+    #   h1>=12;
+    #   h2>=12;
+    #   h3>=12;
+    #   h0+h1+h2>=48;
+    #   h0+h1>=12;
+    #   h2+h3>=60;
+    #
+    #the solution H=[12,12,24,36]
+    def makeTable(x,y):
+        return Table([
+                ['00', '01', '02', '03', '04', '05\nline2\nline3\nline4'],
+                ['', '11', '12', x, '',''],
+                ['20', '21', y, '23', '24',''],
+                ['30', '31', '', '33', '34','35'],
+                ],
+                style=[
+                    ('TOPPADDING',(0,0),(-1,-1),0),
+                    ('BOTTOMPADDING',(0,0),(-1,-1),0),
+                    ('RIGHTPADDING',(0,0),(-1,-1),0),
+                    ('LEFTPADDING',(0,0),(-1,-1),0),
+                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
+                    ('BACKGROUND', (0, 0), (0, 1), colors.pink),
+                    ('SPAN',(0,0),(0,1)),
+                    ('BACKGROUND', (2, 2), (2, 3), colors.orange),
+                    ('SPAN',(2,2),(2,3)),
+                    ('SPAN',(3,1),(4,1)),
+                    ('SPAN',(5,0),(5,2)),
+                ])
     p_style= ParagraphStyle('Normal')
-    data=  [['00', '01', '02', '03', '04'],
-            ['', '11', '12', Paragraph('This is a string',p_style), ''],
-            ['20', '21', Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style), '23', '24'],
-            ['30', '31', '', '33', '34']]
-    lst.append(Table(data,style=sty))
+    lst.append(makeTable(
+            Paragraph('This is a string',p_style),
+            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
+            ))
+
     lst.append(Spacer(10,10))
-    data1=  [['00', '01', '02', '03', '04'],
-            ['', '11', '12', XPreformatted('This is a string',p_style), ''],
-            ['20', '21', Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs',p_style), '23', '24'],
-            ['30', '31', '', '33', '34']]
-    lst.append(Table(data1,style=sty))
+    lst.append(makeTable(
+            XPreformatted('This is a string',p_style),
+            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
+            ))
     lst.append(Spacer(10,10))
-    data2=  [['00', '01', '02', '03', '04'],
-            ['', '11', '12', 'This is a string', ''],
-            ['20', '21','22\nblub\nasfd\nafd\nasdfs', '23', '24'],
-            ['30', '31', '', '33', '34']]
-    lst.append(Table(data2,style=sty))
-    data3=  [['00', '01', '02', '03', '04'],
-            ['', '11', '12', 'This is a string', ''],
-            ['20', '21', Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs',p_style), '23', '24'],
-            ['30', '31', '', '33', '34']]
-    lst.append(Table(data3,style=sty))
+    lst.append(makeTable(
+            'This is a string',
+            '22\nblub\nasfd\nafd\nasdfs',
+            ))
+    lst.append(Spacer(10,10))
+    lst.append(makeTable(
+            'This is a string',
+            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
+            ))
     SimpleDocTemplate(outputfile('tables.pdf'), showBoundary=1).build(lst)
 
 class TablesTestCase(unittest.TestCase):