graphics.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. """!
  2. @package mapwin.graphics
  3. @brief Map display canvas - buffered window.
  4. Classes:
  5. - graphics::GraphicsSet
  6. - graphics::GraphicsSetItem
  7. (C) 2006-2013 by the GRASS Development Team
  8. This program is free software under the GNU General Public License
  9. (>=v2). Read the file COPYING that comes with GRASS for details.
  10. @author Stepan Turek <stepan.turek seznam.cz> (handlers support, GraphicsSet)
  11. """
  12. from copy import copy
  13. import wx
  14. from core.utils import _
  15. class GraphicsSet:
  16. def __init__(self, parentMapWin, graphicsType,
  17. setStatusFunc=None, drawFunc=None, mapCoords=True):
  18. """!Class, which contains instances of GraphicsSetItem and
  19. draws them For description of parameters look at method
  20. RegisterGraphicsToDraw in BufferedWindow class.
  21. """
  22. self.pens = {
  23. "default": wx.Pen(colour=wx.BLACK, width=2, style=wx.SOLID),
  24. "selected": wx.Pen(colour=wx.GREEN, width=2, style=wx.SOLID),
  25. "unused": wx.Pen(colour=wx.LIGHT_GREY, width=2, style=wx.SOLID),
  26. "highest": wx.Pen(colour=wx.RED, width=2, style=wx.SOLID)
  27. }
  28. # list contains instances of GraphicsSetItem
  29. self.itemsList = []
  30. self.properties = {}
  31. self.graphicsType = graphicsType
  32. self.parentMapWin = parentMapWin
  33. self.setStatusFunc = setStatusFunc
  34. self.mapCoords = mapCoords
  35. if drawFunc:
  36. self.drawFunc = drawFunc
  37. elif self.graphicsType == "point":
  38. self.properties["size"] = 5
  39. self.properties["text"] = {}
  40. self.properties["text"]['font'] = wx.Font(pointSize=self.properties["size"],
  41. family=wx.FONTFAMILY_DEFAULT,
  42. style=wx.FONTSTYLE_NORMAL,
  43. weight=wx.FONTWEIGHT_NORMAL)
  44. self.properties["text"]['active'] = True
  45. self.drawFunc = self.parentMapWin.DrawCross
  46. elif self.graphicsType == "line":
  47. self.drawFunc = self.parentMapWin.DrawLines
  48. elif self.graphicsType == "rectangle":
  49. self.drawFunc = self.parentMapWin.DrawRectangle
  50. def Draw(self, pdc):
  51. """!Draws all containing items.
  52. @param pdc - device context, where items are drawn
  53. """
  54. itemOrderNum = 0
  55. for item in self.itemsList:
  56. if self.setStatusFunc is not None:
  57. self.setStatusFunc(item, itemOrderNum)
  58. if item.GetPropertyVal("hide") is True:
  59. itemOrderNum += 1
  60. continue
  61. if self.graphicsType == "point":
  62. if item.GetPropertyVal("penName"):
  63. self.parentMapWin.pen = self.pens[item.GetPropertyVal("penName")]
  64. else:
  65. self.parentMapWin.pen = self.pens["default"]
  66. if self.mapCoords:
  67. coords = self.parentMapWin.Cell2Pixel(item.GetCoords())
  68. else:
  69. coords = item.GetCoords()
  70. size = self.properties["size"]
  71. self.properties["text"]['coords'] = [coords[0] + size, coords[1] + size, size, size]
  72. self.properties["text"]['color'] = self.parentMapWin.pen.GetColour()
  73. self.properties["text"]['text'] = item.GetPropertyVal("label")
  74. self.drawFunc(pdc=pdc,
  75. coords=coords,
  76. text=self.properties["text"],
  77. size=self.properties["size"])
  78. elif self.graphicsType == "line":
  79. if item.GetPropertyVal("penName"):
  80. self.parentMapWin.polypen = self.pens[item.GetPropertyVal("penName")]
  81. else:
  82. self.parentMapWin.polypen = self.pens["default"]
  83. if self.mapCoords:
  84. coords = [self.parentMapWin.Cell2Pixel(coords) for coords in item.GetCoords()]
  85. else:
  86. coords = item.GetCoords()
  87. self.drawFunc(pdc=pdc,
  88. polycoords=coords)
  89. elif self.graphicsType == "rectangle":
  90. if item.GetPropertyVal("penName"):
  91. pen = self.pens[item.GetPropertyVal("penName")]
  92. else:
  93. pen = self.pens["default"]
  94. if self.mapCoords:
  95. coords = [self.parentMapWin.Cell2Pixel(coords) for coords in item.GetCoords()]
  96. else:
  97. coords = item.GetCoords()
  98. self.drawFunc(pdc=pdc, pen=pen,
  99. point1=coords[0],
  100. point2=coords[1])
  101. itemOrderNum += 1
  102. def AddItem(self, coords, penName=None, label=None, hide=False):
  103. """!Append item to the list.
  104. Added item is put to the last place in drawing order.
  105. Could be 'point' or 'line' according to graphicsType.
  106. @param coords - list of east, north coordinates (double) of item
  107. Example: point: [1023, 122]
  108. line: [[10, 12],[20,40],[23, 2334]]
  109. rectangle: [[10, 12], [33, 45]]
  110. @param penName (string) the 'default' pen is used if is not defined
  111. @param label (string) label, which will be drawn with point. It is
  112. relavant just for 'point' type.
  113. @param hide (bool) If it is True, the item is not drawn
  114. when self.Draw is called. Hidden items are also counted in drawing
  115. order.
  116. @return (GraphicsSetItem) - added item reference
  117. """
  118. item = GraphicsSetItem(coords=coords, penName=penName, label=label, hide=hide)
  119. self.itemsList.append(item)
  120. return item
  121. def DeleteItem(self, item):
  122. """!Deletes item
  123. @param item (GraphicsSetItem) - item to remove
  124. @return True if item was removed
  125. @return False if item was not found
  126. """
  127. try:
  128. self.itemsList.remove(item)
  129. except ValueError:
  130. return False
  131. return True
  132. def GetAllItems(self):
  133. """!Returns list of all containing instances of GraphicsSetItem, in order
  134. as they are drawn. If you want to change order of drawing use: SetItemDrawOrder method.
  135. """
  136. # user can edit objects but not order in list, that is reason,
  137. # why is returned shallow copy of data list it should be used
  138. # SetItemDrawOrder for changing order
  139. return copy(self.itemsList)
  140. def GetItem(self, drawNum):
  141. """!Get given item from the list.
  142. @param drawNum (int) - drawing order (index) number of item
  143. @return instance of GraphicsSetItem which is drawn in drawNum order
  144. @return False if drawNum was out of range
  145. """
  146. if drawNum < len(self.itemsList) and drawNum >= 0:
  147. return self.itemsList[drawNum]
  148. else:
  149. return False
  150. def SetPropertyVal(self, propName, propVal):
  151. """!Set property value
  152. @param propName (string) - property name: "size", "text"
  153. - both properties are relevant for "point" type
  154. @param propVal - property value to be set
  155. @return True - if value was set
  156. @return False - if propName is not "size" or "text" or type is "line"
  157. """
  158. if propName in self.properties:
  159. self.properties[propName] = propVal
  160. return True
  161. return False
  162. def GetPropertyVal(self, propName):
  163. """!Get property value
  164. Raises KeyError if propName is not "size" or "text" or type is
  165. "line"
  166. @param propName (string) property name: "size", "text"
  167. both properties are relevant for "point" type
  168. @return value of property
  169. """
  170. if propName in self.properties:
  171. return self.properties[propName]
  172. raise KeyError(_("Property does not exist: %s") % (propName))
  173. def AddPen(self, penName, pen):
  174. """!Add pen
  175. @param penName (string) - name of added pen
  176. @param pen (wx.Pen) - added pen
  177. @return True - if pen was added
  178. @return False - if pen already exists
  179. """
  180. if penName in self.pens:
  181. return False
  182. self.pens[penName] = pen
  183. return True
  184. def GetPen(self, penName):
  185. """!Get existing pen
  186. @param penName (string) - name of pen
  187. @return wx.Pen reference if is found
  188. @return None if penName was not found
  189. """
  190. if penName in self.pens:
  191. return self.pens[penName]
  192. return None
  193. def SetItemDrawOrder(self, item, drawNum):
  194. """!Set draw order for item
  195. @param item (GraphicsSetItem)
  196. @param drawNum (int) - drawing order of item to be set
  197. @return True - if order was changed
  198. @return False - if drawNum is out of range or item was not found
  199. """
  200. if drawNum < len(self.itemsList) and drawNum >= 0 and \
  201. item in self.itemsList:
  202. self.itemsList.insert(drawNum, self.itemsList.pop(self.itemsList.index(item)))
  203. return True
  204. return False
  205. def GetItemDrawOrder(self, item):
  206. """!Get draw order for given item
  207. @param item (GraphicsSetItem)
  208. @return (int) - drawing order of item
  209. @return None - if item was not found
  210. """
  211. try:
  212. return self.itemsList.index(item)
  213. except ValueError:
  214. return None
  215. class GraphicsSetItem:
  216. def __init__(self, coords, penName=None, label=None, hide=False):
  217. """!Could be point or line according to graphicsType in
  218. GraphicsSet class
  219. @param coords - list of coordinates (double) of item
  220. Example: point: [1023, 122]
  221. line: [[10, 12],[20,40],[23, 2334]]
  222. rectangle: [[10, 12], [33, 45]]
  223. @param penName (string) if it is not defined 'default' pen is used
  224. @param label (string) label, which will be drawn with point. It is
  225. relevant just for 'point' type
  226. @param hide (bool) if it is True, item is not drawn
  227. Hidden items are also counted in drawing order in
  228. GraphicsSet class.
  229. """
  230. self.coords = coords
  231. self.properties = {"penName": penName,
  232. "hide": hide,
  233. "label": label}
  234. def SetPropertyVal(self, propName, propVal):
  235. """!Set property value
  236. @param propName (string) - property name: "penName", "hide" or "label"
  237. - property "label" is relevant just for 'point' type
  238. @param propVal - property value to be set
  239. @return True - if value was set
  240. @return False - if propName is not "penName", "hide" or "label"
  241. """
  242. if propName in self.properties:
  243. self.properties[propName] = propVal
  244. return True
  245. return False
  246. def GetPropertyVal(self, propName):
  247. """!Get property value
  248. Raises KeyError if propName is not "penName", "hide" or
  249. "label".
  250. @param propName (string) - property name: "penName", "hide" or "label"
  251. - property "label" is relevant just for 'point' type
  252. @return value of property
  253. """
  254. if propName in self.properties:
  255. return self.properties[propName]
  256. raise KeyError(_("Property does not exist: %s") % (propName))
  257. def SetCoords(self, coords):
  258. """!Set coordinates of item
  259. @param coords - list of east, north coordinates (double) of item
  260. Example: point: [1023, 122]
  261. line: [[10, 12],[20,40],[23, 2334]]
  262. rectangle: [[10, 12], [33, 45]]
  263. """
  264. self.coords = coords
  265. def GetCoords(self):
  266. """!Get item coordinates
  267. @returns coordinates
  268. """
  269. return self.coords