[Checkins] SVN: z3c.rml/trunk/src/z3c/rml/ Started extending RML to support charts. All you need to do is to run the

Stephan Richter srichter at cosmos.phy.tufts.edu
Wed Mar 14 12:49:55 EDT 2007


Log message for revision 73172:
  Started extending RML to support charts. All you need to do is to run the 
  tests and you can see the output. 
  

Changed:
  U   z3c.rml/trunk/src/z3c/rml/attr.py
  U   z3c.rml/trunk/src/z3c/rml/canvas.py
  A   z3c.rml/trunk/src/z3c/rml/chart.py
  U   z3c.rml/trunk/src/z3c/rml/element.py
  U   z3c.rml/trunk/src/z3c/rml/flowable.py
  A   z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-latin1.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-utf8.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart3d.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-linePlot.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-mergeWith.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart3d.rml
  A   z3c.rml/trunk/src/z3c/rml/tests/input/tag-spiderChart.rml

-=-
Modified: z3c.rml/trunk/src/z3c/rml/attr.py
===================================================================
--- z3c.rml/trunk/src/z3c/rml/attr.py	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/attr.py	2007-03-14 16:49:54 UTC (rev 73172)
@@ -23,6 +23,7 @@
 import reportlab.lib.styles
 import reportlab.lib.units
 import reportlab.lib.utils
+import reportlab.graphics.widgets.markers
 import urllib
 from lxml import etree
 
@@ -39,7 +40,7 @@
         self.name = name
         self.default = default
 
-    def convert(self, value):
+    def convert(self, value, context=None):
         return value
 
     def get(self, element, default=DEFAULT, context=None):
@@ -101,7 +102,6 @@
         if value.startswith('(') and value.endswith(')'):
             value = value[1:-1]
         value = value.strip()
-        v = value
         values = self.splitre.split(value)
         result = [self.valueType.convert(value.strip(), context)
                   for value in values]
@@ -222,6 +222,12 @@
         return self.convert(value, context)
 
 
+class Symbol(Text):
+
+    def convert(self, value, context=None):
+        return reportlab.graphics.widgets.markers.makeMarker(value)
+
+
 class TextNode(Attribute):
     """Text ndoes are not really attributes, but behave mostly like it."""
 

Modified: z3c.rml/trunk/src/z3c/rml/canvas.py
===================================================================
--- z3c.rml/trunk/src/z3c/rml/canvas.py	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/canvas.py	2007-03-14 16:49:54 UTC (rev 73172)
@@ -18,7 +18,8 @@
 __docformat__ = "reStructuredText"
 import zope.interface
 import reportlab.pdfgen.canvas
-from z3c.rml import attr, element, error, flowable, form, interfaces, stylesheet
+from z3c.rml import attr, element, flowable, interfaces, stylesheet
+from z3c.rml import chart, form
 
 
 class DrawString(element.FunctionElement):
@@ -329,11 +330,20 @@
         'skew': Skew,
         'transform': Transform,
         'lineMode': LineMode,
+        # Charts
+        'barChart': chart.BarChart,
+        'barChart3D': chart.BarChart3D,
+        'linePlot': chart.LinePlot,
+        'pieChart': chart.PieChart,
+        'pieChart3D': chart.PieChart3D,
+        'spiderChart': chart.SpiderChart
         }
 
 
 class PageDrawing(Drawing):
 
+    subElements = Drawing.subElements.copy()
+
     def process(self):
         super(Drawing, self).process()
         self.context.showPage()

