shape.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. from PyQt4.QtGui import *
  4. from PyQt4.QtCore import *
  5. # FIXME:
  6. # - Add support for highlighting vertices.
  7. # TODO:
  8. # - [opt] Store paths instead of creating new ones at each paint.
  9. DEFAULT_LINE_COLOR = QColor(0, 255, 0, 128)
  10. DEFAULT_FILL_COLOR = QColor(255, 0, 0, 128)
  11. DEFAULT_SELECT_COLOR = QColor(255, 255, 255)
  12. class Shape(object):
  13. P_SQUARE, P_ROUND = range(2)
  14. ## The following class variables influence the drawing
  15. ## of _all_ shape objects.
  16. line_color = DEFAULT_LINE_COLOR
  17. fill_color = DEFAULT_FILL_COLOR
  18. sel_fill_color=QColor(0, 128, 255, 155)
  19. select_color = DEFAULT_SELECT_COLOR
  20. point_type = P_ROUND
  21. point_size = 8
  22. scale = 1.0
  23. def __init__(self, label=None, line_color=None):
  24. self.label = label
  25. self.points = []
  26. self.fill = False
  27. self.selected = False
  28. self.highlightStart = False
  29. if line_color is not None:
  30. # Override the class line_color attribute
  31. # with an object attribute. Currently this
  32. # is used for drawing the pending line a different color.
  33. self.line_color = line_color
  34. def addPoint(self, point):
  35. self.points.append(point)
  36. def popPoint(self):
  37. if self.points:
  38. return self.points.pop()
  39. return None
  40. def isClosed(self):
  41. return len(self.points) > 1 and self[0] == self[-1]
  42. def paint(self, painter):
  43. if self.points:
  44. pen = QPen(self.select_color if self.selected else self.line_color)
  45. # Try using integer sizes for smoother drawing(?)
  46. pen.setWidth(max(1, int(round(2.0 / self.scale))))
  47. painter.setPen(pen)
  48. line_path = QPainterPath()
  49. vrtx_path = QPainterPath()
  50. line_path.moveTo(QPointF(self.points[0]))
  51. self.drawVertex(vrtx_path, self.points[0],
  52. highlight=self.highlightStart)
  53. for p in self.points[1:]:
  54. line_path.lineTo(QPointF(p))
  55. # Skip last element, otherwise its vertex is not filled.
  56. if p != self.points[0]:
  57. self.drawVertex(vrtx_path, p)
  58. painter.drawPath(line_path)
  59. painter.fillPath(vrtx_path, self.line_color)
  60. if self.fill:
  61. if self.selected:
  62. fillColor=self.sel_fill_color
  63. else:
  64. fillColor=self.fill_color
  65. painter.fillPath(line_path,fillColor)
  66. def drawVertex(self, path, point, highlight=False):
  67. d = self.point_size / self.scale
  68. if highlight:
  69. d *= 4
  70. if self.point_type == self.P_SQUARE:
  71. path.addRect(point.x() - d/2, point.y() - d/2, d, d)
  72. else:
  73. path.addEllipse(point, d/2.0, d/2.0)
  74. def containsPoint(self, point):
  75. return self.makePath().contains(point)
  76. def makePath(self):
  77. path = QPainterPath(self.points[0])
  78. for p in self.points[1:]:
  79. path.lineTo(p)
  80. return path
  81. def boundingRect(self):
  82. return self.makePath().boundingRect()
  83. def moveBy(self, offset):
  84. self.points = [p + offset for p in self.points]
  85. def copy(self):
  86. shape = Shape("Copy of %s" % self.label )
  87. shape.points= [p for p in self.points]
  88. shape.fill = self.fill
  89. shape.selected = self.selected
  90. return shape
  91. def __len__(self):
  92. return len(self.points)
  93. def __getitem__(self, key):
  94. return self.points[key]
  95. def __setitem__(self, key, value):
  96. self.points[key] = value