~toolpart/openobject-server/toolpart

« back to all changes in this revision

Viewing changes to bin/reportlab/graphics/charts/linecharts.py

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#Copyright ReportLab Europe Ltd. 2000-2004
 
2
#see license.txt for license details
 
3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/charts/linecharts.py
 
4
"""
 
5
This modules defines a very preliminary Line Chart example.
 
6
"""
 
7
__version__=''' $Id$ '''
 
8
 
 
9
import string
 
10
from types import FunctionType, StringType
 
11
 
 
12
from reportlab.lib import colors
 
13
from reportlab.lib.validators import isNumber, isColor, isColorOrNone, isListOfStrings, \
 
14
                                    isListOfStringsOrNone, SequenceOf, isBoolean, NoneOr, \
 
15
                                    isListOfNumbersOrNone
 
16
from reportlab.lib.attrmap import *
 
17
from reportlab.lib.formatters import Formatter
 
18
from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection, PropHolder
 
19
from reportlab.graphics.shapes import Line, Rect, Group, Drawing, Polygon, PolyLine
 
20
from reportlab.graphics.widgets.signsandsymbols import NoEntry
 
21
from reportlab.graphics.charts.axes import XCategoryAxis, YValueAxis
 
22
from reportlab.graphics.charts.textlabels import Label
 
23
from reportlab.graphics.widgets.markers import uSymbol2Symbol, isSymbol, makeMarker
 
24
from reportlab.graphics.charts.areas import PlotArea
 
25
 
 
26
class LineChartProperties(PropHolder):
 
27
    _attrMap = AttrMap(
 
28
        strokeWidth = AttrMapValue(isNumber, desc='Width of a line.'),
 
29
        strokeColor = AttrMapValue(isColorOrNone, desc='Color of a line.'),
 
30
        strokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array of a line.'),
 
31
        symbol = AttrMapValue(NoneOr(isSymbol), desc='Widget placed at data points.'),
 
32
        )
 
33
 
 
34
class LineChart(PlotArea):
 
35
    pass
 
36
 
 
37
# This is conceptually similar to the VerticalBarChart.
 
38
# Still it is better named HorizontalLineChart... :-/
 
39
 
 
40
class HorizontalLineChart(LineChart):
 
41
    """Line chart with multiple lines.
 
42
 
 
43
    A line chart is assumed to have one category and one value axis.
 
44
    Despite its generic name this particular line chart class has
 
45
    a vertical value axis and a horizontal category one. It may
 
46
    evolve into individual horizontal and vertical variants (like
 
47
    with the existing bar charts).
 
48
 
 
49
    Available attributes are:
 
50
 
 
51
        x: x-position of lower-left chart origin
 
52
        y: y-position of lower-left chart origin
 
53
        width: chart width
 
54
        height: chart height
 
55
 
 
56
        useAbsolute: disables auto-scaling of chart elements (?)
 
57
        lineLabelNudge: distance of data labels to data points
 
58
        lineLabels: labels associated with data values
 
59
        lineLabelFormat: format string or callback function
 
60
        groupSpacing: space between categories
 
61
 
 
62
        joinedLines: enables drawing of lines
 
63
 
 
64
        strokeColor: color of chart lines (?)
 
65
        fillColor: color for chart background (?)
 
66
        lines: style list, used cyclically for data series
 
67
 
 
68
        valueAxis: value axis object
 
69
        categoryAxis: category axis object
 
70
        categoryNames: category names
 
71
 
 
72
        data: chart data, a list of data series of equal length
 
73
    """
 
