123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- from reportlab.lib.colors import Color, white, black
- from reportlab.graphics.charts.textlabels import Label
- from reportlab.graphics.shapes import Polygon, Line, Circle, String, Drawing, PolyLine, Group, Rect
- from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection
- from reportlab.lib.attrmap import *
- from reportlab.lib.validators import *
- from reportlab.lib.units import cm
- from reportlab.pdfbase.pdfmetrics import stringWidth, getFont
- from reportlab.graphics.widgets.grids import ShadedRect, Grid
- class SlideBox(Widget):
- """Returns a slidebox widget"""
- _attrMap = AttrMap(
- labelFontName = AttrMapValue(isString, desc="Name of font used for the labels"),
- labelFontSize = AttrMapValue(isNumber, desc="Size of font used for the labels"),
- labelStrokeColor = AttrMapValue(isColorOrNone, desc="Colour for for number outlines"),
- labelFillColor = AttrMapValue(isColorOrNone, desc="Colour for number insides"),
- startColor = AttrMapValue(isColor, desc='Color of first box'),
- endColor = AttrMapValue(isColor, desc='Color of last box'),
- numberOfBoxes = AttrMapValue(isInt, desc='How many boxes there are'),
- trianglePosition = AttrMapValue(isInt, desc='Which box is highlighted by the triangles'),
- triangleHeight = AttrMapValue(isNumber, desc="Height of indicator triangles"),
- triangleWidth = AttrMapValue(isNumber, desc="Width of indicator triangles"),
- triangleFillColor = AttrMapValue(isColor, desc="Colour of indicator triangles"),
- triangleStrokeColor = AttrMapValue(isColorOrNone, desc="Colour of indicator triangle outline"),
- triangleStrokeWidth = AttrMapValue(isNumber, desc="Colour of indicator triangle outline"),
- boxHeight = AttrMapValue(isNumber, desc="Height of the boxes"),
- boxWidth = AttrMapValue(isNumber, desc="Width of the boxes"),
- boxSpacing = AttrMapValue(isNumber, desc="Space between the boxes"),
- boxOutlineColor = AttrMapValue(isColorOrNone, desc="Colour used to outline the boxes (if any)"),
- boxOutlineWidth = AttrMapValue(isNumberOrNone, desc="Width of the box outline (if any)"),
- leftPadding = AttrMapValue(isNumber, desc='Padding on left of drawing'),
- rightPadding = AttrMapValue(isNumber, desc='Padding on right of drawing'),
- topPadding = AttrMapValue(isNumber, desc='Padding at top of drawing'),
- bottomPadding = AttrMapValue(isNumber, desc='Padding at bottom of drawing'),
- background = AttrMapValue(isColorOrNone, desc='Colour of the background to the drawing (if any)'),
- sourceLabelText = AttrMapValue(isNoneOrString, desc="Text used for the 'source' label (can be empty)"),
- sourceLabelOffset = AttrMapValue(isNumber, desc='Padding at bottom of drawing'),
- sourceLabelFontName = AttrMapValue(isString, desc="Name of font used for the 'source' label"),
- sourceLabelFontSize = AttrMapValue(isNumber, desc="Font size for the 'source' label"),
- sourceLabelFillColor = AttrMapValue(isColorOrNone, desc="Colour ink for the 'source' label (bottom right)"),
- )
- def __init__(self):
- self.labelFontName = "Helvetica-Bold"
- self.labelFontSize = 10
- self.labelStrokeColor = black
- self.labelFillColor = white
- self.startColor = colors.Color(232/255.0,224/255.0,119/255.0)
- self.endColor = colors.Color(25/255.0,77/255.0,135/255.0)
- self.numberOfBoxes = 7
- self.trianglePosition = 7
- self.triangleHeight = 0.12*cm
- self.triangleWidth = 0.38*cm
- self.triangleFillColor = white
- self.triangleStrokeColor = black
- self.triangleStrokeWidth = 0.58
- self.boxHeight = 0.55*cm
- self.boxWidth = 0.73*cm
- self.boxSpacing = 0.075*cm
- self.boxOutlineColor = black
- self.boxOutlineWidth = 0.58
- self.leftPadding=5
- self.rightPadding=5
- self.topPadding=5
- self.bottomPadding=5
- self.background=None
- self.sourceLabelText = "Source: ReportLab"
- self.sourceLabelOffset = 0.2*cm
- self.sourceLabelFontName = "Helvetica-Oblique"
- self.sourceLabelFontSize = 6
- self.sourceLabelFillColor = black
- def _getDrawingDimensions(self):
- tx=(self.numberOfBoxes*self.boxWidth)
- if self.numberOfBoxes>1: tx=tx+((self.numberOfBoxes-1)*self.boxSpacing)
- tx=tx+self.leftPadding+self.rightPadding
- ty=self.boxHeight+self.triangleHeight
- ty=ty+self.topPadding+self.bottomPadding+self.sourceLabelOffset+self.sourceLabelFontSize
- return (tx,ty)
- def _getColors(self):
- # for calculating intermediate colors...
- numShades = self.numberOfBoxes+1
- fillColorStart = self.startColor
- fillColorEnd = self.endColor
- colorsList =[]
- for i in range(0,numShades):
- colorsList.append(colors.linearlyInterpolatedColor(fillColorStart, fillColorEnd, 0, numShades-1, i))
- return colorsList
- def demo(self,drawing=None):
- from reportlab.lib import colors
- if not drawing:
- tx,ty=self._getDrawingDimensions()
- drawing = Drawing(tx,ty)
- drawing.add(self.draw())
- return drawing
- def draw(self):
- g = Group()
- ys = self.bottomPadding+(self.triangleHeight/2)+self.sourceLabelOffset+self.sourceLabelFontSize
- if self.background:
- x,y = self._getDrawingDimensions()
- g.add(Rect(-self.leftPadding,-ys,x,y,
- strokeColor=None,
- strokeWidth=0,
- fillColor=self.background))
- ascent=getFont(self.labelFontName).face.ascent/1000.
- if ascent==0: ascent=0.718 # default (from helvetica)
- ascent=ascent*self.labelFontSize # normalize
- colorsList = self._getColors()
- # Draw the boxes - now uses ShadedRect from grids
- x=0
- for f in range (0,self.numberOfBoxes):
- sr=ShadedRect()
- sr.x=x
- sr.y=0
- sr.width=self.boxWidth
- sr.height=self.boxHeight
- sr.orientation = 'vertical'
- sr.numShades = 30
- sr.fillColorStart = colorsList[f]
- sr.fillColorEnd = colorsList[f+1]
- sr.strokeColor = None
- sr.strokeWidth = 0
- g.add(sr)
- g.add(Rect(x,0,self.boxWidth,self.boxHeight,
- strokeColor=self.boxOutlineColor,
- strokeWidth=self.boxOutlineWidth,
- fillColor=None))
- g.add(String(x+self.boxWidth/2.,(self.boxHeight-ascent)/2.,
- text = str(f+1),
- fillColor = self.labelFillColor,
- strokeColor=self.labelStrokeColor,
- textAnchor = 'middle',
- fontName = self.labelFontName,
- fontSize = self.labelFontSize))
- x=x+self.boxWidth+self.boxSpacing
- #do triangles
- xt = (self.trianglePosition*self.boxWidth)
- if self.trianglePosition>1:
- xt = xt+(self.trianglePosition-1)*self.boxSpacing
- xt = xt-(self.boxWidth/2)
- g.add(Polygon(
- strokeColor = self.triangleStrokeColor,
- strokeWidth = self.triangleStrokeWidth,
- fillColor = self.triangleFillColor,
- points=[xt,self.boxHeight-(self.triangleHeight/2),
- xt-(self.triangleWidth/2),self.boxHeight+(self.triangleHeight/2),
- xt+(self.triangleWidth/2),self.boxHeight+(self.triangleHeight/2),
- xt,self.boxHeight-(self.triangleHeight/2)]))
- g.add(Polygon(
- strokeColor = self.triangleStrokeColor,
- strokeWidth = self.triangleStrokeWidth,
- fillColor = self.triangleFillColor,
- points=[xt,0+(self.triangleHeight/2),
- xt-(self.triangleWidth/2),0-(self.triangleHeight/2),
- xt+(self.triangleWidth/2),0-(self.triangleHeight/2),
- xt,0+(self.triangleHeight/2)]))
- #source label
- if self.sourceLabelText != None:
- g.add(String(x-self.boxSpacing,0-(self.triangleHeight/2)-self.sourceLabelOffset-(self.sourceLabelFontSize),
- text = self.sourceLabelText,
- fillColor = self.sourceLabelFillColor,
- textAnchor = 'end',
- fontName = self.sourceLabelFontName,
- fontSize = self.sourceLabelFontSize))
- g.shift(self.leftPadding, ys)
- return g
- if __name__ == "__main__":
- d = SlideBox()
- d.demo().save(fnRoot="slidebox")
|