GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
mapdisp/frame.py
Go to the documentation of this file.
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']