mapwindow.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. """!
  2. @package gui_core.mapwindow
  3. @brief Map display canvas - base class for buffered window.
  4. Classes:
  5. - MapWindow
  6. (C) 2006-2011 by the GRASS Development Team
  7. This program is free software under the GNU General Public
  8. License (>=v2). Read the file COPYING that comes with GRASS
  9. for details.
  10. @author Martin Landa <landa.martin gmail.com>
  11. @author Michael Barton
  12. @author Jachym Cepicky
  13. """
  14. import wx
  15. from core.settings import UserSettings
  16. class MapWindow(object):
  17. """!Abstract map display window class
  18. Superclass for BufferedWindow class (2D display mode), and GLWindow
  19. (3D display mode).
  20. Subclasses have to define
  21. - _bindMouseEvents method which binds MouseEvent handlers
  22. - Pixel2Cell
  23. - Cell2Pixel (if it is possible)
  24. """
  25. def __init__(self, parent, id = wx.ID_ANY,
  26. Map = None, tree = None, lmgr = None, **kwargs):
  27. self.parent = parent # MapFrame
  28. self.Map = Map
  29. self.tree = tree
  30. self.lmgr = lmgr
  31. # mouse attributes -- position on the screen, begin and end of
  32. # dragging, and type of drawing
  33. self.mouse = {
  34. 'begin': [0, 0], # screen coordinates
  35. 'end' : [0, 0],
  36. 'use' : "pointer",
  37. 'box' : "point"
  38. }
  39. # last east, north coordinates, changes on mouse motion
  40. self.lastEN = None
  41. # stores overridden cursor
  42. self._overriddenCursor = None
  43. def RegisterMouseEventHandler(self, event, handler, cursor = None):
  44. """!Binds event handler
  45. Call event.Skip() in handler to allow default processing in MapWindow.
  46. @code
  47. # your class methods
  48. def OnButton(self, event):
  49. # current map display's map window
  50. # expects LayerManager to be the parent
  51. self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow()
  52. if self.mapwin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction,
  53. wx.StockCursor(wx.CURSOR_CROSS)):
  54. self.parent.GetLayerTree().GetMapDisplay().Raise()
  55. else:
  56. # handle that you cannot get coordinates
  57. def OnMouseAction(self, event):
  58. # get real world coordinates of mouse click
  59. coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:])
  60. self.text.SetLabel('Coor: ' + str(coor))
  61. self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN)
  62. event.Skip()
  63. @endcode
  64. @param event one of mouse events
  65. @param handler function to handle event
  66. @param cursor cursor which temporary overrides current cursor
  67. @return True if successful
  68. @return False if event cannot be bind
  69. """
  70. # if it is a VDigitWindow it cannot be used
  71. # hasattr is ugly
  72. if hasattr(self, "digit"):
  73. return False
  74. self.Bind(event, handler)
  75. self.mouse['useBeforeGenericEvent'] = self.mouse['use']
  76. self.mouse['use'] = 'genericEvent'
  77. if cursor:
  78. self._overriddenCursor = self.GetCursor()
  79. self.SetCursor(cursor)
  80. return True
  81. def UnregisterMouseEventHandler(self, event):
  82. """!Unbinds event handler a restores previous state
  83. You should unbind to restore normal MapWindow behaviour.
  84. Note that this operation will unbind any other external (non-MapWindow) handlers.
  85. @param event event to unbind
  86. @return True if successful
  87. @return False if event cannot be unbind
  88. """
  89. if hasattr(self, "digit"):
  90. return False
  91. # it is not yet possible in wxPython to unbind exact event
  92. ret = self.Unbind(event)
  93. # restore bind state
  94. self._bindMouseEvents()
  95. # restore mouse use (previous state)
  96. self.mouse['use'] = self.mouse['useBeforeGenericEvent']
  97. # restore overridden cursor
  98. if self._overriddenCursor:
  99. self.SetCursor(self._overriddenCursor)
  100. return ret
  101. def Pixel2Cell(self, (x, y)):
  102. raise NotImplementedError()
  103. def Cell2Pixel(self, (east, north)):
  104. raise NotImplementedError()
  105. def OnMotion(self, event):
  106. """!Tracks mouse motion and update statusbar
  107. @see GetLastEN
  108. """
  109. try:
  110. self.lastEN = self.Pixel2Cell(event.GetPositionTuple())
  111. except (ValueError):
  112. self.lastEN = None
  113. # FIXME: special case for vdigit and access to statusbarManager
  114. if self.parent.statusbarManager.GetMode() == 0: # Coordinates
  115. updated = False
  116. if hasattr(self, "digit"):
  117. precision = int(UserSettings.Get(group = 'projection', key = 'format',
  118. subkey = 'precision'))
  119. updated = self._onMotion(self.lastEN, precision)
  120. if not updated:
  121. self.parent.CoordinatesChanged()
  122. event.Skip()
  123. def GetLastEN(self):
  124. """!Returns last coordinates of mouse cursor.
  125. @see OnMotion
  126. """
  127. return self.lastEN
  128. def GetLayerByName(self, name, mapType, dataType = 'layer'):
  129. """!Get layer from layer tree by nam
  130. @param name layer name
  131. @param type 'item' / 'layer' / 'nviz'
  132. @return layer / map layer properties / nviz properties
  133. @return None
  134. """
  135. if not self.tree:
  136. return None
  137. try:
  138. mapLayer = self.Map.GetListOfLayers(l_type = mapType, l_name = name)[0]
  139. except IndexError:
  140. return None
  141. if dataType == 'layer':
  142. return mapLayer
  143. item = self.tree.FindItemByData('maplayer', mapLayer)
  144. if not item:
  145. return None
  146. if dataType == 'nviz':
  147. return self.tree.GetPyData(item)[0]['nviz']
  148. return item
  149. def GetSelectedLayer(self, type = 'layer', multi = False):
  150. """!Get selected layer from layer tree
  151. @param type 'item' / 'layer' / 'nviz'
  152. @param multi return first selected layer or all
  153. @return layer / map layer properties / nviz properties
  154. @return None / [] on failure
  155. """
  156. ret = []
  157. if not self.tree or \
  158. not self.tree.GetSelection():
  159. if multi:
  160. return []
  161. else:
  162. return None
  163. if multi and \
  164. type == 'item':
  165. return self.tree.GetSelections()
  166. for item in self.tree.GetSelections():
  167. if not item.IsChecked():
  168. if multi:
  169. continue
  170. else:
  171. return None
  172. if type == 'item': # -> multi = False
  173. return item
  174. try:
  175. if type == 'nviz':
  176. layer = self.tree.GetPyData(item)[0]['nviz']
  177. else:
  178. layer = self.tree.GetPyData(item)[0]['maplayer']
  179. except:
  180. layer = None
  181. if multi:
  182. ret.append(layer)
  183. else:
  184. return layer
  185. return ret