mapwindow.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. """!
  2. @package gui_core.mapwindow
  3. @brief Map display canvas - base class for buffered window.
  4. Classes:
  5. - mapwindow::MapWindow
  6. (C) 2006-2012 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Martin Landa <landa.martin gmail.com>
  10. @author Michael Barton
  11. @author Jachym Cepicky
  12. @author Vaclav Petras <wenzeslaus gmail.com> (handlers support)
  13. @author Stepan Turek <stepan.turek seznam.cz> (handlers support)
  14. """
  15. import wx
  16. from core.settings import UserSettings
  17. from core.gcmd import GError
  18. from grass.script import core as grass
  19. class MapWindow(object):
  20. """!Abstract map display window class
  21. Superclass for BufferedWindow class (2D display mode), and GLWindow
  22. (3D display mode).
  23. Subclasses have to define
  24. - _bindMouseEvents method which binds MouseEvent handlers
  25. - Pixel2Cell
  26. - Cell2Pixel (if it is possible)
  27. """
  28. def __init__(self, parent, giface, Map, frame, **kwargs):
  29. self.parent = parent
  30. self.Map = Map
  31. self.Map.SetParentMapWindow(self)
  32. self.frame = frame
  33. self._giface = giface
  34. # mouse attributes -- position on the screen, begin and end of
  35. # dragging, and type of drawing
  36. self.mouse = {
  37. 'begin': [0, 0], # screen coordinates
  38. 'end' : [0, 0],
  39. 'use' : "pointer",
  40. 'box' : "point"
  41. }
  42. # last east, north coordinates, changes on mouse motion
  43. self.lastEN = None
  44. # stores overridden cursor
  45. self._overriddenCursor = None
  46. # dictionary where event types are stored as keys and lists of
  47. # handlers for these types as values
  48. self.handlersContainer = {
  49. wx.EVT_LEFT_DOWN : [],
  50. wx.EVT_LEFT_UP : [],
  51. wx.EVT_LEFT_DCLICK : [],
  52. wx.EVT_MIDDLE_DOWN : [],
  53. wx.EVT_MIDDLE_UP : [],
  54. wx.EVT_MIDDLE_DCLICK : [],
  55. wx.EVT_RIGHT_DOWN : [],
  56. wx.EVT_RIGHT_UP : [],
  57. wx.EVT_RIGHT_DCLICK : [],
  58. wx.EVT_MOTION : [],
  59. wx.EVT_ENTER_WINDOW : [],
  60. wx.EVT_LEAVE_WINDOW : [],
  61. wx.EVT_MOUSEWHEEL : [],
  62. wx.EVT_MOUSE_EVENTS : []
  63. }
  64. wx.CallAfter(self.InitBinding)
  65. def __del__(self):
  66. self.UnregisterAllHandlers()
  67. def InitBinding(self):
  68. """!Binds helper functions, which calls all handlers
  69. registered to events with the events
  70. """
  71. for ev, handlers in self.handlersContainer.iteritems():
  72. self.Bind(ev, self.EventTypeHandler(handlers))
  73. def EventTypeHandler(self, evHandlers):
  74. return lambda event:self.HandlersCaller(event, evHandlers)
  75. def HandlersCaller(self, event, handlers):
  76. """!Hepler function which calls all handlers registered for
  77. event
  78. """
  79. for handler in handlers:
  80. try:
  81. handler(event)
  82. except:
  83. handlers.remove(handler)
  84. GError(parent = self,
  85. message=_("Error occured during calling of handler: %s \n"
  86. "Handler was unregistered.") % handler.__name__)
  87. event.Skip()
  88. def RegisterMouseEventHandler(self, event, handler, cursor = None):
  89. """!Binds event handler
  90. Call event.Skip() in handler to allow default processing in MapWindow.
  91. If any error occures inside of handler, the handler is removed.
  92. Before handler is unregistered it is called with
  93. string value "unregistered" of event parameter.
  94. @code
  95. # your class methods
  96. def OnButton(self, event):
  97. # current map display's map window
  98. # expects LayerManager to be the parent
  99. self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow()
  100. if self.mapwin.RegisterEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction,
  101. wx.StockCursor(wx.CURSOR_CROSS)):
  102. self.parent.GetLayerTree().GetMapDisplay().Raise()
  103. else:
  104. # handle that you cannot get coordinates
  105. def OnMouseAction(self, event):
  106. # get real world coordinates of mouse click
  107. coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:])
  108. self.text.SetLabel('Coor: ' + str(coor))
  109. self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction)
  110. event.Skip()
  111. @endcode
  112. @param event one of mouse events
  113. @param handler function to handle event
  114. @param cursor cursor which temporary overrides current cursor
  115. @return True if successful
  116. @return False if event cannot be bind
  117. """
  118. # inserts handler into list
  119. for containerEv, handlers in self.handlersContainer.iteritems():
  120. if event == containerEv:
  121. handlers.append(handler)
  122. self.mouse['useBeforeGenericEvent'] = self.mouse['use']
  123. self.mouse['use'] = 'genericEvent'
  124. if cursor:
  125. self._overriddenCursor = self.GetCursor()
  126. self.SetCursor(cursor)
  127. return True
  128. def UnregisterAllHandlers(self):
  129. """!Unregisters all registered handlers
  130. Before each handler is unregistered it is called with string
  131. value "unregistered" of event parameter.
  132. """
  133. for containerEv, handlers in self.handlersContainer.iteritems():
  134. for handler in handlers:
  135. try:
  136. handler("unregistered")
  137. handlers.remove(handler)
  138. except:
  139. GError(parent = self,
  140. message = _("Error occured during unregistration of handler: %s \n \
  141. Handler was unregistered.") % handler.__name__)
  142. handlers.remove(handler)
  143. def UnregisterMouseEventHandler(self, event, handler):
  144. """!Unbinds event handler for event
  145. Before handler is unregistered it is called with string value
  146. "unregistered" of event parameter.
  147. @param handler handler to unbind
  148. @param event event from which handler will be unbinded
  149. @return True if successful
  150. @return False if event cannot be unbind
  151. """
  152. # removes handler from list
  153. for containerEv, handlers in self.handlersContainer.iteritems():
  154. if event != containerEv:
  155. continue
  156. try:
  157. handler("unregistered")
  158. if handler in handlers:
  159. handlers.remove(handler)
  160. else:
  161. grass.warning(_("Handler: %s was not registered") \
  162. % handler.__name__)
  163. except:
  164. GError(parent = self,
  165. message = _("Error occured during unregistration of handler: %s \n \
  166. Handler was unregistered") % handler.__name__)
  167. handlers.remove(handler)
  168. # restore mouse use (previous state)
  169. self.mouse['use'] = self.mouse['useBeforeGenericEvent']
  170. # restore overridden cursor
  171. if self._overriddenCursor:
  172. self.SetCursor(self._overriddenCursor)
  173. return True
  174. def Pixel2Cell(self, (x, y)):
  175. raise NotImplementedError()
  176. def Cell2Pixel(self, (east, north)):
  177. raise NotImplementedError()
  178. def OnMotion(self, event):
  179. """!Tracks mouse motion and update statusbar
  180. @see GetLastEN
  181. """
  182. try:
  183. self.lastEN = self.Pixel2Cell(event.GetPositionTuple())
  184. except (ValueError):
  185. self.lastEN = None
  186. # FIXME: special case for vdigit and access to statusbarManager
  187. if self.frame.statusbarManager.GetMode() == 0: # Coordinates
  188. updated = False
  189. if hasattr(self, "digit"):
  190. precision = int(UserSettings.Get(group = 'projection', key = 'format',
  191. subkey = 'precision'))
  192. updated = self._onMotion(self.lastEN, precision)
  193. if not updated:
  194. self.frame.CoordinatesChanged()
  195. event.Skip()
  196. def GetLastEN(self):
  197. """!Returns last coordinates of mouse cursor.
  198. @see OnMotion
  199. """
  200. return self.lastEN