74
 
 
75
    _attrMap = AttrMap(BASE=LineChart,
 
76
        useAbsolute = AttrMapValue(isNumber, desc='Flag to use absolute spacing values.'),
 
77
        lineLabelNudge = AttrMapValue(isNumber, desc='Distance between a data point and its label.'),
 
78
        lineLabels = AttrMapValue(None, desc='Handle to the list of data point labels.'),
 
79
        lineLabelFormat = AttrMapValue(None, desc='Formatting string or function used for data point labels.'),
 
80
        lineLabelArray = AttrMapValue(None, desc='explicit array of line label values, must match size of data if present.'),
 
81
        groupSpacing = AttrMapValue(isNumber, desc='? - Likely to disappear.'),
 
82
        joinedLines = AttrMapValue(isNumber, desc='Display data points joined with lines if true.'),
 
83
        lines = AttrMapValue(None, desc='Handle of the lines.'),
 
84
        valueAxis = AttrMapValue(None, desc='Handle of the value axis.'),
 
85
        categoryAxis = AttrMapValue(None, desc='Handle of the category axis.'),
 
86
        categoryNames = AttrMapValue(isListOfStringsOrNone, desc='List of category names.'),
 
87
        data = AttrMapValue(None, desc='Data to be plotted, list of (lists of) numbers.'),
 
88
        inFill = AttrMapValue(isBoolean, desc='Whether infilling should be done.'),
 
89
        reversePlotOrder = AttrMapValue(isBoolean, desc='If true reverse plot order.'),
 
90
        annotations = AttrMapValue(None, desc='list of callables, will be called with self, xscale, yscale.'),
 
91
        )
 
92
 
 
93
    def __init__(self):
 
94
        LineChart.__init__(self)
 
95
 
 
96
        # Allow for a bounding rectangle.
 
97
        self.strokeColor = None
 
98
        self.fillColor = None
 
99
 
 
100
        # Named so we have less recoding for the horizontal one :-)
 
101
        self.categoryAxis = XCategoryAxis()
 
102
        self.valueAxis = YValueAxis()
 
103
 
 
104
        # This defines two series of 3 points.  Just an example.
 
105
        self.data = [(100,110,120,130),
 
106
                     (70, 80, 80, 90)]
 
107
        self.categoryNames = ('North','South','East','West')
 
108
 
 
109
        self.lines = TypedPropertyCollection(LineChartProperties)
 
110
        self.lines.strokeWidth = 1
 
111
        self.lines[0].strokeColor = colors.red
 
112
        self.lines[1].strokeColor = colors.green
 
113
        self.lines[2].strokeColor = colors.blue
 
114
 
 
115
        # control spacing. if useAbsolute = 1 then
 
116
        # the next parameters are in points; otherwise
 
117
        # they are 'proportions' and are normalized to
 
118
        # fit the available space.
 
119
        self.useAbsolute = 0   #- not done yet
 
120
        self.groupSpacing = 1 #5
 
121
 
 
122
        self.lineLabels = TypedPropertyCollection(Label)
 
123
        self.lineLabelFormat = None
 
124
        self.lineLabelArray = None
 
125
 
 
126
        # This says whether the origin is above or below
 
127
        # the data point. +10 means put the origin ten points
 
128
        # above the data point if value > 0, or ten
 
129
        # points below if data value < 0.  This is different
 
130
        # to label dx/dy which are not dependent on the
 
131
        # sign of the data.
 
132
        self.lineLabelNudge = 10
 
133
        # If you have multiple series, by default they butt
 
134
        # together.
 
135
 
 
136
        # New line chart attributes.
 
137
        self.joinedLines = 1 # Connect items with straight lines.
 
138
        self.inFill = 0
 
139
        self.reversePlotOrder = 0
 
140
 
 
141
 
 
142
    def demo(self):
 
143
        """Shows basic use of a line chart."""
 
144
 
 
145
        drawing = Drawing(200, 100)
 
146
 
 
147
        data = [
 
148
                (13, 5, 20, 22, 37, 45, 19, 4),
 
149
                (14, 10, 21, 28, 38, 46, 25, 5)
 
150
                ]
 
151
 
 
152
        lc = HorizontalLineChart()
 
153
 
 
154
        lc.x = 20
 
155
        lc.y = 10
 
156
        lc.height = 85
 
157
        lc.width = 170
 
158
        lc.data = data
 
159
        lc.lines.symbol = makeMarker('Circle')
 
160
 
 
161
        drawing.add(lc)
 
162
 
 
163
        return drawing
 
164
 
 
165
 
 
166
    def calcPositions(self):
 
167
        """Works out where they go.
 
168
 
 
169
        Sets an attribute _positions which is a list of
 
170
        lists of (x, y) matching the data.
 
171
        """
 
172
 
 
173
        self._seriesCount = len(self.data)
 
174
        self._rowLength = max(map(len,self.data))
 