Added: z3c.rml/trunk/src/z3c/rml/chart.py
===================================================================
--- z3c.rml/trunk/src/z3c/rml/chart.py	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/chart.py	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,652 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Chart Element Processing
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import reportlab.lib.formatters
+from reportlab.graphics import shapes
+from reportlab.graphics.charts import barcharts, lineplots, piecharts
+from reportlab.graphics.charts import spider, doughnut
+from z3c.rml import attr, element
+
+try:
+    import reportlab.graphics.barcode
+except ImportError:
+    # barcode package has not been installed
+    import reportlab.graphics
+    reportlab.graphics.barcode = types.ModuleType('barcode')
+    reportlab.graphics.barcode.getCodeNames = lambda : ()
+
+# Patches against Reportlab 2.0
+lineplots.Formatter = reportlab.lib.formatters.Formatter
+
+
+class PropertyItem(element.Element):
+    attrs = None
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        self.context.append(attrs)
+
+
+class PropertyCollection(element.ContainerElement):
+    propertyName = None
+    attrs = None
+    subElements = None
+
+    def processAttributes(self):
+        prop = getattr(self.context, self.propertyName)
+        # Get global properties
+        attrs = element.extractAttributes(self.attrs, self.element)
+        for name, value in attrs.items():
+            setattr(prop, name, value)
+
+    def process(self):
+        self.processAttributes()
+        # Get item specific properties
+        prop = getattr(self.context, self.propertyName)
+        dataList = []
+        self.processSubElements(dataList)
+        for index, data in enumerate(dataList):
+            for name, value in data.items():
+                setattr(prop[index], name, value)
+
+
+class Text(element.Element):
+    attrs = (
+        attr.Measurement('x'),
+        attr.Measurement('y'),
+        attr.Float('angle', 0),
+        attr.TextNode(),
+        attr.Measurement('fontSize'),
+        attr.Color('fillColor'),
+        attr.Text('fontName'),
+        attr.Choice(
+            'textAnchor',
+            ('start','middle','end','boxauto')),
+        )
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        string = shapes.String(
+            attrs.pop('x'), attrs.pop('y'), attrs.pop('TEXT'))
+        angle = attrs.pop('angle')
+        for name, value in attrs.items():
+            setattr(string, name, value)
+        group = shapes.Group(string)
+        group.translate(0,0)
+        group.rotate(angle)
+        self.parent.parent.drawing.add(group)
+
+
+class Texts(element.ContainerElement):
+    subElements = {'text': Text}
+
+
+class Series(element.Element):
+    attrList = None
+
+    def process(self):
+        attrs = element.extractPositionalArguments(self.attrList, self.element)
+        self.context.append(attrs[0])
+
+class Data(element.ContainerElement):
+    series = None
+
+    def process(self):
+        data = []
+        self.subElements = {'series': self.series}
+        self.processSubElements(data)
+        self.context.data = data
+
+class Series1D(Series):
+    attrList = (attr.TextNodeSequence(attr.Float()),)
+
+class Data1D(Data):
+    series = Series1D
+
+class SingleData1D(Data1D):
+
+    def process(self):
+        data = []
+        self.subElements = {'series': self.series}
+        self.processSubElements(data)
+        self.context.data = data[0]
+
+class Series2D(Series):
+    attrList = (attr.TextNodeGrid(attr.Float(), 2),)
+
+class Data2D(Data):
+    series = Series2D
+
+
+class Bar(PropertyItem):
+    attrs = (
+        attr.Color('strokeColor'),
+        attr.Measurement('strokeWidth'),
+        attr.Color('fillColor') )
+
+
+class Bars(PropertyCollection):
+    propertyName = 'bars'
+    attrs = Bar.attrs
+    subElements = {'bar': Bar}
+
+
+class Label(PropertyItem):
+    attrs = (
+        attr.Measurement('x'),
+        attr.Measurement('y'),
+        attr.Measurement('dx'),
+        attr.Measurement('dy'),
+        attr.Float('angle'),
+        attr.Choice(
+            'boxAnchor',
+            ('nw','n','ne','w','c','e','sw','s','se', 'autox', 'autoy')),
+        attr.Color('boxStrokeColor'),
+        attr.Measurement('boxStrokeWidth'),
+        attr.Color('boxFillColor'),
+        attr.Text('boxTarget'),
+        attr.Color('fillColor'),
+        attr.Color('strokeColor'),
+        attr.Measurement('strokeWidth'),
+        attr.Text('fontName'),
+        attr.Measurement('fontSize'),
+        attr.Measurement('leading'),
+        attr.Measurement('width'),
+        attr.Measurement('maxWidth'),
+        attr.Measurement('height'),
+        attr.Choice('textAnchor', ('start','middle','end','boxauto')),
+        attr.Bool('visible'),
+        attr.Measurement('topPadding'),
+        attr.Measurement('leftPadding'),
+        attr.Measurement('rightPadding'),
+        attr.Measurement('bottomPadding'),
+        attr.TextNode()
+        )
+    attrs[-1].name = 'text'
+
+
+class Labels(PropertyCollection):
+    propertyName = 'labels'
+    attrs = Label.attrs[:-1]
+    subElements = {'label': Label}
+
+
+class Axis(element.ContainerElement):
+    name = ''
+    attrs = (
+        attr.Bool('visible'),
+        attr.Bool('visibleAxis'),
+        attr.Bool('visibleTicks'),
+        attr.Bool('visibleLabels'),
+        attr.Bool('visibleGrid'),
+        attr.Measurement('strokeWidth'),
+        attr.Color('strokeColor'),
+        attr.Sequence('strokeDashArray', attr.Float()),
+        attr.Measurement('gridStrokeWidth'),
+        attr.Color('gridStrokeColor'),
+        attr.Sequence('gridStrokeDashArray', attr.Float()),
+        attr.Measurement('gridStart'),
+        attr.Measurement('gridEnd'),
+        attr.Choice('style', ('parallel', 'stacked', 'parallel_3d')),
+        )
+
+    subElements = {'labels': Labels}
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element, self)
+        axis = getattr(self.context, self.__name__)
+        for name, value in attrs.items():
+            setattr(axis, name, value)
+        self.processSubElements(axis)
+
+
+class Name(element.Element):
+    attrs = (attr.TextNode(),)
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        self.context.append(attrs['TEXT'])
+
+
+class CategoryNames(element.ContainerElement):
+    subElements = {'name': Name}
+
+    def process(self):
+        self.context.categoryNames = []
+        self.processSubElements(self.context.categoryNames)
+
+class CategoryAxis(Axis):
+    name = 'categoryAxis'
+    attrs = Axis.attrs + (
+        attr.Sequence('categoryNames', attr.Text()),
+        attr.Bool('joinAxis'),
+        attr.Measurement('joinAxisPos'),
+        attr.Bool('reverseDirection'),
+        attr.Choice('labelAxisMode', ('high', 'low', 'axis')),
+        attr.Bool('tickShift'),
+        )
+    subElements = Axis.subElements.copy()
+    subElements.update({
+        'categoryNames': CategoryNames,
+        })
+
+class XCategoryAxis(CategoryAxis):
+    attrs = CategoryAxis.attrs + (
+        attr.Measurement('tickUp'),
+        attr.Measurement('tickDown'),
+        attr.Choice('joinAxisMode',
+                    ('bottom', 'top', 'value', 'points', 'None')) )
+
+
+class YCategoryAxis(CategoryAxis):
+    attrs = CategoryAxis.attrs + (
+        attr.Measurement('tickLeft'),
+        attr.Measurement('tickRight'),
+        attr.Choice('joinAxisMode',
+                    ('bottom', 'top', 'value', 'points', 'None')) )
+
+
+class ValueAxis(Axis):
+    name = 'valueAxis'
+    attrs = Axis.attrs + (
+        attr.Bool('forceZero'), # TODO: Support 'near'
+        attr.Measurement('minimumTickSpacing'),
+        attr.Int('maximumTicks'),
+        attr.Text('labelTextFormat'),
+        attr.Text('labelTextPostFormat'),
+        attr.Float('labelTextScale'),
+        attr.Float('valueMin'),
+        attr.Float('valueMax'),
+        attr.Float('valueStep'),
+        attr.Measurement('valueSteps'),
+        attr.Text('rangeRound'),
+        attr.Float('zrangePref'),
+        )
+
+
+class XValueAxis(ValueAxis):
+    attrs = ValueAxis.attrs + (
+        attr.Measurement('tickUp'),
+        attr.Measurement('tickDown'),
+        attr.Bool('joinAxis'),
+        attr.Choice('joinAxisMode',
+                    ('bottom', 'top', 'value', 'points', 'None')),
+        attr.Float('joinAxisPos'),
+        )
+
+class YValueAxis(ValueAxis):
+    attrs = ValueAxis.attrs + (
+        attr.Measurement('tickLeft'),
+        attr.Measurement('tickRight'),
+        attr.Bool('joinAxis'),
+        attr.Choice('joinAxisMode',
+                    ('bottom', 'top', 'value', 'points', 'None')),
+        attr.Float('joinAxisPos'),
+        )
+
+
+class Line(PropertyItem):
+    attrs = (
+        attr.Measurement('strokeWidth'),
+        attr.Color('strokeColor'),
+        attr.Sequence('strokeDashArray', attr.Float()),
+        attr.Symbol('symbol'),
+        attr.Text('name'),
+        )
+
+
+class Lines(PropertyCollection):
+    propertyName = 'lines'
+    attrs = Line.attrs[:-1]
+    subElements = {'line': Line}
+
+
+class SliceLabel(Label):
+    attrs = Label.attrs[2:]
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        for name, value in attrs.items():
+            self.context['label_'+name] = value
+        # Now we do not have simple labels anymore
+        self.parent.parent.context.simpleLabels = False
+
+class SlicePointer(element.Element):
+    attrs = (
+        attr.Color('strokeColor'),
+        attr.Measurement('strokeWidth'),
+        attr.Measurement('elbowLength'),
+        attr.Measurement('edgePad'),
+        attr.Measurement('piePad'),
+        )
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        for name, value in attrs.items():
+            self.context['label_pointer_'+name] = value
+
+class Slice(element.ContainerElement):
+    attrs = (
+        attr.Measurement('strokeWidth'),
+        attr.Color('fillColor'),
+        attr.Color('strokeColor'),
+        attr.Sequence('strokeDashArray', attr.Float()),
+        attr.Measurement('popout'),
+        attr.Text('fontName'),
+        attr.Measurement('fontSize'),
+        attr.Measurement('labelRadius'),
+        attr.Symbol('swatchMarker'),
+        )
+
+    subElements = {
+        'label': SliceLabel,
+        'pointer': SlicePointer}
+
+    def process(self):
+        attrs = element.extractAttributes(self.attrs, self.element)
+        self.processSubElements(attrs)
+        self.context.append(attrs)
+
+class Slice3D(Slice):
+    attrs = Slice.attrs + (
+        attr.Color('fillColorShaded'),
+        )
+
+    subElements = {}
+    # Sigh, the 3-D Pie does not support advanced slice labels. :-(
+    #     'label': SliceLabel}
+
+class Slices(element.ContainerElement):
+    attrs = Slice.attrs[:-1]
+    subElements = {'slice': Slice}
+
+    def process(self):
+        # Get global slice properties
+        attrs = element.extractAttributes(self.attrs, self.element)
+        for name, value in attrs.items():
+            setattr(self.context.slices, name, value)
+        # Get slice specific properties
+        slicesData = []
+        self.processSubElements(slicesData)
+        for index, sliceData in enumerate(slicesData):
+            for name, value in sliceData.items():
+                setattr(self.context.slices[index], name, value)
+
+class Slices3D(Slices):
+    attrs = Slice3D.attrs[:-1]
+    subElements = {'slice': Slice3D}
+
+
+class SimpleLabels(element.ContainerElement):
+    subElements = {'label': Name}
+
+    def process(self):
+        self.context.labels = []
+        self.processSubElements(self.context.labels)
+
+
+class Strand(PropertyItem):
+    attrs = (
+        attr.Measurement('strokeWidth'),
+        attr.Color('fillColor'),
+        attr.Color('strokeColor'),
+        attr.Sequence('strokeDashArray', attr.Float()),
+        attr.Symbol('symbol'),
+        attr.Measurement('symbolSize'),
+        attr.Text('name'),
+        )
+
+
+class Strands(PropertyCollection):
+    propertyName = 'strands'
+    attrs = Strand.attrs[:-1]
+    subElements = {'strand': Strand}
+
+
+class StrandLabel(Label):
+    attrs = Label.attrs[2:-1] + (attr.TextNode(),)
+    attrs[-1].name = '_text'
+    attrs += (
+        attr.Int('row'),
+        attr.Int('col'),
+        attr.Attribute('format'),
+        attr.Float('dR')
+        )
+
+class StrandLabels(PropertyCollection):
+    propertyName = 'strandLabels'
+    attrs = StrandLabel.attrs[:-1]
+    subElements = {'label': StrandLabel}
+
+    def process(self):
+        self.processAttributes()
+        # Get item specific properties
+        prop = getattr(self.context, self.propertyName)
+        dataList = []
+        self.processSubElements(dataList)
+        for data in dataList:
+            row = data.pop('row')
+            col = data.pop('col')
+            for name, value in data.items():
+                setattr(prop[row, col], name, value)
+
+
+class Spoke(PropertyItem):
+    attrs = (
+        attr.Measurement('strokeWidth'),
+        attr.Color('fillColor'),
+        attr.Color('strokeColor'),
+        attr.Sequence('strokeDashArray', attr.Float()),
+        attr.Measurement('labelRadius'),
+        attr.Bool('visible'),
+        )
+
+
+class Spokes(PropertyCollection):
+    propertyName = 'spokes'
+    attrs = Spoke.attrs[:-1]
+    subElements = {'spoke': Spoke}
+
+
+class SpokeLabel(Label):
+    attrs = Label.attrs[2:-1] + (attr.TextNode(),)
+    attrs[-1].name = '_text'
+
+class SpokeLabels(PropertyCollection):
+    propertyName = 'spokeLabels'
+    attrs = SpokeLabel.attrs[:-1]
+    subElements = {'label': SpokeLabel}
+
+
+class Chart(element.ContainerElement):
+    attrs = (
+        # Drawing Options
+        attr.Measurement('dx'),
+        attr.Measurement('dy'),
+        attr.Measurement('dwidth'),
+        attr.Measurement('dheight'),
+        attr.Float('angle'),
+        # Plot Area Options
+        attr.Measurement('x'),
+        attr.Measurement('y'),
+        attr.Measurement('width'),
+        attr.Measurement('height'),
+        attr.Color('strokeColor'),
+        attr.Measurement('strokeWidth'),
+        attr.Color('fillColor'),
+        attr.Bool('debug'),
+        )
+
+    subElements = {
+        'texts': Texts
+        }
+
+    def getAttributes(self):
+        attrs = [(attr.name, attr) for attr in self.attrs]
+        return element.extractKeywordArguments(attrs, self.element)
+
+    def createChart(self, attributes):
+        raise NotImplementedError
+
+    def process(self):
+        attrs = self.getAttributes()
+        angle = attrs.pop('angle', 0)
+        x, y = attrs.pop('dx'), attrs.pop('dy')
+        self.drawing = shapes.Drawing(attrs.pop('dwidth'), attrs.pop('dheight'))
+        chart = self.createChart(attrs)
+        self.processSubElements(chart)
+        group = shapes.Group(chart)
+        group.translate(0,0)
+        group.rotate(angle)
+        self.drawing.add(group)
+        self.drawing.drawOn(self.context, x, y)
+
+
+class BarChart(Chart):
+    nameBase = 'BarChart'
+    attrs = Chart.attrs + (
+        attr.Choice('direction', ('horizontal', 'vertical'), 'horizontal'),
+        attr.Bool('useAbsolute', False),
+        attr.Measurement('barWidth', 10),
+        attr.Measurement('groupSpacing', 5),
+        attr.Measurement('barSpacing', 0),
+        )
+
+    subElements = Chart.subElements.copy()
+    subElements.update({
+        'data': Data1D,
+        'bars': Bars,
+        })
+
+    def createChart(self, attrs):
+        direction = attrs.pop('direction')
+        # Setup sub-elements based on direction
+        if direction == 'horizontal':
+            self.subElements['categoryAxis'] = YCategoryAxis
+            self.subElements['valueAxis'] = XValueAxis
+        else:
+            self.subElements['categoryAxis'] = XCategoryAxis
+            self.subElements['valueAxis'] = YValueAxis
+        # Generate the chart
+        chart = getattr(
+            barcharts, direction.capitalize()+self.nameBase)()
+        for name, value in attrs.items():
+            setattr(chart, name, value)
+        return chart
+
+
+class BarChart3D(BarChart):
+    nameBase = 'BarChart3D'
+    attrs = BarChart.attrs + (
+        attr.Float('theta_x'),
+        attr.Float('theta_y'),
+        attr.Measurement('zDepth'),
+        attr.Measurement('zSpace')
+        )
+
+
+class LinePlot(Chart):
+    attrs = Chart.attrs + (
+        attr.Bool('reversePlotOrder'),
+        attr.Measurement('lineLabelNudge'),
+        attr.Attribute('lineLabelFormat'),
+        attr.Bool('joinedLines'),
+        )
+
+    subElements = Chart.subElements.copy()
+    subElements.update({
+        'data': Data2D,
+        'lines': Lines,
+        'xValueAxis': XValueAxis,
+        'yValueAxis': YValueAxis,
+        'lineLabels': Labels,
+        })
+
+    def createChart(self, attrs):
+        # Generate the chart
+        chart = lineplots.LinePlot()
+        for name, value in attrs.items():
+            setattr(chart, name, value)
+        return chart
+
+class PieChart(Chart):
+    chartClass = piecharts.Pie
+    attrs = Chart.attrs + (
+        attr.Int('startAngle'),
+        attr.Choice('direction', ('clockwise', 'anticlockwise')),
+        attr.Bool('checkLabelOverlap'),
+        attr.Choice('pointerLabelMode',
+                    {'none': None,
+                     'leftright': 'LeftRight',
+                     'leftandright': 'LeftAndRight'}),
+        attr.Bool('sameRadii'),
+        attr.Choice('orderMode', ('fixed', 'alternate')),
+        attr.Measurement('xradius'),
+        attr.Measurement('yradius'),
+        )
+
+    subElements = Chart.subElements.copy()
+    subElements.update({
+        'data': SingleData1D,
+        'slices': Slices,
+        'labels': SimpleLabels,
+        })
+
+    def createChart(self, attrs):
+        # Generate the chart
+        chart = self.chartClass()
+        for name, value in attrs.items():
+            setattr(chart, name, value)
+        return chart
+
+class PieChart3D(PieChart):
+    chartClass = piecharts.Pie3d
+    attrs = PieChart.attrs + (
+        attr.Float('perspective'),
+        attr.Measurement('depth_3d'),
+        attr.Float('angle_3d'),
+        )
+
+    subElements = PieChart.subElements.copy()
+    subElements.update({
+        'slices': Slices3D,
+        })
+
+class SpiderChart(Chart):
+    attrs = Chart.attrs + (
+        attr.Int('startAngle'),
+        attr.Choice('direction', ('clockwise', 'anticlockwise')),
+        attr.Float('startAngle'),
+        )
+
+    subElements = Chart.subElements.copy()
+    subElements.update({
+        'data': Data1D,
+        'strands': Strands,
+        'strandLabels': StrandLabels,
+        'spokes': Spokes,
+        'spokeLabels': SpokeLabels,
+        'labels': SimpleLabels,
+        })
+
+    def createChart(self, attrs):
+        # Generate the chart
+        chart = spider.SpiderChart()
+        for name, value in attrs.items():
+            setattr(chart, name, value)
+        return chart


