mapwindow.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. """!
  2. @package swipe.mapwindow
  3. @brief Map Swipe map window.
  4. Class _MouseEvent taken from wxPython FloatCanvas source code (Christopher Barker).
  5. Classes:
  6. - mapwindow::SwipeBufferedWindow
  7. - mapwindow::_MouseEvent
  8. (C) 2012 by the GRASS Development Team
  9. This program is free software under the GNU General Public License
  10. (>=v2). Read the file COPYING that comes with GRASS for details.
  11. @author Anna Kratochvilova <kratochanna gmail.com>
  12. """
  13. import wx
  14. from core.debug import Debug
  15. from core.utils import _
  16. from mapdisp.mapwindow import BufferedWindow
  17. EVT_MY_MOUSE_EVENTS = wx.NewEventType()
  18. EVT_MY_MOTION = wx.NewEventType()
  19. EVT_MOUSE_EVENTS = wx.PyEventBinder(EVT_MY_MOUSE_EVENTS)
  20. EVT_MOTION = wx.PyEventBinder(EVT_MY_MOTION)
  21. class SwipeBufferedWindow(BufferedWindow):
  22. """!A subclass of BufferedWindow class.
  23. Enables to draw the image translated.
  24. Special mouse events with changed coordinates are used.
  25. """
  26. def __init__(self, parent, giface, Map, frame, **kwargs):
  27. BufferedWindow.__init__(self, parent = parent, giface = giface,
  28. Map=Map, frame=frame, **kwargs)
  29. Debug.msg(2, "SwipeBufferedWindow.__init__()")
  30. self.specialSize = super(SwipeBufferedWindow, self).GetClientSize()
  31. self.specialCoords = [0, 0]
  32. self.imageId = 99
  33. self.movingSash = False
  34. self._mode = 'swipe'
  35. self.lineid = wx.NewId()
  36. def _bindMouseEvents(self):
  37. """!Binds wx mouse events and custom mouse events"""
  38. wx.EVT_MOUSE_EVENTS(self, self._mouseActions)
  39. wx.EVT_MOTION(self, self._mouseMotion)
  40. self.Bind(EVT_MOTION, self.OnMotion)
  41. self.Bind(EVT_MOUSE_EVENTS, self.MouseActions)
  42. self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
  43. def _RaiseMouseEvent(self, Event, EventType):
  44. """!This is called in various other places to raise a Mouse Event
  45. """
  46. Debug.msg(5, "SwipeBufferedWindow._RaiseMouseEvent()")
  47. # this computes the new coordinates from the mouse coords.
  48. x, y = Event.GetPosition()
  49. pt = x - self.GetImageCoords()[0], y - self.GetImageCoords()[1]
  50. evt = _MouseEvent(EventType, Event, self.GetId(), pt)
  51. self.GetEventHandler().ProcessEvent(evt)
  52. # this skip was not in the original code but is needed here
  53. Event.Skip()
  54. def _mouseActions(self, event):
  55. self._RaiseMouseEvent(event, EVT_MY_MOUSE_EVENTS)
  56. def _mouseMotion(self, event):
  57. self._RaiseMouseEvent(event, EVT_MY_MOTION)
  58. def GetClientSize(self):
  59. """!Overriden method which returns simulated window size.
  60. """
  61. if self._mode == 'swipe':
  62. return self.specialSize
  63. else:
  64. return super(SwipeBufferedWindow, self).GetClientSize()
  65. def SetClientSize(self, size):
  66. """!Overriden method which sets simulated window size.
  67. """
  68. Debug.msg(3, "SwipeBufferedWindow.SetClientSize(): size = %s" % size)
  69. self.specialSize = size
  70. def SetMode(self, mode):
  71. """!Sets mode of the window.
  72. @param mode mode can be 'swipe' or 'mirror'
  73. """
  74. self._mode = mode
  75. def GetImageCoords(self):
  76. """!Returns coordinates of rendered image"""
  77. if self._mode == 'swipe':
  78. return self.specialCoords
  79. else:
  80. return (0, 0)
  81. def SetImageCoords(self, coords):
  82. """!Sets coordinates of rendered image"""
  83. Debug.msg(3, "SwipeBufferedWindow.SetImageCoords(): coords = %s, %s" % (coords[0], coords[1]))
  84. self.specialCoords = coords
  85. def OnSize(self, event):
  86. """!Calls superclass's OnSize method only when needed"""
  87. Debug.msg(5, "SwipeBufferedWindow.OnSize()")
  88. if not self.movingSash:
  89. super(SwipeBufferedWindow, self).OnSize(event)
  90. def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0], pen = None):
  91. """!Draws image (map) with translated coordinates.
  92. """
  93. Debug.msg(2, "SwipeBufferedWindow.Draw()")
  94. if pdctype == 'image':
  95. coords = self.GetImageCoords()
  96. return super(SwipeBufferedWindow, self).Draw(pdc, img, drawid, pdctype, coords, pen)
  97. def OnLeftDown(self, event):
  98. """!Left mouse button pressed.
  99. In case of 'pointer' mode, coordinates must be adjusted.
  100. """
  101. if self.mouse['use'] == 'pointer':
  102. evX, evY = event.GetPositionTuple()[:]
  103. imX, imY = self.GetImageCoords()
  104. self.lastpos = evX + imX, evY + imY
  105. # get decoration or text id
  106. self.dragid = None
  107. idlist = self.pdc.FindObjects(self.lastpos[0], self.lastpos[1],
  108. self.hitradius)
  109. if 99 in idlist:
  110. idlist.remove(99)
  111. if idlist:
  112. self.dragid = idlist[0] #drag whatever is on top
  113. else:
  114. super(SwipeBufferedWindow, self).OnLeftDown(event)
  115. def OnDragging(self, event):
  116. """!Mouse dragging - overlay (text) is moving.
  117. Coordinates must be adjusted.
  118. """
  119. if (self.mouse['use'] == 'pointer' and self.dragid != None):
  120. evX, evY = event.GetPositionTuple()
  121. imX, imY = self.GetImageCoords()
  122. self.DragItem(self.dragid, (evX + imX, evY + imY))
  123. else:
  124. super(SwipeBufferedWindow, self).OnDragging(event)
  125. def TranslateImage(self, dx, dy):
  126. """!Translate image and redraw.
  127. """
  128. Debug.msg(5, "SwipeBufferedWindow.TranslateImage(): dx = %s, dy = %s" % (dx, dy))
  129. self.pdc.TranslateId(self.imageId, dx, dy)
  130. self.Refresh()
  131. def SetRasterNameText(self, name, textId):
  132. """!Sets text label with map name."""
  133. self.textdict[textId] = {'bbox': wx.Rect(), 'coords': [10, 10],
  134. 'font': self.GetFont(), 'color': wx.BLACK,
  135. 'rotation': 0, 'text': name,
  136. 'active': True}
  137. def MouseDraw(self, pdc = None, begin = None, end = None):
  138. """!Overriden method to recompute coordinates back to original values
  139. so that e.g. drawing of zoom box is done properly"""
  140. Debug.msg(5, "SwipeBufferedWindow.MouseDraw()")
  141. offsetX, offsetY = self.GetImageCoords()
  142. begin = (self.mouse['begin'][0] + offsetX, self.mouse['begin'][1] + offsetY)
  143. end = (self.mouse['end'][0] + offsetX, self.mouse['end'][1] + offsetY)
  144. super(SwipeBufferedWindow, self).MouseDraw(pdc, begin, end)
  145. def DrawMouseCross(self, coords):
  146. """!Draw moving cross."""
  147. self.pdcTmp.ClearId(self.lineid)
  148. self.lineid = self.DrawCross(pdc = self.pdcTmp, coords = coords, size = 10, pen = wx.BLACK_PEN)
  149. class _MouseEvent(wx.PyCommandEvent):
  150. """!
  151. This event class takes a regular wxWindows mouse event as a parameter,
  152. and wraps it so that there is access to all the original methods. This
  153. is similar to subclassing, but you can't subclass a wxWindows event.
  154. The goal is to be able to it just like a regular mouse event.
  155. Difference is that it is a CommandEvent, which propagates up the
  156. window hierarchy until it is handled.
  157. """
  158. def __init__(self, EventType, NativeEvent, WinID, changed = None):
  159. Debug.msg(5, "_MouseEvent:__init__()")
  160. wx.PyCommandEvent.__init__(self)
  161. self.SetEventType(EventType)
  162. self._NativeEvent = NativeEvent
  163. self.changed = changed
  164. def GetPosition(self):
  165. return wx.Point(*self.changed)
  166. def GetPositionTuple(self):
  167. return self.changed
  168. def GetX(self):
  169. return self.changed[0]
  170. def GetY(self):
  171. return self.changed[1]
  172. # this delegates all other attributes to the native event.
  173. def __getattr__(self, name):
  174. return getattr(self._NativeEvent, name)