[reportlab-users] [patch] value labels for PieChart
Gael Chardon
gael.dev at 4now.net
Mon Sep 25 06:28:22 EDT 2006
Hello,
herefater a little patch that add a new feature to PieChart class.
It optionally draw a value (typically the percent) on each slice.
The idea:
- User sets percentFormat slice attribute to a string or a function ;
- Optionally user can set percentFontName, percentFontSize,
percentFontColor.
- If percentFormat is a string then it is used to format the percent
value (a float) that represent the slice.
- If percentFormat is callable, the function is called for every slice
with two arguments: the current slice value and the sum. The funcion
should returns the string to draw.
See sample4() in diff file
Hope it helps.
--
Gael Chardon
-------------- next part --------------
Index: piecharts.py
===================================================================
--- piecharts.py (révision 2971)
+++ piecharts.py (copie de travail)
@@ -15,6 +15,7 @@
import copy
from math import sin, cos, pi
+from types import FunctionType, StringType
from reportlab.lib import colors
from reportlab.lib.validators import isColor, isNumber, isListOfNumbersOrNone,\
@@ -65,6 +66,10 @@
fontSize = AttrMapValue(isNumber),
fontColor = AttrMapValue(isColorOrNone),
labelRadius = AttrMapValue(isNumber),
+ percentFormat = AttrMapValue(None, desc='Formatting string or function used for wedges label (percent).'),
+ percentFontName = AttrMapValue(isString),
+ percentFontSize = AttrMapValue(isNumber),
+ percentFontColor = AttrMapValue(isColorOrNone),
label_dx = AttrMapValue(isNumber),
label_dy = AttrMapValue(isNumber),
label_angle = AttrMapValue(isNumber),
@@ -120,6 +125,10 @@
self.label_pointer_elbowLength = 3
self.label_pointer_edgePad = 2
self.label_pointer_piePad = 3
+ self.percentFormat = None
+ self.percentFontName = STATE_DEFAULTS["fontName"]
+ self.percentFontSize = STATE_DEFAULTS["fontSize"]
+ self.percentFontColor = STATE_DEFAULTS["fillColor"]
def _addWedgeLabel(self,text,add,angle,labelX,labelY,wedgeStyle,labelClass=WedgeLabel):
# now draw a label
@@ -637,7 +646,8 @@
cx, cy = centerx, centery
text = gSN(i)
popout = wedgeStyle.popout
- if text or popout:
+ percentFormat = wedgeStyle.percentFormat
+ if text or popout or percentFormat:
averageAngle = (a1+a2)/2.0
aveAngleRadians = averageAngle/_180_pi
cosAA = cos(aveAngleRadians)
@@ -658,6 +668,24 @@
theWedge.strokeDashArray = wedgeStyle.strokeDashArray
g_add(theWedge)
+
+ if percentFormat:
+ p = float(self.data[i])/self._sum
+ if callable(percentFormat):
+ percentStr = percentFormat(self.data[i], self._sum)
+ elif type(percentFormat) is StringType:
+ percentStr = percentFormat % (100.*p)
+ else:
+ msg = "Unknown formatter type %s, expected string or function" % percentFormat
+ raise Exception, msg
+ thePercentLabel = String(cx+0.55*(xradius*cosAA), cy+0.55*(yradius*sinAA), percentStr)
+ thePercentLabel.textAnchor = "middle"
+ thePercentLabel.fontSize = wedgeStyle.percentFontSize
+ thePercentLabel.fontName = wedgeStyle.percentFontName
+ thePercentLabel.fillColor = wedgeStyle.percentFontColor
+ thePercentLabel._pmv = averageAngle
+ g_add(thePercentLabel)
+
if text:
labelRadius = wedgeStyle.labelRadius
rx = xradius*labelRadius
@@ -1280,3 +1308,36 @@
d.add(pc)
return d
+
+def sample4_percent_formatter(value, sum):
+ if sum:
+ text = "%.1f%% (%d)" % (100.*value/sum, value)
+ else:
+ text = ""
+ return text
+
+def sample4():
+ "Make a pie chart with a very slim slice and percent labels."
+
+ d = Drawing(400, 200)
+
+ pc = Pie()
+ pc.x = 125
+ pc.y = 25
+
+ pc.data = [120, 20, 60]
+
+ pc.width = 150
+ pc.height = 150
+ pc.slices.strokeWidth=1#0.5
+ pc.slices[0].fillColor = colors.steelblue
+ pc.slices[1].fillColor = colors.thistle
+ pc.slices[2].fillColor = colors.cornflower
+
+ pc.slices[0].percentFormat = "%.1f%%"
+ pc.slices[1].percentFormat = "%.2f%%"
+ pc.slices[2].percentFormat = sample4_percent_formatter
+
+ d.add(pc)
+
+ return d
More information about the reportlab-users
mailing list