summaryrefslogtreecommitdiff
path: root/bin/reportlab/graphics/charts/dotbox.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/reportlab/graphics/charts/dotbox.py')
-rw-r--r--bin/reportlab/graphics/charts/dotbox.py165
1 files changed, 165 insertions, 0 deletions
diff --git a/bin/reportlab/graphics/charts/dotbox.py b/bin/reportlab/graphics/charts/dotbox.py
new file mode 100644
index 00000000000..6962d278822
--- /dev/null
+++ b/bin/reportlab/graphics/charts/dotbox.py
@@ -0,0 +1,165 @@
+from reportlab.lib.colors import blue, _PCMYK_black
+from reportlab.graphics.charts.textlabels import Label
+from reportlab.graphics.shapes import Circle, Drawing, Group, Line, Rect, String
+from reportlab.graphics.widgetbase import Widget
+from reportlab.lib.attrmap import *
+from reportlab.lib.validators import *
+from reportlab.lib.units import cm
+from reportlab.pdfbase.pdfmetrics import getFont
+from reportlab.graphics.charts.lineplots import _maxWidth
+
+class DotBox(Widget):
+ """Returns a dotbox widget."""
+
+ #Doesn't use TypedPropertyCollection for labels - this can be a later improvement
+ _attrMap = AttrMap(
+ xlabels = AttrMapValue(isNoneOrListOfNoneOrStrings,
+ desc="List of text labels for boxes on left hand side"),
+ ylabels = AttrMapValue(isNoneOrListOfNoneOrStrings,
+ desc="Text label for second box on left hand side"),
+ labelFontName = AttrMapValue(isString,
+ desc="Name of font used for the labels"),
+ labelFontSize = AttrMapValue(isNumber,
+ desc="Size of font used for the labels"),
+ labelOffset = AttrMapValue(isNumber,
+ desc="Space between label text and grid edge"),
+ strokeWidth = AttrMapValue(isNumber,
+ desc='Width of the grid and dot outline'),
+ gridDivWidth = AttrMapValue(isNumber,
+ desc="Width of each 'box'"),
+ gridColor = AttrMapValue(isColor,
+ desc='Colour for the box and gridding'),
+ dotDiameter = AttrMapValue(isNumber,
+ desc="Diameter of the circle used for the 'dot'"),
+ dotColor = AttrMapValue(isColor,
+ desc='Colour of the circle on the box'),
+ dotXPosition = AttrMapValue(isNumber,
+ desc='X Position of the circle'),
+ dotYPosition = AttrMapValue(isNumber,
+ desc='X Position of the circle'),
+ x = AttrMapValue(isNumber,
+ desc='X Position of dotbox'),
+ y = AttrMapValue(isNumber,
+ desc='Y Position of dotbox'),
+ )
+
+ def __init__(self):
+ self.xlabels=["Value", "Blend", "Growth"]
+ self.ylabels=["Small", "Medium", "Large"]
+ self.labelFontName = "Helvetica"
+ self.labelFontSize = 6
+ self.labelOffset = 5
+ self.strokeWidth = 0.5
+ self.gridDivWidth=0.5*cm
+ self.gridColor=colors.Color(25/255.0,77/255.0,135/255.0)
+ self.dotDiameter=0.4*cm
+ self.dotColor=colors.Color(232/255.0,224/255.0,119/255.0)
+ self.dotXPosition = 1
+ self.dotYPosition = 1
+ self.x = 30
+ self.y = 5
+
+
+ def _getDrawingDimensions(self):
+ leftPadding=rightPadding=topPadding=bottomPadding=5
+ #find width of grid
+ tx=len(self.xlabels)*self.gridDivWidth
+ #add padding (and offset)
+ tx=tx+leftPadding+rightPadding+self.labelOffset
+ #add in maximum width of text
+ tx=tx+_maxWidth(self.xlabels, self.labelFontName, self.labelFontSize)
+ #find height of grid
+ ty=len(self.ylabels)*self.gridDivWidth
+ #add padding (and offset)
+ ty=ty+topPadding+bottomPadding+self.labelOffset
+ #add in maximum width of text
+ ty=ty+_maxWidth(self.ylabels, self.labelFontName, self.labelFontSize)
+ #print (tx, ty)
+ return (tx,ty)
+
+ def demo(self,drawing=None):
+ if not drawing:
+ tx,ty=self._getDrawingDimensions()
+ drawing = Drawing(tx,ty)
+ drawing.add(self.draw())
+ return drawing
+
+ def draw(self):
+ g = Group()
+
+ #box
+ g.add(Rect(self.x,self.y,len(self.xlabels)*self.gridDivWidth,len(self.ylabels)*self.gridDivWidth,
+ strokeColor=self.gridColor,
+ strokeWidth=self.strokeWidth,
+ fillColor=None))
+
+ #internal gridding
+ for f in range (1,len(self.ylabels)):
+ #horizontal
+ g.add(Line(strokeColor=self.gridColor,
+ strokeWidth=self.strokeWidth,
+ x1 = self.x,
+ y1 = self.y+f*self.gridDivWidth,
+ x2 = self.x+len(self.xlabels)*self.gridDivWidth,
+ y2 = self.y+f*self.gridDivWidth))
+ for f in range (1,len(self.xlabels)):
+ #vertical
+ g.add(Line(strokeColor=self.gridColor,
+ strokeWidth=self.strokeWidth,
+ x1 = self.x+f*self.gridDivWidth,
+ y1 = self.y,
+ x2 = self.x+f*self.gridDivWidth,
+ y2 = self.y+len(self.ylabels)*self.gridDivWidth))
+
+ # draw the 'dot'
+ g.add(Circle(strokeColor=self.gridColor,
+ strokeWidth=self.strokeWidth,
+ fillColor=self.dotColor,
+ cx = self.x+(self.dotXPosition*self.gridDivWidth),
+ cy = self.y+(self.dotYPosition*self.gridDivWidth),
+ r = self.dotDiameter/2.0))
+
+ #used for centering y-labels (below)
+ ascent=getFont(self.labelFontName).face.ascent
+ if ascent==0:
+ ascent=0.718 # default (from helvetica)
+ ascent=ascent*self.labelFontSize # normalize
+
+ #do y-labels
+ if self.ylabels != None:
+ for f in range (len(self.ylabels)-1,-1,-1):
+ if self.ylabels[f]!= None:
+ g.add(String(strokeColor=self.gridColor,
+ text = self.ylabels[f],
+ fontName = self.labelFontName,
+ fontSize = self.labelFontSize,
+ fillColor=_PCMYK_black,
+ x = self.x-self.labelOffset,
+ y = self.y+(f*self.gridDivWidth+(self.gridDivWidth-ascent)/2.0),
+ textAnchor = 'end'))
+
+ #do x-labels
+ if self.xlabels != None:
+ for f in range (0,len(self.xlabels)):
+ if self.xlabels[f]!= None:
+ l=Label()
+ l.x=self.x+(f*self.gridDivWidth)+(self.gridDivWidth+ascent)/2.0
+ l.y=self.y+(len(self.ylabels)*self.gridDivWidth)+self.labelOffset
+ l.angle=90
+ l.textAnchor='start'
+ l.fontName = self.labelFontName
+ l.fontSize = self.labelFontSize
+ l.fillColor = _PCMYK_black
+ l.setText(self.xlabels[f])
+ l.boxAnchor = 'sw'
+ l.draw()
+ g.add(l)
+
+ return g
+
+
+
+
+if __name__ == "__main__":
+ d = DotBox()
+ d.demo().save(fnRoot="dotbox") \ No newline at end of file