|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package gui_core.mapwindow 00003 00004 @brief Map display canvas - base class for buffered window. 00005 00006 Classes: 00007 - mapwindow::MapWindow 00008 00009 (C) 2006-2011 by the GRASS Development Team 00010 00011 This program is free software under the GNU General Public License 00012 (>=v2). Read the file COPYING that comes with GRASS for details. 00013 00014 @author Martin Landa <landa.martin gmail.com> 00015 @author Michael Barton 00016 @author Jachym Cepicky 00017 """ 00018 00019 import wx 00020 00021 from core.settings import UserSettings 00022 00023 class MapWindow(object): 00024 """!Abstract map display window class 00025 00026 Superclass for BufferedWindow class (2D display mode), and GLWindow 00027 (3D display mode). 00028 00029 Subclasses have to define 00030 - _bindMouseEvents method which binds MouseEvent handlers 00031 - Pixel2Cell 00032 - Cell2Pixel (if it is possible) 00033 00034 """ 00035 def __init__(self, parent, id = wx.ID_ANY, 00036 Map = None, tree = None, lmgr = None, **kwargs): 00037 self.parent = parent # MapFrame 00038 self.Map = Map 00039 self.tree = tree 00040 self.lmgr = lmgr 00041 00042 # mouse attributes -- position on the screen, begin and end of 00043 # dragging, and type of drawing 00044 self.mouse = { 00045 'begin': [0, 0], # screen coordinates 00046 'end' : [0, 0], 00047 'use' : "pointer", 00048 'box' : "point" 00049 } 00050 # last east, north coordinates, changes on mouse motion 00051 self.lastEN = None 00052 00053 # stores overridden cursor 00054 self._overriddenCursor = None 00055 00056 def RegisterMouseEventHandler(self, event, handler, cursor = None): 00057 """!Binds event handler 00058 00059 Call event.Skip() in handler to allow default processing in MapWindow. 00060 00061 \code 00062 # your class methods 00063 def OnButton(self, event): 00064 # current map display's map window 00065 # expects LayerManager to be the parent 00066 self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow() 00067 if self.mapwin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction, 00068 wx.StockCursor(wx.CURSOR_CROSS)): 00069 self.parent.GetLayerTree().GetMapDisplay().Raise() 00070 else: 00071 # handle that you cannot get coordinates 00072 00073 def OnMouseAction(self, event): 00074 # get real world coordinates of mouse click 00075 coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:]) 00076 self.text.SetLabel('Coor: ' + str(coor)) 00077 self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN) 00078 event.Skip() 00079 \endcode 00080 00081 @param event one of mouse events 00082 @param handler function to handle event 00083 @param cursor cursor which temporary overrides current cursor 00084 00085 @return True if successful 00086 @return False if event cannot be bind 00087 """ 00088 00089 # if it is a VDigitWindow it cannot be used 00090 # hasattr is ugly 00091 if hasattr(self, "digit"): 00092 return False 00093 00094 self.Bind(event, handler) 00095 self.mouse['useBeforeGenericEvent'] = self.mouse['use'] 00096 self.mouse['use'] = 'genericEvent' 00097 00098 if cursor: 00099 self._overriddenCursor = self.GetCursor() 00100 self.SetCursor(cursor) 00101 00102 return True 00103 00104 00105 def UnregisterMouseEventHandler(self, event): 00106 """!Unbinds event handler a restores previous state 00107 00108 You should unbind to restore normal MapWindow behaviour. 00109 Note that this operation will unbind any other external (non-MapWindow) handlers. 00110 00111 @param event event to unbind 00112 00113 @return True if successful 00114 @return False if event cannot be unbind 00115 """ 00116 if hasattr(self, "digit"): 00117 return False 00118 00119 # it is not yet possible in wxPython to unbind exact event 00120 ret = self.Unbind(event) 00121 00122 # restore bind state 00123 self._bindMouseEvents() 00124 00125 # restore mouse use (previous state) 00126 self.mouse['use'] = self.mouse['useBeforeGenericEvent'] 00127 00128 # restore overridden cursor 00129 if self._overriddenCursor: 00130 self.SetCursor(self._overriddenCursor) 00131 00132 return ret 00133 00134 def Pixel2Cell(self, (x, y)): 00135 raise NotImplementedError() 00136 00137 def Cell2Pixel(self, (east, north)): 00138 raise NotImplementedError() 00139 00140 def OnMotion(self, event): 00141 """!Tracks mouse motion and update statusbar 00142 00143 @see GetLastEN 00144 """ 00145 try: 00146 self.lastEN = self.Pixel2Cell(event.GetPositionTuple()) 00147 except (ValueError): 00148 self.lastEN = None 00149 # FIXME: special case for vdigit and access to statusbarManager 00150 if self.parent.statusbarManager.GetMode() == 0: # Coordinates 00151 updated = False 00152 if hasattr(self, "digit"): 00153 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00154 subkey = 'precision')) 00155 updated = self._onMotion(self.lastEN, precision) 00156 00157 if not updated: 00158 self.parent.CoordinatesChanged() 00159 00160 event.Skip() 00161 00162 def GetLastEN(self): 00163 """!Returns last coordinates of mouse cursor. 00164 00165 @see OnMotion 00166 """ 00167 return self.lastEN 00168 00169 def GetLayerByName(self, name, mapType, dataType = 'layer'): 00170 """!Get layer from layer tree by nam 00171 00172 @param name layer name 00173 @param type 'item' / 'layer' / 'nviz' 00174 00175 @return layer / map layer properties / nviz properties 00176 @return None 00177 """ 00178 if not self.tree: 00179 return None 00180 00181 try: 00182 mapLayer = self.Map.GetListOfLayers(l_type = mapType, l_name = name)[0] 00183 except IndexError: 00184 return None 00185 00186 if dataType == 'layer': 00187 return mapLayer 00188 item = self.tree.FindItemByData('maplayer', mapLayer) 00189 if not item: 00190 return None 00191 if dataType == 'nviz': 00192 return self.tree.GetPyData(item)[0]['nviz'] 00193 00194 return item 00195 00196 def GetSelectedLayer(self, type = 'layer', multi = False): 00197 """!Get selected layer from layer tree 00198 00199 @param type 'item' / 'layer' / 'nviz' 00200 @param multi return first selected layer or all 00201 00202 @return layer / map layer properties / nviz properties 00203 @return None / [] on failure 00204 """ 00205 ret = [] 00206 if not self.tree or \ 00207 not self.tree.GetSelection(): 00208 if multi: 00209 return [] 00210 else: 00211 return None 00212 00213 if multi and \ 00214 type == 'item': 00215 return self.tree.GetSelections() 00216 00217 for item in self.tree.GetSelections(): 00218 if not item.IsChecked(): 00219 if multi: 00220 continue 00221 else: 00222 return None 00223 00224 if type == 'item': # -> multi = False 00225 return item 00226 00227 try: 00228 if type == 'nviz': 00229 layer = self.tree.GetPyData(item)[0]['nviz'] 00230 else: 00231 layer = self.tree.GetPyData(item)[0]['maplayer'] 00232 except: 00233 layer = None 00234 00235 if multi: 00236 ret.append(layer) 00237 else: 00238 return layer 00239 00240 return ret