GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mapdisp/frame.py
Go to the documentation of this file.
1 """!
2 @package mapdisp.frame
3 
4 @brief Map display with toolbar for various display management
5 functions, and additional toolbars (vector digitizer, 3d view).
6 
7 Can be used either from Layer Manager or as d.mon backend.
8 
9 Classes:
10  - mapdisp::MapFrame
11 
12 (C) 2006-2011 by the GRASS Development Team
13 
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
16 
17 @author Michael Barton
18 @author Jachym Cepicky
19 @author Martin Landa <landa.martin gmail.com>
20 @author Vaclav Petras <wenzeslaus gmail.com> (MapFrameBase)
21 @author Anna Kratochvilova <kratochanna gmail.com> (MapFrameBase)
22 """
23 
24 import os
25 import sys
26 import math
27 import copy
28 
29 from core import globalvar
30 import wx
31 import wx.aui
32 
33 sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons"))
34 sys.path.append(os.path.join(globalvar.ETCDIR, "python"))
35 
36 from core import globalvar
37 from core.render import EVT_UPDATE_PRGBAR
38 from vdigit.toolbars import VDigitToolbar
39 from mapdisp.toolbars import MapToolbar, NvizIcons
40 from mapdisp.gprint import PrintOptions
41 from core.gcmd import GError, GMessage, RunCommand
42 from dbmgr.dialogs import DisplayAttributesDialog
43 from core.utils import ListOfCatsToRange, GetLayerNameFromCmd
44 from gui_core.dialogs import GetImageHandlers, ImageSizeDialog, DecorationDialog, TextLayerDialog
45 from core.debug import Debug
46 from core.settings import UserSettings
47 from gui_core.mapdisp import MapFrameBase
48 from mapdisp.mapwindow import BufferedWindow
49 from modules.histogram import HistogramFrame
50 from wxplot.profile import ProfileFrame
51 
52 from mapdisp import statusbar as sb
53 
54 import grass.script as grass
55 
56 haveCtypes = False
57 
58 class MapFrame(MapFrameBase):
59  """!Main frame for map display window. Drawing takes place in
60  child double buffered drawing window.
61  """
62  def __init__(self, parent = None, title = _("GRASS GIS - Map display"),
63  toolbars = ["map"], tree = None, notebook = None, lmgr = None,
64  page = None, Map = None, auimgr = None, name = 'MapWindow', **kwargs):
65  """!Main map display window with toolbars, statusbar and
66  BufferedWindow (map canvas)
67 
68  @param toolbars array of activated toolbars, e.g. ['map', 'digit']
69  @param tree reference to layer tree
70  @param notebook control book ID in Layer Manager
71  @param lmgr Layer Manager
72  @param page notebook page with layer tree
73  @param Map instance of render.Map
74  @param auimgs AUI manager
75  @param name frame name
76  @param kwargs wx.Frame attributes
77  """
78  MapFrameBase.__init__(self, parent = parent, title = title, toolbars = toolbars,
79  Map = Map, auimgr = auimgr, name = name, **kwargs)
80 
81  self._layerManager = lmgr # Layer Manager object
82  self.tree = tree # Layer Manager layer tree object
83  self.page = page # Notebook page holding the layer tree
84  self.layerbook = notebook # Layer Manager layer tree notebook
85  #
86  # Add toolbars
87  #
88  for toolb in toolbars:
89  self.AddToolbar(toolb)
90 
91  #
92  # Add statusbar
93  #
94 
95  # items for choice
96  self.statusbarItems = [sb.SbCoordinates,
97  sb.SbRegionExtent,
98  sb.SbCompRegionExtent,
99  sb.SbShowRegion,
100  sb.SbAlignExtent,
101  sb.SbResolution,
102  sb.SbDisplayGeometry,
103  sb.SbMapScale,
104  sb.SbGoTo,
105  sb.SbProjection]
106 
107  self.statusbarItemsHiddenInNviz = (sb.SbAlignExtent,
108  sb.SbDisplayGeometry,
109  sb.SbShowRegion,
110  sb.SbResolution,
111  sb.SbMapScale)
112 
113  # create statusbar and its manager
114  statusbar = self.CreateStatusBar(number = 4, style = 0)
115  statusbar.SetStatusWidths([-5, -2, -1, -1])
116  self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
117 
118  # fill statusbar manager
119  self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
120  self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
121  self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
122 
123  self.statusbarManager.Update()
124 
125  #
126  # Init map display (buffered DC & set default cursor)
127  #
128  self.MapWindow2D = BufferedWindow(self, id = wx.ID_ANY,
129  Map = self.Map, tree = self.tree, lmgr = self._layerManager)
130  # default is 2D display mode
131  self.MapWindow = self.MapWindow2D
132  self.MapWindow.SetCursor(self.cursors["default"])
133  # used by vector digitizer
134  self.MapWindowVDigit = None
135  # used by Nviz (3D display mode)
136  self.MapWindow3D = None
137 
138  #
139  # initialize region values
140  #
141  self._initMap(map = self.Map)
142 
143  #
144  # Bind various events
145  #
146  self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
147  self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
148  self.Bind(EVT_UPDATE_PRGBAR, self.OnUpdateProgress)
149 
150  #
151  # Update fancy gui style
152  #
153  self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane().
154  Dockable(False).BestSize((-1,-1)).Name('2d').
155  CloseButton(False).DestroyOnClose(True).
156  Layer(0))
157  self._mgr.Update()
158 
159  #
160  # Init print module and classes
161  #
162  self.printopt = PrintOptions(self, self.MapWindow)
163 
164  #
165  # Init zoom history
166  #
167  self.MapWindow.ZoomHistory(self.Map.region['n'],
168  self.Map.region['s'],
169  self.Map.region['e'],
170  self.Map.region['w'])
171 
172  #
173  # Re-use dialogs
174  #
175  self.dialogs = {}
176  self.dialogs['attributes'] = None
177  self.dialogs['category'] = None
178  self.dialogs['barscale'] = None
179  self.dialogs['legend'] = None
180 
181  self.decorationDialog = None # decoration/overlays
182 
183  def GetMapWindow(self):
184  return self.MapWindow
185 
186  def _addToolbarVDigit(self):
187  """!Add vector digitizer toolbar
188  """
189  from vdigit.main import haveVDigit
190 
191  if not haveVDigit:
192  from vdigit import errorMsg
193  msg = _("Unable to start wxGUI vector digitizer.\nDo you want to start "
194  "TCL/TK digitizer (v.digit) instead?\n\n"
195  "Details: %s" % errorMsg)
196 
197  self.toolbars['map'].combo.SetValue(_("2D view"))
198  dlg = wx.MessageDialog(parent = self,
199  message = msg,
200  caption=_("Vector digitizer failed"),
201  style = wx.YES_NO | wx.CENTRE)
202  if dlg.ShowModal() == wx.ID_YES:
203  mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetName()
204  self._layerManager.goutput.RunCmd(['v.digit', 'map=%s' % mapName],
205  switchPage = False)
206  dlg.Destroy()
207 
208  self.toolbars['map'].combo.SetValue(_("2D view"))
209  return
210 
211  if self._layerManager:
212  log = self._layerManager.goutput
213  else:
214  log = None
215 
216  if not self.MapWindowVDigit:
217  from vdigit.mapwindow import VDigitWindow
218  self.MapWindowVDigit = VDigitWindow(self, id = wx.ID_ANY,
219  Map = self.Map, tree = self.tree,
220  lmgr = self._layerManager)
221  self.MapWindowVDigit.Show()
222  self._mgr.AddPane(self.MapWindowVDigit, wx.aui.AuiPaneInfo().CentrePane().
223  Dockable(False).BestSize((-1,-1)).Name('vdigit').
224  CloseButton(False).DestroyOnClose(True).
225  Layer(0))
226 
227  self.MapWindow = self.MapWindowVDigit
228 
229  if self._mgr.GetPane('2d').IsShown():
230  self._mgr.GetPane('2d').Hide()
231  elif self._mgr.GetPane('3d').IsShown():
232  self._mgr.GetPane('3d').Hide()
233  self._mgr.GetPane('vdigit').Show()
234  self.toolbars['vdigit'] = VDigitToolbar(parent = self, mapcontent = self.Map,
235  layerTree = self.tree,
236  log = log)
237  self.MapWindowVDigit.SetToolbar(self.toolbars['vdigit'])
238 
239  self._mgr.AddPane(self.toolbars['vdigit'],
240  wx.aui.AuiPaneInfo().
241  Name("vdigittoolbar").Caption(_("Vector Digitizer Toolbar")).
242  ToolbarPane().Top().Row(1).
243  LeftDockable(False).RightDockable(False).
244  BottomDockable(False).TopDockable(True).
245  CloseButton(False).Layer(2).
246  BestSize((self.toolbars['vdigit'].GetBestSize())))
247  # change mouse to draw digitized line
248  self.MapWindow.mouse['box'] = "point"
249  self.MapWindow.zoomtype = 0
250  self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SOLID)
251  self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SOLID)
252 
253  def AddNviz(self):
254  """!Add 3D view mode window
255  """
256  from nviz.main import haveNviz, GLWindow
257 
258  # check for GLCanvas and OpenGL
259  if not haveNviz:
260  self.toolbars['map'].combo.SetValue(_("2D view"))
261  GError(parent = self,
262  message = _("Unable to switch to 3D display mode.\nThe Nviz python extension "
263  "was not found or loaded properly.\n"
264  "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg))
265  return
266 
267  # disable 3D mode for other displays
268  for page in range(0, self._layerManager.GetLayerNotebook().GetPageCount()):
269  mapdisp = self._layerManager.GetLayerNotebook().GetPage(page).maptree.GetMapDisplay()
270  if self._layerManager.GetLayerNotebook().GetPage(page) != self._layerManager.currentPage:
271  if '3D' in mapdisp.toolbars['map'].combo.GetString(1):
272  mapdisp.toolbars['map'].combo.Delete(1)
273  self.toolbars['map'].Enable2D(False)
274  # add rotate tool to map toolbar
275  self.toolbars['map'].InsertTool((('rotate', NvizIcons['rotate'],
276  self.OnRotate, wx.ITEM_CHECK, 7),)) # 7 is position
277  self.toolbars['map'].InsertTool((('flyThrough', NvizIcons['flyThrough'],
278  self.OnFlyThrough, wx.ITEM_CHECK, 8),))
279  self.toolbars['map'].ChangeToolsDesc(mode2d = False)
280  # update status bar
281 
282  self.statusbarManager.HideStatusbarChoiceItemsByClass(self.statusbarItemsHiddenInNviz)
283  self.statusbarManager.SetMode(0)
284 
285  # erase map window
286  self.MapWindow.EraseMap()
287 
288  self._layerManager.goutput.WriteCmdLog(_("Starting 3D view mode..."),
289  switchPage = False)
290  self.SetStatusText(_("Please wait, loading data..."), 0)
291 
292  # create GL window
293  if not self.MapWindow3D:
294  self.MapWindow3D = GLWindow(self, id = wx.ID_ANY,
295  Map = self.Map, tree = self.tree, lmgr = self._layerManager)
296  self.MapWindow = self.MapWindow3D
297  self.MapWindow.SetCursor(self.cursors["default"])
298 
299  # add Nviz notebookpage
300  self._layerManager.AddNvizTools()
301 
302  # switch from MapWindow to MapWindowGL
303  self._mgr.GetPane('2d').Hide()
304  self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane().
305  Dockable(False).BestSize((-1,-1)).Name('3d').
306  CloseButton(False).DestroyOnClose(True).
307  Layer(0))
308 
309  self.MapWindow3D.Show()
310  self.MapWindow3D.ResetViewHistory()
311  self.MapWindow3D.UpdateView(None)
312  else:
313  self.MapWindow = self.MapWindow3D
314  os.environ['GRASS_REGION'] = self.Map.SetRegion(windres = True)
315  self.MapWindow3D.GetDisplay().Init()
316  del os.environ['GRASS_REGION']
317 
318  # switch from MapWindow to MapWindowGL
319  self._mgr.GetPane('2d').Hide()
320  self._mgr.GetPane('3d').Show()
321 
322  # add Nviz notebookpage
323  self._layerManager.AddNvizTools()
324  self.MapWindow3D.ResetViewHistory()
325  for page in ('view', 'light', 'fringe', 'constant', 'cplane', 'animation'):
326  self._layerManager.nviz.UpdatePage(page)
327 
328  self.MapWindow3D.overlays = self.MapWindow2D.overlays
329  self.MapWindow3D.textdict = self.MapWindow2D.textdict
330  # update overlays needs to be called after because getClientSize
331  # is called during update and it must give reasonable values
332  wx.CallAfter(self.MapWindow3D.UpdateOverlays)
333 
334  self.SetStatusText("", 0)
335  self._mgr.Update()
336 
337  def RemoveNviz(self):
338  """!Restore 2D view"""
339  try:
340  self.toolbars['map'].RemoveTool(self.toolbars['map'].rotate)
341  self.toolbars['map'].RemoveTool(self.toolbars['map'].flyThrough)
342  except AttributeError:
343  pass
344 
345  # update status bar
346  self.statusbarManager.ShowStatusbarChoiceItemsByClass(self.statusbarItemsHiddenInNviz)
347  self.statusbarManager.SetMode(UserSettings.Get(group = 'display',
348  key = 'statusbarMode',
349  subkey = 'selection'))
350  self.SetStatusText(_("Please wait, unloading data..."), 0)
351  self._layerManager.goutput.WriteCmdLog(_("Switching back to 2D view mode..."),
352  switchPage = False)
353  if self.MapWindow3D:
354  self.MapWindow3D.OnClose(event = None)
355  # switch from MapWindowGL to MapWindow
356  self._mgr.GetPane('2d').Show()
357  self._mgr.GetPane('3d').Hide()
358 
359  self.MapWindow = self.MapWindow2D
360  # remove nviz notebook page
361  self._layerManager.RemoveNvizTools()
362  try:
363  self.MapWindow2D.overlays = self.MapWindow3D.overlays
364  self.MapWindow2D.textdict = self.MapWindow3D.textdict
365  except AttributeError:
366  pass
367  self.MapWindow.UpdateMap()
368  self._mgr.Update()
369 
370  def AddToolbar(self, name):
371  """!Add defined toolbar to the window
372 
373  Currently known toolbars are:
374  - 'map' - basic map toolbar
375  - 'vdigit' - vector digitizer
376  - 'gcpdisp' - GCP Manager Display
377  """
378  # default toolbar
379  if name == "map":
380  self.toolbars['map'] = MapToolbar(self, self.Map)
381 
382  self._mgr.AddPane(self.toolbars['map'],
383  wx.aui.AuiPaneInfo().
384  Name("maptoolbar").Caption(_("Map Toolbar")).
385  ToolbarPane().Top().Name('mapToolbar').
386  LeftDockable(False).RightDockable(False).
387  BottomDockable(False).TopDockable(True).
388  CloseButton(False).Layer(2).
389  BestSize((self.toolbars['map'].GetBestSize())))
390 
391  # vector digitizer
392  elif name == "vdigit":
393  self._addToolbarVDigit()
394 
395  self._mgr.Update()
396 
397  def RemoveToolbar (self, name):
398  """!Removes defined toolbar from the window
399 
400  @todo Only hide, activate by calling AddToolbar()
401  """
402  # cannot hide main toolbar
403  if name == "map":
404  return
405 
406  self._mgr.DetachPane(self.toolbars[name])
407  self.toolbars[name].Destroy()
408  self.toolbars.pop(name)
409 
410  if name == 'vdigit':
411  self._mgr.GetPane('vdigit').Hide()
412  self._mgr.GetPane('2d').Show()
413  self.MapWindow = self.MapWindow2D
414 
415  self.toolbars['map'].combo.SetValue(_("2D view"))
416  self.toolbars['map'].Enable2D(True)
417 
418  self._mgr.Update()
419 
420  def IsPaneShown(self, name):
421  """!Check if pane (toolbar, mapWindow ...) of given name is currently shown"""
422  if self._mgr.GetPane(name).IsOk():
423  return self._mgr.GetPane(name).IsShown()
424  return False
425 
426  def OnUpdateProgress(self, event):
427  """!Update progress bar info
428  """
429  self.GetProgressBar().SetValue(event.value)
430 
431  event.Skip()
432 
433  def OnFocus(self, event):
434  """!Change choicebook page to match display.
435  """
436  # change bookcontrol page to page associated with display
437  if self.page:
438  pgnum = self.layerbook.GetPageIndex(self.page)
439  if pgnum > -1:
440  self.layerbook.SetSelection(pgnum)
441  self._layerManager.currentPage = self.layerbook.GetCurrentPage()
442 
443  event.Skip()
444 
445  def RemoveQueryLayer(self):
446  """!Removes temporary map layers (queries)"""
447  qlayer = self.GetMap().GetListOfLayers(l_name = globalvar.QUERYLAYER)
448  for layer in qlayer:
449  self.GetMap().DeleteLayer(layer)
450 
451  def OnRender(self, event):
452  """!Re-render map composition (each map layer)
453  """
454  self.RemoveQueryLayer()
455 
456  # delete tmp lines
457  if self.MapWindow.mouse["use"] in ("measure",
458  "profile"):
459  self.MapWindow.polycoords = []
460  self.MapWindow.ClearLines()
461 
462  # deselect features in vdigit
463  if self.GetToolbar('vdigit'):
464  if self.MapWindow.digit:
465  self.MapWindow.digit.GetDisplay().SetSelected([])
466  self.MapWindow.UpdateMap(render = True, renderVector = True)
467  else:
468  self.MapWindow.UpdateMap(render = True)
469 
470  # update statusbar
471  self.StatusbarUpdate()
472 
473  def OnPointer(self, event):
474  """!Pointer button clicked
475  """
476  if self.GetMapToolbar():
477  if event:
478  self.toolbars['map'].OnTool(event)
479  self.toolbars['map'].action['desc'] = ''
480 
481  self.MapWindow.mouse['use'] = "pointer"
482  self.MapWindow.mouse['box'] = "point"
483 
484  # change the cursor
485  if self.GetToolbar('vdigit'):
486  # digitization tool activated
487  self.MapWindow.SetCursor(self.cursors["cross"])
488 
489  # reset mouse['box'] if needed
490  if self.toolbars['vdigit'].GetAction() in ['addLine']:
491  if self.toolbars['vdigit'].GetAction('type') in ['point', 'centroid']:
492  self.MapWindow.mouse['box'] = 'point'
493  else: # line, boundary
494  self.MapWindow.mouse['box'] = 'line'
495  elif self.toolbars['vdigit'].GetAction() in ['addVertex', 'removeVertex', 'splitLine',
496  'editLine', 'displayCats', 'queryMap',
497  'copyCats']:
498  self.MapWindow.mouse['box'] = 'point'
499  else: # moveLine, deleteLine
500  self.MapWindow.mouse['box'] = 'box'
501 
502  else:
503  self.MapWindow.SetCursor(self.cursors["default"])
504 
505  def OnRotate(self, event):
506  """!Rotate 3D view
507  """
508  if self.GetMapToolbar():
509  self.toolbars['map'].OnTool(event)
510  self.toolbars['map'].action['desc'] = ''
511 
512  self.MapWindow.mouse['use'] = "rotate"
513 
514  # change the cursor
515  self.MapWindow.SetCursor(self.cursors["hand"])
516 
517  def OnFlyThrough(self, event):
518  """!Fly-through mode
519  """
520  if self.toolbars['map']:
521  self.toolbars['map'].OnTool(event)
522  self.toolbars['map'].action['desc'] = ''
523 
524  self.MapWindow.mouse['use'] = "fly"
525 
526  # change the cursor
527  self.MapWindow.SetCursor(self.cursors["hand"])
528  self.MapWindow.SetFocus()
529 
530  def OnZoomRegion(self, event):
531  """
532  Zoom to region
533  """
534  self.Map.getRegion()
535  self.Map.getResolution()
536  self.UpdateMap()
537  # event.Skip()
538 
539  def OnAlignRegion(self, event):
540  """
541  Align region
542  """
543  if not self.Map.alignRegion:
544  self.Map.alignRegion = True
545  else:
546  self.Map.alignRegion = False
547  # event.Skip()
548 
549  def SaveToFile(self, event):
550  """!Save map to image
551  """
552  if self.IsPaneShown('3d'):
553  filetype = "TIF file (*.tif)|*.tif|PPM file (*.ppm)|*.ppm"
554  ltype = [{ 'ext' : 'tif', 'type' : 'tif' },
555  { 'ext' : 'ppm', 'type' : 'ppm' }]
556  else:
557  img = self.MapWindow.img
558  if not img:
559  GMessage(parent = self,
560  message = _("Nothing to render (empty map). Operation canceled."))
561  return
562  filetype, ltype = GetImageHandlers(img)
563 
564  # get size
565  dlg = ImageSizeDialog(self)
566  dlg.CentreOnParent()
567  if dlg.ShowModal() != wx.ID_OK:
568  dlg.Destroy()
569  return
570  width, height = dlg.GetValues()
571  dlg.Destroy()
572 
573  # get filename
574  dlg = wx.FileDialog(parent = self,
575  message = _("Choose a file name to save the image "
576  "(no need to add extension)"),
577  wildcard = filetype,
578  style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
579 
580  if dlg.ShowModal() == wx.ID_OK:
581  path = dlg.GetPath()
582  if not path:
583  dlg.Destroy()
584  return
585 
586  base, ext = os.path.splitext(path)
587  fileType = ltype[dlg.GetFilterIndex()]['type']
588  extType = ltype[dlg.GetFilterIndex()]['ext']
589  if ext != extType:
590  path = base + '.' + extType
591 
592  self.MapWindow.SaveToFile(path, fileType,
593  width, height)
594 
595  dlg.Destroy()
596 
597  def PrintMenu(self, event):
598  """
599  Print options and output menu for map display
600  """
601  point = wx.GetMousePosition()
602  printmenu = wx.Menu()
603  # Add items to the menu
604  setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup'))
605  printmenu.AppendItem(setup)
606  self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
607 
608  preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview'))
609  printmenu.AppendItem(preview)
610  self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
611 
612  doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display'))
613  printmenu.AppendItem(doprint)
614  self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
615 
616  # Popup the menu. If an item is selected then its handler
617  # will be called before PopupMenu returns.
618  self.PopupMenu(printmenu)
619  printmenu.Destroy()
620 
621  def OnCloseWindow(self, event):
622  """!Window closed.
623  Also close associated layer tree page
624  """
625  pgnum = None
626  self.Map.Clean()
627 
628  # close edited map and 3D tools properly
629  if self.GetToolbar('vdigit'):
630  maplayer = self.toolbars['vdigit'].GetLayer()
631  if maplayer:
632  self.toolbars['vdigit'].OnExit()
633  if self.IsPaneShown('3d'):
634  self.RemoveNviz()
635 
636  if not self._layerManager:
637  self.Destroy()
638  elif self.page:
639  pgnum = self.layerbook.GetPageIndex(self.page)
640  if pgnum > -1:
641  self.layerbook.DeletePage(pgnum)
642 
643  def Query(self, x, y, layers):
644  """!Query selected layers.
645 
646  Calls QueryMap in case of raster or more vectors,
647  or QueryVector in case of one vector with db connection.
648 
649  @param x,y coordinates
650  @param layers selected tree item layers
651  """
652  num = 0
653  filteredLayers = []
654  for layer in layers:
655  ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
656  if ltype in ('raster', 'rgb', 'his',
657  'vector', 'thememap', 'themechart'):
658  filteredLayers.append(layer)
659 
660  if not filteredLayers:
661  GMessage(parent = self,
662  message = _('No raster or vector map layer selected for querying.'))
663  return
664 
665  layers = filteredLayers
666  # set query snap distance for v.what at map unit equivalent of 10 pixels
667  qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width)
668  east, north = self.MapWindow.Pixel2Cell((x, y))
669 
670  posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset,
671  y + self.MapWindow.dialogOffset))
672 
673  isRaster = False
674  nVectors = 0
675  isDbConnection = False
676  for l in layers:
677  maplayer = self.tree.GetPyData(l)[0]['maplayer']
678  if maplayer.GetType() == 'raster':
679  isRaster = True
680  break
681  if maplayer.GetType() == 'vector':
682  nVectors += 1
683  isDbConnection = grass.vector_db(maplayer.GetName())
684 
685  if not self.IsPaneShown('3d'):
686  if isRaster or nVectors > 1 or not isDbConnection:
687  self.QueryMap(east, north, qdist, layers)
688  else:
689  self.QueryVector(east, north, qdist, posWindow, layers[0])
690  else:
691  if isRaster:
692  self.MapWindow.QuerySurface(x, y)
693  if nVectors > 1 or not isDbConnection:
694  self.QueryMap(east, north, qdist, layers)
695  elif nVectors == 1:
696  self.QueryVector(east, north, qdist, posWindow, layers[0])
697 
698  def QueryMap(self, east, north, qdist, layers):
699  """!Query raster or vector map layers by r/v.what
700 
701  @param east,north coordinates
702  @param qdist query distance
703  @param layers selected tree items
704  """
705  rast = list()
706  vect = list()
707  rcmd = ['r.what', '--v']
708  vcmd = ['v.what', '--v']
709 
710  for layer in layers:
711  ltype = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
712  dcmd = self.tree.GetPyData(layer)[0]['cmd']
713  name, found = GetLayerNameFromCmd(dcmd)
714 
715  if not found:
716  continue
717  if ltype == 'raster':
718  rast.append(name)
719  elif ltype in ('rgb', 'his'):
720  for iname in name.split('\n'):
721  rast.append(iname)
722  elif ltype in ('vector', 'thememap', 'themechart'):
723  vect.append(name)
724 
725  # use display region settings instead of computation region settings
726  self.tmpreg = os.getenv("GRASS_REGION")
727  os.environ["GRASS_REGION"] = self.Map.SetRegion(windres = False)
728 
729  # build query commands for any selected rasters and vectors
730  if rast:
731  rcmd.append('-f')
732  rcmd.append('-n')
733  rcmd.append('input=%s' % ','.join(rast))
734  rcmd.append('east_north=%f,%f' % (float(east), float(north)))
735 
736  if vect:
737  # check for vector maps open to be edited
738  digitToolbar = self.GetToolbar('vdigit')
739  if digitToolbar:
740  lmap = digitToolbar.GetLayer().GetName()
741  for name in vect:
742  if lmap == name:
743  self._layerManager.goutput.WriteWarning(_("Vector map <%s> "
744  "opened for editing - skipped.") % map)
745  vect.remove(name)
746 
747  if len(vect) < 1:
748  self._layerManager.goutput.WriteCmdLog(_("Nothing to query."))
749  return
750 
751  vcmd.append('-a')
752  vcmd.append('map=%s' % ','.join(vect))
753  vcmd.append('east_north=%f,%f' % (float(east), float(north)))
754  vcmd.append('distance=%f' % float(qdist))
755 
756  Debug.msg(1, "QueryMap(): raster=%s vector=%s" % (','.join(rast),
757  ','.join(vect)))
758  # parse query command(s)
759 
760  if rast and not self.IsPaneShown('3d'):
761  self._layerManager.goutput.RunCmd(rcmd,
762  compReg = False,
763  onDone = self._QueryMapDone)
764  if vect:
765  self._layerManager.goutput.RunCmd(vcmd,
766  onDone = self._QueryMapDone)
767 
768  def _QueryMapDone(self, cmd, returncode):
769  """!Restore settings after querying (restore GRASS_REGION)
770 
771  @param returncode command return code
772  """
773  if hasattr(self, "tmpreg"):
774  if self.tmpreg:
775  os.environ["GRASS_REGION"] = self.tmpreg
776  elif 'GRASS_REGION' in os.environ:
777  del os.environ["GRASS_REGION"]
778  elif 'GRASS_REGION' in os.environ:
779  del os.environ["GRASS_REGION"]
780 
781  if hasattr(self, "tmpreg"):
782  del self.tmpreg
783 
784  def QueryVector(self, east, north, qdist, posWindow, layer):
785  """!Query vector map layer features
786 
787  Attribute data of selected vector object are displayed in GUI dialog.
788  Data can be modified (On Submit)
789  """
790  mapName = self.tree.GetPyData(layer)[0]['maplayer'].name
791 
792  if self.tree.GetPyData(layer)[0]['maplayer'].GetMapset() != \
793  grass.gisenv()['MAPSET']:
794  mode = 'display'
795  else:
796  mode = 'update'
797 
798  if self.dialogs['attributes'] is None:
799  dlg = DisplayAttributesDialog(parent = self.MapWindow,
800  map = mapName,
801  query = ((east, north), qdist),
802  pos = posWindow,
803  action = mode)
804  self.dialogs['attributes'] = dlg
805 
806  else:
807  # selection changed?
808  if not self.dialogs['attributes'].mapDBInfo or \
809  self.dialogs['attributes'].mapDBInfo.map != mapName:
810  self.dialogs['attributes'].UpdateDialog(map = mapName, query = ((east, north), qdist),
811  action = mode)
812  else:
813  self.dialogs['attributes'].UpdateDialog(query = ((east, north), qdist),
814  action = mode)
815  if not self.dialogs['attributes'].IsFound():
816  self._layerManager.goutput.WriteLog(_('Nothing found.'))
817 
818  cats = self.dialogs['attributes'].GetCats()
819 
820  qlayer = None
821  if not self.IsPaneShown('3d') and self.IsAutoRendered():
822  try:
823  qlayer = self.Map.GetListOfLayers(l_name = globalvar.QUERYLAYER)[0]
824  except IndexError:
825  pass
826 
827  if self.dialogs['attributes'].mapDBInfo and cats:
828  if not self.IsPaneShown('3d') and self.IsAutoRendered():
829  # highlight feature & re-draw map
830  if qlayer:
831  qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats,
832  useId = False,
833  addLayer = False))
834  else:
835  qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId = False)
836 
837  # set opacity based on queried layer
838  opacity = self.tree.GetPyData(layer)[0]['maplayer'].GetOpacity(float = True)
839  qlayer.SetOpacity(opacity)
840 
841  self.MapWindow.UpdateMap(render = False, renderVector = False)
842  if not self.dialogs['attributes'].IsShown():
843  self.dialogs['attributes'].Show()
844  else:
845  if qlayer:
846  self.Map.DeleteLayer(qlayer)
847  self.MapWindow.UpdateMap(render = False, renderVector = False)
848  if self.dialogs['attributes'].IsShown():
849  self.dialogs['attributes'].Hide()
850 
851  def OnQuery(self, event):
852  """!Query tools menu"""
853  if self.GetMapToolbar():
854  self.toolbars['map'].OnTool(event)
855  action = self.toolbars['map'].GetAction()
856 
857  self.toolbars['map'].action['desc'] = 'queryMap'
858  self.MapWindow.mouse['use'] = "query"
859 
860  if not self.IsStandalone():
861  # switch to output console to show query results
862  self._layerManager.notebook.SetSelectionByName('output')
863 
864  self.MapWindow.mouse['box'] = "point"
865  self.MapWindow.zoomtype = 0
866 
867  # change the cursor
868  self.MapWindow.SetCursor(self.cursors["cross"])
869 
870  def AddTmpVectorMapLayer(self, name, cats, useId = False, addLayer = True):
871  """!Add temporal vector map layer to map composition
872 
873  @param name name of map layer
874  @param useId use feature id instead of category
875  """
876  # color settings from ATM
877  color = UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'color')
878  colorStr = str(color[0]) + ":" + \
879  str(color[1]) + ":" + \
880  str(color[2])
881 
882  # icon used in vector display and its size
883  icon = ''
884  size = 0
885  vparam = self.tree.GetPyData(self.tree.layer_selected)[0]['cmd']
886  for p in vparam:
887  if '=' in p:
888  parg,pval = p.split('=', 1)
889  if parg == 'icon': icon = pval
890  elif parg == 'size': size = float(pval)
891 
892  pattern = ["d.vect",
893  "map=%s" % name,
894  "color=%s" % colorStr,
895  "fcolor=%s" % colorStr,
896  "width=%d" % UserSettings.Get(group = 'atm', key = 'highlight', subkey = 'width')]
897  if icon != '':
898  pattern.append('icon=%s' % icon)
899  if size > 0:
900  pattern.append('size=%i' % size)
901 
902  if useId:
903  cmd = pattern
904  cmd.append('-i')
905  cmd.append('cats=%s' % str(cats))
906  else:
907  cmd = []
908  for layer in cats.keys():
909  cmd.append(copy.copy(pattern))
910  lcats = cats[layer]
911  cmd[-1].append("layer=%d" % layer)
912  cmd[-1].append("cats=%s" % ListOfCatsToRange(lcats))
913 
914  if addLayer:
915  if useId:
916  return self.Map.AddLayer(type = 'vector', name = globalvar.QUERYLAYER, command = cmd,
917  l_active = True, l_hidden = True, l_opacity = 1.0)
918  else:
919  return self.Map.AddLayer(type = 'command', name = globalvar.QUERYLAYER, command = cmd,
920  l_active = True, l_hidden = True, l_opacity = 1.0)
921  else:
922  return cmd
923 
924  def OnMeasure(self, event):
925  """!Init measurement routine that calculates map distance
926  along transect drawn on map display
927  """
928  self.totaldist = 0.0 # total measured distance
929 
930  # switch Layer Manager to output console to show measure results
931  self._layerManager.notebook.SetSelectionByName('output')
932 
933  # change mouse to draw line for measurement
934  self.MapWindow.mouse['use'] = "measure"
935  self.MapWindow.mouse['box'] = "line"
936  self.MapWindow.zoomtype = 0
937  self.MapWindow.pen = wx.Pen(colour = 'red', width = 2, style = wx.SHORT_DASH)
938  self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SHORT_DASH)
939 
940  # change the cursor
941  self.MapWindow.SetCursor(self.cursors["pencil"])
942 
943  # initiating output
944  self._layerManager.goutput.WriteWarning(_('Click and drag with left mouse button '
945  'to measure.\n'
946  'Double click with left button to clear.'))
947 
948  if self.Map.projinfo['proj'] != 'xy':
949  units = self.Map.projinfo['units']
950  self._layerManager.goutput.WriteCmdLog(_('Measuring distance') + ' ('
951  + units + '):')
952  else:
953  self._layerManager.goutput.WriteCmdLog(_('Measuring distance:'))
954 
955  if self.Map.projinfo['proj'] == 'll':
956  try:
957  import grass.lib.gis as gislib
958  global haveCtypes
959  haveCtypes = True
960 
961  gislib.G_begin_distance_calculations()
962  except ImportError, e:
963  self._layerManager.goutput.WriteWarning(_('Geodesic distance is not yet '
964  'supported by this tool.\n'
965  'Reason: %s' % e))
966 
967  def MeasureDist(self, beginpt, endpt):
968  """!Calculate map distance from screen distance
969  and print to output window
970  """
971  self._layerManager.notebook.SetSelectionByName('output')
972 
973  dist, (north, east) = self.MapWindow.Distance(beginpt, endpt)
974 
975  dist = round(dist, 3)
976  d, dunits = self.FormatDist(dist)
977 
978  self.totaldist += dist
979  td, tdunits = self.FormatDist(self.totaldist)
980 
981  strdist = str(d)
982  strtotdist = str(td)
983 
984  if self.Map.projinfo['proj'] == 'xy' or 'degree' not in self.Map.projinfo['unit']:
985  angle = int(math.degrees(math.atan2(north,east)) + 0.5)
986  # uncomment below (or flip order of atan2(y,x) above) to use
987  # the mathematical theta convention (CCW from +x axis)
988  #angle = 90 - angle
989  if angle < 0:
990  angle = 360 + angle
991 
992  mstring = '%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \
993  % (_('segment'), strdist, dunits,
994  _('total distance'), strtotdist, tdunits,
995  _('bearing'), angle, _('degrees (clockwise from grid-north)'),
996  '-' * 60)
997  else:
998  mstring = '%s = %s %s\n%s = %s %s\n%s' \
999  % (_('segment'), strdist, dunits,
1000  _('total distance'), strtotdist, tdunits,
1001  '-' * 60)
1002 
1003  self._layerManager.goutput.WriteLog(mstring)
1004 
1005  return dist
1006 
1007  def OnProfile(self, event):
1008  """!Launch profile tool
1009  """
1010  raster = []
1011  if self.tree.layer_selected and \
1012  self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
1013  raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
1014 
1015  win = ProfileFrame(parent = self, rasterList = raster)
1016 
1017  win.CentreOnParent()
1018  win.Show()
1019  # Open raster select dialog to make sure that a raster (and
1020  # the desired raster) is selected to be profiled
1021  win.OnSelectRaster(None)
1022 
1023  def FormatDist(self, dist):
1024  """!Format length numbers and units in a nice way,
1025  as a function of length. From code by Hamish Bowman
1026  Grass Development Team 2006"""
1027 
1028  mapunits = self.Map.projinfo['units']
1029  if mapunits == 'metres':
1030  mapunits = 'meters'
1031  outunits = mapunits
1032  dist = float(dist)
1033  divisor = 1.0
1034 
1035  # figure out which units to use
1036  if mapunits == 'meters':
1037  if dist > 2500.0:
1038  outunits = 'km'
1039  divisor = 1000.0
1040  else: outunits = 'm'
1041  elif mapunits == 'feet':
1042  # nano-bug: we match any "feet", but US Survey feet is really
1043  # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
1044  # miles the tick markers are rounded to the nearest 10th of a
1045  # mile (528'), the difference in foot flavours is ignored.
1046  if dist > 5280.0:
1047  outunits = 'miles'
1048  divisor = 5280.0
1049  else:
1050  outunits = 'ft'
1051  elif 'degree' in mapunits and \
1052  not haveCtypes:
1053  if dist < 1:
1054  outunits = 'min'
1055  divisor = (1/60.0)
1056  else:
1057  outunits = 'deg'
1058  else:
1059  outunits = 'meters'
1060 
1061  # format numbers in a nice way
1062  if (dist/divisor) >= 2500.0:
1063  outdist = round(dist/divisor)
1064  elif (dist/divisor) >= 1000.0:
1065  outdist = round(dist/divisor,1)
1066  elif (dist/divisor) > 0.0:
1067  outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor))))
1068  else:
1069  outdist = float(dist/divisor)
1070 
1071  return (outdist, outunits)
1072 
1073  def OnHistogram(self, event):
1074  """!Init histogram display canvas and tools
1075  """
1076  win = HistogramFrame(self)
1077 
1078  win.CentreOnParent()
1079  win.Show()
1080  win.Refresh()
1081  win.Update()
1082 
1083  def OnAddBarscale(self, event):
1084  """!Handler for scale/arrow map decoration menu selection.
1085  """
1086  if self.dialogs['barscale']:
1087  return
1088 
1089  id = 0 # unique index for overlay layer
1090 
1091  # If location is latlon, only display north arrow (scale won't work)
1092  # proj = self.Map.projinfo['proj']
1093  # if proj == 'll':
1094  # barcmd = 'd.barscale -n'
1095  # else:
1096  # barcmd = 'd.barscale'
1097 
1098  # decoration overlay control dialog
1099  self.dialogs['barscale'] = \
1100  DecorationDialog(parent = self, title = _('Scale and North arrow'),
1101  size = (350, 200),
1102  style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
1103  cmd = ['d.barscale', 'at=0,5'],
1104  ovlId = id,
1105  name = 'barscale',
1106  checktxt = _("Show/hide scale and North arrow"),
1107  ctrltxt = _("scale object"))
1108 
1109  self.dialogs['barscale'].CentreOnParent()
1110  ### dialog cannot be show as modal - in the result d.barscale is not selectable
1111  ### self.dialogs['barscale'].ShowModal()
1112  self.dialogs['barscale'].Show()
1113  self.MapWindow.mouse['use'] = 'pointer'
1114 
1115  def OnAddLegend(self, event):
1116  """!Handler for legend map decoration menu selection.
1117  """
1118  if self.dialogs['legend']:
1119  return
1120 
1121  id = 1 # index for overlay layer in render
1122 
1123  cmd = ['d.legend', 'at=5,50,2,5']
1124  if self.tree.layer_selected and \
1125  self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
1126  cmd.append('map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
1127 
1128  # Decoration overlay control dialog
1129  self.dialogs['legend'] = \
1130  DecorationDialog(parent = self, title = ('Legend'),
1131  size = (350, 200),
1132  style = wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
1133  cmd = cmd,
1134  ovlId = id,
1135  name = 'legend',
1136  checktxt = _("Show/hide legend"),
1137  ctrltxt = _("legend object"))
1138 
1139  self.dialogs['legend'].CentreOnParent()
1140  ### dialog cannot be show as modal - in the result d.legend is not selectable
1141  ### self.dialogs['legend'].ShowModal()
1142  self.dialogs['legend'].Show()
1143  self.MapWindow.mouse['use'] = 'pointer'
1144 
1145  def OnAddText(self, event):
1146  """!Handler for text decoration menu selection.
1147  """
1148  if self.MapWindow.dragid > -1:
1149  id = self.MapWindow.dragid
1150  self.MapWindow.dragid = -1
1151  else:
1152  # index for overlay layer in render
1153  if len(self.MapWindow.textdict.keys()) > 0:
1154  id = max(self.MapWindow.textdict.keys()) + 1
1155  else:
1156  id = 101
1157 
1158  self.dialogs['text'] = TextLayerDialog(parent = self, ovlId = id,
1159  title = _('Add text layer'),
1160  size = (400, 200))
1161  self.dialogs['text'].CenterOnParent()
1162 
1163  # If OK button pressed in decoration control dialog
1164  if self.dialogs['text'].ShowModal() == wx.ID_OK:
1165  text = self.dialogs['text'].GetValues()['text']
1166  active = self.dialogs['text'].GetValues()['active']
1167 
1168  # delete object if it has no text or is not active
1169  if text == '' or active == False:
1170  try:
1171  self.MapWindow2D.pdc.ClearId(id)
1172  self.MapWindow2D.pdc.RemoveId(id)
1173  del self.MapWindow.textdict[id]
1174  if self.IsPaneShown('3d'):
1175  self.MapWindow3D.UpdateOverlays()
1176  self.MapWindow.UpdateMap()
1177  else:
1178  self.MapWindow2D.UpdateMap(render = False, renderVector = False)
1179  except:
1180  pass
1181  return
1182 
1183 
1184  self.MapWindow.textdict[id] = self.dialogs['text'].GetValues()
1185 
1186  if self.IsPaneShown('3d'):
1187  self.MapWindow3D.UpdateOverlays()
1188  self.MapWindow3D.UpdateMap()
1189  else:
1190  self.MapWindow2D.pdc.ClearId(id)
1191  self.MapWindow2D.pdc.SetId(id)
1192  self.MapWindow2D.UpdateMap(render = False, renderVector = False)
1193 
1194  self.MapWindow.mouse['use'] = 'pointer'
1195 
1196  def OnAddArrow(self, event):
1197  """!Handler for north arrow menu selection.
1198  Opens Appearance page of nviz notebook.
1199  """
1200 
1201  self._layerManager.nviz.SetPage('decoration')
1202  self.MapWindow3D.SetDrawArrow((70, 70))
1203 
1204  def GetOptData(self, dcmd, type, params, propwin):
1205  """!Callback method for decoration overlay command generated by
1206  dialog created in menuform.py
1207  """
1208  # Reset comand and rendering options in render.Map. Always render decoration.
1209  # Showing/hiding handled by PseudoDC
1210  self.Map.ChangeOverlay(ovltype = type, type = 'overlay', name = '', command = dcmd,
1211  l_active = True, l_render = False)
1212  self.params[type] = params
1213  self.propwin[type] = propwin
1214 
1215  def OnZoomToMap(self, event):
1216  """!Set display extents to match selected raster (including
1217  NULLs) or vector map.
1218  """
1219  self.MapWindow.ZoomToMap()
1220 
1221  def OnZoomToRaster(self, event):
1222  """!Set display extents to match selected raster map (ignore NULLs)
1223  """
1224  self.MapWindow.ZoomToMap(ignoreNulls = True)
1225 
1226  def OnZoomToSaved(self, event):
1227  """!Set display geometry to match extents in
1228  saved region file
1229  """
1230  self.MapWindow.ZoomToSaved()
1231 
1232  def OnDisplayToWind(self, event):
1233  """!Set computational region (WIND file) to match display
1234  extents
1235  """
1236  self.MapWindow.DisplayToWind()
1237 
1238  def OnSaveDisplayRegion(self, event):
1239  """!Save display extents to named region file.
1240  """
1241  self.MapWindow.SaveRegion(display = True)
1242 
1243  def OnSaveWindRegion(self, event):
1244  """!Save computational region to named region file.
1245  """
1246  self.MapWindow.SaveRegion(display = False)
1247 
1248  def OnZoomMenu(self, event):
1249  """!Popup Zoom menu
1250  """
1251  point = wx.GetMousePosition()
1252  zoommenu = wx.Menu()
1253 
1254  for label, handler in ((_('Zoom to computational region'), self.OnZoomToWind),
1255  (_('Zoom to default region'), self.OnZoomToDefault),
1256  (_('Zoom to saved region'), self.OnZoomToSaved),
1257  (_('Set computational region from display extent'), self.OnDisplayToWind),
1258  (_('Save display geometry to named region'), self.OnSaveDisplayRegion),
1259  (_('Save computational region to named region'), self.OnSaveWindRegion)):
1260  mid = wx.MenuItem(zoommenu, wx.ID_ANY, label)
1261  zoommenu.AppendItem(mid)
1262  self.Bind(wx.EVT_MENU, handler, mid)
1263 
1264  # Popup the menu. If an item is selected then its handler will
1265  # be called before PopupMenu returns.
1266  self.PopupMenu(zoommenu)
1267  zoommenu.Destroy()
1268 
1269  def SetProperties(self, render = False, mode = 0, showCompExtent = False,
1270  constrainRes = False, projection = False, alignExtent = True):
1271  """!Set properies of map display window"""
1272  self.SetProperty('render', render)
1273  self.statusbarManager.SetMode(mode)
1274  self.StatusbarUpdate()
1275  self.SetProperty('region', showCompExtent)
1276  self.SetProperty('alignExtent', alignExtent)
1277  self.SetProperty('resolution', constrainRes)
1278  self.SetProperty('projection', projection)
1279 
1280  def IsStandalone(self):
1281  """!Check if Map display is standalone"""
1282  if self._layerManager:
1283  return False
1284 
1285  return True
1286 
1287  def GetLayerManager(self):
1288  """!Get reference to Layer Manager
1289 
1290  @return window reference
1291  @return None (if standalone)
1292  """
1293  return self._layerManager
1294 
1295  def GetMapToolbar(self):
1296  """!Returns toolbar with zooming tools"""
1297  return self.toolbars['map']
def OnAddArrow
Handler for north arrow menu selection.
def Query
Query selected layers.
def OnAddText
Handler for text decoration menu selection.
wxGUI command interface
def OnFocus
Change choicebook page to match display.
def ListOfCatsToRange
Convert list of category number to range(s)
Definition: core/utils.py:207
def OnZoomMenu
Popup Zoom menu.
wxGUI debugging
def OnQuery
Query tools menu.
def SaveToFile
Save map to image.
def OnZoomToSaved
Set display geometry to match extents in saved region file.
wxGUI vector digitizer
def OnRotate
Rotate 3D view.
def OnZoomToRaster
Set display extents to match selected raster map (ignore NULLs)
def SetProperties
Set properies of map display window.
def OnPointer
Pointer button clicked.
def SetValue
Definition: widgets.py:115
#define max(x, y)
Definition: draw2.c:69
def GetOptData
Callback method for decoration overlay command generated by dialog created in menuform.py.
def UpdateDialog
Definition: forms.py:294
def _QueryMapDone
Restore settings after querying (restore GRASS_REGION)
def OnFlyThrough
Fly-through mode.
def GetLayerManager
Get reference to Layer Manager.
def OnAddBarscale
Handler for scale/arrow map decoration menu selection.
def OnSaveDisplayRegion
Save display extents to named region file.
def OnUpdateProgress
Update progress bar info.
Nviz (3D view) module.
Various dialogs used in wxGUI.
def RemoveToolbar
Removes defined toolbar from the window.
Print context and utility functions for printing contents of map display window.
Rendering map layers and overlays into map composition image.
Base classes for Map display window.
def QueryMap
Query raster or vector map layers by r/v.what.
def QueryVector
Query vector map layer features.
def OnSaveWindRegion
Save computational region to named region file.
def IsStandalone
Check if Map display is standalone.
def AddNviz
Add 3D view mode window.
def GetLayerNameFromCmd
Get map name from GRASS command.
Definition: core/utils.py:73
Plotting histogram based on d.histogram.
DBM-related dialogs.
def AddTmpVectorMapLayer
Add temporal vector map layer to map composition.
def OnRender
Re-render map composition (each map layer)
def RemoveNviz
Restore 2D view.
def GetImageHandlers
Get list of supported image handlers.
def OnDisplayToWind
Set computational region (WIND file) to match display extents.
Main frame for map display window.
def OnHistogram
Init histogram display canvas and tools.
def FormatDist
Format length numbers and units in a nice way, as a function of length.
def OnZoomToMap
Set display extents to match selected raster (including NULLs) or vector map.
Misc utilities for wxGUI.
Profiling using PyPlot.
Map display canvas for wxGUI vector digitizer.
def AddToolbar
Add defined toolbar to the window.
def OnProfile
Launch profile tool.
Map display canvas - buffered window.
wxGUI vector digitizer toolbars
def OnAddLegend
Handler for legend map decoration menu selection.
def GetMapToolbar
Returns toolbar with zooming tools.
def MeasureDist
Calculate map distance from screen distance and print to output window.
def IsPaneShown
Check if pane (toolbar, mapWindow ...) of given name is currently shown.
#define round(x)
Definition: draw2.c:71
Default GUI settings.
tuple range
Definition: tools.py:1406
GLWindow
Definition: nviz/main.py:34
def OnMeasure
Init measurement routine that calculates map distance along transect drawn on map display...
def __init__
Main map display window with toolbars, statusbar and BufferedWindow (map canvas)
def RemoveQueryLayer
Removes temporary map layers (queries)
def _addToolbarVDigit
Add vector digitizer toolbar.
Map display frame - toolbars.
def OnCloseWindow
Window closed.