1
from reportlab.lib.colors import blue, _PCMYK_black
2
from reportlab.graphics.charts.textlabels import Label
3
from reportlab.graphics.shapes import Circle, Drawing, Group, Line, Rect, String
4
from reportlab.graphics.widgetbase import Widget
5
from reportlab.lib.attrmap import *
6
from reportlab.lib.validators import *
7
from reportlab.lib.units import cm
8
from reportlab.pdfbase.pdfmetrics import getFont
9
from reportlab.graphics.charts.lineplots import _maxWidth
12
"""Returns a dotbox widget."""
14
#Doesn't use TypedPropertyCollection for labels - this can be a later improvement
16
xlabels = AttrMapValue(isNoneOrListOfNoneOrStrings,
17
desc="List of text labels for boxes on left hand side"),
18
ylabels = AttrMapValue(isNoneOrListOfNoneOrStrings,
19
desc="Text label for second box on left hand side"),
20
labelFontName = AttrMapValue(isString,
21
desc="Name of font used for the labels"),
22
labelFontSize = AttrMapValue(isNumber,
23
desc="Size of font used for the labels"),
24
labelOffset = AttrMapValue(isNumber,
25
desc="Space between label text and grid edge"),
26
strokeWidth = AttrMapValue(isNumber,
27
desc='Width of the grid and dot outline'),
28
gridDivWidth = AttrMapValue(isNumber,
29
desc="Width of each 'box'"),
30
gridColor = AttrMapValue(isColor,
31
desc='Colour for the box and gridding'),
32
dotDiameter = AttrMapValue(isNumber,
33
desc="Diameter of the circle used for the 'dot'"),
34
dotColor = AttrMapValue(isColor,
35
desc='Colour of the circle on the box'),
36
dotXPosition = AttrMapValue(isNumber,
37
desc='X Position of the circle'),
38
dotYPosition = AttrMapValue(isNumber,
39
desc='X Position of the circle'),
40
x = AttrMapValue(isNumber,
41
desc='X Position of dotbox'),
42
y = AttrMapValue(isNumber,
43
desc='Y Position of dotbox'),
47
self.xlabels=["Value", "Blend", "Growth"]
48
self.ylabels=["Small", "Medium", "Large"]
49
self.labelFontName = "Helvetica"
50
self.labelFontSize = 6
52
self.strokeWidth = 0.5
53
self.gridDivWidth=0.5*cm
54
self.gridColor=colors.Color(25/255.0,77/255.0,135/255.0)
55
self.dotDiameter=0.4*cm
56
self.dotColor=colors.Color(232/255.0,224/255.0,119/255.0)
63
def _getDrawingDimensions(self):
64
leftPadding=rightPadding=topPadding=bottomPadding=5
66
tx=len(self.xlabels)*self.gridDivWidth
67
#add padding (and offset)
68
tx=tx+leftPadding+rightPadding+self.labelOffset
69
#add in maximum width of text
70
tx=tx+_maxWidth(self.xlabels, self.labelFontName, self.labelFontSize)
72
ty=len(self.ylabels)*self.gridDivWidth
73
#add padding (and offset)
74
ty=ty+topPadding+bottomPadding+self.labelOffset
75
#add in maximum width of text
76
ty=ty+_maxWidth(self.ylabels, self.labelFontName, self.labelFontSize)
80
def demo(self,drawing=None):
82
tx,ty=self._getDrawingDimensions()
83
drawing = Drawing(tx,ty)
84
drawing.add(self.draw())
91
g.add(Rect(self.x,self.y,len(self.xlabels)*self.gridDivWidth,len(self.ylabels)*self.gridDivWidth,
92
strokeColor=self.gridColor,
93
strokeWidth=self.strokeWidth,
97
for f in range (1,len(self.ylabels)):
99
g.add(Line(strokeColor=self.gridColor,
100
strokeWidth=self.strokeWidth,
102
y1 = self.y+f*self.gridDivWidth,
103
x2 = self.x+len(self.xlabels)*self.gridDivWidth,
104
y2 = self.y+f*self.gridDivWidth))
105
for f in range (1,len(self.xlabels)):
107
g.add(Line(strokeColor=self.gridColor,
108
strokeWidth=self.strokeWidth,
109
x1 = self.x+f*self.gridDivWidth,
111
x2 = self.x+f*self.gridDivWidth,
112
y2 = self.y+len(self.ylabels)*self.gridDivWidth))
115
g.add(Circle(strokeColor=self.gridColor,
116
strokeWidth=self.strokeWidth,
117
fillColor=self.dotColor,
118
cx = self.x+(self.dotXPosition*self.gridDivWidth),
119
cy = self.y+(self.dotYPosition*self.gridDivWidth),
120
r = self.dotDiameter/2.0))
122
#used for centering y-labels (below)
123
ascent=getFont(self.labelFontName).face.ascent
125
ascent=0.718 # default (from helvetica)
126
ascent=ascent*self.labelFontSize # normalize
129
if self.ylabels != None:
130
for f in range (len(self.ylabels)-1,-1,-1):
131
if self.ylabels[f]!= None:
132
g.add(String(strokeColor=self.gridColor,
133
text = self.ylabels[f],
134
fontName = self.labelFontName,
135
fontSize = self.labelFontSize,
136
fillColor=_PCMYK_black,
137
x = self.x-self.labelOffset,
138
y = self.y+(f*self.gridDivWidth+(self.gridDivWidth-ascent)/2.0),
142
if self.xlabels != None:
143
for f in range (0,len(self.xlabels)):
144
if self.xlabels[f]!= None:
146
l.x=self.x+(f*self.gridDivWidth)+(self.gridDivWidth+ascent)/2.0
147
l.y=self.y+(len(self.ylabels)*self.gridDivWidth)+self.labelOffset
150
l.fontName = self.labelFontName
151
l.fontSize = self.labelFontSize
152
l.fillColor = _PCMYK_black
153
l.setText(self.xlabels[f])
163
if __name__ == "__main__":
165
d.demo().save(fnRoot="dotbox")
b'\\ No newline at end of file'