GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package layertree.py 00003 00004 @brief Utility classes for map layer management. 00005 00006 Classes: 00007 - AbstractLayer 00008 - Layer 00009 - LayerTree 00010 00011 (C) 2007-2011 by the GRASS Development Team 00012 This program is free software under the GNU General Public 00013 License (>=v2). Read the file COPYING that comes with GRASS 00014 for details. 00015 00016 @author Michael Barton (Arizona State University) 00017 @author Jachym Cepicky (Mendel University of Agriculture) 00018 @author Martin Landa <landa.martin gmail.com> 00019 """ 00020 00021 import os 00022 import sys 00023 import string 00024 00025 import wx 00026 try: 00027 import wx.lib.agw.customtreectrl as CT 00028 except ImportError: 00029 import wx.lib.customtreectrl as CT 00030 import wx.combo 00031 import wx.lib.newevent 00032 import wx.lib.buttons as buttons 00033 try: 00034 import treemixin 00035 except ImportError: 00036 from wx.lib.mixins import treemixin 00037 00038 import globalvar 00039 00040 from grass.script import core as grass 00041 00042 import gdialogs 00043 import menuform 00044 import toolbars 00045 import mapdisp 00046 import render 00047 import histogram 00048 import utils 00049 import profile 00050 from debug import Debug as Debug 00051 from icon import Icons as Icons 00052 from preferences import globalSettings as UserSettings 00053 from vdigit import haveVDigit 00054 from gcmd import GWarning 00055 00056 TREE_ITEM_HEIGHT = 25 00057 00058 class LayerTree(treemixin.DragAndDrop, CT.CustomTreeCtrl): 00059 """!Creates layer tree structure 00060 """ 00061 def __init__(self, parent, 00062 id = wx.ID_ANY, style = wx.SUNKEN_BORDER, 00063 ctstyle = CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT | 00064 CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT | 00065 CT.TR_MULTIPLE, **kwargs): 00066 00067 if 'style' in kwargs: 00068 ctstyle |= kwargs['style'] 00069 del kwargs['style'] 00070 self.disp_idx = kwargs['idx'] 00071 del kwargs['idx'] 00072 self.lmgr = kwargs['lmgr'] 00073 del kwargs['lmgr'] 00074 self.notebook = kwargs['notebook'] # GIS Manager notebook for layer tree 00075 del kwargs['notebook'] 00076 self.auimgr = kwargs['auimgr'] # aui manager 00077 del kwargs['auimgr'] 00078 showMapDisplay = kwargs['showMapDisplay'] 00079 del kwargs['showMapDisplay'] 00080 self.treepg = parent # notebook page holding layer tree 00081 self.Map = render.Map() # instance of render.Map to be associated with display 00082 self.root = None # ID of layer tree root node 00083 self.groupnode = 0 # index value for layers 00084 self.optpage = {} # dictionary of notebook option pages for each map layer 00085 self.layer_selected = None # ID of currently selected layer 00086 self.saveitem = {} # dictionary to preserve layer attributes for drag and drop 00087 self.first = True # indicates if a layer is just added or not 00088 self.flag = '' # flag for drag and drop hittest 00089 self.rerender = False # layer change requires a rerendering if auto render 00090 self.reorder = False # layer change requires a reordering 00091 00092 try: 00093 ctstyle |= CT.TR_ALIGN_WINDOWS 00094 except AttributeError: 00095 pass 00096 00097 if globalvar.hasAgw: 00098 super(LayerTree, self).__init__(parent, id, agwStyle = ctstyle, **kwargs) 00099 else: 00100 super(LayerTree, self).__init__(parent, id, style = ctstyle, **kwargs) 00101 self.SetName("LayerTree") 00102 00103 ### SetAutoLayout() causes that no vertical scrollbar is displayed 00104 ### when some layers are not visible in layer tree 00105 # self.SetAutoLayout(True) 00106 self.SetGradientStyle(1) 00107 self.EnableSelectionGradient(True) 00108 self._setGradient() 00109 00110 # init associated map display 00111 pos = wx.Point((self.disp_idx + 1) * 25, (self.disp_idx + 1) * 25) 00112 self.mapdisplay = mapdisp.MapFrame(self, 00113 id = wx.ID_ANY, pos = pos, 00114 size = globalvar.MAP_WINDOW_SIZE, 00115 style = wx.DEFAULT_FRAME_STYLE, 00116 tree = self, notebook = self.notebook, 00117 lmgr = self.lmgr, page = self.treepg, 00118 Map = self.Map, auimgr = self.auimgr) 00119 00120 # title 00121 self.mapdisplay.SetTitle(_("GRASS GIS Map Display: %(id)d - Location: %(loc)s") % \ 00122 { 'id' : self.disp_idx + 1, 00123 'loc' : grass.gisenv()["LOCATION_NAME"] }) 00124 00125 # show new display 00126 if showMapDisplay is True: 00127 self.mapdisplay.Show() 00128 self.mapdisplay.Refresh() 00129 self.mapdisplay.Update() 00130 00131 self.root = self.AddRoot(_("Map Layers")) 00132 self.SetPyData(self.root, (None, None)) 00133 00134 # create image list to use with layer tree 00135 il = wx.ImageList(16, 16, mask = False) 00136 00137 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16)) 00138 self.folder_open = il.Add(trart) 00139 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16)) 00140 self.folder = il.Add(trart) 00141 00142 bmpsize = (16, 16) 00143 icons = Icons['layerManager'] 00144 trgif = icons["addRast"].GetBitmap(bmpsize) 00145 self.rast_icon = il.Add(trgif) 00146 00147 trgif = icons["addRast3d"].GetBitmap(bmpsize) 00148 self.rast3d_icon = il.Add(trgif) 00149 00150 trgif = icons["addRgb"].GetBitmap(bmpsize) 00151 self.rgb_icon = il.Add(trgif) 00152 00153 trgif = icons["addHis"].GetBitmap(bmpsize) 00154 self.his_icon = il.Add(trgif) 00155 00156 trgif = icons["addShaded"].GetBitmap(bmpsize) 00157 self.shaded_icon = il.Add(trgif) 00158 00159 trgif = icons["addRArrow"].GetBitmap(bmpsize) 00160 self.rarrow_icon = il.Add(trgif) 00161 00162 trgif = icons["addRNum"].GetBitmap(bmpsize) 00163 self.rnum_icon = il.Add(trgif) 00164 00165 trgif = icons["addVect"].GetBitmap(bmpsize) 00166 self.vect_icon = il.Add(trgif) 00167 00168 trgif = icons["addThematic"].GetBitmap(bmpsize) 00169 self.theme_icon = il.Add(trgif) 00170 00171 trgif = icons["addChart"].GetBitmap(bmpsize) 00172 self.chart_icon = il.Add(trgif) 00173 00174 trgif = icons["addGrid"].GetBitmap(bmpsize) 00175 self.grid_icon = il.Add(trgif) 00176 00177 trgif = icons["addGeodesic"].GetBitmap(bmpsize) 00178 self.geodesic_icon = il.Add(trgif) 00179 00180 trgif = icons["addRhumb"].GetBitmap(bmpsize) 00181 self.rhumb_icon = il.Add(trgif) 00182 00183 trgif = icons["addLabels"].GetBitmap(bmpsize) 00184 self.labels_icon = il.Add(trgif) 00185 00186 trgif = icons["addCmd"].GetBitmap(bmpsize) 00187 self.cmd_icon = il.Add(trgif) 00188 00189 self.AssignImageList(il) 00190 00191 self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnExpandNode) 00192 self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnCollapseNode) 00193 self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateLayer) 00194 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnChangeSel) 00195 self.Bind(CT.EVT_TREE_ITEM_CHECKED, self.OnLayerChecked) 00196 self.Bind(wx.EVT_TREE_DELETE_ITEM, self.OnDeleteLayer) 00197 self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnLayerContextMenu) 00198 self.Bind(wx.EVT_TREE_END_DRAG, self.OnEndDrag) 00199 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnRenamed) 00200 self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) 00201 self.Bind(wx.EVT_IDLE, self.OnIdle) 00202 00203 def _setGradient(self, iType = None): 00204 """!Set gradient for items 00205 00206 @param iType bgmap, vdigit or None 00207 """ 00208 if iType == 'bgmap': 00209 self.SetFirstGradientColour(wx.Colour(0, 100, 0)) 00210 self.SetSecondGradientColour(wx.Colour(0, 150, 0)) 00211 elif iType == 'vdigit': 00212 self.SetFirstGradientColour(wx.Colour(100, 0, 0)) 00213 self.SetSecondGradientColour(wx.Colour(150, 0, 0)) 00214 else: 00215 self.SetFirstGradientColour(wx.Colour(100, 100, 100)) 00216 self.SetSecondGradientColour(wx.Colour(150, 150, 150)) 00217 00218 def GetMap(self): 00219 """!Get map instace""" 00220 return self.Map 00221 00222 def GetMapDisplay(self): 00223 """!Get associated MapFrame""" 00224 return self.mapdisplay 00225 00226 def OnIdle(self, event): 00227 """!Only re-order and re-render a composite map image from GRASS during 00228 idle time instead of multiple times during layer changing. 00229 """ 00230 if self.rerender: 00231 if self.mapdisplay.toolbars['vdigit']: 00232 vector = True 00233 else: 00234 vector = False 00235 if self.mapdisplay.statusbarWin['render'].GetValue(): 00236 self.mapdisplay.MapWindow.UpdateMap(render = True, renderVector = vector) 00237 00238 self.rerender = False 00239 00240 event.Skip() 00241 00242 def OnKeyUp(self, event): 00243 """!Key pressed""" 00244 key = event.GetKeyCode() 00245 00246 if key == wx.WXK_DELETE and self.lmgr and \ 00247 not self.GetEditControl(): 00248 self.lmgr.OnDeleteLayer(None) 00249 00250 event.Skip() 00251 00252 def OnLayerContextMenu (self, event): 00253 """!Contextual menu for item/layer""" 00254 if not self.layer_selected: 00255 event.Skip() 00256 return 00257 00258 ltype = self.GetPyData(self.layer_selected)[0]['type'] 00259 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00260 00261 Debug.msg (4, "LayerTree.OnContextMenu: layertype=%s" % \ 00262 ltype) 00263 00264 if not hasattr (self, "popupID"): 00265 self.popupID = dict() 00266 for key in ('remove', 'rename', 'opacity', 'nviz', 'zoom', 00267 'region', 'export', 'attr', 'edit0', 'edit1', 00268 'bgmap', 'topo', 'meta', 'null', 'zoom1', 'region1', 00269 'color', 'hist', 'univar', 'prof', 'properties'): 00270 self.popupID[key] = wx.NewId() 00271 00272 self.popupMenu = wx.Menu() 00273 00274 numSelected = len(self.GetSelections()) 00275 00276 self.popupMenu.Append(self.popupID['remove'], text = _("Remove")) 00277 self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id = self.popupID['remove']) 00278 00279 if ltype != "command": 00280 self.popupMenu.Append(self.popupID['rename'], text = _("Rename")) 00281 self.Bind(wx.EVT_MENU, self.OnRenameLayer, id = self.popupID['rename']) 00282 if numSelected > 1: 00283 self.popupMenu.Enable(self.popupID['rename'], False) 00284 00285 # map layer items 00286 if ltype not in ("group", "command"): 00287 self.popupMenu.AppendSeparator() 00288 self.popupMenu.Append(self.popupID['opacity'], text = _("Change opacity level")) 00289 self.Bind(wx.EVT_MENU, self.OnPopupOpacityLevel, id = self.popupID['opacity']) 00290 self.popupMenu.Append(self.popupID['properties'], text = _("Properties")) 00291 self.Bind(wx.EVT_MENU, self.OnPopupProperties, id = self.popupID['properties']) 00292 00293 if numSelected > 1: 00294 self.popupMenu.Enable(self.popupID['opacity'], False) 00295 self.popupMenu.Enable(self.popupID['properties'], False) 00296 00297 if ltype in ('raster', 'vector', '3d-raster') and self.mapdisplay.toolbars['nviz']: 00298 self.popupMenu.Append(self.popupID['nviz'], _("3D view properties")) 00299 self.Bind (wx.EVT_MENU, self.OnNvizProperties, id = self.popupID['nviz']) 00300 00301 if ltype in ('raster', 'vector', 'rgb'): 00302 self.popupMenu.Append(self.popupID['zoom'], text = _("Zoom to selected map(s)")) 00303 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id = self.popupID['zoom']) 00304 self.popupMenu.Append(self.popupID['region'], text = _("Set computational region from selected map(s)")) 00305 self.Bind(wx.EVT_MENU, self.OnSetCompRegFromMap, id = self.popupID['region']) 00306 00307 # specific items 00308 try: 00309 mltype = self.GetPyData(self.layer_selected)[0]['type'] 00310 except: 00311 mltype = None 00312 00313 # vector layers (specific items) 00314 if mltype and mltype == "vector": 00315 self.popupMenu.AppendSeparator() 00316 self.popupMenu.Append(self.popupID['export'], text = _("Export")) 00317 self.Bind(wx.EVT_MENU, lambda x: self.lmgr.OnMenuCmd(cmd = ['v.out.ogr', 00318 'input=%s' % mapLayer.GetName()]), 00319 id = self.popupID['export']) 00320 00321 self.popupMenu.AppendSeparator() 00322 self.popupMenu.Append(self.popupID['attr'], text = _("Show attribute data")) 00323 self.Bind(wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id = self.popupID['attr']) 00324 00325 self.popupMenu.Append(self.popupID['edit0'], text = _("Start editing")) 00326 self.popupMenu.Append(self.popupID['edit1'], text = _("Stop editing")) 00327 self.popupMenu.Enable(self.popupID['edit1'], False) 00328 self.Bind (wx.EVT_MENU, self.OnStartEditing, id = self.popupID['edit0']) 00329 self.Bind (wx.EVT_MENU, self.OnStopEditing, id = self.popupID['edit1']) 00330 00331 layer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00332 # enable editing only for vector map layers available in the current mapset 00333 digitToolbar = self.mapdisplay.toolbars['vdigit'] 00334 if digitToolbar: 00335 # background vector map 00336 self.popupMenu.Append(self.popupID['bgmap'], 00337 text = _("Use as background vector map for digitizer"), 00338 kind = wx.ITEM_CHECK) 00339 self.Bind(wx.EVT_MENU, self.OnSetBgMap, id = self.popupID['bgmap']) 00340 if UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value', 00341 internal = True) == layer.GetName(): 00342 self.popupMenu.Check(self.popupID['bgmap'], True) 00343 00344 self.popupMenu.Append(self.popupID['topo'], text = _("Rebuild topology")) 00345 self.Bind(wx.EVT_MENU, self.OnTopology, id = self.popupID['topo']) 00346 00347 if layer.GetMapset() != grass.gisenv()['MAPSET']: 00348 # only vector map in current mapset can be edited 00349 self.popupMenu.Enable (self.popupID['edit0'], False) 00350 self.popupMenu.Enable (self.popupID['edit1'], False) 00351 self.popupMenu.Enable (self.popupID['topo'], False) 00352 elif digitToolbar and digitToolbar.GetLayer(): 00353 # vector map already edited 00354 vdigitLayer = digitToolbar.GetLayer() 00355 if vdigitLayer is layer: 00356 self.popupMenu.Enable(self.popupID['edit0'], False) 00357 self.popupMenu.Enable(self.popupID['edit1'], True) 00358 self.popupMenu.Enable(self.popupID['remove'], False) 00359 self.popupMenu.Enable(self.popupID['bgmap'], False) 00360 self.popupMenu.Enable(self.popupID['topo'], False) 00361 else: 00362 self.popupMenu.Enable(self.popupID['edit0'], False) 00363 self.popupMenu.Enable(self.popupID['edit1'], False) 00364 self.popupMenu.Enable(self.popupID['bgmap'], True) 00365 00366 self.popupMenu.Append(self.popupID['meta'], _("Metadata")) 00367 self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID['meta']) 00368 if numSelected > 1: 00369 self.popupMenu.Enable(self.popupID['attr'], False) 00370 self.popupMenu.Enable(self.popupID['edit0'], False) 00371 self.popupMenu.Enable(self.popupID['edit1'], False) 00372 self.popupMenu.Enable(self.popupID['meta'], False) 00373 self.popupMenu.Enable(self.popupID['bgmap'], False) 00374 self.popupMenu.Enable(self.popupID['topo'], False) 00375 self.popupMenu.Enable(self.popupID['export'], False) 00376 00377 # raster layers (specific items) 00378 elif mltype and mltype == "raster": 00379 self.popupMenu.Append(self.popupID['zoom1'], text = _("Zoom to selected map(s) (ignore NULLs)")) 00380 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id = self.popupID['zoom1']) 00381 self.popupMenu.Append(self.popupID['region1'], text = _("Set computational region from selected map(s) (ignore NULLs)")) 00382 self.Bind(wx.EVT_MENU, self.OnSetCompRegFromRaster, id = self.popupID['region1']) 00383 00384 self.popupMenu.AppendSeparator() 00385 self.popupMenu.Append(self.popupID['export'], text = _("Export")) 00386 self.Bind(wx.EVT_MENU, lambda x: self.lmgr.OnMenuCmd(cmd = ['r.out.gdal', 00387 'input=%s' % mapLayer.GetName()]), 00388 id = self.popupID['export']) 00389 00390 self.popupMenu.AppendSeparator() 00391 self.popupMenu.Append(self.popupID['color'], _("Set color table")) 00392 self.Bind (wx.EVT_MENU, self.OnColorTable, id = self.popupID['color']) 00393 self.popupMenu.Append(self.popupID['hist'], _("Histogram")) 00394 self.Bind (wx.EVT_MENU, self.OnHistogram, id = self.popupID['hist']) 00395 self.popupMenu.Append(self.popupID['univar'], _("Univariate raster statistics")) 00396 self.Bind (wx.EVT_MENU, self.OnUnivariateStats, id = self.popupID['univar']) 00397 self.popupMenu.Append(self.popupID['prof'], _("Profile")) 00398 self.Bind (wx.EVT_MENU, self.OnProfile, id = self.popupID['prof']) 00399 self.popupMenu.Append(self.popupID['meta'], _("Metadata")) 00400 self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID['meta']) 00401 00402 if numSelected > 1: 00403 self.popupMenu.Enable(self.popupID['zoom1'], False) 00404 self.popupMenu.Enable(self.popupID['region1'], False) 00405 self.popupMenu.Enable(self.popupID['color'], False) 00406 self.popupMenu.Enable(self.popupID['hist'], False) 00407 self.popupMenu.Enable(self.popupID['univar'], False) 00408 self.popupMenu.Enable(self.popupID['prof'], False) 00409 self.popupMenu.Enable(self.popupID['meta'], False) 00410 self.popupMenu.Enable(self.popupID['nviz'], False) 00411 self.popupMenu.Enable(self.popupID['export'], False) 00412 00413 self.PopupMenu(self.popupMenu) 00414 self.popupMenu.Destroy() 00415 00416 def OnTopology(self, event): 00417 """!Rebuild topology of selected vector map""" 00418 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00419 cmd = ['v.build', 00420 'map=%s' % mapLayer.GetName()] 00421 self.lmgr.goutput.RunCmd(cmd, switchPage = True) 00422 00423 def OnMetadata(self, event): 00424 """!Print metadata of raster/vector map layer 00425 TODO: Dialog to modify metadata 00426 """ 00427 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00428 mltype = self.GetPyData(self.layer_selected)[0]['type'] 00429 00430 if mltype == 'raster': 00431 cmd = ['r.info'] 00432 elif mltype == 'vector': 00433 cmd = ['v.info'] 00434 cmd.append('map=%s' % mapLayer.GetName()) 00435 00436 # print output to command log area 00437 self.lmgr.goutput.RunCmd(cmd, switchPage = True) 00438 00439 def OnSetCompRegFromRaster(self, event): 00440 """!Set computational region from selected raster map (ignore NULLs)""" 00441 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00442 00443 cmd = ['g.region', 00444 '-p', 00445 'zoom=%s' % mapLayer.GetName()] 00446 00447 # print output to command log area 00448 self.lmgr.goutput.RunCmd(cmd) 00449 00450 def OnSetCompRegFromMap(self, event): 00451 """!Set computational region from selected raster/vector map 00452 """ 00453 rast = [] 00454 vect = [] 00455 rast3d = [] 00456 for layer in self.GetSelections(): 00457 mapLayer = self.GetPyData(layer)[0]['maplayer'] 00458 mltype = self.GetPyData(layer)[0]['type'] 00459 00460 if mltype == 'raster': 00461 rast.append(mapLayer.GetName()) 00462 elif mltype == 'vector': 00463 vect.append(mapLayer.GetName()) 00464 elif mltype == '3d-raster': 00465 rast3d.append(mapLayer.GetName()) 00466 elif mltype == 'rgb': 00467 for rname in mapLayer.GetName().splitlines(): 00468 rast.append(rname) 00469 00470 cmd = ['g.region'] 00471 if rast: 00472 cmd.append('rast=%s' % ','.join(rast)) 00473 if vect: 00474 cmd.append('vect=%s' % ','.join(vect)) 00475 if rast3d: 00476 cmd.append('rast3d=%s' % ','.join(rast3d)) 00477 00478 # print output to command log area 00479 if len(cmd) > 1: 00480 cmd.append('-p') 00481 self.lmgr.goutput.RunCmd(cmd) 00482 00483 def OnProfile(self, event): 00484 """!Plot profile of given raster map layer""" 00485 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00486 if not mapLayer.GetName(): 00487 wx.MessageBox(parent = self, 00488 message = _("Unable to create profile of " 00489 "raster map."), 00490 caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00491 return False 00492 00493 if not hasattr (self, "profileFrame"): 00494 self.profileFrame = None 00495 00496 if hasattr (self.mapdisplay, "profile") and self.mapdisplay.profile: 00497 self.profileFrame = self.mapdisplay.profile 00498 00499 if not self.profileFrame: 00500 self.profileFrame = profile.ProfileFrame(self.mapdisplay, 00501 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300), 00502 style = wx.DEFAULT_FRAME_STYLE, rasterList = [mapLayer.GetName()]) 00503 # show new display 00504 self.profileFrame.Show() 00505 00506 def OnColorTable(self, event): 00507 """!Set color table for raster map""" 00508 name = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName() 00509 menuform.GUI(parent = self).ParseCommand(['r.colors', 00510 'map=%s' % name]) 00511 00512 def OnHistogram(self, event): 00513 """ 00514 Plot histogram for given raster map layer 00515 """ 00516 mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00517 if not mapLayer.GetName(): 00518 wx.MessageBox(parent = self, 00519 message = _("Unable to display histogram of " 00520 "raster map."), 00521 caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00522 return False 00523 00524 if not hasattr (self, "histogramFrame"): 00525 self.histogramFrame = None 00526 00527 if hasattr (self.mapdisplay, "histogram") and self.mapdisplay.histogram: 00528 self.histogramFrame = self.mapdisplay.histogram 00529 00530 if not self.histogramFrame: 00531 self.histogramFrame = histogram.HistFrame(self, 00532 id = wx.ID_ANY, 00533 pos = wx.DefaultPosition, size = globalvar.HIST_WINDOW_SIZE, 00534 style = wx.DEFAULT_FRAME_STYLE) 00535 # show new display 00536 self.histogramFrame.Show() 00537 00538 self.histogramFrame.SetHistLayer(mapLayer.GetName()) 00539 self.histogramFrame.HistWindow.UpdateHist() 00540 self.histogramFrame.Refresh() 00541 self.histogramFrame.Update() 00542 00543 return True 00544 00545 def OnUnivariateStats(self, event): 00546 """!Univariate raster statistics""" 00547 name = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName() 00548 menuform.GUI(parent = self).ParseCommand(['r.univar', 00549 'map=%s' % name]) 00550 00551 def OnStartEditing(self, event): 00552 """!Start editing vector map layer requested by the user 00553 """ 00554 try: 00555 maplayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00556 except: 00557 event.Skip() 00558 return 00559 00560 if not self.mapdisplay.toolbars['vdigit']: # enable tool 00561 self.mapdisplay.AddToolbar('vdigit') 00562 00563 if not self.mapdisplay.toolbars['vdigit']: 00564 return 00565 00566 self.mapdisplay.toolbars['vdigit'].StartEditing(maplayer) 00567 00568 self._setGradient('vdigit') 00569 self.RefreshLine(self.layer_selected) 00570 00571 def OnStopEditing(self, event): 00572 """!Stop editing the current vector map layer 00573 """ 00574 maplayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00575 00576 self.mapdisplay.toolbars['vdigit'].OnExit() 00577 if self.lmgr: 00578 self.lmgr.toolbars['tools'].Enable('vdigit', enable = True) 00579 00580 self._setGradient() 00581 self.RefreshLine(self.layer_selected) 00582 00583 def OnSetBgMap(self, event): 00584 """!Set background vector map for editing sesstion""" 00585 digit = self.mapdisplay.GetWindow().digit 00586 if event.IsChecked(): 00587 mapName = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName() 00588 UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value', 00589 value = str(mapName), internal = True) 00590 digit.OpenBackgroundMap(mapName) 00591 self._setGradient('bgmap') 00592 else: 00593 UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value', 00594 value = '', internal = True) 00595 digit.CloseBackgroundMap() 00596 self._setGradient() 00597 00598 self.RefreshLine(self.layer_selected) 00599 00600 def OnPopupProperties (self, event): 00601 """!Popup properties dialog""" 00602 self.PropertiesDialog(self.layer_selected) 00603 00604 def OnPopupOpacityLevel(self, event): 00605 """!Popup opacity level indicator""" 00606 if not self.GetPyData(self.layer_selected)[0]['ctrl']: 00607 return 00608 00609 maplayer = self.GetPyData(self.layer_selected)[0]['maplayer'] 00610 current_opacity = maplayer.GetOpacity() 00611 00612 dlg = gdialogs.SetOpacityDialog(self, opacity = current_opacity, 00613 title = _("Set opacity <%s>") % maplayer.GetName()) 00614 dlg.CentreOnParent() 00615 00616 if dlg.ShowModal() == wx.ID_OK: 00617 new_opacity = dlg.GetOpacity() # string 00618 self.Map.ChangeOpacity(maplayer, new_opacity) 00619 maplayer.SetOpacity(new_opacity) 00620 self.SetItemText(self.layer_selected, 00621 self._getLayerName(self.layer_selected)) 00622 00623 # vector layer currently edited 00624 if self.mapdisplay.toolbars['vdigit'] and \ 00625 self.mapdisplay.toolbars['vdigit'].GetLayer() == maplayer: 00626 alpha = int(new_opacity * 255) 00627 self.mapdisplay.GetWindow().digit.GetDisplay().UpdateSettings(alpha = alpha) 00628 00629 # redraw map if auto-rendering is enabled 00630 self.rerender = True 00631 self.reorder = True 00632 00633 def OnNvizProperties(self, event): 00634 """!Nviz-related properties (raster/vector/volume) 00635 00636 @todo vector/volume 00637 """ 00638 self.lmgr.notebook.SetSelectionByName('nviz') 00639 ltype = self.GetPyData(self.layer_selected)[0]['type'] 00640 if ltype == 'raster': 00641 self.lmgr.nviz.SetPage('surface') 00642 elif ltype == 'vector': 00643 self.lmgr.nviz.SetPage('vector') 00644 elif ltype == '3d-raster': 00645 self.lmgr.nviz.SetPage('volume') 00646 00647 def OnRenameLayer (self, event): 00648 """!Rename layer""" 00649 self.EditLabel(self.layer_selected) 00650 self.GetEditControl().SetSelection(-1, -1) 00651 00652 def OnRenamed(self, event): 00653 """!Layer renamed""" 00654 item = self.layer_selected 00655 self.GetPyData(item)[0]['label'] = event.GetLabel() 00656 self.SetItemText(item, self._getLayerName(item)) # not working, why? 00657 00658 event.Skip() 00659 00660 def AddLayer(self, ltype, lname = None, lchecked = None, 00661 lopacity = 1.0, lcmd = None, lgroup = None, lvdigit = None, lnviz = None, multiple = True): 00662 """!Add new item to the layer tree, create corresponding MapLayer instance. 00663 Launch property dialog if needed (raster, vector, etc.) 00664 00665 @param ltype layer type (raster, vector, 3d-raster, ...) 00666 @param lname layer name 00667 @param lchecked if True layer is checked 00668 @param lopacity layer opacity level 00669 @param lcmd command (given as a list) 00670 @param lgroup index of group item (-1 for root) or None 00671 @param lvdigit vector digitizer settings (eg. geometry attributes) 00672 @param lnviz layer Nviz properties 00673 @param multiple True to allow multiple map layers in layer tree 00674 """ 00675 if lname and not multiple: 00676 # check for duplicates 00677 item = self.GetFirstVisibleItem() 00678 while item and item.IsOk(): 00679 if self.GetPyData(item)[0]['type'] == 'vector': 00680 name = self.GetPyData(item)[0]['maplayer'].GetName() 00681 if name == lname: 00682 return 00683 item = self.GetNextVisible(item) 00684 00685 self.first = True 00686 params = {} # no initial options parameters 00687 00688 # deselect active item 00689 if self.layer_selected: 00690 self.SelectItem(self.layer_selected, select = False) 00691 00692 Debug.msg (3, "LayerTree().AddLayer(): ltype=%s" % (ltype)) 00693 00694 if ltype == 'command': 00695 # generic command item 00696 ctrl = wx.TextCtrl(self, id = wx.ID_ANY, value = '', 00697 pos = wx.DefaultPosition, size = (self.GetSize()[0]-100,25), 00698 # style = wx.TE_MULTILINE|wx.TE_WORDWRAP) 00699 style = wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP) 00700 ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged) 00701 # ctrl.Bind(wx.EVT_TEXT, self.OnCmdChanged) 00702 elif ltype == 'group': 00703 # group item 00704 ctrl = None 00705 grouptext = _('Layer group:') + str(self.groupnode) 00706 self.groupnode += 1 00707 else: 00708 btnbmp = Icons['layerManager']["layerOptions"].GetBitmap((16,16)) 00709 ctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24,24)) 00710 ctrl.SetToolTipString(_("Click to edit layer settings")) 00711 self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, ctrl) 00712 # add layer to the layer tree 00713 if self.layer_selected and self.layer_selected != self.GetRootItem(): 00714 if self.GetPyData(self.layer_selected)[0]['type'] == 'group' \ 00715 and self.IsExpanded(self.layer_selected): 00716 # add to group (first child of self.layer_selected) if group expanded 00717 layer = self.PrependItem(parent = self.layer_selected, 00718 text = '', ct_type = 1, wnd = ctrl) 00719 else: 00720 # prepend to individual layer or non-expanded group 00721 if lgroup == -1: 00722 # -> last child of root (loading from workspace) 00723 layer = self.AppendItem(parentId = self.root, 00724 text = '', ct_type = 1, wnd = ctrl) 00725 elif lgroup > -1: 00726 # -> last child of group (loading from workspace) 00727 parent = self.FindItemByIndex(index = lgroup) 00728 if not parent: 00729 parent = self.root 00730 layer = self.AppendItem(parentId = parent, 00731 text = '', ct_type = 1, wnd = ctrl) 00732 elif lgroup is None: 00733 # -> previous sibling of selected layer 00734 parent = self.GetItemParent(self.layer_selected) 00735 layer = self.InsertItem(parentId = parent, 00736 input = self.GetPrevSibling(self.layer_selected), 00737 text = '', ct_type = 1, wnd = ctrl) 00738 else: # add first layer to the layer tree (first child of root) 00739 layer = self.PrependItem(parent = self.root, text = '', ct_type = 1, wnd = ctrl) 00740 00741 # layer is initially unchecked as inactive (beside 'command') 00742 # use predefined value if given 00743 if lchecked is not None: 00744 checked = lchecked 00745 else: 00746 checked = True 00747 00748 self.CheckItem(layer, checked = checked) 00749 00750 # add text and icons for each layer ltype 00751 label = _('(double click to set properties)') + ' ' * 15 00752 if ltype == 'raster': 00753 self.SetItemImage(layer, self.rast_icon) 00754 self.SetItemText(layer, '%s %s' % (_('raster'), label)) 00755 elif ltype == '3d-raster': 00756 self.SetItemImage(layer, self.rast3d_icon) 00757 self.SetItemText(layer, '%s %s' % (_('3d raster'), label)) 00758 elif ltype == 'rgb': 00759 self.SetItemImage(layer, self.rgb_icon) 00760 self.SetItemText(layer, '%s %s' % (_('RGB'), label)) 00761 elif ltype == 'his': 00762 self.SetItemImage(layer, self.his_icon) 00763 self.SetItemText(layer, '%s %s' % (_('HIS'), label)) 00764 elif ltype == 'shaded': 00765 self.SetItemImage(layer, self.shaded_icon) 00766 self.SetItemText(layer, '%s %s' % (_('Shaded relief'), label)) 00767 elif ltype == 'rastnum': 00768 self.SetItemImage(layer, self.rnum_icon) 00769 self.SetItemText(layer, '%s %s' % (_('raster cell numbers'), label)) 00770 elif ltype == 'rastarrow': 00771 self.SetItemImage(layer, self.rarrow_icon) 00772 self.SetItemText(layer, '%s %s' % (_('raster flow arrows'), label)) 00773 elif ltype == 'vector': 00774 self.SetItemImage(layer, self.vect_icon) 00775 self.SetItemText(layer, '%s %s' % (_('vector'), label)) 00776 elif ltype == 'thememap': 00777 self.SetItemImage(layer, self.theme_icon) 00778 self.SetItemText(layer, '%s %s' % (_('thematic map'), label)) 00779 elif ltype == 'themechart': 00780 self.SetItemImage(layer, self.chart_icon) 00781 self.SetItemText(layer, '%s %s' % (_('thematic charts'), label)) 00782 elif ltype == 'grid': 00783 self.SetItemImage(layer, self.grid_icon) 00784 self.SetItemText(layer, '%s %s' % (_('grid'), label)) 00785 elif ltype == 'geodesic': 00786 self.SetItemImage(layer, self.geodesic_icon) 00787 self.SetItemText(layer, '%s %s' % (_('geodesic line'), label)) 00788 elif ltype == 'rhumb': 00789 self.SetItemImage(layer, self.rhumb_icon) 00790 self.SetItemText(layer, '%s %s' % (_('rhumbline'), label)) 00791 elif ltype == 'labels': 00792 self.SetItemImage(layer, self.labels_icon) 00793 self.SetItemText(layer, '%s %s' % (_('vector labels'), label)) 00794 elif ltype == 'command': 00795 self.SetItemImage(layer, self.cmd_icon) 00796 elif ltype == 'group': 00797 self.SetItemImage(layer, self.folder) 00798 self.SetItemText(layer, grouptext) 00799 00800 self.first = False 00801 00802 if ltype != 'group': 00803 if lcmd and len(lcmd) > 1: 00804 cmd = lcmd 00805 render = False 00806 name, found = utils.GetLayerNameFromCmd(lcmd) 00807 else: 00808 cmd = [] 00809 if ltype == 'command' and lname: 00810 for c in lname.split(';'): 00811 cmd.append(c.split(' ')) 00812 00813 render = False 00814 name = None 00815 00816 if ctrl: 00817 ctrlId = ctrl.GetId() 00818 else: 00819 ctrlId = None 00820 00821 # add a data object to hold the layer's command (does not apply to generic command layers) 00822 self.SetPyData(layer, ({'cmd' : cmd, 00823 'type' : ltype, 00824 'ctrl' : ctrlId, 00825 'label' : None, 00826 'maplayer' : None, 00827 'vdigit' : lvdigit, 00828 'nviz' : lnviz, 00829 'propwin' : None}, 00830 None)) 00831 00832 # find previous map layer instance 00833 prevItem = self.GetFirstChild(self.root)[0] 00834 prevMapLayer = None 00835 pos = -1 00836 while prevItem and prevItem.IsOk() and prevItem != layer: 00837 if self.GetPyData(prevItem)[0]['maplayer']: 00838 prevMapLayer = self.GetPyData(prevItem)[0]['maplayer'] 00839 00840 prevItem = self.GetNextSibling(prevItem) 00841 00842 if prevMapLayer: 00843 pos = self.Map.GetLayerIndex(prevMapLayer) 00844 else: 00845 pos = -1 00846 00847 maplayer = self.Map.AddLayer(pos = pos, 00848 type = ltype, command = self.GetPyData(layer)[0]['cmd'], name = name, 00849 l_active = checked, l_hidden = False, 00850 l_opacity = lopacity, l_render = render) 00851 self.GetPyData(layer)[0]['maplayer'] = maplayer 00852 00853 # run properties dialog if no properties given 00854 if len(cmd) == 0: 00855 self.PropertiesDialog(layer, show = True) 00856 00857 else: # group 00858 self.SetPyData(layer, ({'cmd' : None, 00859 'type' : ltype, 00860 'ctrl' : None, 00861 'label' : None, 00862 'maplayer' : None, 00863 'propwin' : None}, 00864 None)) 00865 00866 # select new item 00867 self.SelectItem(layer, select = True) 00868 self.layer_selected = layer 00869 00870 # use predefined layer name if given 00871 if lname: 00872 if ltype == 'group': 00873 self.SetItemText(layer, lname) 00874 elif ltype == 'command': 00875 ctrl.SetValue(lname) 00876 else: 00877 self.SetItemText(layer, self._getLayerName(layer, lname)) 00878 00879 # updated progress bar range (mapwindow statusbar) 00880 if checked is True: 00881 self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True))) 00882 00883 return layer 00884 00885 def PropertiesDialog (self, layer, show = True): 00886 """!Launch the properties dialog""" 00887 if 'propwin' in self.GetPyData(layer)[0] and \ 00888 self.GetPyData(layer)[0]['propwin'] is not None: 00889 # recycle GUI dialogs 00890 win = self.GetPyData(layer)[0]['propwin'] 00891 # update properties (columns, layers) 00892 win.notebookpanel.OnUpdateSelection(None) 00893 if win.IsShown(): 00894 win.SetFocus() 00895 else: 00896 win.Show() 00897 00898 return 00899 00900 completed = '' 00901 params = self.GetPyData(layer)[1] 00902 ltype = self.GetPyData(layer)[0]['type'] 00903 00904 Debug.msg (3, "LayerTree.PropertiesDialog(): ltype=%s" % \ 00905 ltype) 00906 00907 if self.GetPyData(layer)[0]['cmd']: 00908 module = menuform.GUI(parent = self, show = show, centreOnParent = False) 00909 module.ParseCommand(self.GetPyData(layer)[0]['cmd'], 00910 completed = (self.GetOptData,layer,params)) 00911 00912 self.GetPyData(layer)[0]['cmd'] = module.GetCmd() 00913 elif ltype == 'raster': 00914 cmd = ['d.rast'] 00915 00916 if UserSettings.Get(group='cmd', key='rasterOverlay', subkey='enabled'): 00917 cmd.append('-o') 00918 00919 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(cmd, 00920 completed = (self.GetOptData,layer,params)) 00921 00922 elif ltype == '3d-raster': 00923 cmd = ['d.rast3d'] 00924 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(cmd, 00925 completed = (self.GetOptData,layer,params)) 00926 00927 elif ltype == 'rgb': 00928 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rgb'], 00929 completed = (self.GetOptData,layer,params)) 00930 00931 elif ltype == 'his': 00932 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.his'], 00933 completed = (self.GetOptData,layer,params)) 00934 00935 elif ltype == 'shaded': 00936 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.shadedmap'], 00937 completed = (self.GetOptData,layer,params)) 00938 00939 elif ltype == 'rastarrow': 00940 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rast.arrow'], 00941 completed = (self.GetOptData,layer,params)) 00942 00943 elif ltype == 'rastnum': 00944 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rast.num'], 00945 completed = (self.GetOptData,layer,params)) 00946 00947 elif ltype == 'vector': 00948 types = list() 00949 for ftype in ['point', 'line', 'boundary', 'centroid', 'area', 'face']: 00950 if UserSettings.Get(group = 'cmd', key = 'showType', subkey = [ftype, 'enabled']): 00951 types.append(ftype) 00952 00953 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect', 'type=%s' % ','.join(types)], 00954 completed = (self.GetOptData,layer,params)) 00955 00956 elif ltype == 'thememap': 00957 # -s flag requested, otherwise only first thematic category is displayed 00958 # should be fixed by C-based d.thematic.* modules 00959 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect.thematic', '-s'], 00960 completed = (self.GetOptData,layer,params)) 00961 00962 elif ltype == 'themechart': 00963 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect.chart'], 00964 completed = (self.GetOptData,layer,params)) 00965 00966 elif ltype == 'grid': 00967 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.grid'], 00968 completed = (self.GetOptData,layer,params)) 00969 00970 elif ltype == 'geodesic': 00971 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.geodesic'], 00972 completed = (self.GetOptData,layer,params)) 00973 00974 elif ltype == 'rhumb': 00975 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rhumbline'], 00976 completed = (self.GetOptData,layer,params)) 00977 00978 elif ltype == 'labels': 00979 menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.labels'], 00980 completed = (self.GetOptData,layer,params)) 00981 00982 elif ltype == 'cmdlayer': 00983 pass 00984 elif ltype == 'group': 00985 pass 00986 00987 def OnActivateLayer(self, event): 00988 """!Double click on the layer item. 00989 Launch property dialog, or expand/collapse group of items, etc. 00990 """ 00991 self.lmgr.WorkspaceChanged() 00992 layer = event.GetItem() 00993 self.layer_selected = layer 00994 00995 self.PropertiesDialog (layer) 00996 00997 if self.GetPyData(layer)[0]['type'] == 'group': 00998 if self.IsExpanded(layer): 00999 self.Collapse(layer) 01000 else: 01001 self.Expand(layer) 01002 01003 def OnDeleteLayer(self, event): 01004 """!Remove selected layer item from the layer tree""" 01005 self.lmgr.WorkspaceChanged() 01006 item = event.GetItem() 01007 01008 try: 01009 item.properties.Close(True) 01010 except: 01011 pass 01012 01013 if item != self.root: 01014 Debug.msg (3, "LayerTree.OnDeleteLayer(): name=%s" % \ 01015 (self.GetItemText(item))) 01016 else: 01017 self.root = None 01018 01019 # unselect item 01020 self.Unselect() 01021 self.layer_selected = None 01022 01023 try: 01024 if self.GetPyData(item)[0]['type'] != 'group': 01025 self.Map.DeleteLayer( self.GetPyData(item)[0]['maplayer']) 01026 except: 01027 pass 01028 01029 # redraw map if auto-rendering is enabled 01030 self.rerender = True 01031 self.reorder = True 01032 01033 if self.mapdisplay.toolbars['vdigit']: 01034 self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers (updateTool = True) 01035 01036 # update progress bar range (mapwindow statusbar) 01037 self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True))) 01038 01039 event.Skip() 01040 01041 def OnLayerChecked(self, event): 01042 """!Enable/disable data layer""" 01043 self.lmgr.WorkspaceChanged() 01044 01045 item = event.GetItem() 01046 checked = item.IsChecked() 01047 01048 digitToolbar = self.mapdisplay.toolbars['vdigit'] 01049 if self.first == False: 01050 # change active parameter for item in layers list in render.Map 01051 if self.GetPyData(item)[0]['type'] == 'group': 01052 child, cookie = self.GetFirstChild(item) 01053 while child: 01054 self.CheckItem(child, checked) 01055 mapLayer = self.GetPyData(child)[0]['maplayer'] 01056 if not digitToolbar or \ 01057 (digitToolbar and digitToolbar.GetLayer() != mapLayer): 01058 # ignore when map layer is edited 01059 self.Map.ChangeLayerActive(mapLayer, checked) 01060 child = self.GetNextSibling(child) 01061 else: 01062 mapLayer = self.GetPyData(item)[0]['maplayer'] 01063 if not digitToolbar or \ 01064 (digitToolbar and digitToolbar.GetLayer() != mapLayer): 01065 # ignore when map layer is edited 01066 self.Map.ChangeLayerActive(mapLayer, checked) 01067 01068 # 01069 # update progress bar range (mapwindow statusbar) 01070 # 01071 self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True))) 01072 01073 # 01074 # nviz 01075 # 01076 if self.mapdisplay.toolbars['nviz'] and \ 01077 self.GetPyData(item) is not None: 01078 # nviz - load/unload data layer 01079 mapLayer = self.GetPyData(item)[0]['maplayer'] 01080 01081 self.mapdisplay.SetStatusText(_("Please wait, updating data..."), 0) 01082 01083 if checked: # enable 01084 if mapLayer.type == 'raster': 01085 self.mapdisplay.MapWindow.LoadRaster(item) 01086 elif mapLayer.type == '3d-raster': 01087 self.mapdisplay.MapWindow.LoadRaster3d(item) 01088 elif mapLayer.type == 'vector': 01089 npoints, nlines, nfeatures, mapIs3D = self.lmgr.nviz.VectorInfo(mapLayer) 01090 if npoints > 0: 01091 self.mapdisplay.MapWindow.LoadVector(item, points = True) 01092 if nlines > 0: 01093 self.mapdisplay.MapWindow.LoadVector(item, points = False) 01094 01095 else: # disable 01096 if mapLayer.type == 'raster': 01097 self.mapdisplay.MapWindow.UnloadRaster(item) 01098 elif mapLayer.type == '3d-raster': 01099 self.mapdisplay.MapWindow.UnloadRaster3d(item) 01100 elif mapLayer.type == 'vector': 01101 self.mapdisplay.MapWindow.UnloadVector(item) 01102 01103 self.mapdisplay.SetStatusText("", 0) 01104 01105 # redraw map if auto-rendering is enabled 01106 self.rerender = True 01107 self.reorder = True 01108 01109 def OnCmdChanged(self, event): 01110 """!Change command string""" 01111 ctrl = event.GetEventObject().GetId() 01112 cmd = event.GetString() 01113 01114 layer = self.GetFirstVisibleItem() 01115 01116 while layer and layer.IsOk(): 01117 if self.GetPyData(layer)[0]['ctrl'] == ctrl: 01118 break 01119 01120 layer = self.GetNextVisible(layer) 01121 01122 # change parameters for item in layers list in render.Map 01123 self.ChangeLayer(layer) 01124 01125 event.Skip() 01126 01127 def OnChangeSel(self, event): 01128 """!Selection changed""" 01129 oldlayer = event.GetOldItem() 01130 layer = event.GetItem() 01131 if layer == oldlayer: 01132 event.Veto() 01133 return 01134 01135 digitToolbar = self.mapdisplay.toolbars['vdigit'] 01136 if digitToolbar: 01137 mapLayer = self.GetPyData(layer)[0]['maplayer'] 01138 bgmap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value', 01139 internal = True) 01140 01141 if digitToolbar.GetLayer() == mapLayer: 01142 self._setGradient('vdigit') 01143 elif bgmap == mapLayer.GetName(): 01144 self._setGradient('bgmap') 01145 else: 01146 self._setGradient() 01147 else: 01148 self._setGradient() 01149 01150 self.layer_selected = layer 01151 01152 try: 01153 if self.IsSelected(oldlayer): 01154 self.SetItemWindowEnabled(oldlayer, True) 01155 else: 01156 self.SetItemWindowEnabled(oldlayer, False) 01157 01158 if self.IsSelected(layer): 01159 self.SetItemWindowEnabled(layer, True) 01160 else: 01161 self.SetItemWindowEnabled(layer, False) 01162 except: 01163 pass 01164 01165 try: 01166 self.RefreshLine(oldlayer) 01167 self.RefreshLine(layer) 01168 except: 01169 pass 01170 01171 # update statusbar -> show command string 01172 if self.GetPyData(layer) and self.GetPyData(layer)[0]['maplayer']: 01173 cmd = self.GetPyData(layer)[0]['maplayer'].GetCmd(string = True) 01174 if len(cmd) > 0: 01175 self.lmgr.SetStatusText(cmd) 01176 01177 # set region if auto-zooming is enabled 01178 if self.GetPyData(layer) and self.GetPyData(layer)[0]['cmd'] and \ 01179 UserSettings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'): 01180 mapLayer = self.GetPyData(layer)[0]['maplayer'] 01181 if mapLayer.GetType() in ('raster', 'vector'): 01182 render = self.mapdisplay.statusbarWin['render'].IsChecked() 01183 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,], 01184 render = render) 01185 01186 # update nviz tools 01187 if self.mapdisplay.toolbars['nviz'] and \ 01188 self.GetPyData(self.layer_selected) is not None: 01189 if self.layer_selected.IsChecked(): 01190 # update Nviz tool window 01191 type = self.GetPyData(self.layer_selected)[0]['maplayer'].type 01192 01193 if type == 'raster': 01194 self.lmgr.nviz.UpdatePage('surface') 01195 self.lmgr.nviz.SetPage('surface') 01196 elif type == 'vector': 01197 self.lmgr.nviz.UpdatePage('vector') 01198 self.lmgr.nviz.SetPage('vector') 01199 elif type == '3d-raster': 01200 self.lmgr.nviz.UpdatePage('volume') 01201 self.lmgr.nviz.SetPage('volume') 01202 01203 def OnCollapseNode(self, event): 01204 """!Collapse node 01205 """ 01206 if self.GetPyData(self.layer_selected)[0]['type'] == 'group': 01207 self.SetItemImage(self.layer_selected, self.folder) 01208 01209 def OnExpandNode(self, event): 01210 """!Expand node 01211 """ 01212 self.layer_selected = event.GetItem() 01213 if self.GetPyData(self.layer_selected)[0]['type'] == 'group': 01214 self.SetItemImage(self.layer_selected, self.folder_open) 01215 01216 def OnEndDrag(self, event): 01217 self.StopDragging() 01218 dropTarget = event.GetItem() 01219 self.flag = self.HitTest(event.GetPoint())[1] 01220 if self.IsValidDropTarget(dropTarget): 01221 self.UnselectAll() 01222 if dropTarget != None: 01223 self.SelectItem(dropTarget) 01224 self.OnDrop(dropTarget, self._dragItem) 01225 elif dropTarget == None: 01226 self.OnDrop(dropTarget, self._dragItem) 01227 01228 def OnDrop(self, dropTarget, dragItem): 01229 # save everthing associated with item to drag 01230 try: 01231 old = dragItem # make sure this member exists 01232 except: 01233 return 01234 01235 Debug.msg (4, "LayerTree.OnDrop(): layer=%s" % \ 01236 (self.GetItemText(dragItem))) 01237 01238 # recreate data layer, insert copy of layer in new position, and delete original at old position 01239 newItem = self.RecreateItem (dragItem, dropTarget) 01240 01241 # if recreated layer is a group, also recreate its children 01242 if self.GetPyData(newItem)[0]['type'] == 'group': 01243 (child, cookie) = self.GetFirstChild(dragItem) 01244 if child: 01245 while child: 01246 self.RecreateItem(child, dropTarget, parent = newItem) 01247 self.Delete(child) 01248 child = self.GetNextChild(old, cookie)[0] 01249 01250 # delete layer at original position 01251 try: 01252 self.Delete(old) # entry in render.Map layers list automatically deleted by OnDeleteLayer handler 01253 except AttributeError: 01254 pass 01255 01256 # redraw map if auto-rendering is enabled 01257 self.rerender = True 01258 self.reorder = True 01259 01260 # select new item 01261 self.SelectItem(newItem) 01262 01263 def RecreateItem (self, dragItem, dropTarget, parent = None): 01264 """!Recreate item (needed for OnEndDrag()) 01265 """ 01266 Debug.msg (4, "LayerTree.RecreateItem(): layer=%s" % \ 01267 self.GetItemText(dragItem)) 01268 01269 # fetch data (dragItem) 01270 checked = self.IsItemChecked(dragItem) 01271 image = self.GetItemImage(dragItem, 0) 01272 text = self.GetItemText(dragItem) 01273 if self.GetPyData(dragItem)[0]['ctrl']: 01274 # recreate data layer 01275 btnbmp = Icons['layerManager']["layerOptions"].GetBitmap((16,16)) 01276 newctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24, 24)) 01277 newctrl.SetToolTipString(_("Click to edit layer settings")) 01278 self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, newctrl) 01279 data = self.GetPyData(dragItem) 01280 01281 elif self.GetPyData(dragItem)[0]['type'] == 'command': 01282 # recreate command layer 01283 oldctrl = None 01284 newctrl = wx.TextCtrl(self, id = wx.ID_ANY, value = '', 01285 pos = wx.DefaultPosition, size = (250,25), 01286 style = wx.TE_MULTILINE|wx.TE_WORDWRAP) 01287 try: 01288 newctrl.SetValue(self.GetPyData(dragItem)[0]['maplayer'].GetCmd(string = True)) 01289 except: 01290 pass 01291 newctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged) 01292 newctrl.Bind(wx.EVT_TEXT, self.OnCmdChanged) 01293 data = self.GetPyData(dragItem) 01294 01295 elif self.GetPyData(dragItem)[0]['type'] == 'group': 01296 # recreate group 01297 newctrl = None 01298 data = None 01299 01300 # decide where to put recreated item 01301 if dropTarget != None and dropTarget != self.GetRootItem(): 01302 if parent: 01303 # new item is a group 01304 afteritem = parent 01305 else: 01306 # new item is a single layer 01307 afteritem = dropTarget 01308 01309 # dragItem dropped on group 01310 if self.GetPyData(afteritem)[0]['type'] == 'group': 01311 newItem = self.PrependItem(afteritem, text = text, \ 01312 ct_type = 1, wnd = newctrl, image = image, \ 01313 data = data) 01314 self.Expand(afteritem) 01315 else: 01316 #dragItem dropped on single layer 01317 newparent = self.GetItemParent(afteritem) 01318 newItem = self.InsertItem(newparent, self.GetPrevSibling(afteritem), \ 01319 text = text, ct_type = 1, wnd = newctrl, \ 01320 image = image, data = data) 01321 else: 01322 # if dragItem not dropped on a layer or group, append or prepend it to the layer tree 01323 if self.flag & wx.TREE_HITTEST_ABOVE: 01324 newItem = self.PrependItem(self.root, text = text, \ 01325 ct_type = 1, wnd = newctrl, image = image, \ 01326 data = data) 01327 elif (self.flag & wx.TREE_HITTEST_BELOW) or (self.flag & wx.TREE_HITTEST_NOWHERE) \ 01328 or (self.flag & wx.TREE_HITTEST_TOLEFT) or (self.flag & wx.TREE_HITTEST_TORIGHT): 01329 newItem = self.AppendItem(self.root, text = text, \ 01330 ct_type = 1, wnd = newctrl, image = image, \ 01331 data = data) 01332 01333 #update new layer 01334 self.SetPyData(newItem, self.GetPyData(dragItem)) 01335 if newctrl: 01336 self.GetPyData(newItem)[0]['ctrl'] = newctrl.GetId() 01337 else: 01338 self.GetPyData(newItem)[0]['ctrl'] = None 01339 01340 self.CheckItem(newItem, checked = checked) # causes a new render 01341 01342 return newItem 01343 01344 def _getLayerName(self, item, lname = ''): 01345 """!Get layer name string 01346 01347 @param lname optional layer name 01348 """ 01349 mapLayer = self.GetPyData(item)[0]['maplayer'] 01350 if not lname: 01351 lname = self.GetPyData(item)[0]['label'] 01352 opacity = int(mapLayer.GetOpacity(float = True) * 100) 01353 if not lname: 01354 dcmd = self.GetPyData(item)[0]['cmd'] 01355 lname, found = utils.GetLayerNameFromCmd(dcmd, layerType = mapLayer.GetType(), 01356 fullyQualified = True) 01357 if not found: 01358 return None 01359 01360 if opacity < 100: 01361 return lname + ' (%s %d' % (_('opacity:'), opacity) + '%)' 01362 01363 return lname 01364 01365 def GetOptData(self, dcmd, layer, params, propwin): 01366 """!Process layer data (when changes in propertiesdialog are applied)""" 01367 # set layer text to map name 01368 if dcmd: 01369 self.GetPyData(layer)[0]['cmd'] = dcmd 01370 mapText = self._getLayerName(layer) 01371 mapName, found = utils.GetLayerNameFromCmd(dcmd) 01372 mapLayer = self.GetPyData(layer)[0]['maplayer'] 01373 self.SetItemText(layer, mapName) 01374 01375 if not mapText or not found: 01376 propwin.Hide() 01377 GWarning(parent = self, 01378 message = _("Map <%s> not found.") % mapName) 01379 return 01380 01381 # update layer data 01382 if params: 01383 self.SetPyData(layer, (self.GetPyData(layer)[0], params)) 01384 self.GetPyData(layer)[0]['propwin'] = propwin 01385 01386 # change parameters for item in layers list in render.Map 01387 self.ChangeLayer(layer) 01388 01389 # set region if auto-zooming is enabled 01390 if dcmd and UserSettings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'): 01391 mapLayer = self.GetPyData(layer)[0]['maplayer'] 01392 if mapLayer.GetType() in ('raster', 'vector'): 01393 render = UserSettings.Get(group = 'display', key = 'autoRendering', subkey = 'enabled') 01394 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,], 01395 render = render) 01396 01397 # update nviz session 01398 if self.mapdisplay.toolbars['nviz'] and dcmd: 01399 mapLayer = self.GetPyData(layer)[0]['maplayer'] 01400 mapWin = self.mapdisplay.MapWindow 01401 if len(mapLayer.GetCmd()) > 0: 01402 id = -1 01403 if mapLayer.type == 'raster': 01404 if mapWin.IsLoaded(layer): 01405 mapWin.UnloadRaster(layer) 01406 01407 mapWin.LoadRaster(layer) 01408 01409 elif mapLayer.type == '3d-raster': 01410 if mapWin.IsLoaded(layer): 01411 mapWin.UnloadRaster3d(layer) 01412 01413 mapWin.LoadRaster3d(layer) 01414 01415 elif mapLayer.type == 'vector': 01416 if mapWin.IsLoaded(layer): 01417 mapWin.UnloadVector(layer) 01418 01419 mapWin.LoadVector(layer) 01420 01421 # reset view when first layer loaded 01422 nlayers = len(mapWin.Map.GetListOfLayers(l_type = ('raster', 'vector'), 01423 l_active = True)) 01424 if nlayers < 2: 01425 mapWin.ResetView() 01426 01427 def ReorderLayers(self): 01428 """!Add commands from data associated with any valid layers 01429 (checked or not) to layer list in order to match layers in 01430 layer tree.""" 01431 01432 # make a list of visible layers 01433 treelayers = [] 01434 01435 vislayer = self.GetFirstVisibleItem() 01436 01437 if not vislayer or self.GetPyData(vislayer) is None: 01438 return 01439 01440 itemList = "" 01441 01442 for item in range(self.GetCount()): 01443 itemList += self.GetItemText(vislayer) + ',' 01444 if self.GetPyData(vislayer)[0]['type'] != 'group': 01445 treelayers.append(self.GetPyData(vislayer)[0]['maplayer']) 01446 01447 if not self.GetNextVisible(vislayer): 01448 break 01449 else: 01450 vislayer = self.GetNextVisible(vislayer) 01451 01452 Debug.msg (4, "LayerTree.ReorderLayers(): items=%s" % \ 01453 (itemList)) 01454 01455 # reorder map layers 01456 treelayers.reverse() 01457 self.Map.ReorderLayers(treelayers) 01458 self.reorder = False 01459 01460 def ChangeLayer(self, item): 01461 """!Change layer""" 01462 type = self.GetPyData(item)[0]['type'] 01463 layerName = None 01464 01465 if type == 'command': 01466 win = self.FindWindowById(self.GetPyData(item)[0]['ctrl']) 01467 if win.GetValue() != None: 01468 cmd = win.GetValue().split(';') 01469 cmdlist = [] 01470 for c in cmd: 01471 cmdlist.append(c.split(' ')) 01472 opac = 1.0 01473 chk = self.IsItemChecked(item) 01474 hidden = not self.IsVisible(item) 01475 elif type != 'group': 01476 if self.GetPyData(item)[0] is not None: 01477 cmdlist = self.GetPyData(item)[0]['cmd'] 01478 opac = self.GetPyData(item)[0]['maplayer'].GetOpacity(float = True) 01479 chk = self.IsItemChecked(item) 01480 hidden = not self.IsVisible(item) 01481 # determine layer name 01482 layerName, found = utils.GetLayerNameFromCmd(cmdlist, fullyQualified = True) 01483 if not found: 01484 layerName = self.GetItemText(item) 01485 01486 maplayer = self.Map.ChangeLayer(layer = self.GetPyData(item)[0]['maplayer'], type = type, 01487 command = cmdlist, name = layerName, 01488 l_active = chk, l_hidden = hidden, l_opacity = opac, l_render = False) 01489 01490 self.GetPyData(item)[0]['maplayer'] = maplayer 01491 01492 # if digitization tool enabled -> update list of available vector map layers 01493 if self.mapdisplay.toolbars['vdigit']: 01494 self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool = True) 01495 01496 # redraw map if auto-rendering is enabled 01497 self.rerender = True 01498 self.reorder = True 01499 01500 def OnCloseWindow(self, event): 01501 pass 01502 # self.Map.Clean() 01503 01504 def FindItemByData(self, key, value): 01505 """!Find item based on key and value (see PyData[0]) 01506 01507 @return item instance 01508 @return None not found 01509 """ 01510 item = self.GetFirstChild(self.root)[0] 01511 return self.__FindSubItemByData(item, key, value) 01512 01513 def FindItemByIndex(self, index): 01514 """!Find item by index (starting at 0) 01515 01516 @return item instance 01517 @return None not found 01518 """ 01519 item = self.GetFirstChild(self.root)[0] 01520 i = 0 01521 while item and item.IsOk(): 01522 if i == index: 01523 return item 01524 01525 item = self.GetNextVisible(item) 01526 i += 1 01527 01528 return None 01529 01530 def EnableItemType(self, type, enable = True): 01531 """!Enable/disable items in layer tree""" 01532 item = self.GetFirstChild(self.root)[0] 01533 while item and item.IsOk(): 01534 mapLayer = self.GetPyData(item)[0]['maplayer'] 01535 if mapLayer and type == mapLayer.type: 01536 self.EnableItem(item, enable) 01537 01538 item = self.GetNextSibling(item) 01539 01540 def __FindSubItemByData(self, item, key, value): 01541 """!Support method for FindItemByValue""" 01542 while item and item.IsOk(): 01543 try: 01544 itemValue = self.GetPyData(item)[0][key] 01545 except KeyError: 01546 return None 01547 01548 if value == itemValue: 01549 return item 01550 if self.GetPyData(item)[0]['type'] == 'group': 01551 subItem = self.GetFirstChild(item)[0] 01552 found = self.__FindSubItemByData(subItem, key, value) 01553 if found: 01554 return found 01555 item = self.GetNextSibling(item) 01556 01557 return None 01558