Property changes on: z3c.rml/trunk/src/z3c/rml/chart.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: z3c.rml/trunk/src/z3c/rml/element.py
===================================================================
--- z3c.rml/trunk/src/z3c/rml/element.py	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/element.py	2007-03-14 16:49:54 UTC (rev 73172)
@@ -38,13 +38,25 @@
         else:
             for subElement in self.element.getchildren():
                 if subElement.tag in self.subElements:
-                    self.subElements[subElement.tag](
-                        subElement, self, context).process()
+                    elem = self.subElements[subElement.tag](
+                        subElement, self, context)
+                    elem.__name__ = subElement.tag
+                    elem.process()
 
+
     def process(self):
         self.processSubElements(self.context)
 
 
+def extractAttributes(attrs, element, context=None):
+    values = {}
+    for Attr in attrs:
+        value = Attr.get(element, context=context)
+        if value is not attr.DEFAULT:
+            values[Attr.name] = value
+    return values
+
+
 def extractPositionalArguments(argsList, element, context=None):
     args = []
     for Attr in argsList:

Modified: z3c.rml/trunk/src/z3c/rml/flowable.py
===================================================================
--- z3c.rml/trunk/src/z3c/rml/flowable.py	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/flowable.py	2007-03-14 16:49:54 UTC (rev 73172)
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Style Related Element Processing
+"""Flowable Element Processing
 
 $Id$
 """

