GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mapdisp.py
Go to the documentation of this file.
1 """!
2 @package gui_core.mapdisp
3 
4 @brief Base classes for Map display window
5 
6 Classes:
7  - mapdisp::MapFrameBase
8 
9 (C) 2009-2011 by the GRASS Development Team
10 
11 This program is free software under the GNU General Public License
12 (>=v2). Read the file COPYING that comes with GRASS for details.
13 
14 @author Martin Landa <landa.martin gmail.com>
15 @author Michael Barton <michael.barton@asu.edu>
16 """
17 
18 import os
19 import sys
20 
21 import wx
22 
23 from core import globalvar
24 from core.debug import Debug
25 
26 from grass.script import core as grass
27 
28 class MapFrameBase(wx.Frame):
29  """!Base class for map display window
30 
31  Derived class must use statusbarManager or override
32  GetProperty, SetProperty and HasProperty methods.
33  If derived class enables and disables auto-rendering,
34  it should override IsAutoRendered method.
35  """
36  def __init__(self, parent = None, id = wx.ID_ANY, title = None,
37  style = wx.DEFAULT_FRAME_STYLE, toolbars = None,
38  Map = None, auimgr = None, name = None, **kwargs):
39  """!
40  @param toolbars array of activated toolbars, e.g. ['map', 'digit']
41  @param Map instance of render.Map
42  @param auimgs AUI manager
43  @param name frame name
44  @param kwargs wx.Frame attributes
45  """
46 
47 
48  self.Map = Map # instance of render.Map
49  self.parent = parent
50 
51  wx.Frame.__init__(self, parent, id, title, style = style, name = name, **kwargs)
52 
53  # available cursors
54  self.cursors = {
55  # default: cross
56  # "default" : wx.StockCursor(wx.CURSOR_DEFAULT),
57  "default" : wx.StockCursor(wx.CURSOR_ARROW),
58  "cross" : wx.StockCursor(wx.CURSOR_CROSS),
59  "hand" : wx.StockCursor(wx.CURSOR_HAND),
60  "pencil" : wx.StockCursor(wx.CURSOR_PENCIL),
61  "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE)
62  }
63 
64  #
65  # set the size & system icon
66  #
67  self.SetClientSize(self.GetSize())
68  self.iconsize = (16, 16)
69 
70  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
71 
72  # toolbars
73  self.toolbars = {}
74 
75  #
76  # Fancy gui
77  #
78  self._mgr = wx.aui.AuiManager(self)
79 
80  def _initMap(self, map):
81  """!Initialize map display, set dimensions and map region
82  """
83  if not grass.find_program('g.region', ['--help']):
84  sys.exit(_("GRASS module '%s' not found. Unable to start map "
85  "display window.") % 'g.region')
86 
87  self.width, self.height = self.GetClientSize()
88 
89  Debug.msg(2, "MapFrame._initMap():")
90  map.ChangeMapSize(self.GetClientSize())
91  map.region = map.GetRegion() # g.region -upgc
92  # self.Map.SetRegion() # adjust region to match display window
93 
94  def SetProperty(self, name, value):
95  """!Sets property"""
96  self.statusbarManager.SetProperty(name, value)
97 
98  def GetProperty(self, name):
99  """!Returns property"""
100  return self.statusbarManager.GetProperty(name)
101 
102  def HasProperty(self, name):
103  """!Checks whether object has property"""
104  return self.statusbarManager.HasProperty(name)
105 
106  def GetPPM(self):
107  """! Get pixel per meter
108 
109  @todo now computed every time, is it necessary?
110  @todo enable user to specify ppm (and store it in UserSettings)
111  """
112  # TODO: need to be fixed...
113  ### screen X region problem
114  ### user should specify ppm
115  dc = wx.ScreenDC()
116  dpSizePx = wx.DisplaySize() # display size in pixels
117  dpSizeMM = wx.DisplaySizeMM() # display size in mm (system)
118  dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches
119  sysPpi = dc.GetPPI()
120  comPpi = (dpSizePx[0] / dpSizeIn[0],
121  dpSizePx[1] / dpSizeIn[1])
122 
123  ppi = comPpi # pixel per inch
124  ppm = ((ppi[0] / 2.54) * 100, # pixel per meter
125  (ppi[1] / 2.54) * 100)
126 
127  Debug.msg(4, "MapFrameBase.GetPPM(): size: px=%d,%d mm=%f,%f "
128  "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % \
129  (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1],
130  dpSizeIn[0], dpSizeIn[1],
131  sysPpi[0], sysPpi[1], comPpi[0], comPpi[1],
132  ppm[0], ppm[1]))
133 
134  return ppm
135 
136  def SetMapScale(self, value, map = None):
137  """! Set current map scale
138 
139  @param value scale value (n if scale is 1:n)
140  @param map Map instance (if none self.Map is used)
141  """
142  if not map:
143  map = self.Map
144 
145  region = self.Map.region
146  dEW = value * (region['cols'] / self.GetPPM()[0])
147  dNS = value * (region['rows'] / self.GetPPM()[1])
148  region['n'] = region['center_northing'] + dNS / 2.
149  region['s'] = region['center_northing'] - dNS / 2.
150  region['w'] = region['center_easting'] - dEW / 2.
151  region['e'] = region['center_easting'] + dEW / 2.
152 
153  # add to zoom history
154  self.GetWindow().ZoomHistory(region['n'], region['s'],
155  region['e'], region['w'])
156 
157  def GetMapScale(self, map = None):
158  """! Get current map scale
159 
160  @param map Map instance (if none self.Map is used)
161  """
162  if not map:
163  map = self.Map
164 
165  region = map.region
166  ppm = self.GetPPM()
167 
168  heightCm = region['rows'] / ppm[1] * 100
169  widthCm = region['cols'] / ppm[0] * 100
170 
171  Debug.msg(4, "MapFrame.GetMapScale(): width_cm=%f, height_cm=%f" %
172  (widthCm, heightCm))
173 
174  xscale = (region['e'] - region['w']) / (region['cols'] / ppm[0])
175  yscale = (region['n'] - region['s']) / (region['rows'] / ppm[1])
176  scale = (xscale + yscale) / 2.
177 
178  Debug.msg(3, "MapFrame.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" % \
179  (xscale, yscale, scale))
180 
181  return scale
182 
183  def GetProgressBar(self):
184  """!Returns progress bar
185 
186  Progress bar can be used by other classes.
187  """
188  return self.statusbarManager.GetProgressBar()
189 
190  def GetMap(self):
191  """!Returns current Map instance
192  """
193  return self.Map
194 
195  def GetWindow(self):
196  """!Get map window"""
197  return self.MapWindow
198 
199  def GetMapToolbar(self):
200  """!Returns toolbar with zooming tools"""
201  raise NotImplementedError()
202 
203  def GetToolbar(self, name):
204  """!Returns toolbar if exists else None.
205 
206  Toolbars dictionary contains currently used toolbars only.
207  """
208  if name in self.toolbars:
209  return self.toolbars[name]
210 
211  return None
212 
213  def StatusbarUpdate(self):
214  """!Update statusbar content"""
215  self.statusbarManager.Update()
216 
217  def IsAutoRendered(self):
218  """!Check if auto-rendering is enabled"""
219  return self.GetProperty('render')
220 
222  """!Shows current coordinates on statusbar.
223 
224  Used in BufferedWindow to report change of map coordinates (under mouse cursor).
225  """
226  self.statusbarManager.ShowItem('coordinates')
227 
229  """!Reposition items in statusbar"""
230  self.statusbarManager.Reposition()
231 
232  def StatusbarEnableLongHelp(self, enable = True):
233  """!Enable/disable toolbars long help"""
234  for toolbar in self.toolbars.itervalues():
235  toolbar.EnableLongHelp(enable)
236 
237  def IsStandalone(self):
238  """!Check if Map display is standalone"""
239  raise NotImplementedError("IsStandalone")
240 
241  def OnRender(self, event):
242  """!Re-render map composition (each map layer)
243  """
244  raise NotImplementedError("OnRender")
245 
246  def OnDraw(self, event):
247  """!Re-display current map composition
248  """
249  self.MapWindow.UpdateMap(render = False)
250 
251  def OnErase(self, event):
252  """!Erase the canvas
253  """
254  self.MapWindow.EraseMap()
255 
256  def OnZoomIn(self, event):
257  """!Zoom in the map.
258  Set mouse cursor, zoombox attributes, and zoom direction
259  """
260  toolbar = self.GetMapToolbar()
261  self._switchTool(toolbar, event)
262 
263  win = self.GetWindow()
264  self._prepareZoom(mapWindow = win, zoomType = 1)
265 
266  def OnZoomOut(self, event):
267  """!Zoom out the map.
268  Set mouse cursor, zoombox attributes, and zoom direction
269  """
270  toolbar = self.GetMapToolbar()
271  self._switchTool(toolbar, event)
272 
273  win = self.GetWindow()
274  self._prepareZoom(mapWindow = win, zoomType = -1)
275 
276  def _prepareZoom(self, mapWindow, zoomType):
277  """!Prepares MapWindow for zoom, toggles toolbar
278 
279  @param mapWindow MapWindow to prepare
280  @param zoomType 1 for zoom in, -1 for zoom out
281  """
282  mapWindow.mouse['use'] = "zoom"
283  mapWindow.mouse['box'] = "box"
284  mapWindow.zoomtype = zoomType
285  mapWindow.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
286 
287  # change the cursor
288  mapWindow.SetCursor(self.cursors["cross"])
289 
290  def _switchTool(self, toolbar, event):
291  """!Helper function to switch tools"""
292  if toolbar:
293  toolbar.OnTool(event)
294  toolbar.action['desc'] = ''
295 
296  def OnPointer(self, event):
297  """!Sets mouse mode to pointer."""
298  self.MapWindow.mouse['use'] = 'pointer'
299 
300  def OnPan(self, event):
301  """!Panning, set mouse to drag
302  """
303  toolbar = self.GetMapToolbar()
304  self._switchTool(toolbar, event)
305 
306  win = self.GetWindow()
307  self._preparePan(mapWindow = win)
308 
309  def _preparePan(self, mapWindow):
310  """!Prepares MapWindow for pan, toggles toolbar
311 
312  @param mapWindow MapWindow to prepare
313  """
314  mapWindow.mouse['use'] = "pan"
315  mapWindow.mouse['box'] = "pan"
316  mapWindow.zoomtype = 0
317 
318  # change the cursor
319  mapWindow.SetCursor(self.cursors["hand"])
320 
321  def OnZoomBack(self, event):
322  """!Zoom last (previously stored position)
323  """
324  self.MapWindow.ZoomBack()
325 
326  def OnZoomToMap(self, event):
327  """!
328  Set display extents to match selected raster (including NULLs)
329  or vector map.
330  """
331  self.MapWindow.ZoomToMap(layers = self.Map.GetListOfLayers())
332 
333  def OnZoomToWind(self, event):
334  """!Set display geometry to match computational region
335  settings (set with g.region)
336  """
337  self.MapWindow.ZoomToWind()
338 
339  def OnZoomToDefault(self, event):
340  """!Set display geometry to match default region settings
341  """
342  self.MapWindow.ZoomToDefault()
def OnRender
Re-render map composition (each map layer)
Definition: mapdisp.py:241
def OnZoomBack
Zoom last (previously stored position)
Definition: mapdisp.py:321
def StatusbarUpdate
Update statusbar content.
Definition: mapdisp.py:213
Base class for map display window.
Definition: mapdisp.py:28
def GetPPM
Get pixel per meter.
Definition: mapdisp.py:106
def GetWindow
Get map window.
Definition: mapdisp.py:195
def HasProperty
Checks whether object has property.
Definition: mapdisp.py:102
def OnZoomToWind
Set display geometry to match computational region settings (set with g.region)
Definition: mapdisp.py:333
wxGUI debugging
def OnDraw
Re-display current map composition.
Definition: mapdisp.py:246
def OnZoomOut
Zoom out the map.
Definition: mapdisp.py:266
def CoordinatesChanged
Shows current coordinates on statusbar.
Definition: mapdisp.py:221
def GetMapToolbar
Returns toolbar with zooming tools.
Definition: mapdisp.py:199
def OnZoomIn
Zoom in the map.
Definition: mapdisp.py:256
def OnPointer
Sets mouse mode to pointer.
Definition: mapdisp.py:296
def _preparePan
Prepares MapWindow for pan, toggles toolbar.
Definition: mapdisp.py:309
def GetMapScale
Get current map scale.
Definition: mapdisp.py:157
def OnZoomToMap
Set display extents to match selected raster (including NULLs) or vector map.
Definition: mapdisp.py:326
def GetToolbar
Returns toolbar if exists else None.
Definition: mapdisp.py:203
def SetProperty
Sets property.
Definition: mapdisp.py:94
def OnPan
Panning, set mouse to drag.
Definition: mapdisp.py:300
def SetMapScale
Set current map scale.
Definition: mapdisp.py:136
def StatusbarEnableLongHelp
Enable/disable toolbars long help.
Definition: mapdisp.py:232
def GetProgressBar
Returns progress bar.
Definition: mapdisp.py:183
def GetMap
Returns current Map instance.
Definition: mapdisp.py:190
def _switchTool
Helper function to switch tools.
Definition: mapdisp.py:290
def IsAutoRendered
Check if auto-rendering is enabled.
Definition: mapdisp.py:217
def IsStandalone
Check if Map display is standalone.
Definition: mapdisp.py:237
def _prepareZoom
Prepares MapWindow for zoom, toggles toolbar.
Definition: mapdisp.py:276
def OnZoomToDefault
Set display geometry to match default region settings.
Definition: mapdisp.py:339
def GetProperty
Returns property.
Definition: mapdisp.py:98
def StatusbarReposition
Reposition items in statusbar.
Definition: mapdisp.py:228
def OnErase
Erase the canvas.
Definition: mapdisp.py:251