a new table widget has been added
authormeitham
Tue, 22 Sep 2009 11:27:25 +0000
changeset 3228 60250a3b480d
parent 3227 750fe33ccd5e
child 3229 366fafbe1fef
a new table widget has been added
src/reportlab/graphics/widgets/table.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/reportlab/graphics/widgets/table.py	Tue Sep 22 11:27:25 2009 +0000
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+#Copyright ReportLab Europe Ltd. 2000-2004
+#see license.txt for license details
+#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/widgets/grids.py
+__version__=''' $Id$ '''
+
+from reportlab.graphics.widgetbase import Widget
+from reportlab.graphics.charts.textlabels import Label
+from reportlab.graphics import shapes
+from reportlab.lib import colors
+from reportlab.lib.validators import *
+from reportlab.lib.attrmap import *
+
+from reportlab.graphics.shapes import Drawing
+
+class TableWidget(Widget):
+    """A two dimensions table of labels
+    """
+
+    _attrMap = AttrMap(
+        x = AttrMapValue(isNumber, desc="x position of left edge of table"),
+        y = AttrMapValue(isNumber, desc="y position of bottom edge of table"),
+        width = AttrMapValue(isNumber, desc="table width"),
+        height = AttrMapValue(isNumber, desc="table height"),
+        borderStrokeColor = AttrMapValue(isColorOrNone, desc="table border color"),
+        fillColor = AttrMapValue(isColorOrNone, desc="table fill color"),
+        borderStrokeWidth = AttrMapValue(isNumber, desc="border line width"),
+        horizontalDividerStrokeColor = AttrMapValue(isColorOrNone, desc="table inner horizontal lines color"),
+        verticalDividerStrokeColor = AttrMapValue(isColorOrNone, desc="table inner vertical lines color"),
+        horizontalDividerStrokeWidth = AttrMapValue(isNumber, desc="table inner horizontal lines width"),
+        verticalDividerStrokeWidth = AttrMapValue(isNumber, desc="table inner vertical lines width"),
+        dividerDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array for dividerLines.'),
+        data = AttrMapValue(None, desc="a list of list of strings to be displayed in the cells"),
+        boxAnchor = AttrMapValue(isBoxAnchor, desc="location of the table anchoring point"),
+        fontName = AttrMapValue(isString, desc="text font in the table"),
+        fontSize = AttrMapValue(isNumber, desc="font size of the table"),
+        fontColor = AttrMapValue(isColorOrNone, desc="font color"),
+        alignment = AttrMapValue(OneOf("left", "right"), desc="Alignment of text within cells"),
+        textAnchor = AttrMapValue(OneOf('start','middle','end','numeric'), desc="Alignment of text within cells"),
+    )
+
+    def __init__(self, x=10, y=10, **kw):
+
+        self.x = x
+        self.y = y
+        self.width = 200
+        self.height = 100
+        self.borderStrokeColor = colors.black
+        self.fillColor = None
+        self.borderStrokeWidth = 0.5
+        self.horizontalDividerStrokeColor = colors.black
+        self.verticalDividerStrokeColor = colors.black
+        self.horizontalDividerStrokeWidth = 0.5
+        self.verticalDividerStrokeWidth = 0.25
+        self.dividerDashArray = None
+        self.data = [['North','South','East','West'],[100,110,120,130],['A','B','C','D']] # list of rows each row is a list of columns
+        self.boxAnchor = 'nw'
+        #self.fontName = None
+        self.fontSize = 8
+        self.fontColor = colors.black
+        self.alignment = 'right'
+        self.textAnchor = 'start'
+
+
+        for k, v in kw.items():
+            if k in self.__class__._attrMap.keys():
+                setattr(self, k, v)
+                print 'setting %s = %s'%(k, v)
+            else:
+                raise ValueError('invalid argument supplied for class %s'%self.__class__)
+
+    def demo(self):
+        """ returns a sample of this widget with data
+        """
+        d = Drawing(400, 200)
+        t = TableWidget()
+        d.add(t, name='table')
+        d.table.dividerDashArray = (1, 3, 2)
+        d.table.verticalDividerStrokeColor = None
+        d.table.borderStrokeWidth = 0
+        d.table.borderStrokeColor = colors.red
+        return d
+
+    def draw(self):
+        """ returns a group of shapes
+        """
+        g = shapes.Group()
+
+        #overall border and fill
+        if self.borderStrokeColor or self.fillColor: # adds border and filling color
+            rect = shapes.Rect(self.x, self.y, self.width, self.height)
+            rect.fillColor = self.fillColor
+            rect.strokeColor = self.borderStrokeColor
+            rect.strokeWidth = self.borderStrokeWidth
+            g.add(rect)
+
+        #special case - for an empty table we want to avoid divide-by-zero
+        data = self.preProcessData(self.data)
+        rows = len(self.data)
+        cols = len(self.data[0])
+        #print "(rows,cols)=(%s, %s)"%(rows,cols)
+        row_step = self.height / float(rows)
+        col_step = self.width / float(cols)
+        #print "(row_step,col_step)=(%s, %s)"%(row_step,col_step)
+        # draw the grid
+        if self.horizontalDividerStrokeColor:
+            for i in xrange(rows): # make horizontal lines
+                x1 = self.x
+                x2 = self.x + self.width
+                y = self.y + row_step*i
+                #print 'line (%s, %s), (%s, %s)'%(x1, y, x2, y)
+                line = shapes.Line(x1, y, x2, y)
+                line.strokeDashArray = self.dividerDashArray
+                line.strokeWidth = self.horizontalDividerStrokeWidth
+                line.strokeColor = self.horizontalDividerStrokeColor
+                g.add(line)
+        if self.verticalDividerStrokeColor:
+            for i in xrange(cols): # make vertical lines
+                x = self.x+col_step*i
+                y1 = self.y
+                y2 = self.y + self.height
+                #print 'line (%s, %s), (%s, %s)'%(x, y1, x, y2)
+                line = shapes.Line(x, y1, x, y2)
+                line.strokeDashArray = self.dividerDashArray
+                line.strokeWidth = self.verticalDividerStrokeWidth
+                line.strokeColor = self.verticalDividerStrokeColor
+                g.add(line)
+
+        # since we plot data from down up, we reverse the list
+        self.data.reverse()
+        for (j, row) in enumerate(self.data):
+            y = self.y + j*row_step + 0.5*row_step - 0.5 * self.fontSize
+            for (i, datum) in enumerate(row):
+                if datum:
+                    x = self.x + i*col_step + 0.5*col_step
+                    s = shapes.String(x, y, str(datum), textAnchor=self.textAnchor)
+                    s.fontName = self.fontName
+                    s.fontSize = self.fontSize
+                    s.fillColor = self.fontColor
+                    g.add(s)
+        return g
+
+    def preProcessData(self, data):
+        """preprocess and return a new array with at least one row
+        and column (use a None) if needed, and all rows the same
+        length (adding Nones if needed)
+
+        """
+        if not data:
+            return [[None]]
+        #make all rows have similar number of cells, append None when needed
+        max_row = max( [len(x) for x in data] )
+        for rowNo, row in enumerate(data):
+            if len(row) < max_row:
+                row.extend([None]*(max_row-len(row)))
+        return data
+
+#test
+if __name__ == '__main__':
+    d = TableWidget().demo()
+    import os
+    d.save(formats=['pdf'],outDir=os.getcwd(),fnRoot=None)