Added: z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-latin1.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-latin1.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-latin1.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+<document filename="encoding-test-latin1.pdf">
+
+  <template>
+    <pageTemplate id="main">
+      <frame id="first" x1="72" y1="72" width="451" height="698"/>
+    </pageTemplate>
+  </template>
+
+  <stylesheet>
+  </stylesheet>
+
+  <story>
+    <title>Test of Encoding: Latin 1</title>
+    <para>
+      This following paragraph contains multiple European symbols.
+    </para>
+     <spacer length="1in" />
+    <para>
+      Das ist ein &#x201E;Deutscher Text&#x201D;: Er hat eine Länge von über einer
+      Zeile. Das ist aber nötig um alle Funktionen zu zeigen. Ach übrigens,
+      unsere Straße ist nicht für &#x20AC;200.000,00 erhältlich.
+    </para>
+  </story>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-utf8.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-utf8.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/encoding-test-utf8.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="no" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+<document filename="encoding-test-utf8.pdf">
+
+  <template>
+    <pageTemplate id="main">
+      <frame id="first" x1="72" y1="72" width="451" height="698"/>
+    </pageTemplate>
+  </template>
+
+  <stylesheet>
+  </stylesheet>
+
+  <story>
+    <title>Test of Encoding: UTF-8</title>
+    <para>
+      This following paragraph contains multiple European symbols.
+    </para>
+     <spacer length="1in" />
+    <para>
+      Das ist ein &#x201E;Deutscher Text&#x201D;: Er hat eine Länge von über einer
+      Zeile. Das ist aber nötig um alle Funktionen zu zeigen. Ach übrigens,
+      unsere Straße ist nicht für &#x20AC;200.000,00 erhältlich.
+    </para>
+  </story>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-barChart.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      Bar Chart Demo
+    </drawCenteredString>
+
+    <barChart
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+        barSpacing="7"
+        groupSpacing="15">
+      <bars>
+        <bar fillColor="blue" strokeColor="red" strokeWidth="0.5" />
+        <bar fillColor="yellow" strokeColor="green" strokeWidth="1" />
+      </bars>
+      <categoryAxis strokeColor="black" strokeWidth="1">
+        <labels fontName="Helvetica" />
+        <categoryNames>
+          <name>Category 1</name>
+          <name>Category 2</name>
+          <name>Category 3</name>
+          <name>Category 4</name>
+        </categoryNames>
+      </categoryAxis>
+      <valueAxis valueMin="0" valueMax="150" valueStep="30"
+                 visibleTicks="true" visibleLabels="true">
+        <labels fontName="Helvetica" />
+      </valueAxis>
+      <data>
+        <series>100 110 120 130</series>
+        <series> 70  80  85  90</series>
+      </data>
+    </barChart>
+
+    <barChart
+        dx="2in" dy="4in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="2in"
+        direction="vertical">
+      <categoryAxis strokeColor="black" strokeWidth="1"
+                    visibleGrid="true">
+        <labels fontName="Helvetica" />
+        <categoryNames>
+          <name>Category 1</name>
+          <name>Category 2</name>
+          <name>Category 3</name>
+          <name>Category 4</name>
+        </categoryNames>
+      </categoryAxis>
+      <valueAxis valueMin="0" valueMax="150" valueStep="30"
+                 visibleTicks="true" visibleLabels="true"
+                 visibleGrid="true">
+        <labels fontName="Helvetica" />
+      </valueAxis>
+      <data>
+        <series>100 110 120 130</series>
+        <series> 70  80  85  90</series>
+      </data>
+    </barChart>
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart3d.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart3d.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-barChart3d.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-barChart3d.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      3-D Bar Chart Demo
+    </drawCenteredString>
+
+    <barChart3D
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+        barSpacing="7"
+        groupSpacing="15">
+      <bars>
+        <bar fillColor="blue" strokeColor="red" strokeWidth="0.5" />
+        <bar fillColor="yellow" strokeColor="green" strokeWidth="1" />
+      </bars>
+      <categoryAxis strokeColor="black" strokeWidth="1">
+        <labels fontName="Helvetica" />
+        <categoryNames>
+          <name>Category 1</name>
+          <name>Category 2</name>
+          <name>Category 3</name>
+          <name>Category 4</name>
+        </categoryNames>
+      </categoryAxis>
+      <valueAxis valueMin="0" valueMax="150" valueStep="30"
+                 visibleTicks="true" visibleLabels="true">
+        <labels fontName="Helvetica" />
+      </valueAxis>
+      <data>
+        <series>100 110 120 130</series>
+        <series> 70  80  85  90</series>
+      </data>
+    </barChart3D>
+
+    <barChart3D
+        dx="2in" dy="4in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="2in"
+         theta_x="0.3" theta_y="0.3" zDepth="5" zSpace="10"
+        direction="vertical">
+      <categoryAxis strokeColor="black" strokeWidth="1"
+                    visibleGrid="true">
+        <labels fontName="Helvetica" />
+        <categoryNames>
+          <name>Category 1</name>
+          <name>Category 2</name>
+          <name>Category 3</name>
+          <name>Category 4</name>
+        </categoryNames>
+      </categoryAxis>
+      <valueAxis valueMin="0" valueMax="150" valueStep="30"
+                 visibleTicks="true" visibleLabels="true"
+                 visibleGrid="true">
+        <labels fontName="Helvetica" />
+      </valueAxis>
+      <data>
+        <series>100 110 120 130</series>
+        <series> 70  80  85  90</series>
+      </data>
+    </barChart3D>
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-linePlot.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-linePlot.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-linePlot.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-linePlot.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      Line Plot Demo
+    </drawCenteredString>
+
+    <linePlot
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+         joinedLines="true" lineLabelFormat="%2.0f">
+      <lines>
+        <line strokeColor="red" symbol="FilledCircle" />
+        <line strokeColor="blue" symbol="FilledDiamond" />
+      </lines>
+      <xValueAxis valueMin="0" valueMax="5" valueStep="1">
+        <labels fontName="Helvetica" />
+      </xValueAxis>
+      <yValueAxis valueMin="0" valueMax="7" valueStep="1">
+        <labels fontName="Helvetica" />
+      </yValueAxis>
+      <data>
+        <series>
+          1   1
+          2   2
+          2.5 1
+          3   3
+          4   5
+        </series>
+        <series>
+          1   2
+          2   3
+          2.5 2
+          3.5 5
+          4   6
+        </series>
+      </data>
+    </linePlot>
+
+    <linePlot
+        dx="2in" dy="3in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+         joinedLines="true">
+      <lines>
+        <line strokeColor="red" strokeDashArray="1 5 5" symbol="FilledCircle" />
+        <line strokeColor="blue" fillColor="black" symbol="FilledDiamond" />
+      </lines>
+      <xValueAxis valueMin="0" valueMax="5" valueStep="1">
+        <labels fontName="Helvetica" />
+      </xValueAxis>
+      <yValueAxis valueMin="0" valueMax="7" valueStep="1">
+        <labels fontName="Helvetica" />
+      </yValueAxis>
+      <texts>
+        <text x="2.5in" y="-0.5in" textAnchor="middle"
+              fontName="Helvetica-Bold" fontSize="13"
+              fillColor="black">
+          X-Axis Label
+        </text>
+        <text x="1.5in" y="0.3in" angle="90" textAnchor="middle"
+              fontName="Helvetica-Bold" fontSize="13"
+              fillColor="red">
+          Y-Axis Label
+        </text>
+      </texts>
+      <data>
+        <series>
+          1   1
+          2   2
+          2.5 1
+          3   3
+          4   5
+        </series>
+        <series>
+          1   2
+          2   3
+          2.5 2
+          3.5 5
+          4   6
+        </series>
+      </data>
+    </linePlot>
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-mergeWith.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-mergeWith.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-mergeWith.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="pdf-template.pdf">
+  <pageDrawing>
+    <!--mergeWith filename="data/w-2.pdf" page="0" /-->
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-pieChart.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      Pie Demo
+    </drawCenteredString>
+
+    <pieChart
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="3in"  height="3in">
+      <labels>
+        <label>a</label>
+        <label>b</label>
+        <label>c</label>
+        <label>d</label>
+        <label>e</label>
+        <label>f</label>
+      </labels>
+      <slices strokeWidth="0.5">
+        <slice fillColor="darkcyan" />
+        <slice fillColor="blueviolet" />
+        <slice fillColor="blue" />
+        <slice fillColor="cyan" popout="10"
+               strokeWidth="2" strokeDashArray="2 2"/>
+        <slice fillColor="aquamarine" />
+        <slice fillColor="cadetblue" />
+        <slice fillColor="lightcoral" />
+      </slices>
+      <data>
+        <series>10 20 30 40 50 60</series>
+      </data>
+    </pieChart>
+
+    <pieChart
+        dx="2in" dy="3in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+         orderMode="fixed" pointerLabelMode="LeftAndRight"
+         sameRadii="true">
+      <slices strokeWidth="0.5" fontSize="10">
+        <slice fillColor="red" strokeColor="darkred">
+          <label dx="10" dy="10" visible="true">Age 1-10</label>
+          <pointer strokeColor="darkred" />
+        </slice>
+        <slice fillColor="lightgreen" strokeColor="darkgreen">
+          <label visible="true">Age 21-30</label>
+          <pointer strokeColor="darkgreen" />
+        </slice>
+        <slice fillColor="blue" strokeColor="darkblue">
+          <label visible="true">Age 31-40</label>
+          <pointer strokeColor="darkblue" />
+        </slice>
+        <slice fillColor="khaki" strokeColor="darkkhaki"
+               popout="10"
+               strokeWidth="2" strokeDashArray="2 2">
+          <label visible="true">Age 41-50</label>
+          <pointer strokeColor="darkkhaki" />
+        </slice>
+        <slice fillColor="orange" strokeColor="darkorange">
+          <label visible="true">Age 51-60</label>
+          <pointer strokeColor="darkorange" />
+        </slice>
+        <slice fillColor="magenta" strokeColor="darkmagenta">
+          <label visible="true">Age 61-70</label>
+          <pointer strokeColor="darkmagenta" />
+        </slice>
+        <slice fillColor="orchid" strokeColor="darkorchid">
+          <label visible="true">Age 71-80</label>
+          <pointer strokeColor="darkorchid" />
+        </slice>
+      </slices>
+      <data>
+        <series>10 20 30 40 50 60</series>
+      </data>
+    </pieChart>
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart3d.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart3d.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-pieChart3d.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-pieChart3d.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      3-D Pie Chart Demo
+    </drawCenteredString>
+
+    <pieChart3D
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="3in"  height="3in">
+      <labels>
+        <label>a</label>
+        <label>b</label>
+        <label>c</label>
+        <label>d</label>
+        <label>e</label>
+        <label>f</label>
+      </labels>
+      <slices strokeWidth="0.5">
+        <slice fillColor="darkcyan" />
+        <slice fillColor="blueviolet" />
+        <slice fillColor="blue" />
+        <slice fillColor="cyan" popout="10"
+               strokeWidth="2" strokeDashArray="2 2"/>
+        <slice fillColor="aquamarine" />
+        <slice fillColor="cadetblue" />
+        <slice fillColor="lightcoral" />
+      </slices>
+      <data>
+        <series>10 20 30 40 50 60</series>
+      </data>
+    </pieChart3D>
+
+    <pieChart3D
+        dx="2in" dy="3in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="5in"  height="3in"
+         orderMode="fixed" pointerLabelMode="LeftAndRight"
+         sameRadii="true" perspective="50" angle_3d="170">
+      <labels>
+        <label>Age  1-10</label>
+        <label>Age 11-20</label>
+        <label>Age 21-30</label>
+        <label>Age 31-40</label>
+        <label>Age 41-50</label>
+        <label>Age 51-60</label>
+      </labels>
+      <slices strokeWidth="0.5">
+        <slice fillColor="red" fillColorShaded="darkred" />
+        <slice fillColor="lightgreen" fillColorShaded="darkgreen" />
+        <slice fillColor="blue" fillColorShaded="darkblue" />
+        <slice fillColor="khaki" fillColorShaded="darkkhaki"
+               popout="10"
+               strokeWidth="2" strokeDashArray="2 2" />
+        <slice fillColor="orange" fillColorShaded="darkorange" />
+        <slice fillColor="magenta" fillColorShaded="darkmagenta" />
+        <slice fillColor="orchid" fillColorShaded="darkorchid" />
+      </slices>
+      <data>
+        <series>10 20 30 40 50 60</series>
+      </data>
+    </pieChart3D>
+
+  </pageDrawing>
+</document>