175
 
 
176
        if self.useAbsolute:
 
177
            # Dimensions are absolute.
 
178
            normFactor = 1.0
 
179
        else:
 
180
            # Dimensions are normalized to fit.
 
181
            normWidth = self.groupSpacing
 
182
            availWidth = self.categoryAxis.scale(0)[1]
 
183
            normFactor = availWidth / normWidth
 
184
 
 
185
        self._positions = []
 
186
        for rowNo in range(len(self.data)):
 
187
            lineRow = []
 
188
            for colNo in range(len(self.data[rowNo])):
 
189
                datum = self.data[rowNo][colNo]
 
190
                if datum is not None:
 
191
                    (groupX, groupWidth) = self.categoryAxis.scale(colNo)
 
192
                    x = groupX + (0.5 * self.groupSpacing * normFactor)
 
193
                    y = self.valueAxis.scale(0)
 
194
                    height = self.valueAxis.scale(datum) - y
 
195
                    lineRow.append((x, y+height))
 
196
            self._positions.append(lineRow)
 
197
 
 
198
 
 
199
    def _innerDrawLabel(self, rowNo, colNo, x, y):
 
200
        "Draw a label for a given item in the list."
 
201
 
 
202
        labelFmt = self.lineLabelFormat
 
203
        labelValue = self.data[rowNo][colNo]
 
204
 
 
205
        if labelFmt is None:
 
206
            labelText = None
 
207
        elif type(labelFmt) is StringType:
 
208
            if labelFmt == 'values':
 
209
                labelText = self.lineLabelArray[rowNo][colNo]
 
210
            else:
 
211
                labelText = labelFmt % labelValue
 
212
        elif type(labelFmt) is FunctionType:
 
213
            labelText = labelFmt(labelValue)
 
214
        elif isinstance(labelFmt, Formatter):
 
215
            labelText = labelFmt(labelValue)
 
216
        else:
 
217
            msg = "Unknown formatter type %s, expected string or function"
 
218
            raise Exception, msg % labelFmt
 
219
 
 
220
        if labelText:
 
221
            label = self.lineLabels[(rowNo, colNo)]
 
222
            # Make sure labels are some distance off the data point.
 
223
            if y > 0:
 
224
                label.setOrigin(x, y + self.lineLabelNudge)
 
225
            else:
 
226
                label.setOrigin(x, y - self.lineLabelNudge)
 
227
            label.setText(labelText)
 
228
        else:
 
229
            label = None
 
230
        return label
 
231
 
 
232
    def drawLabel(self, G, rowNo, colNo, x, y):
 
233
        '''Draw a label for a given item in the list.
 
234
        G must have an add method'''
 
235
        G.add(self._innerDrawLabel(rowNo,colNo,x,y))
 
236
 
 
237
    def makeLines(self):
 
238
        g = Group()
 
239
 
 
240
        labelFmt = self.lineLabelFormat
 
241
        P = range(len(self._positions))
 
242
        if self.reversePlotOrder: P.reverse()
 
243
        inFill = self.inFill
 
244
        if inFill:
 
245
            inFillY = self.categoryAxis._y
 
246
            inFillX0 = self.valueAxis._x
 
247
            inFillX1 = inFillX0 + self.categoryAxis._length
 
248
            inFillG = getattr(self,'_inFillG',g)
 
249
 
 
250
        # Iterate over data rows.
 
251
        for rowNo in P:
 
252
            row = self._positions[rowNo]
 
253
            styleCount = len(self.lines)
 
254
            styleIdx = rowNo % styleCount
 
255
            rowStyle = self.lines[styleIdx]
 
256
            rowColor = rowStyle.strokeColor
 
257
            dash = getattr(rowStyle, 'strokeDashArray', None)
 
258
 
 
259
            if hasattr(self.lines[styleIdx], 'strokeWidth'):
 
260
                strokeWidth = self.lines[styleIdx].strokeWidth
 
261
            elif hasattr(self.lines, 'strokeWidth'):
 
262
                strokeWidth = self.lines.strokeWidth
 
263
            else:
 
264
                strokeWidth = None
 
265
 
 
266
            # Iterate over data columns.
 
267
            if self.joinedLines:
 
