Prepare for a more general idea of cell size
authorrgbecker
Tue, 22 Apr 2003 17:32:01 +0000
changeset 1917 25b37daf5ab7
parent 1916 8cf26ffbbc3b
child 1918 0cf99b149507
Prepare for a more general idea of cell size
reportlab/platypus/flowables.py
reportlab/platypus/tables.py
--- a/reportlab/platypus/flowables.py	Tue Apr 22 16:12:59 2003 +0000
+++ b/reportlab/platypus/flowables.py	Tue Apr 22 17:32:01 2003 +0000
@@ -1,8 +1,8 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/flowables.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.35 2003/04/05 22:07:51 andy_robinson Exp $
-__version__=''' $Id: flowables.py,v 1.35 2003/04/05 22:07:51 andy_robinson Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.36 2003/04/22 17:32:01 rgbecker Exp $
+__version__=''' $Id: flowables.py,v 1.36 2003/04/22 17:32:01 rgbecker Exp $ '''
 __doc__="""
 A flowable is a "floating element" in a document whose exact position is determined by the
 other elements that precede it, such as a paragraph, a diagram interspersed between paragraphs,
@@ -50,6 +50,9 @@
     2. It draws in its own coordinate system (this requires the
         base API to provide a translate() function.
     """
+    _fixedWidth = 0         #assume wrap results depend on arguments?
+    _fixedHeight = 0
+
     def __init__(self):
         self.width = 0
         self.height = 0
@@ -270,6 +273,8 @@
        are supported.  At the present time images as flowables are always centered horozontally
        in the frame.
     """
+    _fixedWidth = 1
+    _fixedHeight = 1
     def __init__(self, filename, width=None, height=None, kind='direct', mask="auto"):
         """If size to draw at not specified, get it from the image."""
         from reportlab.lib.utils import PIL_Image  #this will raise an error if they do not have PIL.
@@ -321,6 +326,8 @@
 class Spacer(Flowable):
     """A spacer just takes up space and doesn't draw anything - it guarantees
        a gap between objects."""
+    _fixedWidth = 1
+    _fixedHeight = 1
     def __init__(self, width, height):
         self.width = width
         self.height = height
--- a/reportlab/platypus/tables.py	Tue Apr 22 16:12:59 2003 +0000
+++ b/reportlab/platypus/tables.py	Tue Apr 22 17:32:01 2003 +0000
@@ -1,8 +1,8 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/tables.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.64 2003/04/21 22:27:47 andy_robinson Exp $
-__version__=''' $Id: tables.py,v 1.64 2003/04/21 22:27:47 andy_robinson Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.65 2003/04/22 17:32:01 rgbecker Exp $
+__version__=''' $Id: tables.py,v 1.65 2003/04/22 17:32:01 rgbecker Exp $ '''
 __doc__="""
 Tables are created by passing the constructor a tuple of column widths, a tuple of row heights and the data in
 row order. Drawing of the table can be controlled by using a TableStyle instance. This allows control of the
@@ -267,13 +267,10 @@
                         #print 'sizing a spanned cell (%d, %d) with content "%s"' % (j, i, str(v))
                         t = 0.0
                     else:#work out size
-                        t = type(v)
-                        if t in _SeqTypes or isinstance(v,Flowable):
+                        t = self._elementWidth(v,s)
+                        if t is None:
                             raise ValueError, "Flowable %s in cell(%d,%d) can't have auto width\n%s" % (v.identity(30),i,j,self.identity(30))
-                        elif t is not StringType: v = v is None and '' or str(v)
-                        v = string.split(v, "\n")
-                        t = s.leftPadding+s.rightPadding + max(map(lambda a, b=s.fontname,
-                                    c=s.fontsize,d=pdfmetrics.stringWidth: d(a,b,c), v))
+                        t = t + s.leftPadding+s.rightPadding
                     if t>w: w = t   #record a new maximum
                     i = i + 1
 
@@ -290,6 +287,22 @@
 
         self._width = width
 
+    def _elementWidth(self,v,s):
+        t = type(v)
+        if t in _SeqTypes:
+            w = 0
+            for e in v:
+                ew = self._elementWidth(self,v)
+                if ew is None: return None
+                w = max(w,ew)
+            return w
+        elif isinstance(v,Flowable) and v._fixedWidth:
+            return v.width
+        else:
+            if t is not StringType: v = v is None and '' or str(v)
+            v = string.split(v, "\n")
+            return max(map(lambda a, b=s.fontname, c=s.fontsize,d=pdfmetrics.stringWidth: d(a,b,c), v))
+
     def _calc_height(self):
 
         H = self._argH
@@ -358,7 +371,7 @@
         #and assign some withs in a dumb way.
         #this CHANGES the widths array.
         if None in self._colWidths:
-            if self._hasUnsizableElements():
+            if self._hasVariWidthElements():
                 self._calcPreliminaryWidths(availWidth)
 
         # need to know which cells are part of spanned
@@ -385,7 +398,7 @@
             #from the underlying grid
             self._calcSpanRects()
 
-    def _hasUnsizableElements(self, upToRow=None):
+    def _hasVariWidthElements(self, upToRow=None):
         """Check for flowables in table cells and warn up front.
 
         Allow a couple which we know are fixed size such as
@@ -395,20 +408,20 @@
         for row in range(min(self._nrows, upToRow)):
             for col in range(self._ncols):
                 value = self._cellvalues[row][col]
-                if not self._canSize(value):
+                if not self._canGetWidth(value):
                     bad = 1
                     #raise Exception('Unsizable elements found at row %d column %d in table with content:\n %s' % (row, col, value))
         return bad
 
-    def _canSize(self, thing):
+    def _canGetWidth(self, thing):
         "Can we work out the width quickly?"
         if type(thing) in (ListType, TupleType):
             for elem in thing:
-                if not self._canSize(elem):
+                if not self._canGetWidth(elem):
                     return 0
             return 1
         elif isinstance(thing, Flowable):
-            return 0  # must loosen this up
+            return thing._fixedWidth  # must loosen this up
         else: #string, number, None etc.
             #anything else gets passed to str(...)
             # so should be sizable
@@ -441,7 +454,7 @@
                 siz = 1
                 for rowNo in range(self._nrows):
                     value = self._cellvalues[rowNo][colNo]
-                    if not self._canSize(value):
+                    if not self._canGetWidth(value):
                         siz = 0
                         break
                 if siz:
@@ -472,7 +485,6 @@
         self._argW = newColWidths
         if verbose: print 'new widths are:', self._colWidths
         
-
     def _calcSpanRanges(self):
         """Work out rects for tables which do row and column spanning.