GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mapdisplay.py
Go to the documentation of this file.
1 """!
2 @package gcp.mapdisplay
3 
4 @brief Display to manage ground control points with two toolbars, one
5 for various display management functions, one for manipulating GCPs.
6 
7 Classes:
8 - mapdisplay::MapFrame
9 
10 (C) 2006-2011 by the GRASS Development Team
11 
12 This program is free software under the GNU General Public License
13 (>=v2). Read the file COPYING that comes with GRASS for details.
14 
15 @author Markus Metz
16 """
17 
18 import os
19 import math
20 import platform
21 
22 from core import globalvar
23 import wx
24 import wx.aui
25 
26 from core.render import EVT_UPDATE_PRGBAR
27 from mapdisp.toolbars import MapToolbar
28 from gcp.toolbars import GCPDisplayToolbar, GCPManToolbar
29 from mapdisp.gprint import PrintOptions
30 from core.gcmd import GMessage
31 from gui_core.dialogs import GetImageHandlers, ImageSizeDialog
32 from gui_core.mapdisp import MapFrameBase
33 from core.settings import UserSettings
34 from mapdisp.mapwindow import BufferedWindow
35 
36 import mapdisp.statusbar as sb
37 
38 # for standalone app
39 cmdfilename = None
40 
41 class MapFrame(MapFrameBase):
42  """!Main frame for map display window. Drawing takes place in
43  child double buffered drawing window.
44  """
45  def __init__(self, parent=None, title=_("GRASS GIS Manage Ground Control Points"),
46  toolbars=["gcpdisp"], tree=None, notebook=None, lmgr=None,
47  page=None, Map=None, auimgr=None, name = 'GCPMapWindow', **kwargs):
48  """!Main map display window with toolbars, statusbar and
49  DrawWindow
50 
51  @param toolbars array of activated toolbars, e.g. ['map', 'digit']
52  @param tree reference to layer tree
53  @param notebook control book ID in Layer Manager
54  @param lmgr Layer Manager
55  @param page notebook page with layer tree
56  @param Map instance of render.Map
57  @param auimgs AUI manager
58  @param kwargs wx.Frame attribures
59  """
60 
61  MapFrameBase.__init__(self, parent = parent, title = title, toolbars = toolbars,
62  Map = Map, auimgr = auimgr, name = name, **kwargs)
63 
64  self._layerManager = lmgr # Layer Manager object
65  self.tree = tree # Layer Manager layer tree object
66  self.page = page # Notebook page holding the layer tree
67  self.layerbook = notebook # Layer Manager layer tree notebook
68  #
69  # Add toolbars
70  #
71  for toolb in toolbars:
72  self.AddToolbar(toolb)
73 
74  self.activemap = self.toolbars['gcpdisp'].togglemap
75  self.activemap.SetSelection(0)
76 
77  self.SrcMap = self.grwiz.SrcMap # instance of render.Map
78  self.TgtMap = self.grwiz.TgtMap # instance of render.Map
79  self._mgr.SetDockSizeConstraint(0.5, 0.5)
80 
81  #
82  # Add statusbar
83  #
84 
85  # items for choice
86  self.statusbarItems = [sb.SbCoordinates,
87  sb.SbRegionExtent,
88  sb.SbCompRegionExtent,
89  sb.SbShowRegion,
90  sb.SbResolution,
91  sb.SbDisplayGeometry,
92  sb.SbMapScale,
93  sb.SbProjection,
94  sb.SbGoToGCP,
95  sb.SbRMSError]
96 
97 
98  # create statusbar and its manager
99  statusbar = self.CreateStatusBar(number = 4, style = 0)
100  statusbar.SetStatusWidths([-5, -2, -1, -1])
101  self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
102 
103  # fill statusbar manager
104  self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
105  self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
106  self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
107 
108  self.statusbarManager.SetMode(8) # goto GCP
109  self.statusbarManager.Update()
110 
111 
112  #
113  # Init map display (buffered DC & set default cursor)
114  #
115  self.grwiz.SwitchEnv('source')
116  self.SrcMapWindow = BufferedWindow(self, id=wx.ID_ANY,
117  Map=self.SrcMap, tree=self.tree, lmgr=self._layerManager)
118 
119  self.grwiz.SwitchEnv('target')
120  self.TgtMapWindow = BufferedWindow(self, id=wx.ID_ANY,
121  Map=self.TgtMap, tree=self.tree, lmgr=self._layerManager)
123  self.Map = self.SrcMap
124  self.SrcMapWindow.SetCursor(self.cursors["cross"])
125  self.TgtMapWindow.SetCursor(self.cursors["cross"])
126 
127  #
128  # initialize region values
129  #
130  self._initMap(map = self.SrcMap)
131  self._initMap(map = self.TgtMap)
132 
133  #
134  # Bind various events
135  #
136  self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
137  self.Bind(EVT_UPDATE_PRGBAR, self.OnUpdateProgress)
138  self.Bind(wx.EVT_SIZE, self.OnDispResize)
139  self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive)
140 
141  #
142  # Update fancy gui style
143  #
144  # AuiManager wants a CentrePane, workaround to get two equally sized windows
145  self.list = self.CreateGCPList()
146 
147  #self.SrcMapWindow.SetSize((300, 300))
148  #self.TgtMapWindow.SetSize((300, 300))
149  self.list.SetSize((100, 150))
150  self._mgr.AddPane(self.list, wx.aui.AuiPaneInfo().
151  Name("gcplist").Caption(_("GCP List")).LeftDockable(False).
152  RightDockable(False).PinButton().FloatingSize((600,200)).
153  CloseButton(False).DestroyOnClose(True).
154  Top().Layer(1).MinSize((200,100)))
155  self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo().
156  Name("source").Caption(_("Source Display")).Dockable(False).
157  CloseButton(False).DestroyOnClose(True).Floatable(False).
158  Centre())
159  self._mgr.AddPane(self.TgtMapWindow, wx.aui.AuiPaneInfo().
160  Name("target").Caption(_("Target Display")).Dockable(False).
161  CloseButton(False).DestroyOnClose(True).Floatable(False).
162  Right().Layer(0))
163 
164  srcwidth, srcheight = self.SrcMapWindow.GetSize()
165  tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
166  srcwidth = (srcwidth + tgtwidth) / 2
167  self._mgr.GetPane("target").Hide()
168  self._mgr.Update()
169  self._mgr.GetPane("source").BestSize((srcwidth, srcheight))
170  self._mgr.GetPane("target").BestSize((srcwidth, srcheight))
171  if self.show_target:
172  self._mgr.GetPane("target").Show()
173  else:
174  self.activemap.Enable(False)
175  # needed by Mac OS, does not harm on Linux, breaks display on Windows
176  if platform.system() != 'Windows':
177  self._mgr.Update()
178 
179  #
180  # Init print module and classes
181  #
182  self.printopt = PrintOptions(self, self.MapWindow)
183 
184  #
185  # Initialization of digitization tool
186  #
187  self.digit = None
188 
189  # set active map
190  self.MapWindow = self.SrcMapWindow
191  self.Map = self.SrcMap
192 
193  # do not init zoom history here, that happens when zooming to map(s)
194 
195  #
196  # Re-use dialogs
197  #
198  self.dialogs = {}
199  self.dialogs['attributes'] = None
200  self.dialogs['category'] = None
201  self.dialogs['barscale'] = None
202  self.dialogs['legend'] = None
203 
204  self.decorationDialog = None # decoration/overlays
205 
206  def AddToolbar(self, name):
207  """!Add defined toolbar to the window
208 
209  Currently known toolbars are:
210  - 'map' - basic map toolbar
211  - 'vdigit' - vector digitizer
212  - 'gcpdisp' - GCP Manager, Display
213  - 'gcpman' - GCP Manager, points management
214  - 'nviz' - 3D view mode
215  """
216  # default toolbar
217  if name == "map":
218  self.toolbars['map'] = MapToolbar(self, self.Map)
219 
220  self._mgr.AddPane(self.toolbars['map'],
221  wx.aui.AuiPaneInfo().
222  Name("maptoolbar").Caption(_("Map Toolbar")).
223  ToolbarPane().Top().
224  LeftDockable(False).RightDockable(False).
225  BottomDockable(False).TopDockable(True).
226  CloseButton(False).Layer(2).
227  BestSize((self.toolbars['map'].GetSize())))
228 
229  # GCP display
230  elif name == "gcpdisp":
231  self.toolbars['gcpdisp'] = GCPDisplayToolbar(self)
232 
233  self._mgr.AddPane(self.toolbars['gcpdisp'],
234  wx.aui.AuiPaneInfo().
235  Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")).
236  ToolbarPane().Top().
237  LeftDockable(False).RightDockable(False).
238  BottomDockable(False).TopDockable(True).
239  CloseButton(False).Layer(2))
240 
241  if self.show_target == False:
242  self.toolbars['gcpdisp'].Enable('zoommenu', enable = False)
243 
244  self.toolbars['gcpman'] = GCPManToolbar(self)
245 
246  self._mgr.AddPane(self.toolbars['gcpman'],
247  wx.aui.AuiPaneInfo().
248  Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")).
249  ToolbarPane().Top().Row(1).
250  LeftDockable(False).RightDockable(False).
251  BottomDockable(False).TopDockable(True).
252  CloseButton(False).Layer(2))
253 
254  self._mgr.Update()
255 
256  def OnUpdateProgress(self, event):
257  """
258  Update progress bar info
259  """
260  self.GetProgressBar().SetValue(event.value)
261 
262  event.Skip()
263 
264  def OnFocus(self, event):
265  """
266  Change choicebook page to match display.
267  Or set display for georectifying
268  """
269  if self._layerManager and \
270  self._layerManager.gcpmanagement:
271  # in GCP Management, set focus to current MapWindow for mouse actions
272  self.OnPointer(event)
273  self.MapWindow.SetFocus()
274  else:
275  # change bookcontrol page to page associated with display
276  # GCP Manager: use bookcontrol?
277  if self.page:
278  pgnum = self.layerbook.GetPageIndex(self.page)
279  if pgnum > -1:
280  self.layerbook.SetSelection(pgnum)
281 
282  event.Skip()
283 
284  def OnDraw(self, event):
285  """!Re-display current map composition
286  """
287  self.MapWindow.UpdateMap(render = False)
288 
289  def OnRender(self, event):
290  """!Re-render map composition (each map layer)
291  """
292  # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame
293  # delete tmp map layers (queries)
294  qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER)
295  for layer in qlayer:
296  self.Map.DeleteLayer(layer)
297 
298  self.SrcMapWindow.UpdateMap(render=True)
299  if self.show_target:
300  self.TgtMapWindow.UpdateMap(render=True)
301 
302  # update statusbar
303  self.StatusbarUpdate()
304 
305  def OnPointer(self, event):
306  """!Pointer button clicked
307  """
308  self.toolbars['gcpdisp'].OnTool(event)
309  self.toolbars['gcpdisp'].action['desc'] = ''
310 
311  # change the cursor
312  self.SrcMapWindow.SetCursor(self.cursors["cross"])
313  self.SrcMapWindow.mouse['use'] = "pointer"
314  self.SrcMapWindow.mouse['box'] = "point"
315  self.TgtMapWindow.SetCursor(self.cursors["cross"])
316  self.TgtMapWindow.mouse['use'] = "pointer"
317  self.TgtMapWindow.mouse['box'] = "point"
318 
319  def OnZoomIn(self, event):
320  """
321  Zoom in the map.
322  Set mouse cursor, zoombox attributes, and zoom direction
323  """
324  self.toolbars['gcpdisp'].OnTool(event)
325  self.toolbars['gcpdisp'].action['desc'] = ''
326 
327  self.MapWindow.mouse['use'] = "zoom"
328  self.MapWindow.mouse['box'] = "box"
329  self.MapWindow.zoomtype = 1
330  self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
331 
332  # change the cursor
333  self.MapWindow.SetCursor(self.cursors["cross"])
334 
335  if self.MapWindow == self.SrcMapWindow:
336  win = self.TgtMapWindow
337  elif self.MapWindow == self.TgtMapWindow:
338  win = self.SrcMapWindow
339 
340  win.mouse['use'] = "zoom"
341  win.mouse['box'] = "box"
342  win.zoomtype = 1
343  win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
344 
345  # change the cursor
346  win.SetCursor(self.cursors["cross"])
347 
348  def OnZoomOut(self, event):
349  """
350  Zoom out the map.
351  Set mouse cursor, zoombox attributes, and zoom direction
352  """
353  self.toolbars['gcpdisp'].OnTool(event)
354  self.toolbars['gcpdisp'].action['desc'] = ''
355 
356  self.MapWindow.mouse['use'] = "zoom"
357  self.MapWindow.mouse['box'] = "box"
358  self.MapWindow.zoomtype = -1
359  self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
360 
361  # change the cursor
362  self.MapWindow.SetCursor(self.cursors["cross"])
363 
364  if self.MapWindow == self.SrcMapWindow:
365  win = self.TgtMapWindow
366  elif self.MapWindow == self.TgtMapWindow:
367  win = self.SrcMapWindow
368 
369  win.mouse['use'] = "zoom"
370  win.mouse['box'] = "box"
371  win.zoomtype = -1
372  win.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
373 
374  # change the cursor
375  win.SetCursor(self.cursors["cross"])
376 
377  def OnPan(self, event):
378  """
379  Panning, set mouse to drag
380  """
381  self.toolbars['gcpdisp'].OnTool(event)
382  self.toolbars['gcpdisp'].action['desc'] = ''
383 
384  self.MapWindow.mouse['use'] = "pan"
385  self.MapWindow.mouse['box'] = "pan"
386  self.MapWindow.zoomtype = 0
387 
388  # change the cursor
389  self.MapWindow.SetCursor(self.cursors["hand"])
390 
391  if self.MapWindow == self.SrcMapWindow:
392  win = self.TgtMapWindow
393  elif self.MapWindow == self.TgtMapWindow:
394  win = self.SrcMapWindow
395 
396  win.mouse['use'] = "pan"
397  win.mouse['box'] = "pan"
398  win.zoomtype = 0
399 
400  # change the cursor
401  win.SetCursor(self.cursors["hand"])
402 
403  def OnErase(self, event):
404  """
405  Erase the canvas
406  """
407  self.MapWindow.EraseMap()
408 
409  if self.MapWindow == self.SrcMapWindow:
410  win = self.TgtMapWindow
411  elif self.MapWindow == self.TgtMapWindow:
412  win = self.SrcMapWindow
413 
414  win.EraseMap()
415 
416  def OnZoomRegion(self, event):
417  """
418  Zoom to region
419  """
420  self.Map.getRegion()
421  self.Map.getResolution()
422  self.UpdateMap()
423  # event.Skip()
424 
425  def OnAlignRegion(self, event):
426  """
427  Align region
428  """
429  if not self.Map.alignRegion:
430  self.Map.alignRegion = True
431  else:
432  self.Map.alignRegion = False
433  # event.Skip()
434 
435  def SaveToFile(self, event):
436  """!Save map to image
437  """
438  img = self.MapWindow.img
439  if not img:
440  GMessage(parent = self,
441  message = _("Nothing to render (empty map). Operation canceled."))
442  return
443  filetype, ltype = GetImageHandlers(img)
444 
445  # get size
446  dlg = ImageSizeDialog(self)
447  dlg.CentreOnParent()
448  if dlg.ShowModal() != wx.ID_OK:
449  dlg.Destroy()
450  return
451  width, height = dlg.GetValues()
452  dlg.Destroy()
453 
454  # get filename
455  dlg = wx.FileDialog(parent = self,
456  message = _("Choose a file name to save the image "
457  "(no need to add extension)"),
458  wildcard = filetype,
459  style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
460 
461  if dlg.ShowModal() == wx.ID_OK:
462  path = dlg.GetPath()
463  if not path:
464  dlg.Destroy()
465  return
466 
467  base, ext = os.path.splitext(path)
468  fileType = ltype[dlg.GetFilterIndex()]['type']
469  extType = ltype[dlg.GetFilterIndex()]['ext']
470  if ext != extType:
471  path = base + '.' + extType
472 
473  self.MapWindow.SaveToFile(path, fileType,
474  width, height)
475 
476  dlg.Destroy()
477 
478  def PrintMenu(self, event):
479  """
480  Print options and output menu for map display
481  """
482  point = wx.GetMousePosition()
483  printmenu = wx.Menu()
484  # Add items to the menu
485  setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup'))
486  printmenu.AppendItem(setup)
487  self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
488 
489  preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview'))
490  printmenu.AppendItem(preview)
491  self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
492 
493  doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display'))
494  printmenu.AppendItem(doprint)
495  self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
496 
497  # Popup the menu. If an item is selected then its handler
498  # will be called before PopupMenu returns.
499  self.PopupMenu(printmenu)
500  printmenu.Destroy()
501 
502  def FormatDist(self, dist):
503  """!Format length numbers and units in a nice way,
504  as a function of length. From code by Hamish Bowman
505  Grass Development Team 2006"""
506 
507  mapunits = self.Map.projinfo['units']
508  if mapunits == 'metres': mapunits = 'meters'
509  outunits = mapunits
510  dist = float(dist)
511  divisor = 1.0
512 
513  # figure out which units to use
514  if mapunits == 'meters':
515  if dist > 2500.0:
516  outunits = 'km'
517  divisor = 1000.0
518  else: outunits = 'm'
519  elif mapunits == 'feet':
520  # nano-bug: we match any "feet", but US Survey feet is really
521  # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
522  # miles the tick markers are rounded to the nearest 10th of a
523  # mile (528'), the difference in foot flavours is ignored.
524  if dist > 5280.0:
525  outunits = 'miles'
526  divisor = 5280.0
527  else:
528  outunits = 'ft'
529  elif 'degree' in mapunits:
530  if dist < 1:
531  outunits = 'min'
532  divisor = (1/60.0)
533  else:
534  outunits = 'deg'
535 
536  # format numbers in a nice way
537  if (dist/divisor) >= 2500.0:
538  outdist = round(dist/divisor)
539  elif (dist/divisor) >= 1000.0:
540  outdist = round(dist/divisor,1)
541  elif (dist/divisor) > 0.0:
542  outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor))))
543  else:
544  outdist = float(dist/divisor)
545 
546  return (outdist, outunits)
547 
548  def OnZoomToRaster(self, event):
549  """!
550  Set display extents to match selected raster map (ignore NULLs)
551  """
552  self.MapWindow.ZoomToMap(ignoreNulls = True)
553 
554  def OnZoomToSaved(self, event):
555  """!Set display geometry to match extents in
556  saved region file
557  """
558  self.MapWindow.ZoomToSaved()
559 
560  def OnDisplayToWind(self, event):
561  """!Set computational region (WIND file) to match display
562  extents
563  """
564  self.MapWindow.DisplayToWind()
565 
566  def SaveDisplayRegion(self, event):
567  """!Save display extents to named region file.
568  """
569  self.MapWindow.SaveDisplayRegion()
570 
571  def OnZoomMenu(self, event):
572  """!Popup Zoom menu
573  """
574  point = wx.GetMousePosition()
575  zoommenu = wx.Menu()
576  # Add items to the menu
577 
578  zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)'))
579  zoommenu.AppendItem(zoomwind)
580  self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind)
581 
582  zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region'))
583  zoommenu.AppendItem(zoomdefault)
584  self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
585 
586  zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region'))
587  zoommenu.AppendItem(zoomsaved)
588  self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved)
589 
590  savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display'))
591  zoommenu.AppendItem(savewind)
592  self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind)
593 
594  savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region'))
595  zoommenu.AppendItem(savezoom)
596  self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
597 
598  # Popup the menu. If an item is selected then its handler
599  # will be called before PopupMenu returns.
600  self.PopupMenu(zoommenu)
601  zoommenu.Destroy()
602 
603 
604  def IsStandalone(self):
605  """!Check if Map display is standalone"""
606  if self._layerManager:
607  return False
608 
609  return True
610 
611  def GetLayerManager(self):
612  """!Get reference to Layer Manager
613 
614  @return window reference
615  @return None (if standalone)
616  """
617  return self._layerManager
618 
619  def GetSrcWindow(self):
620  return self.SrcMapWindow
621 
622  def GetTgtWindow(self):
623  return self.TgtMapWindow
624 
625  def GetShowTarget(self):
626  return self.show_target
627 
628  def GetMapToolbar(self):
629  """!Returns toolbar with zooming tools"""
630  return self.toolbars['gcpdisp']
def IsStandalone
Check if Map display is standalone.
Definition: mapdisplay.py:604
wxGUI command interface
def OnPointer
Pointer button clicked.
Definition: mapdisplay.py:305
def OnZoomToRaster
Set display extents to match selected raster map (ignore NULLs)
Definition: mapdisplay.py:548
def OnZoomMenu
Popup Zoom menu.
Definition: mapdisplay.py:571
def AddToolbar
Add defined toolbar to the window.
Definition: mapdisplay.py:206
Georectification module - toolbars.
def GetLayerManager
Get reference to Layer Manager.
Definition: mapdisplay.py:611
def GetMapToolbar
Returns toolbar with zooming tools.
Definition: mapdisplay.py:628
def SetValue
Definition: widgets.py:115
def SaveDisplayRegion
Save display extents to named region file.
Definition: mapdisplay.py:566
def OnRender
Re-render map composition (each map layer)
Definition: mapdisplay.py:289
Various dialogs used in wxGUI.
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 OnZoomToSaved
Set display geometry to match extents in saved region file.
Definition: mapdisplay.py:554
def GetImageHandlers
Get list of supported image handlers.
def OnDraw
Re-display current map composition.
Definition: mapdisplay.py:284
def SaveToFile
Save map to image.
Definition: mapdisplay.py:435
def FormatDist
Format length numbers and units in a nice way, as a function of length.
Definition: mapdisplay.py:502
Map display canvas - buffered window.
#define round(x)
Definition: draw2.c:71
Default GUI settings.
Classes for statusbar management.
Main frame for map display window.
Definition: mapdisplay.py:41
def OnDisplayToWind
Set computational region (WIND file) to match display extents.
Definition: mapdisplay.py:560
def __init__
Main map display window with toolbars, statusbar and DrawWindow.
Definition: mapdisplay.py:47
Map display frame - toolbars.