268
                points = []
 
269
                for colNo in range(len(row)):
 
270
                    points += row[colNo]
 
271
                if inFill:
 
272
                    points = points + [inFillX1,inFillY,inFillX0,inFillY]
 
273
                    inFillG.add(Polygon(points,fillColor=rowColor,strokeColor=rowColor,strokeWidth=0.1))
 
274
                else:
 
275
                    line = PolyLine(points,strokeColor=rowColor,strokeLineCap=0,strokeLineJoin=1)
 
276
                    if strokeWidth:
 
277
                        line.strokeWidth = strokeWidth
 
278
                    if dash:
 
279
                        line.strokeDashArray = dash
 
280
                    g.add(line)
 
281
 
 
282
            if hasattr(self.lines[styleIdx], 'symbol'):
 
283
                uSymbol = self.lines[styleIdx].symbol
 
284
            elif hasattr(self.lines, 'symbol'):
 
285
                uSymbol = self.lines.symbol
 
286
            else:
 
287
                uSymbol = None
 
288
 
 
289
            if uSymbol:
 
290
                for colNo in range(len(row)):
 
291
                    x1, y1 = row[colNo]
 
292
                    symbol = uSymbol2Symbol(uSymbol,x1,y1,rowStyle.strokeColor)
 
293
                    if symbol: g.add(symbol)
 
294
 
 
295
            # Draw item labels.
 
296
            for colNo in range(len(row)):
 
297
                x1, y1 = row[colNo]
 
298
                self.drawLabel(g, rowNo, colNo, x1, y1)
 
299
 
 
300
        return g
 
301
 
 
302
    def draw(self):
 
303
        "Draws itself."
 
304
 
 
305
        vA, cA = self.valueAxis, self.categoryAxis
 
306
        vA.setPosition(self.x, self.y, self.height)
 
307
        if vA: vA.joinAxis = cA
 
308
        if cA: cA.joinAxis = vA
 
309
        vA.configure(self.data)
 
310
 
 
311
        # If zero is in chart, put x axis there, otherwise
 
312
        # use bottom.
 
313
        xAxisCrossesAt = vA.scale(0)
 
314
        if ((xAxisCrossesAt > self.y + self.height) or (xAxisCrossesAt < self.y)):
 
315
            y = self.y
 
316
        else:
 
317
            y = xAxisCrossesAt
 
318
 
 
319
        cA.setPosition(self.x, y, self.width)
 
320
        cA.configure(self.data)
 
321
 
 
322
        self.calcPositions()
 
323
 
 
324
        g = Group()
 
325
        g.add(self.makeBackground())
 
326
        if self.inFill:
 
327
            self._inFillG = Group()
 
328
            g.add(self._inFillG)
 
329
 
 
330
        g.add(cA)
 
331
        g.add(vA)
 
332
        vA.gridStart = cA._x
 
333
        vA.gridEnd = cA._x+cA._length
 
334
        cA.gridStart = vA._y
 
335
        cA.gridEnd = vA._y+vA._length
 
336
        cA.makeGrid(g,parent=self)
 
337
        vA.makeGrid(g,parent=self)
 
338
        g.add(self.makeLines())
 
339
        for a in getattr(self,'annotations',()): g.add(a(self,cA.scale,vA.scale))
 
340
        return g
 
341
 
 
342
def _cmpFakeItem(a,b):
 
343
    '''t, z0, z1, x, y = a[:5]'''
 
344
    return cmp((-a[1],a[3],a[0],-a[4]),(-b[1],b[3],b[0],-b[4]))
 
345
 
 
346
class _FakeGroup:
 
347
    def __init__(self):
 
348
        self._data = []
 
349
 
 
350
    def add(self,what):
 
351
        if what: self._data.append(what)
 
352
 
 
353
    def value(self):
 
354
        return self._data
 
355
 
 
356
    def sort(self):
 
357
        self._data.sort(_cmpFakeItem)
 
358
        #for t in self._data: print t
 
359
 
 
360
class HorizontalLineChart3D(HorizontalLineChart):
 