Added: z3c.rml/trunk/src/z3c/rml/tests/input/tag-spiderChart.rml
===================================================================
--- z3c.rml/trunk/src/z3c/rml/tests/input/tag-spiderChart.rml	2007-03-14 16:19:05 UTC (rev 73171)
+++ z3c.rml/trunk/src/z3c/rml/tests/input/tag-spiderChart.rml	2007-03-14 16:49:54 UTC (rev 73172)
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE document SYSTEM "rml.dtd">
+
+<document filename="tag-spiderChart.pdf">
+
+  <stylesheet>
+  </stylesheet>
+
+  <pageDrawing>
+
+    <setFont name="Helvetica-Bold" size="16" />
+    <drawCenteredString x="4.1in" y="11in">
+      Spider Chart Demo
+    </drawCenteredString>
+
+    <spiderChart
+        dx="2in" dy="7in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="3in"  height="3in">
+      <labels>
+        <label>a</label>
+        <label>b</label>
+        <label>c</label>
+        <label>d</label>
+        <label>e</label>
+        <label>f</label>
+      </labels>
+      <strands>
+        <strand strokeColor="cornsilk" fillColor="cornsilk" />
+        <strand strokeColor="cyan" fillColor="cyan" />
+        <strand strokeColor="palegreen" fillColor="palegreen" />
+      </strands>
+      <spokes strokeDashArray="2 2" />
+      <data>
+        <series>12 14 16 14 12</series>
+        <series>6 8 10 12 9 15</series>
+        <series>7 8 17 4 12 8</series>
+      </data>
+    </spiderChart>
+
+    <spiderChart
+        dx="2in" dy="4in" dwidth="6in" dheight="4in"
+         x="0"    y="0"    width="3in"  height="3in">
+      <spokeLabels fontName="Helvetica-Bold">
+        <label>U</label>
+        <label>V</label>
+        <label>W</label>
+        <label>X</label>
+        <label>Y</label>
+        <label>Z</label>
+      </spokeLabels>
+      <strands symbol="FilledDiamond" symbolSize="6">
+        <strand strokeColor="red" fillColor="pink" />
+        <strand strokeColor="blue" fillColor="yellow"
+                symbol="Circle" strokeWidth="0.5" />
+        <strand strokeColor="green" fillColor="palegreen" />
+      </strands>
+      <strandLabels dR="-5" format="values">
+        <label row="0" col="3" dx="-10">special</label>
+        <label row="0" col="1" dy="5">one</label>
+        <label row="0" col="0" dy="5">zero</label>
+        <label row="1" col="0" dy="10">Earth</label>
+        <label row="2" col="2" dx="10">Mars</label>
+      </strandLabels>
+      <spokes strokeDashArray="2 2" />
+      <data>
+        <series>12 14 16 14 12</series>
+        <series>6 8 10 12 9 15</series>
+        <series>7 8 17 4 12 8</series>
+      </data>
+    </spiderChart>
+
+  </pageDrawing>
+</document>



More information about the Checkins mailing list