from reportlab.lib import colors from reportlab.lib.validators import * from reportlab.lib.attrmap import * from reportlab.lib.utils import flatten from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, Group, Polygon from reportlab.graphics.widgetbase import Widget class AdjustableArrow(Widget): """This widget draws an arrow (style one). possible attributes: 'x', 'y', 'size', 'fillColor' """ _attrMap = AttrMap( x = AttrMapValue(isNumber,desc='symbol x coordinate'), y = AttrMapValue(isNumber,desc='symbol y coordinate'), dx = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'), dy = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'), stemThickness = AttrMapValue(isNumber, 'width of the stem'), stemLength = AttrMapValue(isNumber, 'length of the stem'), headProjection = AttrMapValue(isNumber, 'how much the head projects from the stem'), headLength = AttrMapValue(isNumber, 'length of the head'), headSweep = AttrMapValue(isNumber, 'howmuch the head sweeps back (-ve) or forwards (+ve)'), scale = AttrMapValue(isNumber, 'scaling factor'), fillColor = AttrMapValue(isColorOrNone), strokeColor = AttrMapValue(isColorOrNone), strokeWidth = AttrMapValue(isNumber), boxAnchor = AttrMapValue(isBoxAnchor,desc='anchoring point of the label'), right =AttrMapValue(isBoolean,desc='If True (default) the arrow is horizontal pointing right\nFalse means it points up'), angle = AttrMapValue(isNumber, desc='angle of arrow default (0), right True 0 is horizontal to right else vertical up'), ) def __init__(self,**kwds): self._setKeywords(**kwds) self._setKeywords(**dict( x = 0, y = 0, fillColor = colors.red, strokeWidth = 0, strokeColor = None, boxAnchor = 'c', angle = 0, stemThickness = 33, stemLength = 50, headProjection = 15, headLength = 50, headSweep = 0, scale = 1., right=True, )) def draw(self): # general widget bits g = Group() x = self.x y = self.y scale = self.scale stemThickness = self.stemThickness*scale stemLength = self.stemLength*scale headProjection = self.headProjection*scale headLength = self.headLength*scale headSweep = self.headSweep*scale w = stemLength+headLength h = 2*headProjection+stemThickness # shift to the boxAnchor boxAnchor = self.boxAnchor if self.right: if boxAnchor in ('sw','w','nw'): dy = -h elif boxAnchor in ('s','c','n'): dy = -h*0.5 else: dy = 0 if boxAnchor in ('w','c','e'): dx = -w*0.5 elif boxAnchor in ('nw','n','ne'): dx = -w else: dx = 0 points = [ dx, dy+headProjection+stemThickness, dx+stemLength, dy+headProjection+stemThickness, dx+stemLength+headSweep, dy+2*headProjection+stemThickness, dx+stemLength+headLength, dy+0.5*stemThickness+headProjection, dx+stemLength+headSweep, dy, dx+stemLength, dy+headProjection, dx, dy+headProjection, ] else: w,h = h,w if boxAnchor in ('nw','n','ne'): dy = -h elif boxAnchor in ('w','c','e'): dy = -h*0.5 else: dy = 0 if boxAnchor in ('ne','e','se'): dx = -w elif boxAnchor in ('n','c','s'): dx = -w*0.5 else: dx = 0 points = [ dx+headProjection, dy, #sw dx+headProjection+stemThickness, dy, #se dx+headProjection+stemThickness, dy+stemLength, dx+w, dy+stemLength+headSweep, dx+headProjection+0.5*stemThickness, dy+h, dx, dy+stemLength+headSweep, dx+headProjection, dy+stemLength, ] g.add(Polygon( points = points, fillColor = self.fillColor, strokeColor = self.strokeColor, strokeWidth = self.strokeWidth, )) g.translate(x,y) g.rotate(self.angle) return g class AdjustableArrowDrawing(_DrawingEditorMixin,Drawing): def __init__(self,width=100,height=63,*args,**kw): Drawing.__init__(self,width,height,*args,**kw) self._add(self,AdjustableArrow(),name='adjustableArrow',validate=None,desc=None)