361
    _attrMap = AttrMap(BASE=HorizontalLineChart,
 
362
        theta_x = AttrMapValue(isNumber, desc='dx/dz'),
 
363
        theta_y = AttrMapValue(isNumber, desc='dy/dz'),
 
364
        zDepth = AttrMapValue(isNumber, desc='depth of an individual series'),
 
365
        zSpace = AttrMapValue(isNumber, desc='z gap around series'),
 
366
        )
 
367
    theta_x = .5
 
368
    theta_y = .5
 
369
    zDepth = 10
 
370
    zSpace = 3
 
371
 
 
372
    def calcPositions(self):
 
373
        HorizontalLineChart.calcPositions(self)
 
374
        nSeries = self._seriesCount
 
375
        zSpace = self.zSpace
 
376
        zDepth = self.zDepth
 
377
        if self.categoryAxis.style=='parallel_3d':
 
378
            _3d_depth = nSeries*zDepth+(nSeries+1)*zSpace
 
379
        else:
 
380
            _3d_depth = zDepth + 2*zSpace
 
381
        self._3d_dx = self.theta_x*_3d_depth
 
382
        self._3d_dy = self.theta_y*_3d_depth
 
383
 
 
384
    def _calc_z0(self,rowNo):
 
385
        zSpace = self.zSpace
 
386
        if self.categoryAxis.style=='parallel_3d':
 
387
            z0 = rowNo*(self.zDepth+zSpace)+zSpace
 
388
        else:
 
389
            z0 = zSpace
 
390
        return z0
 
391
 
 
392
    def _zadjust(self,x,y,z):
 
393
        return x+z*self.theta_x, y+z*self.theta_y
 
394
 
 
395
    def makeLines(self):
 
396
        labelFmt = self.lineLabelFormat
 
397
        P = range(len(self._positions))
 
398
        if self.reversePlotOrder: P.reverse()
 
399
        inFill = self.inFill
 
400
        assert not inFill, "inFill not supported for 3d yet"
 
401
        #if inFill:
 
402
            #inFillY = self.categoryAxis._y
 
403
            #inFillX0 = self.valueAxis._x
 
404
            #inFillX1 = inFillX0 + self.categoryAxis._length
 
405
            #inFillG = getattr(self,'_inFillG',g)
 
406
        zDepth = self.zDepth
 
407
        _zadjust = self._zadjust
 
408
        theta_x = self.theta_x
 
409
        theta_y = self.theta_y
 
410
        F = _FakeGroup()
 
411
        from utils3d import _make_3d_line_info
 
412
        tileWidth = getattr(self,'_3d_tilewidth',None)
 
413
        if not tileWidth and self.categoryAxis.style!='parallel_3d': tileWidth = 1
 
414
 
 
415
        # Iterate over data rows.
 
416
        for rowNo in P:
 
417
            row = self._positions[rowNo]
 
418
            n = len(row)
 
419
            styleCount = len(self.lines)
 
420
            styleIdx = rowNo % styleCount
 
421
            rowStyle = self.lines[styleIdx]
 
422
            rowColor = rowStyle.strokeColor
 
423
            dash = getattr(rowStyle, 'strokeDashArray', None)
 
424
            z0 = self._calc_z0(rowNo)
 
425
            z1 = z0 + zDepth
 
426
 
 
427
            if hasattr(self.lines[styleIdx], 'strokeWidth'):
 
428
                strokeWidth = self.lines[styleIdx].strokeWidth
 
429
            elif hasattr(self.lines, 'strokeWidth'):
 
430
                strokeWidth = self.lines.strokeWidth
 
431
            else:
 
432
                strokeWidth = None
 
433
 
 
434
            # Iterate over data columns.
 
435
            if self.joinedLines:
 
436
                if n:
 
437
                    x0, y0 = row[0]
 
438
                    for colNo in xrange(1,n):
 
439
                        x1, y1 = row[colNo]
 
440
                        _make_3d_line_info( F, x0, x1, y0, y1, z0, z1,
 
441
                                theta_x, theta_y,
 
442
                                rowColor, fillColorShaded=None, tileWidth=tileWidth,
 
443
                                strokeColor=None, strokeWidth=None, strokeDashArray=None,
 
444
                                shading=0.1)
 
445
                        x0, y0 = x1, y1
 
446
 
 
447
            if hasattr(self.lines[styleIdx], 'symbol'):
 
