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