adjustableArrow.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from reportlab.lib import colors
  2. from reportlab.lib.validators import *
  3. from reportlab.lib.attrmap import *
  4. from reportlab.lib.utils import flatten
  5. from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, Group, Polygon
  6. from reportlab.graphics.widgetbase import Widget
  7. class AdjustableArrow(Widget):
  8. """This widget draws an arrow (style one).
  9. possible attributes:
  10. 'x', 'y', 'size', 'fillColor'
  11. """
  12. _attrMap = AttrMap(
  13. x = AttrMapValue(isNumber,desc='symbol x coordinate'),
  14. y = AttrMapValue(isNumber,desc='symbol y coordinate'),
  15. dx = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'),
  16. dy = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'),
  17. stemThickness = AttrMapValue(isNumber, 'width of the stem'),
  18. stemLength = AttrMapValue(isNumber, 'length of the stem'),
  19. headProjection = AttrMapValue(isNumber, 'how much the head projects from the stem'),
  20. headLength = AttrMapValue(isNumber, 'length of the head'),
  21. headSweep = AttrMapValue(isNumber, 'howmuch the head sweeps back (-ve) or forwards (+ve)'),
  22. scale = AttrMapValue(isNumber, 'scaling factor'),
  23. fillColor = AttrMapValue(isColorOrNone),
  24. strokeColor = AttrMapValue(isColorOrNone),
  25. strokeWidth = AttrMapValue(isNumber),
  26. boxAnchor = AttrMapValue(isBoxAnchor,desc='anchoring point of the label'),
  27. right =AttrMapValue(isBoolean,desc='If True (default) the arrow is horizontal pointing right\nFalse means it points up'),
  28. angle = AttrMapValue(isNumber, desc='angle of arrow default (0), right True 0 is horizontal to right else vertical up'),
  29. )
  30. def __init__(self,**kwds):
  31. self._setKeywords(**kwds)
  32. self._setKeywords(**dict(
  33. x = 0,
  34. y = 0,
  35. fillColor = colors.red,
  36. strokeWidth = 0,
  37. strokeColor = None,
  38. boxAnchor = 'c',
  39. angle = 0,
  40. stemThickness = 33,
  41. stemLength = 50,
  42. headProjection = 15,
  43. headLength = 50,
  44. headSweep = 0,
  45. scale = 1.,
  46. right=True,
  47. ))
  48. def draw(self):
  49. # general widget bits
  50. g = Group()
  51. x = self.x
  52. y = self.y
  53. scale = self.scale
  54. stemThickness = self.stemThickness*scale
  55. stemLength = self.stemLength*scale
  56. headProjection = self.headProjection*scale
  57. headLength = self.headLength*scale
  58. headSweep = self.headSweep*scale
  59. w = stemLength+headLength
  60. h = 2*headProjection+stemThickness
  61. # shift to the boxAnchor
  62. boxAnchor = self.boxAnchor
  63. if self.right:
  64. if boxAnchor in ('sw','w','nw'):
  65. dy = -h
  66. elif boxAnchor in ('s','c','n'):
  67. dy = -h*0.5
  68. else:
  69. dy = 0
  70. if boxAnchor in ('w','c','e'):
  71. dx = -w*0.5
  72. elif boxAnchor in ('nw','n','ne'):
  73. dx = -w
  74. else:
  75. dx = 0
  76. points = [
  77. dx, dy+headProjection+stemThickness,
  78. dx+stemLength, dy+headProjection+stemThickness,
  79. dx+stemLength+headSweep, dy+2*headProjection+stemThickness,
  80. dx+stemLength+headLength, dy+0.5*stemThickness+headProjection,
  81. dx+stemLength+headSweep, dy,
  82. dx+stemLength, dy+headProjection,
  83. dx, dy+headProjection,
  84. ]
  85. else:
  86. w,h = h,w
  87. if boxAnchor in ('nw','n','ne'):
  88. dy = -h
  89. elif boxAnchor in ('w','c','e'):
  90. dy = -h*0.5
  91. else:
  92. dy = 0
  93. if boxAnchor in ('ne','e','se'):
  94. dx = -w
  95. elif boxAnchor in ('n','c','s'):
  96. dx = -w*0.5
  97. else:
  98. dx = 0
  99. points = [
  100. dx+headProjection, dy, #sw
  101. dx+headProjection+stemThickness, dy, #se
  102. dx+headProjection+stemThickness, dy+stemLength,
  103. dx+w, dy+stemLength+headSweep,
  104. dx+headProjection+0.5*stemThickness, dy+h,
  105. dx, dy+stemLength+headSweep,
  106. dx+headProjection, dy+stemLength,
  107. ]
  108. g.add(Polygon(
  109. points = points,
  110. fillColor = self.fillColor,
  111. strokeColor = self.strokeColor,
  112. strokeWidth = self.strokeWidth,
  113. ))
  114. g.translate(x,y)
  115. g.rotate(self.angle)
  116. return g
  117. class AdjustableArrowDrawing(_DrawingEditorMixin,Drawing):
  118. def __init__(self,width=100,height=63,*args,**kw):
  119. Drawing.__init__(self,width,height,*args,**kw)
  120. self._add(self,AdjustableArrow(),name='adjustableArrow',validate=None,desc=None)