GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
gui_core/mapwindow.py
Go to the documentation of this file.
00001 """!
00002 @package gui_core.mapwindow
00003 
00004 @brief Map display canvas - base class for buffered window.
00005 
00006 Classes:
00007  - mapwindow::MapWindow
00008 
00009 (C) 2006-2011 by the GRASS Development Team
00010 
00011 This program is free software under the GNU General Public License
00012 (>=v2). Read the file COPYING that comes with GRASS for details.
00013 
00014 @author Martin Landa <landa.martin gmail.com>
00015 @author Michael Barton
00016 @author Jachym Cepicky
00017 """
00018 
00019 import wx
00020 
00021 from core.settings import UserSettings
00022 
00023 class MapWindow(object):
00024     """!Abstract map display window class
00025     
00026     Superclass for BufferedWindow class (2D display mode), and GLWindow
00027     (3D display mode).
00028     
00029     Subclasses have to define
00030      - _bindMouseEvents method which binds MouseEvent handlers
00031      - Pixel2Cell
00032      - Cell2Pixel (if it is possible)
00033     
00034     """
00035     def __init__(self, parent, id = wx.ID_ANY,
00036                  Map = None, tree = None, lmgr = None, **kwargs):
00037         self.parent = parent # MapFrame
00038         self.Map    = Map
00039         self.tree   = tree
00040         self.lmgr   = lmgr
00041         
00042         # mouse attributes -- position on the screen, begin and end of
00043         # dragging, and type of drawing
00044         self.mouse = {
00045             'begin': [0, 0], # screen coordinates
00046             'end'  : [0, 0],
00047             'use'  : "pointer",
00048             'box'  : "point"
00049             }
00050         # last east, north coordinates, changes on mouse motion
00051         self.lastEN = None 
00052         
00053         # stores overridden cursor
00054         self._overriddenCursor = None
00055 
00056     def RegisterMouseEventHandler(self, event, handler, cursor = None):
00057         """!Binds event handler
00058         
00059         Call event.Skip() in handler to allow default processing in MapWindow.
00060         
00061         \code
00062         # your class methods
00063         def OnButton(self, event):
00064             # current map display's map window
00065             # expects LayerManager to be the parent
00066             self.mapwin = self.parent.GetLayerTree().GetMapDisplay().GetWindow()
00067             if self.mapwin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN, self.OnMouseAction,
00068                                                      wx.StockCursor(wx.CURSOR_CROSS)):
00069                 self.parent.GetLayerTree().GetMapDisplay().Raise()
00070             else:
00071                 # handle that you cannot get coordinates
00072         
00073         def OnMouseAction(self, event):
00074             # get real world coordinates of mouse click
00075             coor = self.mapwin.Pixel2Cell(event.GetPositionTuple()[:])
00076             self.text.SetLabel('Coor: ' + str(coor))
00077             self.mapwin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN)
00078             event.Skip()
00079         \endcode
00080         
00081         @param event one of mouse events
00082         @param handler function to handle event
00083         @param cursor cursor which temporary overrides current cursor
00084         
00085         @return True if successful
00086         @return False if event cannot be bind
00087         """
00088         
00089         # if it is a VDigitWindow it cannot be used
00090         # hasattr is ugly
00091         if hasattr(self, "digit"):
00092             return False
00093         
00094         self.Bind(event, handler)
00095         self.mouse['useBeforeGenericEvent'] = self.mouse['use']
00096         self.mouse['use'] = 'genericEvent'
00097         
00098         if cursor:
00099             self._overriddenCursor = self.GetCursor()
00100             self.SetCursor(cursor)
00101         
00102         return True
00103 
00104 
00105     def UnregisterMouseEventHandler(self, event):
00106         """!Unbinds event handler a restores previous state
00107         
00108         You should unbind to restore normal MapWindow behaviour.
00109         Note that this operation will unbind any other external (non-MapWindow) handlers.
00110         
00111         @param event event to unbind
00112         
00113         @return True if successful
00114         @return False if event cannot be unbind
00115         """
00116         if hasattr(self, "digit"):
00117             return False
00118         
00119         # it is not yet possible in wxPython to unbind exact event
00120         ret = self.Unbind(event)
00121         
00122         # restore bind state
00123         self._bindMouseEvents()
00124         
00125         # restore mouse use (previous state)
00126         self.mouse['use'] = self.mouse['useBeforeGenericEvent']
00127         
00128         # restore overridden cursor
00129         if self._overriddenCursor:
00130             self.SetCursor(self._overriddenCursor)
00131         
00132         return ret
00133     
00134     def Pixel2Cell(self, (x, y)):
00135         raise NotImplementedError()
00136     
00137     def Cell2Pixel(self, (east, north)):
00138         raise NotImplementedError()
00139 
00140     def OnMotion(self, event):
00141         """!Tracks mouse motion and update statusbar
00142         
00143         @see GetLastEN
00144         """
00145         try:
00146             self.lastEN = self.Pixel2Cell(event.GetPositionTuple())
00147         except (ValueError):
00148             self.lastEN = None
00149         # FIXME: special case for vdigit and access to statusbarManager
00150         if self.parent.statusbarManager.GetMode() == 0: # Coordinates            
00151             updated = False
00152             if hasattr(self, "digit"):
00153                 precision = int(UserSettings.Get(group = 'projection', key = 'format',
00154                                              subkey = 'precision'))
00155                 updated = self._onMotion(self.lastEN, precision)
00156 
00157             if not updated:
00158                 self.parent.CoordinatesChanged()
00159         
00160         event.Skip()
00161 
00162     def GetLastEN(self):
00163         """!Returns last coordinates of mouse cursor.
00164         
00165         @see OnMotion
00166         """
00167         return self.lastEN
00168     
00169     def GetLayerByName(self, name, mapType, dataType = 'layer'):
00170         """!Get layer from layer tree by nam
00171         
00172         @param name layer name
00173         @param type 'item' / 'layer' / 'nviz'
00174 
00175         @return layer / map layer properties / nviz properties
00176         @return None
00177         """
00178         if not self.tree:
00179             return None
00180         
00181         try:
00182             mapLayer = self.Map.GetListOfLayers(l_type = mapType, l_name = name)[0]
00183         except IndexError:
00184             return None
00185         
00186         if dataType == 'layer':
00187             return mapLayer
00188         item = self.tree.FindItemByData('maplayer', mapLayer)
00189         if not item:
00190             return None
00191         if dataType == 'nviz':
00192             return self.tree.GetPyData(item)[0]['nviz']
00193         
00194         return item
00195         
00196     def GetSelectedLayer(self, type = 'layer', multi = False):
00197         """!Get selected layer from layer tree
00198         
00199         @param type 'item' / 'layer' / 'nviz'
00200         @param multi return first selected layer or all
00201         
00202         @return layer / map layer properties / nviz properties
00203         @return None / [] on failure
00204         """
00205         ret = []
00206         if not self.tree or \
00207                 not self.tree.GetSelection():
00208             if multi:
00209                 return []
00210             else:
00211                 return None
00212         
00213         if multi and \
00214                 type == 'item':
00215             return self.tree.GetSelections()
00216         
00217         for item in self.tree.GetSelections():
00218             if not item.IsChecked():
00219                 if multi:
00220                     continue
00221                 else:
00222                     return None
00223 
00224             if type == 'item': # -> multi = False
00225                 return item
00226         
00227             try:
00228                 if type == 'nviz':
00229                     layer = self.tree.GetPyData(item)[0]['nviz']
00230                 else:
00231                     layer = self.tree.GetPyData(item)[0]['maplayer']
00232             except:
00233                 layer = None
00234 
00235             if multi:
00236                 ret.append(layer)
00237             else:
00238                 return layer
00239             
00240         return ret