GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package mapdisp.py 00003 00004 @brief GIS map display canvas, with toolbar for various display 00005 management functions, and additional toolbars (vector digitizer, 3d 00006 view). 00007 00008 Can be used either from Layer Manager or as p.mon backend. 00009 00010 Classes: 00011 - MapFrame 00012 - MapApp 00013 00014 Usage: 00015 python mapdisp.py monitor-identifier /path/to/command/file 00016 00017 (C) 2006-2011 by the GRASS Development Team 00018 This program is free software under the GNU General Public 00019 License (>=v2). Read the file COPYING that comes with GRASS 00020 for details. 00021 00022 @author Michael Barton 00023 @author Jachym Cepicky 00024 @author Martin Landa <landa.martin gmail.com> 00025 """ 00026 00027 import os 00028 import sys 00029 import glob 00030 import math 00031 import tempfile 00032 import copy 00033 00034 import globalvar 00035 import wx 00036 import wx.aui 00037 00038 try: 00039 import subprocess 00040 except: 00041 CompatPath = os.path.join(globalvar.ETCWXDIR) 00042 sys.path.append(CompatPath) 00043 from compat import subprocess 00044 00045 gmpath = os.path.join(globalvar.ETCWXDIR, "icons") 00046 sys.path.append(gmpath) 00047 00048 grassPath = os.path.join(globalvar.ETCDIR, "python") 00049 sys.path.append(grassPath) 00050 00051 import render 00052 import toolbars 00053 import menuform 00054 import gselect 00055 import disp_print 00056 import gcmd 00057 import dbm 00058 import dbm_dialogs 00059 import histogram 00060 import profile 00061 import globalvar 00062 import utils 00063 import gdialogs 00064 from grass.script import core as grass 00065 from debug import Debug 00066 from icon import Icons 00067 from preferences import globalSettings as UserSettings 00068 00069 from mapdisp_command import Command 00070 from mapdisp_window import BufferedWindow 00071 00072 # for standalone app 00073 cmdfilename = None 00074 00075 haveCtypes = False 00076 00077 class MapFrame(wx.Frame): 00078 """!Main frame for map display window. Drawing takes place in 00079 child double buffered drawing window. 00080 """ 00081 def __init__(self, parent = None, id = wx.ID_ANY, title = _("GRASS GIS - Map display"), 00082 style = wx.DEFAULT_FRAME_STYLE, toolbars = ["map"], 00083 tree = None, notebook = None, lmgr = None, page = None, 00084 Map = None, auimgr = None, **kwargs): 00085 """!Main map display window with toolbars, statusbar and 00086 DrawWindow 00087 00088 @param toolbars array of activated toolbars, e.g. ['map', 'digit'] 00089 @param tree reference to layer tree 00090 @param notebook control book ID in Layer Manager 00091 @param lmgr Layer Manager 00092 @param page notebook page with layer tree 00093 @param Map instance of render.Map 00094 @param auimgs AUI manager 00095 @param kwargs wx.Frame attribures 00096 """ 00097 self._layerManager = lmgr # Layer Manager object 00098 self.Map = Map # instance of render.Map 00099 self.tree = tree # Layer Manager layer tree object 00100 self.page = page # Notebook page holding the layer tree 00101 self.layerbook = notebook # Layer Manager layer tree notebook 00102 self.parent = parent 00103 00104 if 'name' not in kwargs: 00105 kwargs['name'] = 'MapWindow' 00106 wx.Frame.__init__(self, parent, id, title, style = style, **kwargs) 00107 00108 # available cursors 00109 self.cursors = { 00110 # default: cross 00111 # "default" : wx.StockCursor(wx.CURSOR_DEFAULT), 00112 "default" : wx.StockCursor(wx.CURSOR_ARROW), 00113 "cross" : wx.StockCursor(wx.CURSOR_CROSS), 00114 "hand" : wx.StockCursor(wx.CURSOR_HAND), 00115 "pencil" : wx.StockCursor(wx.CURSOR_PENCIL), 00116 "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE) 00117 } 00118 00119 # 00120 # set the size & system icon 00121 # 00122 self.SetClientSize(self.GetSize()) 00123 self.iconsize = (16, 16) 00124 00125 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO)) 00126 00127 # 00128 # Fancy gui 00129 # 00130 self._mgr = wx.aui.AuiManager(self) 00131 00132 # 00133 # Add toolbars 00134 # 00135 self.toolbars = { 'map' : None, 00136 'vdigit' : None, 00137 'georect' : None, 00138 'gcpdisp' : None, 00139 'nviz' : None } 00140 for toolb in toolbars: 00141 self.AddToolbar(toolb) 00142 00143 # 00144 # Add statusbar 00145 # 00146 self.statusbar = self.CreateStatusBar(number = 4, style = 0) 00147 self.statusbar.SetStatusWidths([-5, -2, -1, -1]) 00148 self.statusbarWin = dict() 00149 self.statusbarWin['toggle'] = wx.Choice(self.statusbar, wx.ID_ANY, 00150 choices = globalvar.MAP_DISPLAY_STATUSBAR_MODE) 00151 self.statusbarWin['toggle'].SetSelection(UserSettings.Get(group = 'display', 00152 key = 'statusbarMode', 00153 subkey = 'selection')) 00154 self.statusbar.Bind(wx.EVT_CHOICE, self.OnToggleStatus, self.statusbarWin['toggle']) 00155 # auto-rendering checkbox 00156 self.statusbarWin['render'] = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00157 label = _("Render")) 00158 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleRender, self.statusbarWin['render']) 00159 self.statusbarWin['render'].SetValue(UserSettings.Get(group = 'display', 00160 key = 'autoRendering', 00161 subkey = 'enabled')) 00162 self.statusbarWin['render'].SetToolTip(wx.ToolTip (_("Enable/disable auto-rendering"))) 00163 # show region 00164 self.statusbarWin['region'] = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00165 label = _("Show computational extent")) 00166 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleShowRegion, self.statusbarWin['region']) 00167 00168 self.statusbarWin['region'].SetValue(False) 00169 self.statusbarWin['region'].Hide() 00170 self.statusbarWin['region'].SetToolTip(wx.ToolTip (_("Show/hide computational " 00171 "region extent (set with g.region). " 00172 "Display region drawn as a blue box inside the " 00173 "computational region, " 00174 "computational region inside a display region " 00175 "as a red box)."))) 00176 # set resolution 00177 self.statusbarWin['resolution'] = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00178 label = _("Constrain display resolution to computational settings")) 00179 self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleResolution, self.statusbarWin['resolution']) 00180 self.statusbarWin['resolution'].SetValue(UserSettings.Get(group = 'display', key = 'compResolution', subkey = 'enabled')) 00181 self.statusbarWin['resolution'].Hide() 00182 self.statusbarWin['resolution'].SetToolTip(wx.ToolTip (_("Constrain display resolution " 00183 "to computational region settings. " 00184 "Default value for new map displays can " 00185 "be set up in 'User GUI settings' dialog."))) 00186 # map scale 00187 self.statusbarWin['mapscale'] = wx.ComboBox(parent = self.statusbar, id = wx.ID_ANY, 00188 style = wx.TE_PROCESS_ENTER, 00189 size = (150, -1)) 00190 self.statusbarWin['mapscale'].SetItems(['1:1000', 00191 '1:5000', 00192 '1:10000', 00193 '1:25000', 00194 '1:50000', 00195 '1:100000', 00196 '1:1000000']) 00197 self.statusbarWin['mapscale'].Hide() 00198 self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale, self.statusbarWin['mapscale']) 00199 self.statusbar.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale, self.statusbarWin['mapscale']) 00200 00201 # go to 00202 self.statusbarWin['goto'] = wx.TextCtrl(parent = self.statusbar, id = wx.ID_ANY, 00203 value = "", style = wx.TE_PROCESS_ENTER, 00204 size = (300, -1)) 00205 self.statusbarWin['goto'].Hide() 00206 self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo, self.statusbarWin['goto']) 00207 00208 # projection 00209 self.statusbarWin['projection'] = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00210 label = _("Use defined projection")) 00211 self.statusbarWin['projection'].SetValue(False) 00212 size = self.statusbarWin['projection'].GetSize() 00213 self.statusbarWin['projection'].SetMinSize((size[0] + 150, size[1])) 00214 self.statusbarWin['projection'].SetToolTip(wx.ToolTip (_("Reproject coordinates displayed " 00215 "in the statusbar. Projection can be " 00216 "defined in GUI preferences dialog " 00217 "(tab 'Display')"))) 00218 self.statusbarWin['projection'].Hide() 00219 00220 # mask 00221 self.statusbarWin['mask'] = wx.StaticText(parent = self.statusbar, id = wx.ID_ANY, 00222 label = '') 00223 self.statusbarWin['mask'].SetForegroundColour(wx.Colour(255, 0, 0)) 00224 00225 # on-render gauge 00226 self.statusbarWin['progress'] = wx.Gauge(parent = self.statusbar, id = wx.ID_ANY, 00227 range = 0, style = wx.GA_HORIZONTAL) 00228 self.statusbarWin['progress'].Hide() 00229 00230 self.StatusbarReposition() # reposition statusbar 00231 00232 # 00233 # Init map display (buffered DC & set default cursor) 00234 # 00235 self.MapWindow2D = BufferedWindow(self, id = wx.ID_ANY, 00236 Map = self.Map, tree = self.tree, lmgr = self._layerManager) 00237 # default is 2D display mode 00238 self.MapWindow = self.MapWindow2D 00239 self.MapWindow.SetCursor(self.cursors["default"]) 00240 # used by vector digitizer 00241 self.MapWindowVDigit = None 00242 # used by Nviz (3D display mode) 00243 self.MapWindow3D = None 00244 00245 # 00246 # initialize region values 00247 # 00248 self._initDisplay() 00249 00250 # 00251 # Bind various events 00252 # 00253 self.Bind(wx.EVT_ACTIVATE, self.OnFocus) 00254 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 00255 self.Bind(render.EVT_UPDATE_PRGBAR, self.OnUpdateProgress) 00256 00257 # 00258 # Update fancy gui style 00259 # 00260 self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane(). 00261 Dockable(False).BestSize((-1,-1)). 00262 CloseButton(False).DestroyOnClose(True). 00263 Layer(0)) 00264 self._mgr.Update() 00265 00266 # 00267 # Init print module and classes 00268 # 00269 self.printopt = disp_print.PrintOptions(self, self.MapWindow) 00270 00271 # 00272 # Init zoom history 00273 # 00274 self.MapWindow.ZoomHistory(self.Map.region['n'], 00275 self.Map.region['s'], 00276 self.Map.region['e'], 00277 self.Map.region['w']) 00278 00279 # 00280 # Re-use dialogs 00281 # 00282 self.dialogs = {} 00283 self.dialogs['attributes'] = None 00284 self.dialogs['category'] = None 00285 self.dialogs['barscale'] = None 00286 self.dialogs['legend'] = None 00287 00288 self.decorationDialog = None # decoration/overlays 00289 00290 def _addToolbarVDigit(self): 00291 """!Add vector digitizer toolbar 00292 """ 00293 from vdigit import haveVDigit 00294 00295 if not haveVDigit: 00296 from vdigit import errorMsg 00297 msg = _("Unable to start wxGUI vector digitizer.\nDo you want to start " 00298 "TCL/TK digitizer (v.digit) instead?\n\n" 00299 "Details: %s" % errorMsg) 00300 00301 self.toolbars['map'].combo.SetValue(_("2D view")) 00302 dlg = wx.MessageDialog(parent = self, 00303 message = msg, 00304 caption=_("Vector digitizer failed"), 00305 style = wx.YES_NO | wx.CENTRE) 00306 if dlg.ShowModal() == wx.ID_YES: 00307 mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetName() 00308 self._layerManager.goutput.RunCmd(['v.digit', 'map=%s' % mapName], 00309 switchPage = False) 00310 dlg.Destroy() 00311 00312 self.toolbars['map'].combo.SetValue(_("2D view")) 00313 return 00314 00315 if self._layerManager: 00316 log = self._layerManager.goutput 00317 else: 00318 log = None 00319 00320 if not self.MapWindowVDigit: 00321 from mapdisp_vdigit import VDigitWindow 00322 self.MapWindowVDigit = VDigitWindow(self, id = wx.ID_ANY, 00323 Map = self.Map, tree = self.tree, 00324 lmgr = self._layerManager) 00325 self.MapWindowVDigit.Show() 00326 00327 self.MapWindow = self.MapWindowVDigit 00328 00329 self._mgr.DetachPane(self.MapWindow2D) 00330 self.MapWindow2D.Hide() 00331 00332 self.toolbars['vdigit'] = toolbars.VDigitToolbar(parent = self, mapcontent = self.Map, 00333 layerTree = self.tree, 00334 log = log) 00335 self.MapWindowVDigit.SetToolbar(self.toolbars['vdigit']) 00336 00337 self._mgr.AddPane(self.MapWindowVDigit, wx.aui.AuiPaneInfo().CentrePane(). 00338 Dockable(False).BestSize((-1,-1)). 00339 CloseButton(False).DestroyOnClose(True). 00340 Layer(0)) 00341 self._mgr.AddPane(self.toolbars['vdigit'], 00342 wx.aui.AuiPaneInfo(). 00343 Name("vdigittoolbar").Caption(_("Vector Digitizer Toolbar")). 00344 ToolbarPane().Top().Row(1). 00345 LeftDockable(False).RightDockable(False). 00346 BottomDockable(False).TopDockable(True). 00347 CloseButton(False).Layer(2). 00348 BestSize((self.toolbars['vdigit'].GetBestSize()))) 00349 # change mouse to draw digitized line 00350 self.MapWindow.mouse['box'] = "point" 00351 self.MapWindow.zoomtype = 0 00352 self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SOLID) 00353 self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SOLID) 00354 00355 def _addToolbarNviz(self): 00356 """!Add 3D view mode toolbar 00357 """ 00358 import nviz 00359 00360 # check for GLCanvas and OpenGL 00361 if not nviz.haveNviz: 00362 self.toolbars['map'].combo.SetValue (_("2D view")) 00363 gcmd.GError(parent = self, 00364 message = _("Unable to switch to 3D display mode.\nThe Nviz python extension " 00365 "was not found or loaded properly.\n" 00366 "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg)) 00367 return 00368 00369 # add Nviz toolbar and disable 2D display mode tools 00370 self.toolbars['nviz'] = toolbars.NvizToolbar(self, self.Map) 00371 self.toolbars['map'].Enable2D(False) 00372 00373 # update status bar 00374 self.statusbarWin['toggle'].Enable(False) 00375 00376 # erase map window 00377 self.MapWindow.EraseMap() 00378 00379 self._layerManager.goutput.WriteCmdLog(_("Starting 3D view mode...")) 00380 self.statusbar.SetStatusText(_("Please wait, loading data..."), 0) 00381 00382 # create GL window & NVIZ toolbar 00383 if not self.MapWindow3D: 00384 self.MapWindow3D = nviz.GLWindow(self, id = wx.ID_ANY, 00385 Map = self.Map, tree = self.tree, lmgr = self._layerManager) 00386 self.MapWindow = self.MapWindow3D 00387 self.MapWindow.SetCursor(self.cursors["default"]) 00388 00389 # add Nviz notebookpage 00390 self._layerManager.AddNviz() 00391 00392 self.MapWindow3D.OnPaint(None) # -> LoadData 00393 self.MapWindow3D.Show() 00394 self.MapWindow3D.UpdateView(None) 00395 else: 00396 self.MapWindow = self.MapWindow3D 00397 # add Nviz notebookpage 00398 self._layerManager.AddNviz() 00399 self._layerManager.nviz.UpdatePage('view') 00400 self._layerManager.nviz.UpdatePage('light') 00401 00402 # switch from MapWindow to MapWindowGL 00403 # add nviz toolbar 00404 self._mgr.DetachPane(self.MapWindow2D) 00405 self.MapWindow2D.Hide() 00406 self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane(). 00407 Dockable(False).BestSize((-1,-1)). 00408 CloseButton(False).DestroyOnClose(True). 00409 Layer(0)) 00410 self._mgr.AddPane(self.toolbars['nviz'], 00411 wx.aui.AuiPaneInfo(). 00412 Name("nviztoolbar").Caption(_("3D View Toolbar")). 00413 ToolbarPane().Top().Row(1). 00414 LeftDockable(False).RightDockable(False). 00415 BottomDockable(False).TopDockable(True). 00416 CloseButton(False).Layer(2). 00417 BestSize((self.toolbars['nviz'].GetBestSize()))) 00418 00419 self.SetStatusText("", 0) 00420 00421 def AddToolbar(self, name): 00422 """!Add defined toolbar to the window 00423 00424 Currently known toolbars are: 00425 - 'map' - basic map toolbar 00426 - 'vdigit' - vector digitizer 00427 - 'gcpdisp' - GCP Manager Display 00428 - 'georect' - georectifier 00429 - 'nviz' - 3D view mode 00430 """ 00431 # default toolbar 00432 if name == "map": 00433 self.toolbars['map'] = toolbars.MapToolbar(self, self.Map) 00434 00435 self._mgr.AddPane(self.toolbars['map'], 00436 wx.aui.AuiPaneInfo(). 00437 Name("maptoolbar").Caption(_("Map Toolbar")). 00438 ToolbarPane().Top(). 00439 LeftDockable(False).RightDockable(False). 00440 BottomDockable(False).TopDockable(True). 00441 CloseButton(False).Layer(2). 00442 BestSize((self.toolbars['map'].GetBestSize()))) 00443 00444 # vector digitizer 00445 elif name == "vdigit": 00446 self._addToolbarVDigit() 00447 # georectifier 00448 elif name == "georect": 00449 self.toolbars['georect'] = toolbars.GRToolbar(self, self.Map) 00450 00451 self._mgr.AddPane(self.toolbars['georect'], 00452 wx.aui.AuiPaneInfo(). 00453 Name("georecttoolbar").Caption(_("Georectification Toolbar")). 00454 ToolbarPane().Top(). 00455 LeftDockable(False).RightDockable(False). 00456 BottomDockable(False).TopDockable(True). 00457 CloseButton(False).Layer(2). 00458 BestSize((self.toolbars['georect'].GetBestSize()))) 00459 # nviz 00460 elif name == "nviz": 00461 self._addToolbarNviz() 00462 00463 self._mgr.Update() 00464 00465 def RemoveToolbar (self, name): 00466 """!Removes defined toolbar from the window 00467 00468 @todo Only hide, activate by calling AddToolbar() 00469 """ 00470 # cannot hide main toolbar 00471 if name == "map": 00472 return 00473 00474 self._mgr.DetachPane(self.toolbars[name]) 00475 self.toolbars[name].Destroy() 00476 self.toolbars[name] = None 00477 00478 if name == 'vdigit': 00479 self._mgr.DetachPane(self.MapWindowVDigit) 00480 self.MapWindowVDigit.Hide() 00481 self.MapWindow2D.Show() 00482 self._mgr.AddPane(self.MapWindow2D, wx.aui.AuiPaneInfo().CentrePane(). 00483 Dockable(False).BestSize((-1,-1)). 00484 CloseButton(False).DestroyOnClose(True). 00485 Layer(0)) 00486 self.MapWindow = self.MapWindow2D 00487 00488 elif name == 'nviz': 00489 # unload data 00490 # self.MapWindow3D.Reset() 00491 # switch from MapWindowGL to MapWindow 00492 self._mgr.DetachPane(self.MapWindow3D) 00493 self.MapWindow3D.Hide() 00494 self.MapWindow2D.Show() 00495 self._mgr.AddPane(self.MapWindow2D, wx.aui.AuiPaneInfo().CentrePane(). 00496 Dockable(False).BestSize((-1,-1)). 00497 CloseButton(False).DestroyOnClose(True). 00498 Layer(0)) 00499 self.MapWindow = self.MapWindow2D 00500 # remove nviz notebook page 00501 self._layerManager.RemoveNviz() 00502 00503 self.MapWindow.UpdateMap() 00504 00505 self.toolbars['map'].combo.SetValue(_("2D view")) 00506 self.toolbars['map'].Enable2D(True) 00507 self.statusbarWin['toggle'].Enable(True) 00508 00509 self._mgr.Update() 00510 00511 def _initDisplay(self): 00512 """!Initialize map display, set dimensions and map region 00513 """ 00514 if not grass.find_program('g.region', ['--help']): 00515 sys.exit(_("GRASS module '%s' not found. Unable to start map " 00516 "display window.") % 'g.region') 00517 00518 self.width, self.height = self.GetClientSize() 00519 00520 Debug.msg(2, "MapFrame._initDisplay():") 00521 self.Map.ChangeMapSize(self.GetClientSize()) 00522 self.Map.region = self.Map.GetRegion() # g.region -upgc 00523 # self.Map.SetRegion() # adjust region to match display window 00524 00525 def OnUpdateProgress(self, event): 00526 """!Update progress bar info 00527 """ 00528 self.statusbarWin['progress'].SetValue(event.value) 00529 00530 event.Skip() 00531 00532 def OnFocus(self, event): 00533 """ 00534 Change choicebook page to match display. 00535 Or set display for georectifying 00536 """ 00537 if self._layerManager and \ 00538 self._layerManager.georectifying: 00539 # in georectifying session; display used to get geographic 00540 # coordinates for GCPs 00541 self.OnPointer(event) 00542 else: 00543 # change bookcontrol page to page associated with display 00544 if self.page: 00545 pgnum = self.layerbook.GetPageIndex(self.page) 00546 if pgnum > -1: 00547 self.layerbook.SetSelection(pgnum) 00548 00549 event.Skip() 00550 00551 def OnDraw(self, event): 00552 """!Re-display current map composition 00553 """ 00554 self.MapWindow.UpdateMap(render = False) 00555 00556 def OnRender(self, event): 00557 """!Re-render map composition (each map layer) 00558 """ 00559 # delete tmp map layers (queries) 00560 qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER) 00561 for layer in qlayer: 00562 self.Map.DeleteLayer(layer) 00563 00564 # delete tmp lines 00565 if self.MapWindow.mouse["use"] in ("measure", 00566 "profile"): 00567 self.MapWindow.polycoords = [] 00568 self.MapWindow.ClearLines() 00569 00570 # deselect features in vdigit 00571 if self.toolbars['vdigit']: 00572 if self.MapWindow.digit: 00573 self.MapWindow.digit.GetDisplay().SetSelected([]) 00574 self.MapWindow.UpdateMap(render = True, renderVector = True) 00575 else: 00576 self.MapWindow.UpdateMap(render = True) 00577 00578 # update statusbar 00579 self.StatusbarUpdate() 00580 00581 def OnPointer(self, event): 00582 """!Pointer button clicked 00583 """ 00584 if self.toolbars['map']: 00585 if event: 00586 self.toolbars['map'].OnTool(event) 00587 self.toolbars['map'].action['desc'] = '' 00588 00589 self.MapWindow.mouse['use'] = "pointer" 00590 self.MapWindow.mouse['box'] = "point" 00591 00592 # change the cursor 00593 if self.toolbars['vdigit']: 00594 # digitization tool activated 00595 self.MapWindow.SetCursor(self.cursors["cross"]) 00596 00597 # reset mouse['box'] if needed 00598 if self.toolbars['vdigit'].GetAction() in ['addLine']: 00599 if self.toolbars['vdigit'].GetAction('type') in ['point', 'centroid']: 00600 self.MapWindow.mouse['box'] = 'point' 00601 else: # line, boundary 00602 self.MapWindow.mouse['box'] = 'line' 00603 elif self.toolbars['vdigit'].GetAction() in ['addVertex', 'removeVertex', 'splitLine', 00604 'editLine', 'displayCats', 'queryMap', 00605 'copyCats']: 00606 self.MapWindow.mouse['box'] = 'point' 00607 else: # moveLine, deleteLine 00608 self.MapWindow.mouse['box'] = 'box' 00609 00610 elif self._layerManager and self._layerManager.georectifying: 00611 self.MapWindow.SetCursor(self.cursors["cross"]) 00612 00613 else: 00614 self.MapWindow.SetCursor(self.cursors["default"]) 00615 00616 def OnZoomIn(self, event): 00617 """ 00618 Zoom in the map. 00619 Set mouse cursor, zoombox attributes, and zoom direction 00620 """ 00621 if self.toolbars['map']: 00622 self.toolbars['map'].OnTool(event) 00623 self.toolbars['map'].action['desc'] = '' 00624 00625 self.MapWindow.mouse['use'] = "zoom" 00626 self.MapWindow.mouse['box'] = "box" 00627 self.MapWindow.zoomtype = 1 00628 self.MapWindow.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH) 00629 00630 # change the cursor 00631 self.MapWindow.SetCursor(self.cursors["cross"]) 00632 00633 def OnZoomOut(self, event): 00634 """ 00635 Zoom out the map. 00636 Set mouse cursor, zoombox attributes, and zoom direction 00637 """ 00638 if self.toolbars['map']: 00639 self.toolbars['map'].OnTool(event) 00640 self.toolbars['map'].action['desc'] = '' 00641 00642 self.MapWindow.mouse['use'] = "zoom" 00643 self.MapWindow.mouse['box'] = "box" 00644 self.MapWindow.zoomtype = -1 00645 self.MapWindow.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH) 00646 00647 # change the cursor 00648 self.MapWindow.SetCursor(self.cursors["cross"]) 00649 00650 def OnZoomBack(self, event): 00651 """ 00652 Zoom last (previously stored position) 00653 """ 00654 self.MapWindow.ZoomBack() 00655 00656 def OnPan(self, event): 00657 """ 00658 Panning, set mouse to drag 00659 """ 00660 if self.toolbars['map']: 00661 self.toolbars['map'].OnTool(event) 00662 self.toolbars['map'].action['desc'] = '' 00663 00664 self.MapWindow.mouse['use'] = "pan" 00665 self.MapWindow.mouse['box'] = "pan" 00666 self.MapWindow.zoomtype = 0 00667 00668 # change the cursor 00669 self.MapWindow.SetCursor(self.cursors["hand"]) 00670 00671 def OnErase(self, event): 00672 """ 00673 Erase the canvas 00674 """ 00675 self.MapWindow.EraseMap() 00676 00677 def OnZoomRegion(self, event): 00678 """ 00679 Zoom to region 00680 """ 00681 self.Map.getRegion() 00682 self.Map.getResolution() 00683 self.UpdateMap() 00684 # event.Skip() 00685 00686 def OnAlignRegion(self, event): 00687 """ 00688 Align region 00689 """ 00690 if not self.Map.alignRegion: 00691 self.Map.alignRegion = True 00692 else: 00693 self.Map.alignRegion = False 00694 # event.Skip() 00695 00696 def OnToggleRender(self, event): 00697 """!Enable/disable auto-rendering 00698 """ 00699 if self.statusbarWin['render'].GetValue(): 00700 self.OnRender(None) 00701 00702 def IsAutoRendered(self): 00703 """!Check if auto-rendering is enabled""" 00704 return self.statusbarWin['render'].IsChecked() 00705 00706 def OnToggleShowRegion(self, event): 00707 """!Show/Hide extent in map canvas 00708 """ 00709 if self.statusbarWin['region'].GetValue(): 00710 # show extent 00711 self.MapWindow.regionCoords = [] 00712 else: 00713 del self.MapWindow.regionCoords 00714 00715 # redraw map if auto-rendering is enabled 00716 if self.statusbarWin['render'].GetValue(): 00717 self.OnRender(None) 00718 00719 def OnToggleResolution(self, event): 00720 """ 00721 Use resolution of computation region settings 00722 for redering image instead of display resolution 00723 """ 00724 # redraw map if auto-rendering is enabled 00725 if self.statusbarWin['render'].GetValue(): 00726 self.OnRender(None) 00727 00728 def OnToggleStatus(self, event): 00729 """ 00730 Toggle status text 00731 """ 00732 self.StatusbarUpdate() 00733 00734 def OnChangeMapScale(self, event): 00735 """ 00736 Map scale changed by user 00737 """ 00738 scale = event.GetString() 00739 00740 try: 00741 if scale[:2] != '1:': 00742 raise ValueError 00743 value = int(scale[2:]) 00744 except ValueError: 00745 self.statusbarWin['mapscale'].SetValue('1:%ld' % int(self.mapScaleValue)) 00746 return 00747 00748 dEW = value * (self.Map.region['cols'] / self.ppm[0]) 00749 dNS = value * (self.Map.region['rows'] / self.ppm[1]) 00750 self.Map.region['n'] = self.Map.region['center_northing'] + dNS / 2. 00751 self.Map.region['s'] = self.Map.region['center_northing'] - dNS / 2. 00752 self.Map.region['w'] = self.Map.region['center_easting'] - dEW / 2. 00753 self.Map.region['e'] = self.Map.region['center_easting'] + dEW / 2. 00754 00755 # add to zoom history 00756 self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'], 00757 self.Map.region['e'], self.Map.region['w']) 00758 00759 # redraw a map 00760 self.MapWindow.UpdateMap() 00761 self.statusbarWin['mapscale'].SetFocus() 00762 00763 def OnGoTo(self, event): 00764 """ 00765 Go to position 00766 """ 00767 try: 00768 if self.statusbarWin['projection'].IsChecked(): 00769 if not UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4'): 00770 self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0) 00771 else: 00772 # reproject values 00773 projIn = UserSettings.Get(group = 'projection', 00774 key = 'statusbar', 00775 subkey = 'proj4') 00776 projOut = gcmd.RunCommand('g.proj', 00777 flags = 'jf', 00778 read = True) 00779 proj = projIn.split(' ')[0].split('=')[1] 00780 if proj in ('ll', 'latlong', 'longlat'): 00781 e, n = self.statusbarWin['goto'].GetValue().split(';') 00782 e, n = utils.DMS2Deg(e, n) 00783 proj, coord1 = utils.ReprojectCoordinates(coord = (e, n), 00784 projIn = projIn, 00785 projOut = projOut, flags = 'd') 00786 e, n = coord1 00787 else: 00788 e, n = map(float, self.statusbarWin['goto'].GetValue().split(';')) 00789 proj, coord1 = utils.ReprojectCoordinates(coord = (e, n), 00790 projIn = projIn, 00791 projOut = projOut, flags = 'd') 00792 e, n = coord1 00793 else: 00794 if self.Map.projinfo['proj'] == 'll': 00795 e, n = self.statusbarWin['goto'].GetValue().split(';') 00796 else: 00797 e, n = map(float, self.statusbarWin['goto'].GetValue().split(';')) 00798 00799 region = self.Map.GetCurrentRegion() 00800 if self.statusbarWin['projection'].IsChecked(): 00801 if not UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4'): 00802 self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0) 00803 else: 00804 region['center_easting'], region['center_northing'] = e, n 00805 else: 00806 if self.Map.projinfo['proj'] == 'll': 00807 region['center_easting'], region['center_northing'] = utils.DMS2Deg(e, n) 00808 else: 00809 region['center_easting'], region['center_northing'] = e, n 00810 except ValueError: 00811 region = self.Map.GetCurrentRegion() 00812 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00813 subkey = 'precision')) 00814 format = UserSettings.Get(group = 'projection', key = 'format', 00815 subkey = 'll') 00816 if self.Map.projinfo['proj'] == 'll' and format == 'DMS': 00817 self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(region['center_easting'], 00818 region['center_northing'], 00819 precision = precision)) 00820 else: 00821 self.statusbarWin['goto'].SetValue("%.*f; %.*f" % \ 00822 (precision, region['center_easting'], 00823 precision, region['center_northing'])) 00824 return 00825 00826 00827 dn = (region['nsres'] * region['rows']) / 2. 00828 region['n'] = region['center_northing'] + dn 00829 region['s'] = region['center_northing'] - dn 00830 de = (region['ewres'] * region['cols']) / 2. 00831 region['e'] = region['center_easting'] + de 00832 region['w'] = region['center_easting'] - de 00833 00834 self.Map.AdjustRegion() 00835 00836 # add to zoom history 00837 self.MapWindow.ZoomHistory(region['n'], region['s'], 00838 region['e'], region['w']) 00839 00840 # redraw a map 00841 self.MapWindow.UpdateMap() 00842 self.statusbarWin['goto'].SetFocus() 00843 00844 def StatusbarUpdate(self): 00845 """!Update statusbar content""" 00846 00847 self.statusbarWin['region'].Hide() 00848 self.statusbarWin['resolution'].Hide() 00849 self.statusbarWin['mapscale'].Hide() 00850 self.statusbarWin['goto'].Hide() 00851 self.statusbarWin['projection'].Hide() 00852 self.mapScaleValue = self.ppm = None 00853 00854 if self.statusbarWin['toggle'].GetSelection() == 0: # Coordinates 00855 self.statusbar.SetStatusText("", 0) 00856 # enable long help 00857 self.StatusbarEnableLongHelp() 00858 00859 elif self.statusbarWin['toggle'].GetSelection() in (1, 2): # Extent 00860 sel = self.statusbarWin['toggle'].GetSelection() 00861 if sel == 1: 00862 region = self.Map.region 00863 else: 00864 region = self.Map.GetRegion() # computation region 00865 00866 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00867 subkey = 'precision')) 00868 format = UserSettings.Get(group = 'projection', key = 'format', 00869 subkey = 'll') 00870 00871 if self.statusbarWin['projection'].IsChecked(): 00872 if not UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4'): 00873 self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0) 00874 else: 00875 projOut = UserSettings.Get(group = 'projection', 00876 key = 'statusbar', 00877 subkey = 'proj4') 00878 proj, coord1 = utils.ReprojectCoordinates(coord = (region["w"], region["s"]), 00879 projOut = projOut, flags = 'd') 00880 proj, coord2 = utils.ReprojectCoordinates(coord = (region["e"], region["n"]), 00881 projOut = projOut, flags = 'd') 00882 if sel == 2: 00883 proj, coord3 = utils.ReprojectCoordinates(coord = (0.0, 0.0), 00884 projOut = projOut, flags = 'd') 00885 proj, coord4 = utils.ReprojectCoordinates(coord = (region["ewres"], region["nsres"]), 00886 projOut = projOut, flags = 'd') 00887 if coord1 and coord2: 00888 if proj in ('ll', 'latlong', 'longlat') and format == 'DMS': 00889 w, s = utils.Deg2DMS(coord1[0], coord1[1], string = False, 00890 precision = precision) 00891 e, n = utils.Deg2DMS(coord2[0], coord2[1], string = False, 00892 precision = precision) 00893 if sel == 1: 00894 self.statusbar.SetStatusText("%s - %s, %s - %s" % 00895 (w, e, s, n), 0) 00896 else: 00897 ewres, nsres = utils.Deg2DMS(abs(coord3[0]) - abs(coord4[0]), 00898 abs(coord3[1]) - abs(coord4[1]), 00899 string = False, hemisphere = False, 00900 precision = precision) 00901 self.statusbar.SetStatusText("%s - %s, %s - %s (%s, %s)" % 00902 (w, e, s, n, ewres, nsres), 0) 00903 else: 00904 w, s = coord1 00905 e, n = coord2 00906 if sel == 1: 00907 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f" % 00908 (precision, w, precision, e, 00909 precision, s, precision, n), 0) 00910 else: 00911 ewres, nsres = coord3 00912 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % 00913 (precision, w, precision, e, 00914 precision, s, precision, n, 00915 precision, ewres, precision, nsres), 0) 00916 else: 00917 self.statusbar.SetStatusText(_("Error in projection (check the settings)"), 0) 00918 else: 00919 if self.Map.projinfo['proj'] == 'll' and format == 'DMS': 00920 w, s = utils.Deg2DMS(region["w"], region["s"], 00921 string = False, precision = precision) 00922 e, n = utils.Deg2DMS(region["e"], region["n"], 00923 string = False, precision = precision) 00924 if sel == 1: 00925 self.statusbar.SetStatusText("%s - %s, %s - %s" % 00926 (w, e, s, n), 0) 00927 else: 00928 ewres, nsres = utils.Deg2DMS(region['ewres'], region['nsres'], 00929 string = False, precision = precision) 00930 self.statusbar.SetStatusText("%s - %s, %s - %s (%s, %s)" % 00931 (w, e, s, n, ewres, nsres), 0) 00932 else: 00933 w, s = region["w"], region["s"] 00934 e, n = region["e"], region["n"] 00935 if sel == 1: 00936 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f" % 00937 (precision, w, precision, e, 00938 precision, s, precision, n), 0) 00939 else: 00940 ewres, nsres = region['ewres'], region['nsres'] 00941 self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % 00942 (precision, w, precision, e, 00943 precision, s, precision, n, 00944 precision, ewres, precision, nsres), 0) 00945 # enable long help 00946 self.StatusbarEnableLongHelp() 00947 00948 elif self.statusbarWin['toggle'].GetSelection() == 3: # Show comp. extent 00949 self.statusbar.SetStatusText("", 0) 00950 self.statusbarWin['region'].Show() 00951 # disable long help 00952 self.StatusbarEnableLongHelp(False) 00953 00954 elif self.statusbarWin['toggle'].GetSelection() == 4: # Display mode 00955 self.statusbar.SetStatusText("", 0) 00956 self.statusbarWin['resolution'].Show() 00957 # disable long help 00958 self.StatusbarEnableLongHelp(False) 00959 00960 elif self.statusbarWin['toggle'].GetSelection() == 5: # Display geometry 00961 self.statusbar.SetStatusText("rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" % 00962 (self.Map.region["rows"], self.Map.region["cols"], 00963 self.Map.region["nsres"], self.Map.region["ewres"]), 0) 00964 # enable long help 00965 self.StatusbarEnableLongHelp() 00966 00967 elif self.statusbarWin['toggle'].GetSelection() == 6: # Map scale 00968 # TODO: need to be fixed... 00969 ### screen X region problem 00970 ### user should specify ppm 00971 dc = wx.ScreenDC() 00972 dpSizePx = wx.DisplaySize() # display size in pixels 00973 dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) 00974 dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches 00975 sysPpi = dc.GetPPI() 00976 comPpi = (dpSizePx[0] / dpSizeIn[0], 00977 dpSizePx[1] / dpSizeIn[1]) 00978 00979 ppi = comPpi # pixel per inch 00980 self.ppm = ((ppi[0] / 2.54) * 100, # pixel per meter 00981 (ppi[1] / 2.54) * 100) 00982 00983 Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): size: px=%d,%d mm=%f,%f " 00984 "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % \ 00985 (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1], 00986 dpSizeIn[0], dpSizeIn[1], 00987 sysPpi[0], sysPpi[1], comPpi[0], comPpi[1], 00988 self.ppm[0], self.ppm[1])) 00989 00990 region = self.Map.region 00991 00992 heightCm = region['rows'] / self.ppm[1] * 100 00993 widthCm = region['cols'] / self.ppm[0] * 100 00994 00995 Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): width_cm=%f, height_cm=%f" % 00996 (widthCm, heightCm)) 00997 00998 xscale = (region['e'] - region['w']) / (region['cols'] / self.ppm[0]) 00999 yscale = (region['n'] - region['s']) / (region['rows'] / self.ppm[1]) 01000 scale = (xscale + yscale) / 2. 01001 01002 Debug.msg(3, "MapFrame.StatusbarUpdate(mapscale): xscale=%f, yscale=%f -> scale=%f" % \ 01003 (xscale, yscale, scale)) 01004 01005 self.statusbar.SetStatusText("") 01006 try: 01007 self.statusbarWin['mapscale'].SetValue("1:%ld" % (scale + 0.5)) 01008 except TypeError: 01009 pass 01010 self.mapScaleValue = scale 01011 self.statusbarWin['mapscale'].Show() 01012 01013 # disable long help 01014 self.StatusbarEnableLongHelp(False) 01015 01016 elif self.statusbarWin['toggle'].GetSelection() == 7: # go to 01017 self.statusbar.SetStatusText("") 01018 region = self.Map.GetCurrentRegion() 01019 precision = int(UserSettings.Get(group = 'projection', key = 'format', 01020 subkey = 'precision')) 01021 format = UserSettings.Get(group = 'projection', key = 'format', 01022 subkey = 'll') 01023 01024 if self.statusbarWin['projection'].IsChecked(): 01025 if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'): 01026 self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0) 01027 else: 01028 proj, coord = utils.ReprojectCoordinates(coord = (region['center_easting'], 01029 region['center_northing']), 01030 projOut = UserSettings.Get(group = 'projection', 01031 key = 'statusbar', 01032 subkey = 'proj4'), 01033 flags = 'd') 01034 if coord: 01035 if proj in ('ll', 'latlong', 'longlat') and format == 'DMS': 01036 self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(coord[0], 01037 coord[1], 01038 precision = precision)) 01039 else: 01040 self.statusbarWin['goto'].SetValue("%.*f; %.*f" % (precision, coord[0], 01041 precision, coord[1])) 01042 else: 01043 self.statusbar.SetStatusText(_("Error in projection (check the settings)"), 0) 01044 else: 01045 if self.Map.projinfo['proj'] == 'll' and format == 'DMS': 01046 self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(region['center_easting'], 01047 region['center_northing'], 01048 precision = precision)) 01049 else: 01050 self.statusbarWin['goto'].SetValue("%.*f; %.*f" % (precision, region['center_easting'], 01051 precision, region['center_northing'])) 01052 self.statusbarWin['goto'].Show() 01053 01054 # disable long help 01055 self.StatusbarEnableLongHelp(False) 01056 01057 elif self.statusbarWin['toggle'].GetSelection() == 8: # projection 01058 self.statusbar.SetStatusText("") 01059 epsg = UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'epsg') 01060 if epsg: 01061 label = '%s (EPSG: %s)' % (_("Use defined projection"), epsg) 01062 self.statusbarWin['projection'].SetLabel(label) 01063 else: 01064 self.statusbarWin['projection'].SetLabel(_("Use defined projection")) 01065 self.statusbarWin['projection'].Show() 01066 01067 # disable long help 01068 self.StatusbarEnableLongHelp(False) 01069 01070 else: 01071 self.statusbar.SetStatusText("", 1) 01072 01073 def StatusbarEnableLongHelp(self, enable = True): 01074 """!Enable/disable toolbars long help""" 01075 for toolbar in self.toolbars.itervalues(): 01076 if toolbar: 01077 toolbar.EnableLongHelp(enable) 01078 01079 def StatusbarReposition(self): 01080 """!Reposition checkbox in statusbar""" 01081 # reposition checkbox 01082 widgets = [(0, self.statusbarWin['region']), 01083 (0, self.statusbarWin['resolution']), 01084 (0, self.statusbarWin['mapscale']), 01085 (0, self.statusbarWin['progress']), 01086 (0, self.statusbarWin['projection']), 01087 (1, self.statusbarWin['toggle']), 01088 (2, self.statusbarWin['mask']), 01089 (3, self.statusbarWin['render'])] 01090 for idx, win in widgets: 01091 rect = self.statusbar.GetFieldRect(idx) 01092 if idx == 0: # show region / mapscale / process bar 01093 # -> size 01094 wWin, hWin = win.GetBestSize() 01095 if win == self.statusbarWin['progress']: 01096 wWin = rect.width - 6 01097 # -> position 01098 # if win == self.statusbarWin['region']: 01099 # x, y = rect.x + rect.width - wWin, rect.y - 1 01100 # align left 01101 # else: 01102 x, y = rect.x + 3, rect.y - 1 01103 w, h = wWin, rect.height + 2 01104 else: # choice || auto-rendering 01105 x, y = rect.x, rect.y - 1 01106 w, h = rect.width, rect.height + 2 01107 if idx == 2: # mask 01108 x += 5 01109 y += 4 01110 elif idx == 3: # render 01111 x += 5 01112 win.SetPosition((x, y)) 01113 win.SetSize((w, h)) 01114 01115 def SaveToFile(self, event): 01116 """!Save map to image 01117 """ 01118 if self.toolbars['nviz']: 01119 filetype = "PPM file (*.ppm)|*.ppm|TIF file (*.tif)|*.tif" 01120 ltype = [{ 'ext' : 'ppm', 'type' : -1 }, 01121 { 'ext' : 'tif', 'type' : wx.BITMAP_TYPE_TIF }] 01122 else: 01123 img = self.MapWindow.img 01124 if not img: 01125 gcmd.GMessage(parent = self, 01126 message = _("Nothing to render (empty map). Operation canceled.")) 01127 return 01128 filetype, ltype = gdialogs.GetImageHandlers(img) 01129 01130 # get size 01131 dlg = gdialogs.ImageSizeDialog(self) 01132 dlg.CentreOnParent() 01133 if dlg.ShowModal() != wx.ID_OK: 01134 dlg.Destroy() 01135 return 01136 width, height = dlg.GetValues() 01137 dlg.Destroy() 01138 01139 # get filename 01140 dlg = wx.FileDialog(parent = self, 01141 message = _("Choose a file name to save the image " 01142 "(no need to add extension)"), 01143 wildcard = filetype, 01144 style = wx.SAVE | wx.FD_OVERWRITE_PROMPT) 01145 01146 if dlg.ShowModal() == wx.ID_OK: 01147 path = dlg.GetPath() 01148 if not path: 01149 dlg.Destroy() 01150 return 01151 01152 base, ext = os.path.splitext(path) 01153 fileType = ltype[dlg.GetFilterIndex()]['type'] 01154 extType = ltype[dlg.GetFilterIndex()]['ext'] 01155 if ext != extType: 01156 path = base + '.' + extType 01157 01158 self.MapWindow.SaveToFile(path, fileType, 01159 width, height) 01160 01161 dlg.Destroy() 01162 01163 def PrintMenu(self, event): 01164 """ 01165 Print options and output menu for map display 01166 """ 01167 point = wx.GetMousePosition() 01168 printmenu = wx.Menu() 01169 # Add items to the menu 01170 setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup')) 01171 printmenu.AppendItem(setup) 01172 self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup) 01173 01174 preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview')) 01175 printmenu.AppendItem(preview) 01176 self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview) 01177 01178 doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display')) 01179 printmenu.AppendItem(doprint) 01180 self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint) 01181 01182 # Popup the menu. If an item is selected then its handler 01183 # will be called before PopupMenu returns. 01184 self.PopupMenu(printmenu) 01185 printmenu.Destroy() 01186 01187 def OnCloseWindow(self, event): 01188 """!Window closed. 01189 Also close associated layer tree page 01190 """ 01191 pgnum = None 01192 self.Map.Clean() 01193 01194 # close edited map and 3D tools properly 01195 if self.toolbars['vdigit']: 01196 maplayer = self.toolbars['vdigit'].GetLayer() 01197 if maplayer: 01198 self.toolbars['vdigit'].OnExit() 01199 01200 if self.toolbars['nviz']: 01201 self.toolbars['nviz'].OnExit() 01202 01203 if not self._layerManager: 01204 self.Destroy() 01205 elif self.page: 01206 pgnum = self.layerbook.GetPageIndex(self.page) 01207 if pgnum > -1: 01208 self.layerbook.DeletePage(pgnum) 01209 01210 def GetRender(self): 01211 """!Returns current instance of render.Map() 01212 """ 01213 return self.Map 01214 01215 def GetWindow(self): 01216 """!Get map window""" 01217 return self.MapWindow 01218 01219 def OnNvizQuerySurface(self, event): 01220 """!Query current surface in 3D view mode""" 01221 if self.toolbars['map'].GetAction() == 'nvizQuerySurface': 01222 self.toolbars['map'].SelectDefault(event) 01223 return 01224 01225 self.toolbars['map'].action['desc'] = 'nvizQuerySurface' 01226 01227 self.MapWindow.mouse['use'] = "nvizQuerySurface" 01228 self._OnQuery() 01229 01230 def OnNvizQueryVector(self, event): 01231 """!Query current vector in 3D view mode""" 01232 if self.toolbars['map'].GetAction() == 'nvizQueryVector': 01233 self.toolbars['map'].SelectDefault(event) 01234 return 01235 01236 self.toolbars['map'].action['desc'] = 'nvizQueryVector' 01237 01238 self.MapWindow.mouse['use'] = "nvizQueryVector" 01239 self._OnQuery() 01240 01241 def QueryMap(self, x, y): 01242 """!Query raster or vector map layers by r/v.what 01243 01244 @param x,y coordinates 01245 """ 01246 # set query snap distance for v.what at map unit equivalent of 10 pixels 01247 qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width) 01248 east, north = self.MapWindow.Pixel2Cell((x, y)) 01249 01250 if not self.IsStandalone(): 01251 num = 0 01252 for layer in self.tree.GetSelections(): 01253 ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType() 01254 if ltype in ('raster', 'rgb', 'his', 01255 'vector', 'thememap', 'themechart'): 01256 num += 1 01257 01258 if num < 1: 01259 gcmd.GMessage(parent = self, 01260 message = _('No raster or vector map layer selected for querying.')) 01261 return 01262 01263 rast = list() 01264 vect = list() 01265 rcmd = ['r.what', '--v'] 01266 vcmd = ['v.what', '--v'] 01267 01268 if self.IsStandalone(): 01269 pass 01270 else: 01271 for layer in self.tree.GetSelections(): 01272 ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType() 01273 dcmd = self.tree.GetPyData(layer)[0]['cmd'] 01274 name, found = utils.GetLayerNameFromCmd(dcmd) 01275 01276 if not found: 01277 continue 01278 if ltype == 'raster': 01279 rast.append(name) 01280 elif ltype in ('rgb', 'his'): 01281 for iname in name.split('\n'): 01282 rast.append(iname) 01283 elif ltype in ('vector', 'thememap', 'themechart'): 01284 vect.append(name) 01285 01286 # use display region settings instead of computation region settings 01287 self.tmpreg = os.getenv("GRASS_REGION") 01288 os.environ["GRASS_REGION"] = self.Map.SetRegion(windres = False) 01289 01290 # build query commands for any selected rasters and vectors 01291 if rast: 01292 rcmd.append('-f') 01293 rcmd.append('-n') 01294 rcmd.append('input=%s' % ','.join(rast)) 01295 rcmd.append('east_north=%f,%f' % (float(east), float(north))) 01296 01297 if vect: 01298 # check for vector maps open to be edited 01299 digitToolbar = self.toolbars['vdigit'] 01300 if digitToolbar: 01301 lmap = digitToolbar.GetLayer().GetName() 01302 for name in vect: 01303 if lmap == name: 01304 self._layerManager.goutput.WriteWarning(_("Vector map <%s> " 01305 "opened for editing - skipped.") % map) 01306 vect.remove(name) 01307 01308 if len(vect) < 1: 01309 self._layerManager.goutput.WriteCmdLog(_("Nothing to query.")) 01310 return 01311 01312 vcmd.append('-a') 01313 vcmd.append('map=%s' % ','.join(vect)) 01314 vcmd.append('east_north=%f,%f' % (float(east), float(north))) 01315 vcmd.append('distance=%f' % float(qdist)) 01316 01317 Debug.msg(1, "QueryMap(): raster=%s vector=%s" % (','.join(rast), 01318 ','.join(vect))) 01319 # parse query command(s) 01320 if not self.IsStandalone(): 01321 if rast: 01322 self._layerManager.goutput.RunCmd(rcmd, 01323 compReg = False, 01324 onDone = self._QueryMapDone) 01325 if vect: 01326 self._layerManager.goutput.RunCmd(vcmd, 01327 onDone = self._QueryMapDone) 01328 else: 01329 if rast: 01330 gcmd.RunCommand(rcmd) 01331 if vect: 01332 gcmd.RunCommand(vcmd) 01333 01334 def _QueryMapDone(self, cmd, returncode): 01335 """!Restore settings after querying (restore GRASS_REGION) 01336 01337 @param returncode command return code 01338 """ 01339 if hasattr(self, "tmpreg"): 01340 if self.tmpreg: 01341 os.environ["GRASS_REGION"] = self.tmpreg 01342 elif 'GRASS_REGION' in os.environ: 01343 del os.environ["GRASS_REGION"] 01344 elif 'GRASS_REGION' in os.environ: 01345 del os.environ["GRASS_REGION"] 01346 01347 if hasattr(self, "tmpreg"): 01348 del self.tmpreg 01349 01350 def QueryVector(self, x, y): 01351 """!Query vector map layer features 01352 01353 Attribute data of selected vector object are displayed in GUI dialog. 01354 Data can be modified (On Submit) 01355 """ 01356 if not self.tree.layer_selected or \ 01357 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] != 'vector': 01358 gcmd.GMessage(parent = self, 01359 message = _("No map layer selected for querying.")) 01360 return 01361 01362 posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset, 01363 y + self.MapWindow.dialogOffset)) 01364 01365 qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / 01366 self.Map.width) 01367 01368 east, north = self.MapWindow.Pixel2Cell((x, y)) 01369 01370 mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name 01371 01372 if self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetMapset() != \ 01373 grass.gisenv()['MAPSET']: 01374 mode = 'display' 01375 else: 01376 mode = 'update' 01377 01378 if self.dialogs['attributes'] is None: 01379 dlg = dbm_dialogs.DisplayAttributesDialog(parent = self.MapWindow, 01380 map = mapName, 01381 query = ((east, north), qdist), 01382 pos = posWindow, 01383 action = mode) 01384 self.dialogs['attributes'] = dlg 01385 01386 else: 01387 # selection changed? 01388 if not self.dialogs['attributes'].mapDBInfo or \ 01389 self.dialogs['attributes'].mapDBInfo.map != mapName: 01390 self.dialogs['attributes'].UpdateDialog(map = mapName, query = ((east, north), qdist), 01391 action = mode) 01392 else: 01393 self.dialogs['attributes'].UpdateDialog(query = ((east, north), qdist), 01394 action = mode) 01395 if not self.dialogs['attributes'].IsFound(): 01396 self._layerManager.goutput.WriteLog(_('Nothing found.')) 01397 01398 cats = self.dialogs['attributes'].GetCats() 01399 01400 try: 01401 qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER)[0] 01402 except IndexError: 01403 qlayer = None 01404 01405 if self.dialogs['attributes'].mapDBInfo and cats: 01406 # highlight feature & re-draw map 01407 if qlayer: 01408 qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats, 01409 useId = False, 01410 addLayer = False)) 01411 else: 01412 qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId = False) 01413 01414 # set opacity based on queried layer 01415 opacity = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetOpacity(float = True) 01416 qlayer.SetOpacity(opacity) 01417 01418 self.MapWindow.UpdateMap(render = False, renderVector = False) 01419 if not self.dialogs['attributes'].IsShown(): 01420 self.dialogs['attributes'].Show() 01421 else: 01422 if qlayer: 01423 self.Map.DeleteLayer(qlayer) 01424 self.MapWindow.UpdateMap(render = False, renderVector = False) 01425 if self.dialogs['attributes'].IsShown(): 01426 self.dialogs['attributes'].Hide() 01427 01428 def OnQuery(self, event): 01429 """!Query tools menu""" 01430 if self.toolbars['map']: 01431 self.toolbars['map'].OnTool(event) 01432 action = self.toolbars['map'].GetAction() 01433 01434 if self.toolbars['nviz']: 01435 toolsmenu = wx.Menu() 01436 raster = wx.MenuItem(parentMenu = toolsmenu, id = wx.ID_ANY, 01437 text = _("Query surface (raster map)"), 01438 kind = wx.ITEM_CHECK) 01439 toolsmenu.AppendItem(raster) 01440 self.Bind(wx.EVT_MENU, self.OnNvizQuerySurface, raster) 01441 if action == "nvizQuerySurface": 01442 raster.Check(True) 01443 vector = wx.MenuItem(parentMenu = toolsmenu, id = wx.ID_ANY, 01444 text = _("Query vector map"), 01445 kind = wx.ITEM_CHECK) 01446 toolsmenu.AppendItem(vector) 01447 self.Bind(wx.EVT_MENU, self.OnNvizQueryVector, vector) 01448 if action == "nvizQueryVector": 01449 vector.Check(True) 01450 01451 self.PopupMenu(toolsmenu) 01452 toolsmenu.Destroy() 01453 else: 01454 self.toolbars['map'].action['desc'] = 'queryMap' 01455 self.MapWindow.mouse['use'] = "query" 01456 01457 if not self.IsStandalone(): 01458 # switch to output console to show query results 01459 self._layerManager.notebook.SetSelectionByName('output') 01460 01461 self.MapWindow.mouse['box'] = "point" 01462 self.MapWindow.zoomtype = 0 01463 01464 # change the cursor 01465 self.MapWindow.SetCursor(self.cursors["cross"]) 01466 01467 def AddTmpVectorMapLayer(self, name, cats, useId = False, addLayer = True): 01468 """!Add temporal vector map layer to map composition 01469 01470 @param name name of map layer 01471 @param useId use feature id instead of category 01472 """ 01473 # color settings from ATM 01474 color = UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'color') 01475 colorStr = str(color[0]) + ":" + \ 01476 str(color[1]) + ":" + \ 01477 str(color[2]) 01478 01479 # icon used in vector display and its size 01480 icon = '' 01481 size = 0 01482 vparam = self.tree.GetPyData(self.tree.layer_selected)[0]['cmd'] 01483 for p in vparam: 01484 if '=' in p: 01485 parg,pval = p.split('=') 01486 if parg == 'icon': icon = pval 01487 elif parg == 'size': size = int(pval) 01488 01489 pattern = ["d.vect", 01490 "map=%s" % name, 01491 "color=%s" % colorStr, 01492 "fcolor=%s" % colorStr, 01493 "width=%d" % UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'width')] 01494 if icon != '': 01495 pattern.append('icon=%s' % icon) 01496 if size > 0: 01497 pattern.append('size=%i' % size) 01498 01499 if useId: 01500 cmd = pattern 01501 cmd.append('-i') 01502 cmd.append('cats=%s' % str(cats)) 01503 else: 01504 cmd = [] 01505 for layer in cats.keys(): 01506 cmd.append(copy.copy(pattern)) 01507 lcats = cats[layer] 01508 cmd[-1].append("layer=%d" % layer) 01509 cmd[-1].append("cats=%s" % utils.ListOfCatsToRange(lcats)) 01510 01511 if addLayer: 01512 if useId: 01513 return self.Map.AddLayer(type = 'vector', name = globalvar.QUERYLAYER, command = cmd, 01514 l_active = True, l_hidden = True, l_opacity = 1.0) 01515 else: 01516 return self.Map.AddLayer(type = 'command', name = globalvar.QUERYLAYER, command = cmd, 01517 l_active = True, l_hidden = True, l_opacity = 1.0) 01518 else: 01519 return cmd 01520 01521 def OnAnalyze(self, event): 01522 """!Analysis tools menu 01523 """ 01524 point = wx.GetMousePosition() 01525 toolsmenu = wx.Menu() 01526 icons = Icons['displayWindow'] 01527 01528 # Add items to the menu 01529 measure = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["measure"].GetLabel()) 01530 measure.SetBitmap(icons["measure"].GetBitmap(self.iconsize)) 01531 toolsmenu.AppendItem(measure) 01532 self.Bind(wx.EVT_MENU, self.OnMeasure, measure) 01533 01534 profile = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["profile"].GetLabel()) 01535 profile.SetBitmap(icons["profile"].GetBitmap(self.iconsize)) 01536 toolsmenu.AppendItem(profile) 01537 self.Bind(wx.EVT_MENU, self.Profile, profile) 01538 01539 histogram = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["histogram"].GetLabel()) 01540 histogram.SetBitmap(icons["histogram"].GetBitmap(self.iconsize)) 01541 toolsmenu.AppendItem(histogram) 01542 self.Bind(wx.EVT_MENU, self.Histogram, histogram) 01543 01544 # Popup the menu. If an item is selected then its handler 01545 # will be called before PopupMenu returns. 01546 self.PopupMenu(toolsmenu) 01547 toolsmenu.Destroy() 01548 01549 def OnMeasure(self, event): 01550 """!Init measurement routine that calculates map distance 01551 along transect drawn on map display 01552 """ 01553 self.totaldist = 0.0 # total measured distance 01554 01555 # switch Layer Manager to output console to show measure results 01556 self._layerManager.notebook.SetSelectionByName('output') 01557 01558 # change mouse to draw line for measurement 01559 self.MapWindow.mouse['use'] = "measure" 01560 self.MapWindow.mouse['box'] = "line" 01561 self.MapWindow.zoomtype = 0 01562 self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SHORT_DASH) 01563 self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SHORT_DASH) 01564 01565 # change the cursor 01566 self.MapWindow.SetCursor(self.cursors["pencil"]) 01567 01568 # initiating output 01569 style = self._layerManager.goutput.cmd_output.StyleWarning 01570 self._layerManager.goutput.WriteLog(_('Click and drag with left mouse button ' 01571 'to measure.%s' 01572 'Double click with left button to clear.') % \ 01573 (os.linesep), style) 01574 if self.Map.projinfo['proj'] != 'xy': 01575 units = self.Map.projinfo['units'] 01576 self._layerManager.goutput.WriteCmdLog(_('Measuring distance') + ' (' 01577 + units + '):') 01578 else: 01579 self._layerManager.goutput.WriteCmdLog(_('Measuring distance:')) 01580 01581 if self.Map.projinfo['proj'] == 'll': 01582 try: 01583 import grass.lib.gis as gislib 01584 global haveCtypes 01585 haveCtypes = True 01586 01587 gislib.G_begin_distance_calculations() 01588 except ImportError, e: 01589 self._layerManager.goutput.WriteWarning(_('Geodesic distance is not yet ' 01590 'supported by this tool.\n' 01591 'Reason: %s' % e)) 01592 01593 def MeasureDist(self, beginpt, endpt): 01594 """!Calculate map distance from screen distance 01595 and print to output window 01596 """ 01597 self._layerManager.notebook.SetSelectionByName('output') 01598 01599 dist, (north, east) = self.MapWindow.Distance(beginpt, endpt) 01600 01601 dist = round(dist, 3) 01602 d, dunits = self.FormatDist(dist) 01603 01604 self.totaldist += dist 01605 td, tdunits = self.FormatDist(self.totaldist) 01606 01607 strdist = str(d) 01608 strtotdist = str(td) 01609 01610 if self.Map.projinfo['proj'] == 'xy' or 'degree' not in self.Map.projinfo['unit']: 01611 angle = int(math.degrees(math.atan2(north,east)) + 0.5) 01612 angle = 180 - angle 01613 if angle < 0: 01614 angle = 360 + angle 01615 01616 mstring = '%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \ 01617 % (_('segment'), strdist, dunits, 01618 _('total distance'), strtotdist, tdunits, 01619 _('bearing'), angle, _('deg'), 01620 '-' * 60) 01621 else: 01622 mstring = '%s = %s %s\n%s = %s %s\n%s' \ 01623 % (_('segment'), strdist, dunits, 01624 _('total distance'), strtotdist, tdunits, 01625 '-' * 60) 01626 01627 self._layerManager.goutput.WriteLog(mstring) 01628 01629 return dist 01630 01631 def Profile(self, event): 01632 """!Init profile canvas and tools 01633 """ 01634 raster = [] 01635 if self.tree.layer_selected and \ 01636 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster': 01637 raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name) 01638 01639 self.profile = profile.ProfileFrame(self, 01640 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300), 01641 style = wx.DEFAULT_FRAME_STYLE, rasterList = raster) 01642 self.profile.Show() 01643 # Open raster select dialog to make sure that a raster (and the desired raster) 01644 # is selected to be profiled 01645 self.profile.OnSelectRaster(None) 01646 01647 def FormatDist(self, dist): 01648 """!Format length numbers and units in a nice way, 01649 as a function of length. From code by Hamish Bowman 01650 Grass Development Team 2006""" 01651 01652 mapunits = self.Map.projinfo['units'] 01653 if mapunits == 'metres': 01654 mapunits = 'meters' 01655 outunits = mapunits 01656 dist = float(dist) 01657 divisor = 1.0 01658 01659 # figure out which units to use 01660 if mapunits == 'meters': 01661 if dist > 2500.0: 01662 outunits = 'km' 01663 divisor = 1000.0 01664 else: outunits = 'm' 01665 elif mapunits == 'feet': 01666 # nano-bug: we match any "feet", but US Survey feet is really 01667 # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000 01668 # miles the tick markers are rounded to the nearest 10th of a 01669 # mile (528'), the difference in foot flavours is ignored. 01670 if dist > 5280.0: 01671 outunits = 'miles' 01672 divisor = 5280.0 01673 else: 01674 outunits = 'ft' 01675 elif 'degree' in mapunits and \ 01676 not haveCtypes: 01677 if dist < 1: 01678 outunits = 'min' 01679 divisor = (1/60.0) 01680 else: 01681 outunits = 'deg' 01682 else: 01683 outunits = 'meters' 01684 01685 # format numbers in a nice way 01686 if (dist/divisor) >= 2500.0: 01687 outdist = round(dist/divisor) 01688 elif (dist/divisor) >= 1000.0: 01689 outdist = round(dist/divisor,1) 01690 elif (dist/divisor) > 0.0: 01691 outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor)))) 01692 else: 01693 outdist = float(dist/divisor) 01694 01695 return (outdist, outunits) 01696 01697 def Histogram(self, event): 01698 """!Init histogram display canvas and tools 01699 """ 01700 self.histogram = histogram.HistFrame(self, 01701 id = wx.ID_ANY, size = globalvar.HIST_WINDOW_SIZE, 01702 style = wx.DEFAULT_FRAME_STYLE) 01703 01704 #show new display 01705 self.histogram.Show() 01706 self.histogram.Refresh() 01707 self.histogram.Update() 01708 01709 01710 def OnDecoration(self, event): 01711 """!Decorations overlay menu 01712 """ 01713 point = wx.GetMousePosition() 01714 decmenu = wx.Menu() 01715 icons = Icons['displayWindow'] 01716 01717 # Add items to the menu 01718 AddScale = wx.MenuItem(decmenu, wx.ID_ANY, icons["addBarscale"].GetLabel()) 01719 AddScale.SetBitmap(icons["addBarscale"].GetBitmap(self.iconsize)) 01720 decmenu.AppendItem(AddScale) 01721 self.Bind(wx.EVT_MENU, self.OnAddBarscale, AddScale) 01722 01723 AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, icons["addLegend"].GetLabel()) 01724 AddLegend.SetBitmap(icons["addLegend"].GetBitmap(self.iconsize)) 01725 decmenu.AppendItem(AddLegend) 01726 self.Bind(wx.EVT_MENU, self.OnAddLegend, AddLegend) 01727 01728 AddText = wx.MenuItem(decmenu, wx.ID_ANY, icons["addText"].GetLabel()) 01729 AddText.SetBitmap(icons["addText"].GetBitmap(self.iconsize)) 01730 decmenu.AppendItem(AddText) 01731 self.Bind(wx.EVT_MENU, self.OnAddText, AddText) 01732 01733 # Popup the menu. If an item is selected then its handler 01734 # will be called before PopupMenu returns. 01735 self.PopupMenu(decmenu) 01736 decmenu.Destroy() 01737 01738 def OnAddBarscale(self, event): 01739 """!Handler for scale/arrow map decoration menu selection. 01740 """ 01741 if self.dialogs['barscale']: 01742 return 01743 01744 id = 0 # unique index for overlay layer 01745 01746 # If location is latlon, only display north arrow (scale won't work) 01747 # proj = self.Map.projinfo['proj'] 01748 # if proj == 'll': 01749 # barcmd = 'd.barscale -n' 01750 # else: 01751 # barcmd = 'd.barscale' 01752 01753 # decoration overlay control dialog 01754 self.dialogs['barscale'] = \ 01755 gdialogs.DecorationDialog(parent = self, title = _('Scale and North arrow'), 01756 size = (350, 200), 01757 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE, 01758 cmd = ['d.barscale', 'at=0,5'], 01759 ovlId = id, 01760 name = 'barscale', 01761 checktxt = _("Show/hide scale and North arrow"), 01762 ctrltxt = _("scale object")) 01763 01764 self.dialogs['barscale'].CentreOnParent() 01765 ### dialog cannot be show as modal - in the result d.barscale is not selectable 01766 ### self.dialogs['barscale'].ShowModal() 01767 self.dialogs['barscale'].Show() 01768 self.MapWindow.mouse['use'] = 'pointer' 01769 01770 def OnAddLegend(self, event): 01771 """!Handler for legend map decoration menu selection. 01772 """ 01773 if self.dialogs['legend']: 01774 return 01775 01776 id = 1 # index for overlay layer in render 01777 01778 cmd = ['d.legend', 'at=5,50,2,5'] 01779 if self.tree.layer_selected and \ 01780 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster': 01781 cmd.append('map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name) 01782 01783 # Decoration overlay control dialog 01784 self.dialogs['legend'] = \ 01785 gdialogs.DecorationDialog(parent = self, title = ('Legend'), 01786 size = (350, 200), 01787 style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE, 01788 cmd = cmd, 01789 ovlId = id, 01790 name = 'legend', 01791 checktxt = _("Show/hide legend"), 01792 ctrltxt = _("legend object")) 01793 01794 self.dialogs['legend'].CentreOnParent() 01795 ### dialog cannot be show as modal - in the result d.legend is not selectable 01796 ### self.dialogs['legend'].ShowModal() 01797 self.dialogs['legend'].Show() 01798 self.MapWindow.mouse['use'] = 'pointer' 01799 01800 def OnAddText(self, event): 01801 """!Handler for text decoration menu selection. 01802 """ 01803 if self.MapWindow.dragid > -1: 01804 id = self.MapWindow.dragid 01805 else: 01806 # index for overlay layer in render 01807 if len(self.MapWindow.textdict.keys()) > 0: 01808 id = self.MapWindow.textdict.keys()[-1] + 1 01809 else: 01810 id = 101 01811 01812 self.dialogs['text'] = gdialogs.TextLayerDialog(parent = self, ovlId = id, 01813 title = _('Add text layer'), 01814 size = (400, 200)) 01815 self.dialogs['text'].CenterOnParent() 01816 01817 # If OK button pressed in decoration control dialog 01818 if self.dialogs['text'].ShowModal() == wx.ID_OK: 01819 text = self.dialogs['text'].GetValues()['text'] 01820 active = self.dialogs['text'].GetValues()['active'] 01821 coords, w, h = self.MapWindow.TextBounds(self.dialogs['text'].GetValues()) 01822 01823 # delete object if it has no text or is not active 01824 if text == '' or active == False: 01825 try: 01826 self.MapWindow.pdc.ClearId(id) 01827 self.MapWindow.pdc.RemoveId(id) 01828 del self.MapWindow.textdict[id] 01829 except: 01830 pass 01831 return 01832 01833 self.MapWindow.pdc.ClearId(id) 01834 self.MapWindow.pdc.SetId(id) 01835 self.MapWindow.textdict[id] = self.dialogs['text'].GetValues() 01836 01837 self.MapWindow.Draw(self.MapWindow.pdcDec, img = self.MapWindow.textdict[id], 01838 drawid = id, pdctype = 'text', coords = coords) 01839 01840 self.MapWindow.UpdateMap(render = False, renderVector = False) 01841 01842 self.MapWindow.mouse['use'] = 'pointer' 01843 01844 def GetOptData(self, dcmd, type, params, propwin): 01845 """!Callback method for decoration overlay command generated by 01846 dialog created in menuform.py 01847 """ 01848 # Reset comand and rendering options in render.Map. Always render decoration. 01849 # Showing/hiding handled by PseudoDC 01850 self.Map.ChangeOverlay(ovltype = type, type = 'overlay', name = '', command = dcmd, 01851 l_active = True, l_render = False) 01852 self.params[type] = params 01853 self.propwin[type] = propwin 01854 01855 def OnZoomToMap(self, event): 01856 """!Set display extents to match selected raster (including 01857 NULLs) or vector map. 01858 """ 01859 self.MapWindow.ZoomToMap() 01860 01861 def OnZoomToRaster(self, event): 01862 """!Set display extents to match selected raster map (ignore NULLs) 01863 """ 01864 self.MapWindow.ZoomToMap(ignoreNulls = True) 01865 01866 def OnZoomToWind(self, event): 01867 """!Set display geometry to match computational region 01868 settings (set with g.region) 01869 """ 01870 self.MapWindow.ZoomToWind() 01871 01872 def OnZoomToDefault(self, event): 01873 """!Set display geometry to match default region settings 01874 """ 01875 self.MapWindow.ZoomToDefault() 01876 01877 def OnZoomToSaved(self, event): 01878 """!Set display geometry to match extents in 01879 saved region file 01880 """ 01881 self.MapWindow.ZoomToSaved() 01882 01883 def OnDisplayToWind(self, event): 01884 """!Set computational region (WIND file) to match display 01885 extents 01886 """ 01887 self.MapWindow.DisplayToWind() 01888 01889 def SaveDisplayRegion(self, event): 01890 """!Save display extents to named region file. 01891 """ 01892 self.MapWindow.SaveDisplayRegion() 01893 01894 def OnZoomMenu(self, event): 01895 """!Popup Zoom menu 01896 """ 01897 point = wx.GetMousePosition() 01898 zoommenu = wx.Menu() 01899 # Add items to the menu 01900 01901 zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)')) 01902 zoommenu.AppendItem(zoomwind) 01903 self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind) 01904 01905 zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region')) 01906 zoommenu.AppendItem(zoomdefault) 01907 self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault) 01908 01909 zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region')) 01910 zoommenu.AppendItem(zoomsaved) 01911 self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved) 01912 01913 savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display extent')) 01914 zoommenu.AppendItem(savewind) 01915 self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind) 01916 01917 savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region')) 01918 zoommenu.AppendItem(savezoom) 01919 self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom) 01920 01921 # Popup the menu. If an item is selected then its handler 01922 # will be called before PopupMenu returns. 01923 self.PopupMenu(zoommenu) 01924 zoommenu.Destroy() 01925 01926 def SetProperties(self, render = False, mode = 0, showCompExtent = False, 01927 constrainRes = False, projection = False): 01928 """!Set properies of map display window""" 01929 self.statusbarWin['render'].SetValue(render) 01930 self.statusbarWin['toggle'].SetSelection(mode) 01931 self.StatusbarUpdate() 01932 self.statusbarWin['region'].SetValue(showCompExtent) 01933 self.statusbarWin['resolution'].SetValue(constrainRes) 01934 self.statusbarWin['projection'].SetValue(projection) 01935 if showCompExtent: 01936 self.MapWindow.regionCoords = [] 01937 01938 def IsStandalone(self): 01939 """!Check if Map display is standalone""" 01940 if self._layerManager: 01941 return False 01942 01943 return True 01944 01945 def GetLayerManager(self): 01946 """!Get reference to Layer Manager 01947 01948 @return window reference 01949 @return None (if standalone) 01950 """ 01951 return self._layerManager 01952 01953 # end of class MapFrame 01954 01955 class MapApp(wx.App): 01956 def OnInit(self): 01957 wx.InitAllImageHandlers() 01958 if __name__ == "__main__": 01959 Map = render.Map() # instance of Map class to render GRASS display output to PPM file 01960 else: 01961 Map = None 01962 01963 self.mapFrm = MapFrame(parent = None, id = wx.ID_ANY, Map = Map, 01964 size = globalvar.MAP_WINDOW_SIZE) 01965 #self.SetTopWindow(Map) 01966 self.mapFrm.Show() 01967 01968 if __name__ == "__main__": 01969 # redraw map, if new command appears 01970 self.redraw = False 01971 status = Command(self, Map, cmdfilename) 01972 status.start() 01973 self.timer = wx.PyTimer(self.watcher) 01974 # check each 0.1s 01975 self.timer.Start(100) 01976 01977 return 1 01978 01979 def OnExit(self): 01980 if __name__ == "__main__": 01981 # stop the timer 01982 self.timer.Stop() 01983 # terminate thread (a bit ugly) 01984 os.system("""!echo "quit" >> %s""" % (cmdfilename)) 01985 01986 def watcher(self): 01987 """!Redraw, if new layer appears""" 01988 if self.redraw: 01989 self.mapFrm.OnDraw(None) 01990 self.redraw = False 01991 return 01992 # end of class MapApp 01993 01994 if __name__ == "__main__": 01995 01996 ###### SET command variable 01997 if len(sys.argv) != 3: 01998 print __doc__ 01999 sys.exit() 02000 02001 title = sys.argv[1] 02002 cmdfilename = sys.argv[2] 02003 02004 import gettext 02005 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True) 02006 02007 print >> sys.stderr, "\nStarting monitor <%s>...\n" % (title) 02008 02009 gm_map = MapApp(0) 02010 # set title 02011 gm_map.mapFrm.SetTitle(_("GRASS GIS Map Display: " + 02012 title + 02013 " - Location: " + grass.gisenv()["LOCATION_NAME"])) 02014 02015 gm_map.MainLoop() 02016 02017 if grass.gisenv().has_key("MONITOR"): 02018 os.system("d.mon sel=%s" % grass.gisenv()["MONITOR"]) 02019 02020 os.remove(cmdfilename) 02021 os.system("""!g.gisenv set="GRASS_PYCMDFILE" """) 02022 02023 print >> sys.stderr, "\nStoping monitor <%s>...\n" % (title) 02024 02025 sys.exit(0)