Files
Phoenix/wx/lib/floatcanvas/SpecialObjects/PieChart.py
2013-05-04 02:00:24 +00:00

139 lines
5.1 KiB
Python

import wx
## import a local version of FloatCanvas
from wx.lib.floatcanvas import FloatCanvas
from wx.lib.floatcanvas.Utilities import BBox
from wx.lib.floatcanvas.Utilities import Colors
import numpy as N
XYObjectMixin = FloatCanvas.XYObjectMixin
LineOnlyMixin = FloatCanvas.LineOnlyMixin
DrawObject = FloatCanvas.DrawObject
class PieChart(XYObjectMixin, LineOnlyMixin, DrawObject):
"""
This is DrawObject for a pie chart
You can pass in a bunch of values, and it will draw a pie chart for
you, and it will make the chart, scaling the size of each "slice" to
match your values.
The parameters are:
XY : The (x,y) coords of the center of the chart
Diameter : The diamter of the chart in worls coords, unless you set
"Scaled" to False, in which case it's in pixel coords.
Values : sequence of values you want to make the chart of.
FillColors=None : sequence of colors you want the slices. If
None, it will choose (no guarantee youll like them!)
FillStyles=None : Fill style you want ("Solid", "Hash", etc)
LineColor = None : Color of lines separating the slices
LineStyle = "Solid" : style of lines separating the slices
LineWidth = 1 : With of lines separating the slices
Scaled = True : Do you want the pie to scale when zooming? or stay the same size in pixels?
InForeground = False: Should it be on the foreground?
"""
##fixme: this should be a longer and better designed set.
## Maybe one from: http://geography.uoregon.edu/datagraphics/color_scales.htm
DefaultColorList = Colors.CategoricalColor1
#["Red", "Green", "Blue", "Purple", "Yellow", "Cyan"]
def __init__(self,
XY,
Diameter,
Values,
FillColors=None,
FillStyles=None,
LineColor = None,
LineStyle = "Solid",
LineWidth = 1,
Scaled = True,
InForeground = False):
DrawObject.__init__(self, InForeground)
self.XY = N.asarray(XY, N.float).reshape( (2,) )
self.Diameter = Diameter
self.Values = N.asarray(Values, dtype=N.float).reshape((-1,1))
if FillColors is None:
FillColors = self.DefaultColorList[:len(Values)]
if FillStyles is None:
FillStyles = ['Solid'] * len(FillColors)
self.FillColors = FillColors
self.FillStyles = FillStyles
self.LineColor = LineColor
self.LineStyle = LineStyle
self.Scaled = Scaled
self.InForeground = InForeground
self.SetPen(LineColor, LineStyle, LineWidth)
self.SetBrushes()
self.CalculatePoints()
def SetFillColors(self, FillColors):
self.FillColors = FillColors
self.SetBrushes()
def SetFillStyles(self, FillStyles):
self.FillStyles = FillStyles
self.SetBrushed()
def SetValues(self, Values):
Values = N.asarray(Values, dtype=N.float).reshape((-1,1))
self.Values = Values
self.CalculatePoints()
def CalculatePoints(self):
# add the zero point to start
Values = N.vstack( ( (0,), self.Values) )
self.Angles = 360. * Values.cumsum()/Values.sum()
self.CalcBoundingBox()
def SetBrushes(self):
self.Brushes = []
for FillColor, FillStyle in zip(self.FillColors, self.FillStyles):
if FillColor is None or FillStyle is None:
self.Brush = wx.TRANSPARENT_BRUSH
else:
self.Brushes.append(self.BrushList.setdefault( (FillColor, FillStyle),
wx.Brush( FillColor, self.FillStyleList[FillStyle] )
)
)
def CalcBoundingBox(self):
if self.Scaled:
self.BoundingBox = BBox.asBBox( ((self.XY-self.Diameter),(self.XY+self.Diameter)) )
else:
self.BoundingBox = BBox.asBBox((self.XY, self.XY))
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
CenterXY = WorldToPixel(self.XY)
if self.Scaled:
Diameter = ScaleWorldToPixel( (self.Diameter,self.Diameter) )[0]
else:
Diameter = self.Diameter
WH = N.array((Diameter,Diameter), dtype = N.float)
Corner = CenterXY - (WH / 2)
dc.SetPen(self.Pen)
for i, brush in enumerate(self.Brushes):
dc.SetBrush( brush )
dc.DrawEllipticArc(Corner[0], Corner[1], WH[0], WH[1], self.Angles[i], self.Angles[i+1])
if HTdc and self.HitAble:
if self.Scaled:
radius = (ScaleWorldToPixel(self.Diameter)/2)[0]# just the x-coord
else:
radius = self.Diameter/2
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
HTdc.DrawCircle(CenterXY, radius)