|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package mapdisp.frame 00003 00004 @brief Map display with toolbar for various display management 00005 functions, and additional toolbars (vector digitizer, 3d view). 00006 00007 Can be used either from Layer Manager or as d.mon backend. 00008 00009 Classes: 00010 - mapdisp::MapFrame 00011 00012 (C) 2006-2011 by the GRASS Development Team 00013 00014 This program is free software under the GNU General Public License 00015 (>=v2). Read the file COPYING that comes with GRASS for details. 00016 00017 @author Michael Barton 00018 @author Jachym Cepicky 00019 @author Martin Landa <landa.martin gmail.com> 00020 @author Vaclav Petras <wenzeslaus gmail.com> (MapFrameBase) 00021 @author Anna Kratochvilova <kratochanna gmail.com> (MapFrameBase) 00022 """ 00023 00024 import os 00025 import sys 00026 import math 00027 import copy 00028 00029 from core import globalvar 00030 import wx 00031 import wx.aui 00032 00033 sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons")) 00034 sys.path.append(os.path.join(globalvar.ETCDIR, "python")) 00035 00036 from core import globalvar 00037 from core.render import EVT_UPDATE_PRGBAR 00038 from vdigit.toolbars import VDigitToolbar 00039 from mapdisp.toolbars import MapToolbar, NvizIcons 00040 from mapdisp.gprint import PrintOptions 00041 from core.gcmd import GError, GMessage, RunCommand 00042 from dbmgr.dialogs import DisplayAttributesDialog 00043 from core.utils import ListOfCatsToRange, GetLayerNameFromCmd 00044 from gui_core.dialogs import GetImageHandlers, ImageSizeDialog, DecorationDialog, TextLayerDialog 00045 from core.debug import Debug 00046 from core.settings import UserSettings 00047 from gui_core.mapdisp import MapFrameBase 00048 from mapdisp.mapwindow import BufferedWindow 00049 from modules.histogram import HistogramFrame 00050 from wxplot.profile import ProfileFrame 00051 00052 from mapdisp import statusbar as sb 00053 00054 from grass.script import core as grass 00055 00056 haveCtypes = False 00057 00058 class MapFrame(MapFrameBase): 00059 """!Main frame for map display window. Drawing takes place in 00060 child double buffered drawing window. 00061 """ 00062 def __init__(self, parent = None, title = _("GRASS GIS - Map display"), 00063 toolbars = ["map"], tree = None, notebook = None, lmgr = None, 00064 page = None, Map = None, auimgr = None, name = 'MapWindow', **kwargs): 00065 """!Main map display window with toolbars, statusbar and 00066 BufferedWindow (map canvas) 00067 00068 @param toolbars array of activated toolbars, e.g. ['map', 'digit'] 00069 @param tree reference to layer tree 00070 @param notebook control book ID in Layer Manager 00071 @param lmgr Layer Manager 00072 @param page notebook page with layer tree 00073 @param Map instance of render.Map 00074 @param auimgs AUI manager 00075 @param name frame name 00076 @param kwargs wx.Frame attributes 00077 """ 00078 MapFrameBase.__init__(self, parent = parent, title = title, toolbars = toolbars, 00079 Map = Map, auimgr = auimgr, name = name, **kwargs) 00080 00081 self._layerManager = lmgr # Layer Manager object 00082 self.tree = tree # Layer Manager layer tree object 00083 self.page = page # Notebook page holding the layer tree 00084 self.layerbook = notebook # Layer Manager layer tree notebook 00085 # 00086 # Add toolbars 00087 # 00088 for toolb in toolbars: 00089 self.AddToolbar(toolb) 00090 00091 # 00092 # Add statusbar 00093 # 00094 00095 # items for choice 00096 self.statusbarItems = [sb.SbCoordinates, 00097 sb.SbRegionExtent, 00098 sb.SbCompRegionExtent, 00099 sb.SbShowRegion, 00100 sb.SbAlignExtent, 00101 sb.SbResolution, 00102 sb.SbDisplayGeometry, 00103 sb.SbMapScale, 00104 sb.SbGoTo, 00105 sb.SbProjection] 00106 00107 self.statusbarItemsHiddenInNviz = (sb.SbAlignExtent, 00108 sb.SbDisplayGeometry, 00109 sb.SbShowRegion, 00110 sb.SbResolution, 00111 sb.SbMapScale) 00112 00113 # create statusbar and its manager 00114 statusbar = self.CreateStatusBar(number = 4, style = 0) 00115 statusbar.SetStatusWidths([-5, -2, -1, -1]) 00116 self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar) 00117 00118 # fill statusbar manager 00119 self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar) 00120 self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2)) 00121 self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3)) 00122 00123 self.statusbarManager.Update() 00124 00125 # 00126 # Init map display (buffered DC & set default cursor) 00127 # 00128 self.MapWindow2D = BufferedWindow(self, id = wx.ID_ANY, 00129 Map = self.Map, tree = self.tree, lmgr = self._layerManager) 00130 # default is 2D display mode 00131 self.MapWindow = self.MapWindow2D 00132 self.MapWindow.SetCursor(self.cursors["default"]) 00133 # used by vector digitizer 00134 self.MapWindowVDigit = None 00135 # used by Nviz (3D display mode) 00136 self.MapWindow3D = None 00137 00138 # 00139 # initialize region values 00140 # 00141 self._initMap(map = self.Map) 00142 00143 # 00144 # Bind various events 00145 # 00146 self.Bind(wx.EVT_ACTIVATE, self.OnFocus) 00147 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 00148 self.Bind(EVT_UPDATE_PRGBAR, self.OnUpdateProgress) 00149 00150 # 00151 # Update fancy gui style 00152 # 00153 self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane(). 00154 Dockable(False).BestSize((-1,-1)).Name('2d'). 00155 CloseButton(False).DestroyOnClose(True). 00156 Layer(0)) 00157 self._mgr.Update() 00158 00159 # 00160 # Init print module and classes 00161 # 00162 self.printopt = PrintOptions(self, self.MapWindow) 00163 00164 # 00165 # Init zoom history 00166 # 00167 self.MapWindow.ZoomHistory(self.Map.region['n'], 00168 self.Map.region['s'], 00169 self.Map.region['e'], 00170 self.Map.region['w']) 00171 00172 # 00173 # Re-use dialogs 00174 # 00175 self.dialogs = {} 00176 self.dialogs['attributes'] = None 00177 self.dialogs['category'] = None 00178 self.dialogs['barscale'] = None 00179 self.dialogs['legend'] = None 00180 00181 self.decorationDialog = None # decoration/overlays 00182 00183 def GetMapWindow(self): 00184 return self.MapWindow 00185 00186 def _addToolbarVDigit(self): 00187 """!Add vector digitizer toolbar 00188 """ 00189 from vdigit.main import haveVDigit 00190 00191 if not haveVDigit: 00192 from vdigit import errorMsg 00193 msg = _("Unable to start wxGUI vector digitizer.\nDo you want to start " 00194 "TCL/TK digitizer (v.digit) instead?\n\n" 00195 "Details: %s" % errorMsg) 00196 00197 self.toolbars['map'].combo.SetValue(_("2D view")) 00198 dlg = wx.MessageDialog(parent = self, 00199 message = msg, 00200 caption=_("Vector digitizer failed"), 00201 style = wx.YES_NO | wx.CENTRE) 00202 if dlg.ShowModal() == wx.ID_YES: 00203 mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetName() 00204 self._layerManager.goutput.RunCmd(['v.digit', 'map=%s' % mapName], 00205 switchPage = False) 00206 dlg.Destroy() 00207 00208 self.toolbars['map'].combo.SetValue(_("2D view")) 00209 return 00210 00211 if self._layerManager: 00212 log = self._layerManager.goutput 00213 else: 00214 log = None 00215 00216 if not self.MapWindowVDigit: 00217 from vdigit.mapwindow import VDigitWindow 00218 self.MapWindowVDigit = VDigitWindow(self, id = wx.ID_ANY, 00219 Map = self.Map, tree = self.tree, 00220 lmgr = self._layerManager) 00221 self.MapWindowVDigit.Show() 00222 self._mgr.AddPane(self.MapWindowVDigit, wx.aui.AuiPaneInfo().CentrePane(). 00223 Dockable(False).BestSize((-1,-1)).Name('vdigit'). 00224 CloseButton(False).DestroyOnClose(True). 00225 Layer(0)) 00226 00227 self.MapWindow = self.MapWindowVDigit 00228 00229 if self._mgr.GetPane('2d').IsShown(): 00230 self._mgr.GetPane('2d').Hide() 00231 elif self._mgr.GetPane('3d').IsShown(): 00232 self._mgr.GetPane('3d').Hide() 00233 self._mgr.GetPane('vdigit').Show() 00234 self.toolbars['vdigit'] = VDigitToolbar(parent = self, mapcontent = self.Map, 00235 layerTree = self.tree, 00236 log = log) 00237 self.MapWindowVDigit.SetToolbar(self.toolbars['vdigit']) 00238 00239 self._mgr.AddPane(self.toolbars['vdigit'], 00240 wx.aui.AuiPaneInfo(). 00241 Name("vdigittoolbar").Caption(_("Vector Digitizer Toolbar")). 00242 ToolbarPane().Top().Row(1). 00243 LeftDockable(False).RightDockable(False). 00244 BottomDockable(False).TopDockable(True). 00245 CloseButton(False).Layer(2). 00246 BestSize((self.toolbars['vdigit'].GetBestSize()))) 00247 # change mouse to draw digitized line 00248 self.MapWindow.mouse['box'] = "point" 00249 self.MapWindow.zoomtype = 0 00250 self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SOLID) 00251 self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SOLID) 00252 00253 def AddNviz(self): 00254 """!Add 3D view mode window 00255 """ 00256 from nviz.main import haveNviz, GLWindow 00257 00258 # check for GLCanvas and OpenGL 00259 if not haveNviz: 00260 self.toolbars['map'].combo.SetValue(_("2D view")) 00261 GError(parent = self, 00262 message = _("Unable to switch to 3D display mode.\nThe Nviz python extension " 00263 "was not found or loaded properly.\n" 00264 "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg)) 00265 return 00266 00267 # disable 3D mode for other displays 00268 for page in range(0, self._layerManager.gm_cb.GetPageCount()): 00269 if self._layerManager.gm_cb.GetPage(page) != self._layerManager.curr_page: 00270 if '3D' in self._layerManager.gm_cb.GetPage(page).maptree.mapdisplay.toolbars['map'].combo.GetString(1): 00271 self._layerManager.gm_cb.GetPage(page).maptree.mapdisplay.toolbars['map'].combo.Delete(1) 00272 self.toolbars['map'].Enable2D(False) 00273 # add rotate tool to map toolbar 00274 self.toolbars['map'].InsertTool((('rotate', NvizIcons['rotate'], 00275 self.OnRotate, wx.ITEM_CHECK, 7),)) # 7 is position 00276 self.toolbars['map'].InsertTool((('flyThrough', NvizIcons['flyThrough'], 00277 self.OnFlyThrough, wx.ITEM_CHECK, 8),)) 00278 self.toolbars['map'].ChangeToolsDesc(mode2d = False) 00279 # update status bar 00280 00281 self.statusbarManager.HideStatusbarChoiceItemsByClass(self.statusbarItemsHiddenInNviz) 00282 self.statusbarManager.SetMode(0) 00283 00284 # erase map window 00285 self.MapWindow.EraseMap() 00286 00287 self._layerManager.goutput.WriteCmdLog(_("Starting 3D view mode..."), 00288 switchPage = False) 00289 self.SetStatusText(_("Please wait, loading data..."), 0) 00290 00291 # create GL window 00292 if not self.MapWindow3D: 00293 self.MapWindow3D = GLWindow(self, id = wx.ID_ANY, 00294 Map = self.Map, tree = self.tree, lmgr = self._layerManager) 00295 self.MapWindow = self.MapWindow3D 00296 self.MapWindow.SetCursor(self.cursors["default"]) 00297 00298 # add Nviz notebookpage 00299 self._layerManager.AddNvizTools() 00300 00301 # switch from MapWindow to MapWindowGL 00302 self._mgr.GetPane('2d').Hide() 00303 self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane(). 00304 Dockable(False).BestSize((-1,-1)).Name('3d'). 00305 CloseButton(False).DestroyOnClose(True). 00306 Layer(0)) 00307 00308 self.MapWindow3D.OnPaint(None) # -> LoadData 00309 self.MapWindow3D.Show() 00310 self.MapWindow3D.ResetViewHistory() 00311 self.MapWindow3D.UpdateView(None) 00312 else: 00313 self.MapWindow = self.MapWindow3D 00314 os.environ['GRASS_REGION'] = self.Map.SetRegion(windres = True) 00315 self.MapWindow3D.GetDisplay().Init() 00316 del os.environ['GRASS_REGION'] 00317 00318 # switch from MapWindow to MapWindowGL 00319 self._mgr.GetPane('2d').Hide() 00320 self._mgr.GetPane('3d').Show() 00321 00322 # add Nviz notebookpage 00323 self._layerManager.AddNvizTools() 00324 self.MapWindow3D.ResetViewHistory() 00325 for page in ('view', 'light', 'fringe', 'constant', 'cplane', 'animation'): 00326 self._layerManager.nviz.UpdatePage(page) 00327 00328 self.MapWindow3D.overlays = self.MapWindow2D.overlays 00329 self.MapWindow3D.textdict = self.MapWindow2D.textdict 00330 # update overlays needs to be called after because getClientSize 00331 # is called during update and it must give reasonable values 00332 wx.CallAfter(self.MapWindow3D.UpdateOverlays) 00333 00334 self.SetStatusText("", 0) 00335 self._mgr.Update() 00336 00337 def RemoveNviz(self): 00338 """!Restore 2D view""" 00339 self.toolbars['map'].RemoveTool(self.toolbars['map'].rotate) 00340 self.toolbars['map'].RemoveTool(self.toolbars['map'].flyThrough) 00341 # update status bar 00342 self.statusbarManager.ShowStatusbarChoiceItemsByClass(self.statusbarItemsHiddenInNviz) 00343 self.statusbarManager.SetMode(UserSettings.Get(group = 'display', 00344 key = 'statusbarMode', 00345 subkey = 'selection')) 00346 self.SetStatusText(_("Please wait, unloading data..."), 0) 00347 self._layerManager.goutput.WriteCmdLog(_("Switching back to 2D view mode..."), 00348 switchPage = False) 00349 self.MapWindow3D.OnClose(event = None) 00350 # switch from MapWindowGL to MapWindow 00351 self._mgr.GetPane('2d').Show() 00352 self._mgr.GetPane('3d').Hide() 00353 00354 self.MapWindow = self.MapWindow2D 00355 # remove nviz notebook page 00356 self._layerManager.RemoveNvizTools() 00357 00358 self.MapWindow2D.overlays = self.MapWindow3D.overlays 00359 self.MapWindow2D.textdict = self.MapWindow3D.textdict 00360 self.MapWindow.UpdateMap() 00361 self._mgr.Update() 00362 00363 def AddToolbar(self, name): 00364 """!Add defined toolbar to the window 00365 00366 Currently known toolbars are: 00367 - 'map' - basic map toolbar 00368 - 'vdigit' - vector digitizer 00369 - 'gcpdisp' - GCP Manager Display 00370 """ 00371 # default toolbar 00372 if name == "map": 00373 self.toolbars['map'] = MapToolbar(self, self.Map) 00374 00375 self._mgr.AddPane(self.toolbars['map'], 00376 wx.aui.AuiPaneInfo(). 00377 Name("maptoolbar").Caption(_("Map Toolbar")). 00378 ToolbarPane().Top().Name('mapToolbar'). 00379 LeftDockable(False).RightDockable(False). 00380 BottomDockable(False).TopDockable(True). 00381 CloseButton(False).Layer(2). 00382 BestSize((self.toolbars['map'].GetBestSize()))) 00383 00384 # vector digitizer 00385 elif name == "vdigit": 00386 self._addToolbarVDigit() 00387 00388 self._mgr.Update() 00389 00390 def RemoveToolbar (self, name): 00391 """!Removes defined toolbar from the window 00392 00393 @todo Only hide, activate by calling AddToolbar() 00394 """ 00395 # cannot hide main toolbar 00396 if name == "map": 00397 return 00398 00399 self._mgr.DetachPane(self.toolbars[name]) 00400 self.toolbars[name].Destroy() 00401 self.toolbars.pop(name) 00402 00403 if name == 'vdigit': 00404 self._mgr.GetPane('vdigit').Hide() 00405 self._mgr.GetPane('2d').Show() 00406 self.MapWindow = self.MapWindow2D 00407 00408 self.toolbars['map'].combo.SetValue(_("2D view")) 00409 self.toolbars['map'].Enable2D(True) 00410 00411 self._mgr.Update() 00412 00413 def IsPaneShown(self, name): 00414 """!Check if pane (toolbar, mapWindow ...) of given name is currently shown""" 00415 if self._mgr.GetPane(name).IsOk(): 00416 return self._mgr.GetPane(name).IsShown() 00417 return False 00418 00419 def OnUpdateProgress(self, event): 00420 """!Update progress bar info 00421 """ 00422 self.GetProgressBar().SetValue(event.value) 00423 00424 event.Skip() 00425 00426 def OnFocus(self, event): 00427 """!Change choicebook page to match display. 00428 """ 00429 # change bookcontrol page to page associated with display 00430 if self.page: 00431 pgnum = self.layerbook.GetPageIndex(self.page) 00432 if pgnum > -1: 00433 self.layerbook.SetSelection(pgnum) 00434 self._layerManager.curr_page = self.layerbook.GetCurrentPage() 00435 00436 event.Skip() 00437 00438 def OnRender(self, event): 00439 """!Re-render map composition (each map layer) 00440 """ 00441 # delete tmp map layers (queries) 00442 qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER) 00443 for layer in qlayer: 00444 self.Map.DeleteLayer(layer) 00445 00446 # delete tmp lines 00447 if self.MapWindow.mouse["use"] in ("measure", 00448 "profile"): 00449 self.MapWindow.polycoords = [] 00450 self.MapWindow.ClearLines() 00451 00452 # deselect features in vdigit 00453 if self.GetToolbar('vdigit'): 00454 if self.MapWindow.digit: 00455 self.MapWindow.digit.GetDisplay().SetSelected([]) 00456 self.MapWindow.UpdateMap(render = True, renderVector = True) 00457 else: 00458 self.MapWindow.UpdateMap(render = True) 00459 00460 # update statusbar 00461 self.StatusbarUpdate() 00462 00463 def OnPointer(self, event): 00464 """!Pointer button clicked 00465 """ 00466 if self.GetMapToolbar(): 00467 if event: 00468 self.toolbars['map'].OnTool(event) 00469 self.toolbars['map'].action['desc'] = '' 00470 00471 self.MapWindow.mouse['use'] = "pointer" 00472 self.MapWindow.mouse['box'] = "point" 00473 00474 # change the cursor 00475 if self.GetToolbar('vdigit'): 00476 # digitization tool activated 00477 self.MapWindow.SetCursor(self.cursors["cross"]) 00478 00479 # reset mouse['box'] if needed 00480 if self.toolbars['vdigit'].GetAction() in ['addLine']: 00481 if self.toolbars['vdigit'].GetAction('type') in ['point', 'centroid']: 00482 self.MapWindow.mouse['box'] = 'point' 00483 else: # line, boundary 00484 self.MapWindow.mouse['box'] = 'line' 00485 elif self.toolbars['vdigit'].GetAction() in ['addVertex', 'removeVertex', 'splitLine', 00486 'editLine', 'displayCats', 'queryMap', 00487 'copyCats']: 00488 self.MapWindow.mouse['box'] = 'point' 00489 else: # moveLine, deleteLine 00490 self.MapWindow.mouse['box'] = 'box' 00491 00492 else: 00493 self.MapWindow.SetCursor(self.cursors["default"]) 00494 00495 def OnRotate(self, event): 00496 """!Rotate 3D view 00497 """ 00498 if self.GetMapToolbar(): 00499 self.toolbars['map'].OnTool(event) 00500 self.toolbars['map'].action['desc'] = '' 00501 00502 self.MapWindow.mouse['use'] = "rotate" 00503 00504 # change the cursor 00505 self.MapWindow.SetCursor(self.cursors["hand"]) 00506 00507 def OnFlyThrough(self, event): 00508 """!Fly-through mode 00509 """ 00510 if self.toolbars['map']: 00511 self.toolbars['map'].OnTool(event) 00512 self.toolbars['map'].action['desc'] = '' 00513 00514 self.MapWindow.mouse['use'] = "fly" 00515 00516 # change the cursor 00517 self.MapWindow.SetCursor(self.cursors["hand"]) 00518 self.MapWindow.SetFocus() 00519 00520 def OnZoomRegion(self, event): 00521 """ 00522 Zoom to region 00523 """ 00524 self.Map.getRegion() 00525 self.Map.getResolution() 00526 self.UpdateMap() 00527 # event.Skip() 00528 00529 def OnAlignRegion(self, event): 00530 """ 00531 Align region 00532 """ 00533 if not self.Map.alignRegion: 00534 self.Map.alignRegion = True 00535 else: 00536 self.Map.alignRegion = False 00537 # event.Skip() 00538 00539 def SaveToFile(self, event): 00540 """!Save map to image 00541 """ 00542 if self.IsPaneShown('3d'): 00543 filetype = "PPM file (*.ppm)|*.ppm|TIF file (*.tif)|*.tif" 00544 ltype = [{ 'ext' : 'ppm', 'type' : 'ppm' }, 00545 { 'ext' : 'tif', 'type' : 'tif' }] 00546 else: 00547 img = self.MapWindow.img 00548 if not img: 00549 GMessage(parent = self, 00550 message = _("Nothing to render (empty map). Operation canceled.")) 00551 return 00552 filetype, ltype = GetImageHandlers(img) 00553 00554 # get size 00555 dlg = ImageSizeDialog(self) 00556 dlg.CentreOnParent() 00557 if dlg.ShowModal() != wx.ID_OK: 00558 dlg.Destroy() 00559 return 00560 width, height = dlg.GetValues() 00561 dlg.Destroy() 00562 00563 # get filename 00564 dlg = wx.FileDialog(parent = self, 00565 message = _("Choose a file name to save the image " 00566 "(no need to add extension)"), 00567 wildcard = filetype, 00568 style = wx.SAVE | wx.FD_OVERWRITE_PROMPT) 00569 00570 if dlg.ShowModal() == wx.ID_OK: 00571 path = dlg.GetPath() 00572 if not path: 00573 dlg.Destroy() 00574 return 00575 00576 base, ext = os.path.splitext(path) 00577 fileType = ltype[dlg.GetFilterIndex()]['type'] 00578 extType = ltype[dlg.GetFilterIndex()]['ext'] 00579 if ext != extType: 00580 path = base + '.' + extType 00581 00582 self.MapWindow.SaveToFile(path, fileType, 00583 width, height) 00584 00585 dlg.Destroy() 00586 00587 def PrintMenu(self, event): 00588 """ 00589 Print options and output menu for map display 00590 """ 00591 point = wx.GetMousePosition() 00592 printmenu = wx.Menu() 00593 # Add items to the menu 00594 setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup')) 00595 printmenu.AppendItem(setup) 00596 self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup) 00597 00598 preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview')) 00599 printmenu.AppendItem(preview) 00600 self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview) 00601 00602 doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display')) 00603 printmenu.AppendItem(doprint) 00604 self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint) 00605 00606 # Popup the menu. If an item is selected then its handler 00607 # will be called before PopupMenu returns. 00608 self.PopupMenu(printmenu) 00609 printmenu.Destroy() 00610 00611 def OnCloseWindow(self, event): 00612 """!Window closed. 00613 Also close associated layer tree page 00614 """ 00615 pgnum = None 00616 self.Map.Clean() 00617 00618 # close edited map and 3D tools properly 00619 if self.GetToolbar('vdigit'): 00620 maplayer = self.toolbars['vdigit'].GetLayer() 00621 if maplayer: 00622 self.toolbars['vdigit'].OnExit() 00623 if self.IsPaneShown('3d'): 00624 self.RemoveNviz() 00625 00626 if not self._layerManager: 00627 self.Destroy() 00628 elif self.page: 00629 pgnum = self.layerbook.GetPageIndex(self.page) 00630 if pgnum > -1: 00631 self.layerbook.DeletePage(pgnum) 00632 00633 def QueryMap(self, x, y): 00634 """!Query raster or vector map layers by r/v.what 00635 00636 @param x,y coordinates 00637 """ 00638 # set query snap distance for v.what at map unit equivalent of 10 pixels 00639 qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width) 00640 east, north = self.MapWindow.Pixel2Cell((x, y)) 00641 00642 if not self.IsStandalone(): 00643 num = 0 00644 for layer in self.tree.GetSelections(): 00645 ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType() 00646 if ltype in ('raster', 'rgb', 'his', 00647 'vector', 'thememap', 'themechart'): 00648 num += 1 00649 00650 if num < 1: 00651 GMessage(parent = self, 00652 message = _('No raster or vector map layer selected for querying.')) 00653 return 00654 00655 rast = list() 00656 vect = list() 00657 rcmd = ['r.what', '--v'] 00658 vcmd = ['v.what', '--v'] 00659 00660 if self.IsStandalone(): 00661 pass 00662 else: 00663 for layer in self.tree.GetSelections(): 00664 ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType() 00665 dcmd = self.tree.GetPyData(layer)[0]['cmd'] 00666 name, found = GetLayerNameFromCmd(dcmd) 00667 00668 if not found: 00669 continue 00670 if ltype == 'raster': 00671 rast.append(name) 00672 elif ltype in ('rgb', 'his'): 00673 for iname in name.split('\n'): 00674 rast.append(iname) 00675 elif ltype in ('vector', 'thememap', 'themechart'): 00676 vect.append(name) 00677 # rasters are not queried this way in 3D, we don't want them now 00678 if self.IsPaneShown('3d'): 00679 rast = list() 00680 # use display region settings instead of computation region settings 00681 self.tmpreg = os.getenv("GRASS_REGION") 00682 os.environ["GRASS_REGION"] = self.Map.SetRegion(windres = False) 00683 00684 # build query commands for any selected rasters and vectors 00685 if rast: 00686 rcmd.append('-f') 00687 rcmd.append('-n') 00688 rcmd.append('input=%s' % ','.join(rast)) 00689 rcmd.append('east_north=%f,%f' % (float(east), float(north))) 00690 00691 if vect: 00692 # check for vector maps open to be edited 00693 digitToolbar = self.toolbars['vdigit'] 00694 if digitToolbar: 00695 lmap = digitToolbar.GetLayer().GetName() 00696 for name in vect: 00697 if lmap == name: 00698 self._layerManager.goutput.WriteWarning(_("Vector map <%s> " 00699 "opened for editing - skipped.") % map) 00700 vect.remove(name) 00701 00702 if len(vect) < 1: 00703 self._layerManager.goutput.WriteCmdLog(_("Nothing to query.")) 00704 return 00705 00706 vcmd.append('-a') 00707 vcmd.append('map=%s' % ','.join(vect)) 00708 vcmd.append('east_north=%f,%f' % (float(east), float(north))) 00709 vcmd.append('distance=%f' % float(qdist)) 00710 00711 Debug.msg(1, "QueryMap(): raster=%s vector=%s" % (','.join(rast), 00712 ','.join(vect))) 00713 # parse query command(s) 00714 if not self.IsStandalone(): 00715 if rast: 00716 self._layerManager.goutput.RunCmd(rcmd, 00717 compReg = False, 00718 onDone = self._QueryMapDone) 00719 if vect: 00720 self._layerManager.goutput.RunCmd(vcmd, 00721 onDone = self._QueryMapDone) 00722 else: 00723 if rast: 00724 RunCommand(rcmd) 00725 if vect: 00726 RunCommand(vcmd) 00727 00728 def _QueryMapDone(self, cmd, returncode): 00729 """!Restore settings after querying (restore GRASS_REGION) 00730 00731 @param returncode command return code 00732 """ 00733 if hasattr(self, "tmpreg"): 00734 if self.tmpreg: 00735 os.environ["GRASS_REGION"] = self.tmpreg 00736 elif 'GRASS_REGION' in os.environ: 00737 del os.environ["GRASS_REGION"] 00738 elif 'GRASS_REGION' in os.environ: 00739 del os.environ["GRASS_REGION"] 00740 00741 if hasattr(self, "tmpreg"): 00742 del self.tmpreg 00743 00744 def QueryVector(self, x, y): 00745 """!Query vector map layer features 00746 00747 Attribute data of selected vector object are displayed in GUI dialog. 00748 Data can be modified (On Submit) 00749 """ 00750 if not self.tree.layer_selected or \ 00751 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] != 'vector': 00752 GMessage(parent = self, 00753 message = _("No map layer selected for querying.")) 00754 return 00755 00756 posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset, 00757 y + self.MapWindow.dialogOffset)) 00758 00759 qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / 00760 self.Map.width) 00761 00762 east, north = self.MapWindow.Pixel2Cell((x, y)) 00763 00764 mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name 00765 00766 if self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetMapset() != \ 00767 grass.gisenv()['MAPSET']: 00768 mode = 'display' 00769 else: 00770 mode = 'update' 00771 00772 if self.dialogs['attributes'] is None: 00773 dlg = DisplayAttributesDialog(parent = self.MapWindow, 00774 map = mapName, 00775 query = ((east, north), qdist), 00776 pos = posWindow, 00777 action = mode) 00778 self.dialogs['attributes'] = dlg 00779 00780 else: 00781 # selection changed? 00782 if not self.dialogs['attributes'].mapDBInfo or \ 00783 self.dialogs['attributes'].mapDBInfo.map != mapName: 00784 self.dialogs['attributes'].UpdateDialog(map = mapName, query = ((east, north), qdist), 00785 action = mode) 00786 else: 00787 self.dialogs['attributes'].UpdateDialog(query = ((east, north), qdist), 00788 action = mode) 00789 if not self.dialogs['attributes'].IsFound(): 00790 self._layerManager.goutput.WriteLog(_('Nothing found.')) 00791 00792 cats = self.dialogs['attributes'].GetCats() 00793 00794 qlayer = None 00795 if not self.IsPaneShown('3d'): 00796 try: 00797 qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER)[0] 00798 except IndexError: 00799 pass 00800 00801 if self.dialogs['attributes'].mapDBInfo and cats: 00802 if not self.IsPaneShown('3d'): 00803 # highlight feature & re-draw map 00804 if qlayer: 00805 qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats, 00806 useId = False, 00807 addLayer = False)) 00808 else: 00809 qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId = False) 00810 00811 # set opacity based on queried layer 00812 opacity = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetOpacity(float = True) 00813 qlayer.SetOpacity(opacity) 00814 00815 self.MapWindow.UpdateMap(render = False, renderVector = False) 00816 if not self.dialogs['attributes'].IsShown(): 00817 self.dialogs['attributes'].Show() 00818 else: 00819 if qlayer: 00820 self.Map.DeleteLayer(qlayer) 00821 self.MapWindow.UpdateMap(render = False, renderVector = False) 00822 if self.dialogs['attributes'].IsShown(): 00823 self.dialogs['attributes'].Hide() 00824 00825 def OnQuery(self, event): 00826 """!Query tools menu""" 00827 if self.GetMapToolbar(): 00828 self.toolbars['map'].OnTool(event) 00829 action = self.toolbars['map'].GetAction() 00830 00831 self.toolbars['map'].action['desc'] = 'queryMap' 00832 self.MapWindow.mouse['use'] = "query" 00833 00834 if not self.IsStandalone(): 00835 # switch to output console to show query results 00836 self._layerManager.notebook.SetSelectionByName('output') 00837 00838 self.MapWindow.mouse['box'] = "point" 00839 self.MapWindow.zoomtype = 0 00840 00841 # change the cursor 00842 self.MapWindow.SetCursor(self.cursors["cross"]) 00843 00844 def AddTmpVectorMapLayer(self, name, cats, useId = False, addLayer = True): 00845 """!Add temporal vector map layer to map composition 00846 00847 @param name name of map layer 00848 @param useId use feature id instead of category 00849 """ 00850 # color settings from ATM 00851 color = UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'color') 00852 colorStr = str(color[0]) + ":" + \ 00853 str(color[1]) + ":" + \ 00854 str(color[2]) 00855 00856 # icon used in vector display and its size 00857 icon = '' 00858 size = 0 00859 vparam = self.tree.GetPyData(self.tree.layer_selected)[0]['cmd'] 00860 for p in vparam: 00861 if '=' in p: 00862 parg,pval = p.split('=') 00863 if parg == 'icon': icon = pval 00864 elif parg == 'size': size = int(pval) 00865 00866 pattern = ["d.vect", 00867 "map=%s" % name, 00868 "color=%s" % colorStr, 00869 "fcolor=%s" % colorStr, 00870 "width=%d" % UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'width')] 00871 if icon != '': 00872 pattern.append('icon=%s' % icon) 00873 if size > 0: 00874 pattern.append('size=%i' % size) 00875 00876 if useId: 00877 cmd = pattern 00878 cmd.append('-i') 00879 cmd.append('cats=%s' % str(cats)) 00880 else: 00881 cmd = [] 00882 for layer in cats.keys(): 00883 cmd.append(copy.copy(pattern)) 00884 lcats = cats[layer] 00885 cmd[-1].append("layer=%d" % layer) 00886 cmd[-1].append("cats=%s" % ListOfCatsToRange(lcats)) 00887 00888 if addLayer: 00889 if useId: 00890 return self.Map.AddLayer(type = 'vector', name = globalvar.QUERYLAYER, command = cmd, 00891 l_active = True, l_hidden = True, l_opacity = 1.0) 00892 else: 00893 return self.Map.AddLayer(type = 'command', name = globalvar.QUERYLAYER, command = cmd, 00894 l_active = True, l_hidden = True, l_opacity = 1.0) 00895 else: 00896 return cmd 00897 00898 def OnMeasure(self, event): 00899 """!Init measurement routine that calculates map distance 00900 along transect drawn on map display 00901 """ 00902 self.totaldist = 0.0 # total measured distance 00903 00904 # switch Layer Manager to output console to show measure results 00905 self._layerManager.notebook.SetSelectionByName('output') 00906 00907 # change mouse to draw line for measurement 00908 self.MapWindow.mouse['use'] = "measure" 00909 self.MapWindow.mouse['box'] = "line" 00910 self.MapWindow.zoomtype = 0 00911 self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SHORT_DASH) 00912 self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SHORT_DASH) 00913 00914 # change the cursor 00915 self.MapWindow.SetCursor(self.cursors["pencil"]) 00916 00917 # initiating output 00918 style = self._layerManager.goutput.cmd_output.StyleWarning 00919 self._layerManager.goutput.WriteLog(_('Click and drag with left mouse button ' 00920 'to measure.%s' 00921 'Double click with left button to clear.') % \ 00922 (os.linesep), style) 00923 if self.Map.projinfo['proj'] != 'xy': 00924 units = self.Map.projinfo['units'] 00925 self._layerManager.goutput.WriteCmdLog(_('Measuring distance') + ' (' 00926 + units + '):') 00927 else: 00928 self._layerManager.goutput.WriteCmdLog(_('Measuring distance:')) 00929 00930 if self.Map.projinfo['proj'] == 'll': 00931 try: 00932 import grass.lib.gis as gislib 00933 global haveCtypes 00934 haveCtypes = True 00935 00936 gislib.G_begin_distance_calculations() 00937 except ImportError, e: 00938 self._layerManager.goutput.WriteWarning(_('Geodesic distance is not yet ' 00939 'supported by this tool.\n' 00940 'Reason: %s' % e)) 00941 00942 def MeasureDist(self, beginpt, endpt): 00943 """!Calculate map distance from screen distance 00944 and print to output window 00945 """ 00946 self._layerManager.notebook.SetSelectionByName('output') 00947 00948 dist, (north, east) = self.MapWindow.Distance(beginpt, endpt) 00949 00950 dist = round(dist, 3) 00951 d, dunits = self.FormatDist(dist) 00952 00953 self.totaldist += dist 00954 td, tdunits = self.FormatDist(self.totaldist) 00955 00956 strdist = str(d) 00957 strtotdist = str(td) 00958 00959 if self.Map.projinfo['proj'] == 'xy' or 'degree' not in self.Map.projinfo['unit']: 00960 angle = int(math.degrees(math.atan2(north,east)) + 0.5) 00961 angle = 180 - angle 00962 if angle < 0: 00963 angle = 360 + angle 00964 00965 mstring = '%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \ 00966 % (_('segment'), strdist, dunits, 00967 _('total distance'), strtotdist, tdunits, 00968 _('bearing'), angle, _('deg'), 00969 '-' * 60) 00970 else: 00971 mstring = '%s = %s %s\n%s = %s %s\n%s' \ 00972 % (_('segment'), strdist, dunits, 00973 _('total distance'), strtotdist, tdunits, 00974 '-' * 60) 00975 00976 self._layerManager.goutput.WriteLog(mstring) 00977 00978 return dist 00979 00980 def OnProfile(self, event): 00981 """!Launch profile tool 00982 """ 00983 raster = [] 00984 if self.tree.layer_selected and \ 00985 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster': 00986 raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name) 00987 00988 win = ProfileFrame(parent = self, rasterList = raster) 00989 00990 win.CentreOnParent() 00991 win.Show() 00992 # Open raster select dialog to make sure that a raster (and 00993 # the desired raster) is selected to be profiled 00994 win.OnSelectRaster(None) 00995 00996 def FormatDist(self, dist): 00997 """!Format length numbers and units in a nice way, 00998 as a function of length. From code by Hamish Bowman 00999 Grass Development Team 2006""" 01000 01001 mapunits = self.Map.projinfo['units'] 01002 if mapunits == 'metres': 01003 mapunits = 'meters' 01004 outunits = mapunits 01005 dist = float(dist) 01006 divisor = 1.0 01007 01008 # figure out which units to use 01009 if mapunits == 'meters': 01010 if dist > 2500.0: 01011 outunits = 'km' 01012 divisor = 1000.0 01013 else: outunits = 'm' 01014 elif mapunits == 'feet': 01015 # nano-bug: we match any "feet", but US Survey feet is really 01016 # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000 01017 # miles the tick markers are rounded to the nearest 10th of a 01018 # mile (528'), the difference in foot flavours is ignored. 01019 if dist > 5280.0: 01020 outunits = 'miles' 01021 divisor = 5280.0 01022 else: 01023 outunits = 'ft' 01024 elif 'degree' in mapunits and \ 01025 not haveCtypes: 01026 if dist < 1: 01027 outunits = 'min' 01028 divisor = (1/60.0) 01029 else: 01030 outunits = 'deg' 01031 else: 01032 outunits = 'meters' 01033 01034 # format numbers in a nice way 01035 if (dist/divisor) >= 2500.0: 01036 outdist = round(dist/divisor) 01037 elif (dist/divisor) >= 1000.0: 01038 outdist = round(dist/divisor,1) 01039 elif (dist/divisor) > 0.0: 01040 outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor)))) 01041 else: 01042 outdist = float(dist/divisor) 01043 01044 return (outdist, outunits) 01045 01046 def OnHistogram(self, event): 01047 """!Init histogram display canvas and tools 01048 """ 01049 win = HistogramFrame(self) 01050 01051 win.CentreOnParent() 01052 win.Show() 01053 win.Refresh() 01054 win.Update() 01055 01056 def OnAddBarscale(self, event): 01057 """!Handler for scale/arrow map decoration menu selection. 01058 """ 01059 if self.dialogs['barscale']: 01060 return 01061 01062 id = 0 # unique index for overlay layer 01063 01064 # If location is latlon, only display north arrow (scale won't work) 01065 # proj = self.Map.projinfo['proj'] 01066 # if proj == 'll': 01067 # barcmd = 'd.barscale -n' 01068 # else: 01069 # barcmd = 'd.barscale' 01070 01071 # decoration overlay control dialog 01072 self.dialogs['barscale'] = \ 01073 DecorationDialog(parent = self, title = _('Scale and North arrow'), 01074 size = (350, 200), 01075 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE, 01076 cmd = ['d.barscale', 'at=0,5'], 01077 ovlId = id, 01078 name = 'barscale', 01079 checktxt = _("Show/hide scale and North arrow"), 01080 ctrltxt = _("scale object")) 01081 01082 self.dialogs['barscale'].CentreOnParent() 01083 ### dialog cannot be show as modal - in the result d.barscale is not selectable 01084 ### self.dialogs['barscale'].ShowModal() 01085 self.dialogs['barscale'].Show() 01086 self.MapWindow.mouse['use'] = 'pointer' 01087 01088 def OnAddLegend(self, event): 01089 """!Handler for legend map decoration menu selection. 01090 """ 01091 if self.dialogs['legend']: 01092 return 01093 01094 id = 1 # index for overlay layer in render 01095 01096 cmd = ['d.legend', 'at=5,50,2,5'] 01097 if self.tree.layer_selected and \ 01098 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster': 01099 cmd.append('map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name) 01100 01101 # Decoration overlay control dialog 01102 self.dialogs['legend'] = \ 01103 DecorationDialog(parent = self, title = ('Legend'), 01104 size = (350, 200), 01105 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE, 01106 cmd = cmd, 01107 ovlId = id, 01108 name = 'legend', 01109 checktxt = _("Show/hide legend"), 01110 ctrltxt = _("legend object")) 01111 01112 self.dialogs['legend'].CentreOnParent() 01113 ### dialog cannot be show as modal - in the result d.legend is not selectable 01114 ### self.dialogs['legend'].ShowModal() 01115 self.dialogs['legend'].Show() 01116 self.MapWindow.mouse['use'] = 'pointer' 01117 01118 def OnAddText(self, event): 01119 """!Handler for text decoration menu selection. 01120 """ 01121 if self.MapWindow.dragid > -1: 01122 id = self.MapWindow.dragid 01123 self.MapWindow.dragid = -1 01124 else: 01125 # index for overlay layer in render 01126 if len(self.MapWindow.textdict.keys()) > 0: 01127 id = max(self.MapWindow.textdict.keys()) + 1 01128 else: 01129 id = 101 01130 01131 self.dialogs['text'] = TextLayerDialog(parent = self, ovlId = id, 01132 title = _('Add text layer'), 01133 size = (400, 200)) 01134 self.dialogs['text'].CenterOnParent() 01135 01136 # If OK button pressed in decoration control dialog 01137 if self.dialogs['text'].ShowModal() == wx.ID_OK: 01138 text = self.dialogs['text'].GetValues()['text'] 01139 active = self.dialogs['text'].GetValues()['active'] 01140 01141 # delete object if it has no text or is not active 01142 if text == '' or active == False: 01143 try: 01144 self.MapWindow2D.pdc.ClearId(id) 01145 self.MapWindow2D.pdc.RemoveId(id) 01146 del self.MapWindow.textdict[id] 01147 if self.IsPaneShown('3d'): 01148 self.MapWindow3D.UpdateOverlays() 01149 self.MapWindow.UpdateMap() 01150 else: 01151 self.MapWindow2D.UpdateMap(render = False, renderVector = False) 01152 except: 01153 pass 01154 return 01155 01156 01157 self.MapWindow.textdict[id] = self.dialogs['text'].GetValues() 01158 01159 if self.IsPaneShown('3d'): 01160 self.MapWindow3D.UpdateOverlays() 01161 self.MapWindow3D.UpdateMap() 01162 else: 01163 self.MapWindow2D.pdc.ClearId(id) 01164 self.MapWindow2D.pdc.SetId(id) 01165 self.MapWindow2D.UpdateMap(render = False, renderVector = False) 01166 01167 self.MapWindow.mouse['use'] = 'pointer' 01168 01169 def OnAddArrow(self, event): 01170 """!Handler for north arrow menu selection. 01171 Opens Appearance page of nviz notebook. 01172 """ 01173 01174 self._layerManager.nviz.SetPage('decoration') 01175 self.MapWindow3D.SetDrawArrow((70, 70)) 01176 01177 def GetOptData(self, dcmd, type, params, propwin): 01178 """!Callback method for decoration overlay command generated by 01179 dialog created in menuform.py 01180 """ 01181 # Reset comand and rendering options in render.Map. Always render decoration. 01182 # Showing/hiding handled by PseudoDC 01183 self.Map.ChangeOverlay(ovltype = type, type = 'overlay', name = '', command = dcmd, 01184 l_active = True, l_render = False) 01185 self.params[type] = params 01186 self.propwin[type] = propwin 01187 01188 def OnZoomToMap(self, event): 01189 """!Set display extents to match selected raster (including 01190 NULLs) or vector map. 01191 """ 01192 self.MapWindow.ZoomToMap() 01193 01194 def OnZoomToRaster(self, event): 01195 """!Set display extents to match selected raster map (ignore NULLs) 01196 """ 01197 self.MapWindow.ZoomToMap(ignoreNulls = True) 01198 01199 def OnZoomToSaved(self, event): 01200 """!Set display geometry to match extents in 01201 saved region file 01202 """ 01203 self.MapWindow.ZoomToSaved() 01204 01205 def OnDisplayToWind(self, event): 01206 """!Set computational region (WIND file) to match display 01207 extents 01208 """ 01209 self.MapWindow.DisplayToWind() 01210 01211 def SaveDisplayRegion(self, event): 01212 """!Save display extents to named region file. 01213 """ 01214 self.MapWindow.SaveDisplayRegion() 01215 01216 def OnZoomMenu(self, event): 01217 """!Popup Zoom menu 01218 """ 01219 point = wx.GetMousePosition() 01220 zoommenu = wx.Menu() 01221 # Add items to the menu 01222 01223 zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)')) 01224 zoommenu.AppendItem(zoomwind) 01225 self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind) 01226 01227 zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region')) 01228 zoommenu.AppendItem(zoomdefault) 01229 self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault) 01230 01231 zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region')) 01232 zoommenu.AppendItem(zoomsaved) 01233 self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved) 01234 01235 savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display extent')) 01236 zoommenu.AppendItem(savewind) 01237 self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind) 01238 01239 savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region')) 01240 zoommenu.AppendItem(savezoom) 01241 self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom) 01242 01243 # Popup the menu. If an item is selected then its handler 01244 # will be called before PopupMenu returns. 01245 self.PopupMenu(zoommenu) 01246 zoommenu.Destroy() 01247 01248 def SetProperties(self, render = False, mode = 0, showCompExtent = False, 01249 constrainRes = False, projection = False, alignExtent = True): 01250 """!Set properies of map display window""" 01251 self.SetProperty('render', render) 01252 self.statusbarManager.SetMode(mode) 01253 self.StatusbarUpdate() 01254 self.SetProperty('region', showCompExtent) 01255 self.SetProperty('alignExtent', alignExtent) 01256 self.SetProperty('resolution', constrainRes) 01257 self.SetProperty('projection', projection) 01258 01259 def IsStandalone(self): 01260 """!Check if Map display is standalone""" 01261 if self._layerManager: 01262 return False 01263 01264 return True 01265 01266 def GetLayerManager(self): 01267 """!Get reference to Layer Manager 01268 01269 @return window reference 01270 @return None (if standalone) 01271 """ 01272 return self._layerManager 01273 01274 def GetMapToolbar(self): 01275 """!Returns toolbar with zooming tools""" 01276 return self.toolbars['map']