448
                uSymbol = self.lines[styleIdx].symbol
 
449
            elif hasattr(self.lines, 'symbol'):
 
450
                uSymbol = self.lines.symbol
 
451
            else:
 
452
                uSymbol = None
 
453
 
 
454
            if uSymbol:
 
455
                for colNo in xrange(n):
 
456
                    x1, y1 = row[colNo]
 
457
                    x1, y1 = _zadjust(x1,y1,z0)
 
458
                    symbol = uSymbol2Symbol(uSymbol,x1,y1,rowColor)
 
459
                    if symbol: F.add((2,z0,z0,x1,y1,symbol))
 
460
 
 
461
            # Draw item labels.
 
462
            for colNo in xrange(n):
 
463
                x1, y1 = row[colNo]
 
464
                x1, y1 = _zadjust(x1,y1,z0)
 
465
                L = self._innerDrawLabel(rowNo, colNo, x1, y1)
 
466
                if L: F.add((2,z0,z0,x1,y1,L))
 
467
 
 
468
        F.sort()
 
469
        g = Group()
 
470
        map(lambda x,a=g.add: a(x[-1]),F.value())
 
471
        return g
 
472
 
 
473
class VerticalLineChart(LineChart):
 
474
    pass
 
475
 
 
476
 
 
477
def sample1():
 
478
    drawing = Drawing(400, 200)
 
479
 
 
480
    data = [
 
481
            (13, 5, 20, 22, 37, 45, 19, 4),
 
482
            (5, 20, 46, 38, 23, 21, 6, 14)
 
483
            ]
 
484
 
 
485
    lc = HorizontalLineChart()
 
486
 
 
487
    lc.x = 50
 
488
    lc.y = 50
 
489
    lc.height = 125
 
490
    lc.width = 300
 
491
    lc.data = data
 
492
    lc.joinedLines = 1
 
493
    lc.lines.symbol = makeMarker('FilledDiamond')
 
494
    lc.lineLabelFormat = '%2.0f'
 
495
 
 
496
    catNames = string.split('Jan Feb Mar Apr May Jun Jul Aug', ' ')
 
497
    lc.categoryAxis.categoryNames = catNames
 
498
    lc.categoryAxis.labels.boxAnchor = 'n'
 
499
 
 
500
    lc.valueAxis.valueMin = 0
 
501
    lc.valueAxis.valueMax = 60
 
502
    lc.valueAxis.valueStep = 15
 
503
 
 
504
    drawing.add(lc)
 
505
 
 
506
    return drawing
 
507
 
 
508
 
 
509
class SampleHorizontalLineChart(HorizontalLineChart):
 
510
    "Sample class overwriting one method to draw additional horizontal lines."
 
511
 
 
512
    def demo(self):
 
513
        """Shows basic use of a line chart."""
 
514
 
 
515
        drawing = Drawing(200, 100)
 
516
 
 
517
        data = [
 
518
                (13, 5, 20, 22, 37, 45, 19, 4),
 
519
                (14, 10, 21, 28, 38, 46, 25, 5)
 
520
                ]
 
521
 
 
522
        lc = SampleHorizontalLineChart()
 
523
 
 
524
        lc.x = 20
 
525
        lc.y = 10
 
526
        lc.height = 85
 
527
        lc.width = 170
 
528
        lc.data = data
 
529
        lc.strokeColor = colors.white
 
530
        lc.fillColor = colors.HexColor(0xCCCCCC)
 
531
 
 
532
        drawing.add(lc)
 
533
 
 
534
        return drawing
 
535
 
 
536
 
 
537
    def makeBackground(self):
 
538
        g = Group()
 
539
 
 
540
        g.add(HorizontalLineChart.makeBackground(self))
 
541
 
 
542
        valAxis = self.valueAxis
 
543
        valTickPositions = valAxis._tickValues
 
544
 
 
545
        for y in valTickPositions:
 
546
            y = valAxis.scale(y)
 
547
            g.add(Line(self.x, y, self.x+self.width, y,
 
548
                       strokeColor = self.strokeColor))
 
549
 
 
550
        return g
 
551
 
 
552
 
 
553
 
 
554
def sample1a():
 
555
    drawing = Drawing(400, 200)
 
556
 
 
557
    data = [
 
558
            (13, 5, 20, 22, 37, 45, 19, 4),
 
559
            (5, 20, 46, 38, 23, 21, 6, 14)
 
560
            ]
 
561
 
 
562
    lc = SampleHorizontalLineChart()
 
563
 
 
564
    lc.x = 50
 
565
    lc.y = 50
 
566
    lc.height = 125
 
567
    lc.width = 300
 
568
    lc.data = data
 
569
    lc.joinedLines = 1
 
570
    lc.strokeColor = colors.white
 
571
    lc.fillColor = colors.HexColor(0xCCCCCC)
 
572
    lc.lines.symbol = makeMarker('FilledDiamond')
 
573
    lc.lineLabelFormat = '%2.0f'
 
574
 
 
575
    catNames = string.split('Jan Feb Mar Apr May Jun Jul Aug', ' ')
 
576
    lc.categoryAxis.categoryNames = catNames
 
577
    lc.categoryAxis.labels.boxAnchor = 'n'
 
578
 
 
579
    lc.valueAxis.valueMin = 0
 
580
    lc.valueAxis.valueMax = 60
 
581
    lc.valueAxis.valueStep = 15
 
582
 
 
583
    drawing.add(lc)
 
584
 
 
585
    return drawing
 
586
 
 
587
 
 
588
def sample2():
 
589
    drawing = Drawing(400, 200)
 
590
 
 
591
    data = [
 
592
            (13, 5, 20, 22, 37, 45, 19, 4),
 
593
            (5, 20, 46, 38, 23, 21, 6, 14)
 
594
            ]
 
595
 
 
596
    lc = HorizontalLineChart()
 
597
 
 
598
    lc.x = 50
 
599
    lc.y = 50
 
600
    lc.height = 125
 
601
    lc.width = 300
 
602
    lc.data = data
 
603
    lc.joinedLines = 1
 
604
    lc.lines.symbol = makeMarker('Smiley')
 
605
    lc.lineLabelFormat = '%2.0f'
 
606
    lc.strokeColor = colors.black
 
607
    lc.fillColor = colors.lightblue
 
608
 
 
609
    catNames = string.split('Jan Feb Mar Apr May Jun Jul Aug', ' ')
 
610
    lc.categoryAxis.categoryNames = catNames
 
611
    lc.categoryAxis.labels.boxAnchor = 'n'
 
612
 
 
613
    lc.valueAxis.valueMin = 0
 
614
    lc.valueAxis.valueMax = 60
 
615
    lc.valueAxis.valueStep = 15
 
616
 
 
617
    drawing.add(lc)
 
618
 
 
619
    return drawing
 
620
 
 
621
 
 
622
def sample3():
 
623
    drawing = Drawing(400, 200)
 
624
 
 
625
    data = [
 
626
            (13, 5, 20, 22, 37, 45, 19, 4),
 
627
            (5, 20, 46, 38, 23, 21, 6, 14)
 
628
            ]
 
629
 
 
630
    lc = HorizontalLineChart()
 
631
 
 
632
    lc.x = 50
 
633
    lc.y = 50
 
634
    lc.height = 125
 
635
    lc.width = 300
 
636
    lc.data = data
 
637
    lc.joinedLines = 1
 
638
    lc.lineLabelFormat = '%2.0f'
 
639
    lc.strokeColor = colors.black
 
640
 
 
641
    lc.lines[0].symbol = makeMarker('Smiley')
 
642
    lc.lines[1].symbol = NoEntry
 
643
    lc.lines[0].strokeWidth = 2
 
644
    lc.lines[1].strokeWidth = 4
 
645
 
 
646
    catNames = string.split('Jan Feb Mar Apr May Jun Jul Aug', ' ')
 
647
    lc.categoryAxis.categoryNames = catNames
 
648
    lc.categoryAxis.labels.boxAnchor = 'n'
 
649
 
 
650
    lc.valueAxis.valueMin = 0
 
651
    lc.valueAxis.valueMax = 60
 
652
    lc.valueAxis.valueStep = 15
 
653
 
 
654
    drawing.add(lc)
 
655
 
 
656
    return drawing