def testMapWindowApi(self, giface, map_): self.frame = wx.Frame(parent=None, title=_("Map window API test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() mapWindowProperties.showRegion = True width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) giface.mapWindow = window sizer.Add(window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() window.ZoomToWind() self.frame.Show()
def testMapWindowDistance(self, giface, map_): self.frame = wx.Frame( parent=None, title=_("Map window distance measurement test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() mapWindowProperties.showRegion = True width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) giface.mapWindow = window sizer.Add(window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() window.ZoomToWind() self._listenToAllMapWindowSignals(window) self.frame.Show() from mapwin.analysis import MeasureDistanceController self.controller = MeasureDistanceController(giface, window) self.controller.Start()
def testMapWindowDistance(self, giface, map_): self.frame = wx.Frame(parent=None, title=_( "Map window distance measurement test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() mapWindowProperties.showRegion = True width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) giface.mapWindow = window sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() window.ZoomToWind() self._listenToAllMapWindowSignals(window) self.frame.Show() from mapwin.analysis import MeasureDistanceController self.controller = MeasureDistanceController(giface, window) self.controller.Start()
def testMapWindowProfile(self, giface, map_): self.frame = wx.Frame(parent=None, title=_("Map window profile tool test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() mapWindowProperties.showRegion = True width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) giface.mapWindow = window sizer.Add(window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() window.ZoomToWind() self._listenToAllMapWindowSignals(window) self.frame.Show() from mapwin.analysis import ProfileController self.controller = ProfileController(giface, window) self.controller.Start() rasters = [] for layer in giface.GetLayerList().GetSelectedLayers(): if layer.maplayer.GetType() == "raster": rasters.append(layer.maplayer.GetName()) from wxplot.profile import ProfileFrame profileWindow = ProfileFrame( parent=self.frame, giface=giface, controller=self.controller, units=map_.projinfo["units"], rasterList=rasters, ) profileWindow.CentreOnParent() profileWindow.Show() # Open raster select dialog to make sure that a raster (and # the desired raster) is selected to be profiled profileWindow.OnSelectRaster(None)
def testMapWindow(self, giface, map_): self.frame = wx.Frame(parent=None, title=_("Map window test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() self.frame.Show()
def testMapWindowProfile(self, giface, map_): self.frame = wx.Frame(parent=None, title=_("Map window profile tool test frame")) panel = wx.Panel(parent=self.frame, id=wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) mapWindowProperties = MapWindowProperties() mapWindowProperties.setValuesFromUserSettings() mapWindowProperties.showRegion = True width, height = self.frame.GetClientSize() copyOfInitMap(map_, width, height) window = BufferedMapWindow(parent=panel, giface=giface, Map=map_, properties=mapWindowProperties) giface.mapWindow = window sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) panel.SetSizer(sizer) panel.Layout() window.ZoomToWind() self._listenToAllMapWindowSignals(window) self.frame.Show() from mapwin.analysis import ProfileController self.controller = ProfileController(giface, window) self.controller.Start() rasters = [] for layer in giface.GetLayerList().GetSelectedLayers(): if layer.maplayer.GetType() == 'raster': rasters.append(layer.maplayer.GetName()) from wxplot.profile import ProfileFrame profileWindow = ProfileFrame(parent=self.frame, controller=self.controller, units=map_.projinfo['units'], rasterList=rasters) profileWindow.CentreOnParent() profileWindow.Show() # Open raster select dialog to make sure that a raster (and # the desired raster) is selected to be profiled profileWindow.OnSelectRaster(None)
class SwipeMapFrame(DoubleMapFrame): def __init__(self, parent=None, giface=None, title=_("GRASS GIS Map Swipe"), name="swipe", **kwargs): DoubleMapFrame.__init__(self, parent=parent, title=title, name=name, firstMap=Map(), secondMap=Map(), **kwargs) Debug.msg(1, "SwipeMapFrame.__init__()") # # Add toolbars # self.AddToolbars() self._giface = giface # # create widgets # self.splitter = MapSplitter(parent=self, id=wx.ID_ANY) self.sliderH = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL) self.sliderV = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_VERTICAL) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.autoRenderChanged.connect( self.OnAutoRenderChanged) self.firstMapWindow = SwipeBufferedWindow( parent=self.splitter, giface=self._giface, properties=self.mapWindowProperties, Map=self.firstMap) self.secondMapWindow = SwipeBufferedWindow( parent=self.splitter, giface=self._giface, properties=self.mapWindowProperties, Map=self.secondMap) # bind query signal self.firstMapWindow.mapQueried.connect(self.Query) self.secondMapWindow.mapQueried.connect(self.Query) # bind tracking cursosr to mirror it self.firstMapWindow.Bind( wx.EVT_MOTION, lambda evt: self.TrackCursor(evt)) self.secondMapWindow.Bind( wx.EVT_MOTION, lambda evt: self.TrackCursor(evt)) self.MapWindow = self.firstMapWindow # current by default self.firstMapWindow.zoomhistory = self.secondMapWindow.zoomhistory self.SetBindRegions(True) self._mode = 'swipe' self._addPanes() self._bindWindowsActivation() self._setUpMapWindow(self.firstMapWindow) self._setUpMapWindow(self.secondMapWindow) self._mgr.GetPane('sliderV').Hide() self._mgr.GetPane('sliderH').Show() self.slider = self.sliderH self.InitStatusbar() self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.SetSize((800, 600)) self._mgr.Update() self.rasters = {'first': None, 'second': None} self._inputDialog = None self._preferencesDialog = None self._queryDialog = None # default action in map toolbar self.GetMapToolbar().SelectDefault() self.resize = False wx.CallAfter(self.CallAfterInit) def TrackCursor(self, event): """Track cursor in one window and show cross in the other. Only for mirror mode. """ if self._mode == 'swipe': event.Skip() return coords = event.GetPosition() if event.GetId() == self.secondMapWindow.GetId(): self.firstMapWindow.DrawMouseCursor(coords=coords) else: self.secondMapWindow.DrawMouseCursor(coords=coords) event.Skip() def ActivateFirstMap(self, event=None): """Switch tracking direction""" super(SwipeMapFrame, self).ActivateFirstMap(event) self.firstMapWindow.ClearLines() self.firstMapWindow.Refresh() def ActivateSecondMap(self, event=None): """Switch tracking direction""" super(SwipeMapFrame, self).ActivateSecondMap(event) self.secondMapWindow.ClearLines() self.secondMapWindow.Refresh() def CallAfterInit(self): self.InitSliderBindings() self.splitter.SplitVertically( self.firstMapWindow, self.secondMapWindow, 0) self.splitter.Init() if not (self.rasters['first'] and self.rasters['second']): self.OnSelectLayers(event=None) def InitStatusbar(self): """Init statusbar (default items).""" # items for choice self.statusbarItems = [sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbAlignExtent, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbGoTo, sb.SbProjection] # create statusbar and its manager statusbar = self.CreateStatusBar(number=4, style=0) statusbar.SetMinHeight(24) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager( mapframe=self, statusbar=statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass( self.statusbarItems, mapframe=self, statusbar=statusbar) self.statusbarManager.AddStatusbarItem( sb.SbMask(self, statusbar=statusbar, position=2)) sbRender = sb.SbRender(self, statusbar=statusbar, position=3) self.statusbarManager.AddStatusbarItem(sbRender) self.statusbarManager.Update() def ResetSlider(self): if self.splitter.GetSplitMode() == wx.SPLIT_VERTICAL: size = self.splitter.GetSize()[0] else: size = self.splitter.GetSize()[1] self.slider.SetRange(0, size) self.slider.SetValue(self.splitter.GetSashPosition()) def InitSliderBindings(self): self.sliderH.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging) self.sliderH.Bind( wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged) self.sliderV.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging) self.sliderV.Bind( wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged) self.splitter.Bind( wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging) self.splitter.Bind( wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged) def OnSliderPositionChanging(self, event): """Slider changes its position, sash must be moved too.""" Debug.msg(5, "SwipeMapFrame.OnSliderPositionChanging()") self.GetFirstWindow().movingSash = True self.GetSecondWindow().movingSash = True pos = event.GetPosition() if pos > 0: self.splitter.SetSashPosition(pos) self.splitter.OnSashChanging(None) def OnSliderPositionChanged(self, event): """Slider position changed, sash must be moved too.""" Debug.msg(5, "SwipeMapFrame.OnSliderPositionChanged()") self.splitter.SetSashPosition(event.GetPosition()) self.splitter.OnSashChanged(None) def OnSashChanging(self, event): """Sash position is changing, slider must be moved too.""" Debug.msg(5, "SwipeMapFrame.OnSashChanging()") self.slider.SetValue(self.splitter.GetSashPosition()) event.Skip() def OnSashChanged(self, event): """Sash position changed, slider must be moved too.""" Debug.msg(5, "SwipeMapFrame.OnSashChanged()") self.OnSashChanging(event) event.Skip() def OnSize(self, event): Debug.msg(4, "SwipeMapFrame.OnSize()") self.resize = grass.clock() super(SwipeMapFrame, self).OnSize(event) def OnIdle(self, event): if self.resize and grass.clock() - self.resize > 0.2: w1 = self.GetFirstWindow() w2 = self.GetSecondWindow() sizeAll = self.splitter.GetSize() w1.SetClientSize(sizeAll) w2.SetClientSize(sizeAll) w1.OnSize(event) w2.OnSize(event) self.ResetSlider() self.resize = False def OnAutoRenderChanged(self, value): """Auto rendering state changed.""" style = self.splitter.GetWindowStyle() style ^= wx.SP_LIVE_UPDATE self.splitter.SetWindowStyle(style) def AddToolbars(self): """Add defined toolbar to the window Currently known toolbars are: - 'swipeMap' - basic map toolbar - 'swipeMain' - swipe functionality - 'swipeMisc' - misc (settings, help) """ self.toolbars["swipeMap"] = SwipeMapToolbar(self, self._toolSwitcher) self._mgr.AddPane(self.toolbars["swipeMap"], wx.aui.AuiPaneInfo(). Name("swipeMap").Caption(_("Map Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1).Position(1). BestSize((self.toolbars["swipeMap"].GetBestSize()))) self.toolbars["swipeMain"] = SwipeMainToolbar(self) self._mgr.AddPane(self.toolbars["swipeMain"], wx.aui.AuiPaneInfo(). Name("swipeMain").Caption(_("Main Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1).Position(0). BestSize((self.toolbars["swipeMain"].GetBestSize()))) self.toolbars["swipeMisc"] = SwipeMiscToolbar(self) self._mgr.AddPane(self.toolbars["swipeMisc"], wx.aui.AuiPaneInfo(). Name("swipeMisc").Caption(_("Misc Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1).Position(2). BestSize((self.toolbars["swipeMisc"].GetBestSize()))) def _addPanes(self): """Add splitter window and sliders to aui manager""" # splitter window self._mgr.AddPane(self.splitter, wx.aui.AuiPaneInfo(). Name('splitter').CaptionVisible(False).PaneBorder(True). Dockable(False).Floatable(False).CloseButton(False). Center().Layer(1).BestSize((self.splitter.GetBestSize()))) # sliders self._mgr.AddPane(self.sliderH, wx.aui.AuiPaneInfo(). Name('sliderH').CaptionVisible(False).PaneBorder(False). CloseButton(False).Gripper(True).GripperTop(False). BottomDockable(True).TopDockable(True). LeftDockable(False).RightDockable(False). Bottom().Layer(1).BestSize((self.sliderH.GetBestSize()))) self._mgr.AddPane(self.sliderV, wx.aui.AuiPaneInfo(). Name('sliderV').CaptionVisible(False).PaneBorder(False). CloseButton(False).Gripper(True).GripperTop(True). BottomDockable(False).TopDockable(False). LeftDockable(True).RightDockable(True). Right().Layer(1).BestSize((self.sliderV.GetBestSize()))) def ZoomToMap(self): """ Set display extents to match selected raster (including NULLs) or vector map. """ layers = [] if self.rasters['first']: layers += self.firstMap.GetListOfLayers() if self.rasters['second']: layers += self.secondMap.GetListOfLayers() if layers: self.GetFirstWindow().ZoomToMap(layers=layers) self.GetSecondWindow().ZoomToMap(layers=layers) def OnZoomToMap(self, event): """Zoom to map""" self.ZoomToMap() def OnZoomBack(self, event): self.GetFirstWindow().ZoomBack() self.secondMap.region = self.firstMap.region self.Render(self.GetSecondWindow()) def OnSelectLayers(self, event): if self._inputDialog is None: dlg = SwipeMapDialog(self, first=self.rasters['first'], second=self.rasters['second'], firstLayerList=None, secondLayerList=None) dlg.applyChanges.connect(self.OnApplyInputChanges) # connect to convertor object to convert to Map # store reference to convertor is needed otherwise it would be # discarded self._firstConverter = self._connectSimpleLmgr( dlg.GetFirstSimpleLmgr(), self.GetFirstMap()) self._secondConverter = self._connectSimpleLmgr( dlg.GetSecondSimpleLmgr(), self.GetSecondMap()) self._inputDialog = dlg dlg.CentreOnParent() dlg.Show() else: if self._inputDialog.IsShown(): self._inputDialog.Raise() self._inputDialog.SetFocus() else: self._inputDialog.Show() def _connectSimpleLmgr(self, lmgr, renderer): converter = LayerListToRendererConverter(renderer) lmgr.opacityChanged.connect(converter.ChangeLayerOpacity) lmgr.cmdChanged.connect(converter.ChangeLayerCmd) lmgr.layerAdded.connect(converter.AddLayer) lmgr.layerRemoved.connect(converter.RemoveLayer) lmgr.layerActivated.connect(converter.ChangeLayerActive) lmgr.layerMovedUp.connect(converter.MoveLayerUp) lmgr.layerMovedDown.connect(converter.MoveLayerDown) lmgr.anyChange.connect(self._simpleLmgrChanged) return converter def _simpleLmgrChanged(self): if self.IsAutoRendered(): self.OnRender(event=None) def OnApplyInputChanges(self): first, second = self._inputDialog.GetValues() if self._inputDialog.IsSimpleMode(): self.rasters['first'], self.rasters['second'] = first, second res1 = self.SetFirstRaster(name=self.rasters['first']) res2 = self.SetSecondRaster(name=self.rasters['second']) if not (res1 and res2) and first and second: message = '' if not res1: message += _("Map <%s> not found. ") % self.rasters[ 'first'] if not res2: message += _("Map <%s> not found.") % self.rasters[ 'second'] GError(parent=self, message=message) return self.ZoomToMap() else: LayerListToRendererConverter(self.GetFirstMap()).ConvertAll(first) LayerListToRendererConverter( self.GetSecondMap()).ConvertAll(second) self.SetRasterNames() if self.IsAutoRendered(): self.OnRender(event=None) def SetFirstRaster(self, name): """Set raster map to first Map""" raster = grass.find_file(name=name, element='cell') if raster['fullname']: self.rasters['first'] = raster['fullname'] self.SetLayer( name=raster['fullname'], mapInstance=self.GetFirstMap()) return True return False def SetSecondRaster(self, name): """Set raster map to second Map""" raster = grass.find_file(name=name, element='cell') if raster['fullname']: self.rasters['second'] = raster['fullname'] self.SetLayer( name=raster['fullname'], mapInstance=self.GetSecondMap()) return True return False def SetLayer(self, name, mapInstance): """Sets layer in Map. :param name: layer (raster) name """ Debug.msg(3, "SwipeMapFrame.SetLayer(): name=%s" % name) # this simple application enables to keep only one raster mapInstance.DeleteAllLayers() cmdlist = ['d.rast', 'map=%s' % name] # add layer to Map instance (core.render) newLayer = mapInstance.AddLayer( ltype='raster', command=cmdlist, active=True, name=name, hidden=False, opacity=1.0, render=True) def OnSwitchWindows(self, event): """Switch windows position.""" Debug.msg(3, "SwipeMapFrame.OnSwitchWindows()") splitter = self.splitter w1, w2 = splitter.GetWindow1(), splitter.GetWindow2() splitter.ReplaceWindow(w1, w2) splitter.ReplaceWindow(w2, w1) # self.OnSize(None) splitter.OnSashChanged(None) def _saveToFile(self, fileName, fileType): """Creates composite image by rendering both images and pasting them into the new one. .. todo:: specify size of the new image (problem is inaccurate scaling) .. todo:: make dividing line width and color optional """ w1 = self.splitter.GetWindow1() w2 = self.splitter.GetWindow2() lineWidth = 1 # render to temporary files filename1 = grass.tempfile(False) + '1' filename2 = grass.tempfile(False) + '2' width, height = self.splitter.GetClientSize() if self._mode == 'swipe': x, y = w2.GetImageCoords() w1.SaveToFile(filename1, fileType, width, height) w2.SaveToFile(filename2, fileType, width, height) else: fw, fh = w1.GetClientSize() w1.SaveToFile(filename1, fileType, fw, fh) sw, sh = w2.GetClientSize() w2.SaveToFile(filename2, fileType, sw, sh) # create empty white image - needed for line im = wx.EmptyImage(width, height) im.Replace(0, 0, 0, 255, 255, 255) # paste images if self._mode == 'swipe': if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: im1 = wx.Image(filename1).GetSubImage((0, 0, width, -y)) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), -x, -y + lineWidth) else: im1 = wx.Image(filename1).GetSubImage((0, 0, -x, height)) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), -x + lineWidth, -y) else: if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: im1 = wx.Image(filename1) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), 0, fh + lineWidth) else: im1 = wx.Image(filename1) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), fw + lineWidth, 0) im.SaveFile(fileName, fileType) # remove temporary files grass.try_remove(filename1) grass.try_remove(filename2) def SaveToFile(self, event): """Save map to image """ img = self.firstMapWindow.img or self.secondMapWindow.img if not img: GMessage(parent=self, message=_( "Nothing to render (empty map). Operation canceled.")) return filetype, ltype = GetImageHandlers(img) # get filename dlg = wx.FileDialog(parent=self, message=_("Choose a file name to save the image " "(no need to add extension)"), wildcard=filetype, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() if not path: dlg.Destroy() return base, ext = os.path.splitext(path) fileType = ltype[dlg.GetFilterIndex()]['type'] extType = ltype[dlg.GetFilterIndex()]['ext'] if ext != extType: path = base + '.' + extType self._saveToFile(path, fileType) dlg.Destroy() def OnSwitchOrientation(self, event): """Switch orientation of the sash.""" Debug.msg(3, "SwipeMapFrame.OnSwitchOrientation()") splitter = self.splitter splitter.Unsplit() if splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: splitter.SplitVertically( self.firstMapWindow, self.secondMapWindow, 0) self.slider = self.sliderH if self._mode == 'swipe': self._mgr.GetPane('sliderH').Show() self._mgr.GetPane('sliderV').Hide() else: splitter.SplitHorizontally( self.firstMapWindow, self.secondMapWindow, 0) self.slider = self.sliderV if self._mode == 'swipe': self._mgr.GetPane('sliderV').Show() self._mgr.GetPane('sliderH').Hide() self._mgr.Update() splitter.OnSashChanged(None) self.OnSize(None) self.SetRasterNames() def OnAddText(self, event): """Double click on text overlay So far not implemented. """ pass def SetViewMode(self, mode): """Sets view mode. :param mode: view mode ('swipe', 'mirror') """ if self._mode == mode: return self._mode = mode self.toolbars['swipeMain'].SetMode(mode) # set window mode self.GetFirstWindow().SetMode(mode) self.GetSecondWindow().SetMode(mode) # hide/show slider if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: self._mgr.GetPane('sliderV').Show(mode == 'swipe') size = self.splitter.GetSize()[1] / 2 else: self._mgr.GetPane('sliderH').Show(mode == 'swipe') size = self.splitter.GetSize()[0] / 2 # set sash in the middle self.splitter.SetSashPosition(size) self.slider.SetValue(size) self._mgr.Update() # enable / disable sash self.splitter.EnableSash(mode == 'swipe') # hack to make it work self.splitter.OnSashChanged(None) self.SendSizeEvent() def SetRasterNames(self): if not self._inputDialog or self._inputDialog.IsSimpleMode(): if self.rasters['first']: self.GetFirstWindow().SetRasterNameText( self.rasters['first'], 101) if self.rasters['second']: self.GetSecondWindow().SetRasterNameText( self.rasters['second'], 102) else: self.GetFirstWindow().SetRasterNameText('', 101) self.GetSecondWindow().SetRasterNameText('', 102) def Query(self, x, y): """Query active layers from both mapwindows. :param x,y: coordinates """ rasters = ( [layer.GetName() for layer in self.GetFirstMap().GetListOfLayers( ltype='raster', active=True)], [layer.GetName() for layer in self.GetSecondMap().GetListOfLayers( ltype='raster', active=True)]) vectors = ( [layer.GetName() for layer in self.GetFirstMap().GetListOfLayers( ltype='vector', active=True)], [layer.GetName() for layer in self.GetSecondMap().GetListOfLayers( ltype='vector', active=True)]) if not (rasters[0] + rasters[1] + vectors[0] + vectors[1]): GMessage( parent=self, message=_( 'No raster or vector map layer selected for querying.')) return # set query snap distance for v.what at map unit equivalent of 10 # pixels qdist = 10.0 * ( (self.GetFirstMap().region['e'] - self.GetFirstMap().region['w']) / self.GetFirstMap().width) east, north = self.GetFirstWindow().Pixel2Cell((x, y)) # use display region settings instead of computation region settings self.tmpreg = os.getenv("GRASS_REGION") os.environ["GRASS_REGION"] = self.GetFirstMap( ).SetRegion(windres=False) result = [] if rasters[0]: result.extend( grass.raster_what( map=rasters[0], coord=(east, north), localized=True)) if vectors[0]: result.extend( grass.vector_what( map=vectors[0], coord=(east, north), distance=qdist)) if rasters[1]: result.extend( grass.raster_what( map=rasters[1], coord=(east, north), localized=True)) if vectors[1]: result.extend( grass.vector_what( map=vectors[1], coord=(east, north), distance=qdist)) self._QueryMapDone() result = PrepareQueryResults(coordinates=(east, north), result=result) if self._queryDialog: self._queryDialog.Raise() self._queryDialog.SetData(result) else: self._queryDialog = QueryDialog(parent=self, data=result) self._queryDialog.Bind(wx.EVT_CLOSE, self._oncloseQueryDialog) self._queryDialog.redirectOutput.connect( lambda output: self._giface.WriteLog(output)) self._queryDialog.Show() def _oncloseQueryDialog(self, event): self._queryDialog = None event.Skip() def _QueryMapDone(self): """Restore settings after querying (restore GRASS_REGION) """ if hasattr(self, "tmpreg"): if self.tmpreg: os.environ["GRASS_REGION"] = self.tmpreg elif 'GRASS_REGION' in os.environ: del os.environ["GRASS_REGION"] elif 'GRASS_REGION' in os.environ: del os.environ["GRASS_REGION"] if hasattr(self, "tmpreg"): del self.tmpreg def GetMapToolbar(self): """Returns toolbar with zooming tools""" return self.toolbars['swipeMap'] def IsStandalone(self): """Since we do not need layer manager, we are standalone""" return True def OnHelp(self, event): self._giface.Help(entry='wxGUI.mapswipe') def OnPreferences(self, event): if not self._preferencesDialog: dlg = PreferencesDialog(parent=self, giface=self._giface) self._preferencesDialog = dlg self._preferencesDialog.CenterOnParent() self._preferencesDialog.ShowModal() def OnCloseWindow(self, event): self.GetFirstMap().Clean() self.GetSecondMap().Clean() self._mgr.UnInit() if self._inputDialog: self._inputDialog.UnInit() self.Destroy()
class RLiSetupMapPanel(wx.Panel): """Panel with mapwindow used in r.li.setup""" def __init__(self, parent, samplingType, icon=None, map_=None): wx.Panel.__init__(self, parent=parent) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() giface = StandaloneGrassInterface() self.samplingtype = samplingType self.parent = parent if map_: self.map_ = map_ else: self.map_ = Map() self.map_.region = self.map_.GetRegion() self._mgr = wx.aui.AuiManager(self) self.mapWindow = BufferedMapWindow(parent=self, giface=giface, Map=self.map_, properties=self.mapWindowProperties) self._mgr.AddPane(self.mapWindow, wx.aui.AuiPaneInfo().CentrePane(). Dockable(True).BestSize((-1, -1)).Name('mapwindow'). CloseButton(False).DestroyOnClose(True). Layer(0)) self._toolSwitcher = ToolSwitcher() self._toolSwitcher.toggleToolChanged.connect(self._onToolChanged) self.toolbar = RLiSetupToolbar(self, self._toolSwitcher) self.catId = 1 self._mgr.AddPane(self.toolbar, wx.aui.AuiPaneInfo(). Name("maptoolbar").Caption(_("Map Toolbar")). ToolbarPane().Left().Name('mapToolbar'). CloseButton(False).Layer(1).Gripper(False). BestSize((self.toolbar.GetBestSize()))) self._mgr.Update() if self.samplingtype == SamplingType.REGIONS: self.afterRegionDrawn = Signal('RLiSetupMapPanel.afterRegionDrawn') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw(graphicsType='line') elif self.samplingtype in [SamplingType.MUNITSR, SamplingType.MMVWINR]: self.sampleFrameChanged = Signal('RLiSetupMapPanel.sampleFrameChanged') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw(graphicsType='rectangle') elif self.samplingtype in [SamplingType.MUNITSC, SamplingType.MMVWINC]: self.afterCircleDrawn = Signal('RLiSetupMapPanel.afterCircleDrawn') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw(graphicsType='line') else: self.sampleFrameChanged = Signal('RLiSetupMapPanel.sampleFrameChanged') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw(graphicsType='rectangle') self._registeredGraphics.AddPen('rlisetup', wx.Pen(wx.GREEN, width=2, style=wx.SOLID)) self._registeredGraphics.AddItem(coords=[[0, 0], [0, 0]], penName='rlisetup', hide=True) if self.samplingtype != SamplingType.VECT: self.toolbar.SelectDefault() def GetMap(self): return self.map_ def OnPan(self, event): """Panning, set mouse to drag.""" self.mapWindow.SetModePan() def OnZoomIn(self, event): """Zoom in the map.""" self.mapWindow.SetModeZoomIn() def OnZoomOut(self, event): """Zoom out the map.""" self.mapWindow.SetModeZoomOut() def OnZoomToMap(self, event): layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) def OnDrawRadius(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "line" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=1, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._radiusDrawn) def OnDigitizeRegion(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "line" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=1, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._lineSegmentDrawn) self.mapWindow.mouseDClick.connect(self._mouseDbClick) self._registeredGraphics.GetItem(0).SetCoords([]) def OnDraw(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "box" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=2, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._rectangleDrawn) def _lineSegmentDrawn(self, x, y): item = self._registeredGraphics.GetItem(0) coords = item.GetCoords() if len(coords) == 0: coords.extend([self.mapWindow.Pixel2Cell(self.mapWindow.mouse['begin'])]) coords.extend([[x, y]]) item.SetCoords(coords) item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw(self.mapWindow.pdcTmp) def _mouseDbClick(self, x, y): item = self._registeredGraphics.GetItem(0) coords = item.GetCoords() coords.extend([[x, y]]) item.SetCoords(coords) item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw(self.mapWindow.pdc) self.createRegion() def createRegion(self): dlg = wx.TextEntryDialog(None, 'Name of sample region', 'Create region', 'region' + str(self.catId)) ret = dlg.ShowModal() while True: if ret == wx.ID_OK: raster = dlg.GetValue() if checkMapExists(raster): GMessage(parent=self, message=_("The raster file %s already" " exists, please change name") % raster) ret = dlg.ShowModal() else: dlg.Destroy() marea = self.writeArea(self._registeredGraphics.GetItem(0).GetCoords(), raster) self.nextRegion(next=True, area=marea) break else: self.nextRegion(next=False) break def nextRegion(self, next=True, area=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetCoords([]) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) if next is True: self.afterRegionDrawn.emit(marea=area) else: gcmd.GMessage(parent=self.parent, message=_("Raster map not created. Please redraw region.")) def writeArea(self, coords, rasterName): polyfile = tempfile.NamedTemporaryFile(delete=False) polyfile.write("AREA\n") for coor in coords: east, north = coor point = " %s %s\n" % (east, north) polyfile.write(point) catbuf = "=%d a\n" % self.catId polyfile.write(catbuf) self.catId = self.catId + 1 polyfile.close() region_settings = grass.parse_command('g.region', flags='p', delimiter=':') pname = polyfile.name.split('/')[-1] tmpraster = "rast_" + pname tmpvector = "vect_" + pname wx.BeginBusyCursor() wx.Yield() RunCommand('r.in.poly', input=polyfile.name, output=tmpraster, rows=region_settings['rows'], overwrite=True) RunCommand('r.to.vect', input=tmpraster, output=tmpvector, type='area', overwrite=True) RunCommand('v.to.rast', input=tmpvector, output=rasterName, value=1, use='val') wx.EndBusyCursor() grass.use_temp_region() grass.run_command('g.region', vector=tmpvector) region = grass.region() marea = MaskedArea(region, rasterName) RunCommand('g.remove', flags='f', type='raster', name=tmpraster) RunCommand('g.remove', flags='f', type='vector', name=tmpvector) os.unlink(polyfile.name) return marea def _onToolChanged(self): """Helper function to disconnect drawing""" try: self.mapWindow.mouseLeftUp.disconnect(self._rectangleDrawn) self.mapWindow.mouseLeftUp.disconnect(self._radiusDrawn) self.mapWindow.mouseMoving.disconnect(self._mouseMoving) self.mapWindow.mouseLeftDown.disconnect(self._mouseLeftDown) self.mapWindow.mouseDClick.disconnect(self._mouseDbClick) except DispatcherKeyError: pass def _radiusDrawn(self, x, y): """When drawing finished, get region values""" mouse = self.mapWindow.mouse item = self._registeredGraphics.GetItem(0) p1 = mouse['begin'] p2 = mouse['end'] dist, (north, east) = self.mapWindow.Distance(p1, p2, False) circle = Circle(p1, dist) self.mapWindow.ClearLines() self.mapWindow.pdcTmp.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT)) pen = wx.Pen(colour=wx.RED, width=2) self.mapWindow.pdcTmp.SetPen(pen) self.mapWindow.pdcTmp.DrawCircle(circle.point[0], circle.point[1], circle.radius) self._registeredGraphics.Draw(self.mapWindow.pdcTmp) self.createCricle(circle) def createCricle(self, c): dlg = wx.TextEntryDialog(None, 'Name of sample circle region', 'Create circle region', 'circle' + str(self.catId)) ret = dlg.ShowModal() while True: if ret == wx.ID_OK: raster = dlg.GetValue() if checkMapExists(raster): GMessage(parent=self, message=_("The raster file %s already" " exists, please change name") % raster) ret = dlg.ShowModal() else: dlg.Destroy() circle = self.writeCircle(c, raster) self.nextCircle(next=True, circle=circle) break else: self.nextCircle(next=False) break def nextCircle(self, next=True, circle=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) if next is True: self.afterCircleDrawn.emit(region=circle) else: gcmd.GMessage(parent=self.parent, message=_("Raster map not created. redraw region again.")) def writeCircle(self, circle, rasterName): coords = self.mapWindow.Pixel2Cell(circle.point) RunCommand('r.circle', output=rasterName, max=circle.radius, coordinate=coords, flags="b") grass.use_temp_region() grass.run_command('g.region', zoom=rasterName) region = grass.region() marea = MaskedArea(region, rasterName, circle.radius) return marea def _rectangleDrawn(self): """When drawing finished, get region values""" mouse = self.mapWindow.mouse item = self._registeredGraphics.GetItem(0) p1 = self.mapWindow.Pixel2Cell(mouse['begin']) p2 = self.mapWindow.Pixel2Cell(mouse['end']) item.SetCoords([p1, p2]) region = {'n': max(p1[1], p2[1]), 's': min(p1[1], p2[1]), 'w': min(p1[0], p2[0]), 'e': max(p1[0], p2[0])} item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw(self.mapWindow.pdcTmp) if self.samplingtype in [SamplingType.MUNITSR, SamplingType.MMVWINR]: dlg = wx.MessageDialog(self, "Is this area ok?", "select sampling unit", wx.YES_NO | wx.ICON_QUESTION) ret = dlg.ShowModal() if ret == wx.ID_YES: grass.use_temp_region() grass.run_command('g.region', n=region['n'], s=region['s'], e=region['e'], w=region['w']) tregion = grass.region() self.sampleFrameChanged.emit(region=tregion) self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) else: self.nextRegion(next=False) dlg.Destroy() elif self.samplingtype != SamplingType.WHOLE: """When drawing finished, get region values""" self.sampleFrameChanged.emit(region=region)
class MapPanelBase(wx.Panel): """Base class for map display window Derived class must use (create and initialize) \c statusbarManager or override GetProperty(), SetProperty() and HasProperty() methods. Several methods has to be overridden or \c NotImplementedError("MethodName") will be raised. If derived class enables and disables auto-rendering, it should override IsAutoRendered method. It is expected that derived class will call _setUpMapWindow(). Derived class can has one or more map windows (and map renders) but implementation of MapPanelBase expects that one window and one map will be current. Current instances of map window and map renderer should be returned by methods GetWindow() and GetMap() respectively. AUI manager is stored in \c self._mgr. """ def __init__( self, parent=None, id=wx.ID_ANY, title="", auimgr=None, name="", **kwargs, ): """ .. warning:: Use \a auimgr parameter only if you know what you are doing. :param parent: gui parent :param id: wx id :param title: window title :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used) :param name: panel name :param kwargs: arguments passed to \c wx.Panel """ self.parent = parent wx.Panel.__init__(self, parent, id, name=name, **kwargs) # toolbars self.toolbars = {} self.iconsize = (16, 16) # properties are shared in other objects, so defining here self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() # update statusbar when user-defined projection changed self.mapWindowProperties.useDefinedProjectionChanged.connect( self.StatusbarUpdate) # # Fancy gui # if auimgr is None: from wx.aui import AuiManager self._mgr = AuiManager(self) else: self._mgr = auimgr # handles switching between tools in different toolbars self._toolSwitcher = ToolSwitcher() self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool) # set accelerator table self.shortcuts_table = [ (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")), (self.OnRender, wx.ACCEL_CTRL, ord("R")), (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5), ] self._initShortcuts() def _initShortcuts(self): """init shortcuts to acceleration table""" accelTable = [] for handler, entry, kdb in self.shortcuts_table: wxId = NewId() self.Bind(wx.EVT_MENU, handler, id=wxId) accelTable.append((entry, kdb, wxId)) self.SetAcceleratorTable(wx.AcceleratorTable(accelTable)) def _initMap(self, Map): """Initialize map display, set dimensions and map region""" if not grass.find_program("g.region", "--help"): sys.exit( _("GRASS module '%s' not found. Unable to start map " "display window.") % "g.region") Debug.msg(2, "MapPanel._initMap():") Map.ChangeMapSize(self.GetClientSize()) Map.region = Map.GetRegion() # g.region -upgc # self.Map.SetRegion() # adjust region to match display window def _resize(self): Debug.msg(1, "MapPanel_resize():") wm, hw = self.MapWindow.GetClientSize() wf, hf = self.GetSize() dw = wf - wm dh = hf - hw self.SetSize((wf + dw, hf + dh)) def _onToggleTool(self, id): if self._toolSwitcher.IsToolInGroup(id, "mouseUse"): self.GetWindow().UnregisterAllHandlers() def OnSize(self, event): """Adjust statusbar on changing size""" # reposition checkbox in statusbar self.StatusbarReposition() # update statusbar self.StatusbarUpdate() def OnCloseWindow(self, event): self.Destroy() def GetToolSwitcher(self): return self._toolSwitcher def SetProperty(self, name, value): """Sets property""" if hasattr(self.mapWindowProperties, name): setattr(self.mapWindowProperties, name, value) else: self.statusbarManager.SetProperty(name, value) def GetProperty(self, name): """Returns property""" if hasattr(self.mapWindowProperties, name): return getattr(self.mapWindowProperties, name) else: return self.statusbarManager.GetProperty(name) def HasProperty(self, name): """Checks whether object has property""" return self.statusbarManager.HasProperty(name) def GetPPM(self): """Get pixel per meter .. todo:: now computed every time, is it necessary? .. todo:: enable user to specify ppm (and store it in UserSettings) """ # TODO: need to be fixed... # screen X region problem # user should specify ppm dc = wx.ScreenDC() dpSizePx = wx.DisplaySize() # display size in pixels dpSizeMM = wx.DisplaySizeMM() # display size in mm (system) dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches sysPpi = dc.GetPPI() comPpi = (dpSizePx[0] / dpSizeIn[0], dpSizePx[1] / dpSizeIn[1]) ppi = comPpi # pixel per inch ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100) # pixel per meter Debug.msg( 4, "MapPanelBase.GetPPM(): size: px=%d,%d mm=%f,%f " "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % ( dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1], dpSizeIn[0], dpSizeIn[1], sysPpi[0], sysPpi[1], comPpi[0], comPpi[1], ppm[0], ppm[1], ), ) return ppm def SetMapScale(self, value, map=None): """Set current map scale :param value: scale value (n if scale is 1:n) :param map: Map instance (if none self.Map is used) """ if not map: map = self.Map region = self.Map.region dEW = value * (region["cols"] / self.GetPPM()[0]) dNS = value * (region["rows"] / self.GetPPM()[1]) region["n"] = region["center_northing"] + dNS / 2.0 region["s"] = region["center_northing"] - dNS / 2.0 region["w"] = region["center_easting"] - dEW / 2.0 region["e"] = region["center_easting"] + dEW / 2.0 # add to zoom history self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"]) def GetMapScale(self, map=None): """Get current map scale :param map: Map instance (if none self.Map is used) """ if not map: map = self.GetMap() region = map.region ppm = self.GetPPM() heightCm = region["rows"] / ppm[1] * 100 widthCm = region["cols"] / ppm[0] * 100 Debug.msg( 4, "MapPanel.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm)) xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0]) yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1]) scale = (xscale + yscale) / 2.0 Debug.msg( 3, "MapPanel.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" % (xscale, yscale, scale), ) return scale def GetProgressBar(self): """Returns progress bar Progress bar can be used by other classes. """ return self.statusbarManager.GetProgressBar() def GetMap(self): """Returns current map (renderer) instance""" raise NotImplementedError("GetMap") def GetWindow(self): """Returns current map window""" raise NotImplementedError("GetWindow") def GetWindows(self): """Returns list of map windows""" raise NotImplementedError("GetWindows") def GetMapToolbar(self): """Returns toolbar with zooming tools""" raise NotImplementedError("GetMapToolbar") def GetToolbar(self, name): """Returns toolbar if exists and is active, else None.""" if name in self.toolbars and self.toolbars[name].IsShown(): return self.toolbars[name] return None def StatusbarUpdate(self): """Update statusbar content""" if self.statusbarManager: Debug.msg(5, "MapPanelBase.StatusbarUpdate()") self.statusbarManager.Update() def IsAutoRendered(self): """Check if auto-rendering is enabled""" # TODO: this is now not the right place to access this attribute # TODO: add mapWindowProperties to init parameters # and pass the right object in the init of derived class? # or do not use this method at all, let mapwindow decide return self.mapWindowProperties.autoRender def CoordinatesChanged(self): """Shows current coordinates on statusbar.""" # assuming that the first mode is coordinates # probably shold not be here but good solution is not available now if self.statusbarManager: if self.statusbarManager.GetMode() == 0: self.statusbarManager.ShowItem("coordinates") def CreateStatusbar(self, statusbarItems): """Create statusbar (default items).""" # create statusbar and its manager statusbar = wx.StatusBar(self, id=wx.ID_ANY) statusbar.SetMinHeight(24) statusbar.SetFieldsCount(3) statusbar.SetStatusWidths([-6, -2, -1]) self.statusbarManager = sb.SbManager(mapframe=self, statusbar=statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass(statusbarItems, mapframe=self, statusbar=statusbar) self.statusbarManager.AddStatusbarItem( sb.SbRender(self, statusbar=statusbar, position=2)) self.statusbarManager.Update() return statusbar def AddStatusbarPane(self): """Add statusbar as a pane""" self._mgr.AddPane( self.statusbar, wx.aui.AuiPaneInfo().Bottom().MinSize( 30, 30).Fixed().Name("statusbar").CloseButton( False).DestroyOnClose(True).ToolbarPane().Dockable( False).PaneBorder(False).Gripper(False), ) def SetStatusText(self, *args): """Overide wx.StatusBar method""" self.statusbar.SetStatusText(*args) def ShowStatusbar(self, show): """Show/hide statusbar and associated pane""" self._mgr.GetPane("statusbar").Show(show) self._mgr.Update() def IsStatusbarShown(self): """Check if statusbar is shown""" return self._mgr.GetPane("statusbar").IsShown() def StatusbarReposition(self): """Reposition items in statusbar""" if self.statusbarManager: self.statusbarManager.Reposition() def StatusbarEnableLongHelp(self, enable=True): """Enable/disable toolbars long help""" for toolbar in six.itervalues(self.toolbars): if toolbar: toolbar.EnableLongHelp(enable) def ShowAllToolbars(self, show=True): if not show: # hide action = self.RemoveToolbar else: action = self.AddToolbar for toolbar in self.GetToolbarNames(): action(toolbar) def AreAllToolbarsShown(self): return self.GetMapToolbar().IsShown() def GetToolbarNames(self): """Return toolbar names""" return list(self.toolbars.keys()) def AddToolbar(self): """Add defined toolbar to the window""" raise NotImplementedError("AddToolbar") def RemoveToolbar(self, name, destroy=False): """Removes defined toolbar from the window :param name toolbar to remove :param destroy True to destroy otherwise toolbar is only hidden """ self._mgr.DetachPane(self.toolbars[name]) if destroy: self._toolSwitcher.RemoveToolbarFromGroup("mouseUse", self.toolbars[name]) self.toolbars[name].Destroy() self.toolbars.pop(name) else: self.toolbars[name].Hide() self._mgr.Update() def IsPaneShown(self, name): """Check if pane (toolbar, mapWindow ...) of given name is currently shown""" if self._mgr.GetPane(name).IsOk(): return self._mgr.GetPane(name).IsShown() return False def OnRender(self, event): """Re-render map composition (each map layer)""" raise NotImplementedError("OnRender") def OnDraw(self, event): """Re-display current map composition""" self.MapWindow.UpdateMap(render=False) def OnErase(self, event): """Erase the canvas""" self.MapWindow.EraseMap() def OnZoomIn(self, event): """Zoom in the map.""" self.MapWindow.SetModeZoomIn() def OnZoomOut(self, event): """Zoom out the map.""" self.MapWindow.SetModeZoomOut() def _setUpMapWindow(self, mapWindow): """Binds map windows' zoom history signals to map toolbar.""" # enable or disable zoom history tool if self.GetMapToolbar(): mapWindow.zoomHistoryAvailable.connect( lambda: self.GetMapToolbar().Enable("zoomBack", enable=True)) mapWindow.zoomHistoryUnavailable.connect( lambda: self.GetMapToolbar().Enable("zoomBack", enable=False)) mapWindow.mouseMoving.connect(self.CoordinatesChanged) def OnPointer(self, event): """Sets mouse mode to pointer.""" self.MapWindow.SetModePointer() def OnPan(self, event): """Panning, set mouse to drag""" self.MapWindow.SetModePan() def OnZoomBack(self, event): """Zoom last (previously stored position)""" self.MapWindow.ZoomBack() def OnZoomToMap(self, event): """ Set display extents to match selected raster (including NULLs) or vector map. """ self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers()) def OnZoomToWind(self, event): """Set display geometry to match computational region settings (set with g.region) """ self.MapWindow.ZoomToWind() def OnZoomToDefault(self, event): """Set display geometry to match default region settings""" self.MapWindow.ZoomToDefault() def OnMapDisplayProperties(self, event): """Show Map Display Properties dialog""" from mapdisp.properties import MapDisplayPropertiesDialog dlg = MapDisplayPropertiesDialog(parent=self, mapframe=self, properties=self.mapWindowProperties) dlg.CenterOnParent() dlg.Show()
class RLiSetupMapPanel(wx.Panel): """Panel with mapwindow used in r.li.setup""" def __init__(self, parent, samplingType, icon=None, map_=None): wx.Panel.__init__(self, parent=parent) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() giface = StandaloneGrassInterface() self.samplingtype = samplingType self.parent = parent if map_: self.map_ = map_ else: self.map_ = Map() self.map_.region = self.map_.GetRegion() self._mgr = wx.aui.AuiManager(self) self.mapWindow = BufferedMapWindow(parent=self, giface=giface, Map=self.map_, properties=self.mapWindowProperties) self._mgr.AddPane(self.mapWindow, wx.aui.AuiPaneInfo().CentrePane(). Dockable(True).BestSize((-1, -1)).Name('mapwindow'). CloseButton(False).DestroyOnClose(True). Layer(0)) self._toolSwitcher = ToolSwitcher() self._toolSwitcher.toggleToolChanged.connect(self._onToolChanged) self.toolbar = RLiSetupToolbar(self, self._toolSwitcher) self.catId = 1 self._mgr.AddPane(self.toolbar, wx.aui.AuiPaneInfo(). Name("maptoolbar").Caption(_("Map Toolbar")). ToolbarPane().Left().Name('mapToolbar'). CloseButton(False).Layer(1).Gripper(False). BestSize((self.toolbar.GetBestSize()))) self._mgr.Update() if self.samplingtype == SamplingType.REGIONS: self.afterRegionDrawn = Signal('RLiSetupMapPanel.afterRegionDrawn') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw( graphicsType='line') elif self.samplingtype in [SamplingType.MUNITSR, SamplingType.MMVWINR]: self.sampleFrameChanged = Signal( 'RLiSetupMapPanel.sampleFrameChanged') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw( graphicsType='rectangle') elif self.samplingtype in [SamplingType.MUNITSC, SamplingType.MMVWINC]: self.afterCircleDrawn = Signal('RLiSetupMapPanel.afterCircleDrawn') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw( graphicsType='line') else: self.sampleFrameChanged = Signal( 'RLiSetupMapPanel.sampleFrameChanged') self._registeredGraphics = self.mapWindow.RegisterGraphicsToDraw( graphicsType='rectangle') self._registeredGraphics.AddPen('rlisetup', wx.Pen(wx.GREEN, width=2, style=wx.SOLID)) self._registeredGraphics.AddItem(coords=[[0, 0], [0, 0]], penName='rlisetup', hide=True) if self.samplingtype != SamplingType.VECT: self.toolbar.SelectDefault() def GetMap(self): return self.map_ def OnPan(self, event): """Panning, set mouse to drag.""" self.mapWindow.SetModePan() def OnZoomIn(self, event): """Zoom in the map.""" self.mapWindow.SetModeZoomIn() def OnZoomOut(self, event): """Zoom out the map.""" self.mapWindow.SetModeZoomOut() def OnZoomToMap(self, event): layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) def OnDrawRadius(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "line" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=1, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._radiusDrawn) def OnDigitizeRegion(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "line" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=1, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._lineSegmentDrawn) self.mapWindow.mouseDClick.connect(self._mouseDbClick) self._registeredGraphics.GetItem(0).SetCoords([]) def OnDraw(self, event): """Start draw mode""" self.mapWindow.mouse['use'] = "None" self.mapWindow.mouse['box'] = "box" self.mapWindow.pen = wx.Pen(colour=wx.RED, width=2, style=wx.SHORT_DASH) self.mapWindow.SetNamedCursor('cross') self.mapWindow.mouseLeftUp.connect(self._rectangleDrawn) def _lineSegmentDrawn(self, x, y): item = self._registeredGraphics.GetItem(0) coords = item.GetCoords() if len(coords) == 0: coords.extend([self.mapWindow.Pixel2Cell( self.mapWindow.mouse['begin'])]) coords.extend([[x, y]]) item.SetCoords(coords) item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw() def _mouseDbClick(self, x, y): item = self._registeredGraphics.GetItem(0) coords = item.GetCoords() coords.extend([[x, y]]) item.SetCoords(coords) item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw() self.createRegion() def createRegion(self): dlg = wx.TextEntryDialog(None, 'Name of sample region', 'Create region', 'region' + str(self.catId)) ret = dlg.ShowModal() while True: if ret == wx.ID_OK: raster = dlg.GetValue() if checkMapExists(raster): GMessage( parent=self, message=_( "The raster file %s already" " exists, please change name") % raster) ret = dlg.ShowModal() else: dlg.Destroy() marea = self.writeArea( self._registeredGraphics.GetItem(0).GetCoords(), raster) self.nextRegion(next=True, area=marea) break else: self.nextRegion(next=False) break def nextRegion(self, next=True, area=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetCoords([]) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) if next is True: self.afterRegionDrawn.emit(marea=area) else: gcmd.GMessage(parent=self.parent, message=_( "Raster map not created. Please redraw region.")) def writeArea(self, coords, rasterName): polyfile = tempfile.NamedTemporaryFile(delete=False) polyfile.write("AREA\n") for coor in coords: east, north = coor point = " %s %s\n" % (east, north) polyfile.write(point) catbuf = "=%d a\n" % self.catId polyfile.write(catbuf) self.catId = self.catId + 1 polyfile.close() region_settings = grass.parse_command('g.region', flags='p', delimiter=':') pname = polyfile.name.split('/')[-1] tmpraster = "rast_" + pname tmpvector = "vect_" + pname wx.BeginBusyCursor() wx.GetApp().Yield() RunCommand('r.in.poly', input=polyfile.name, output=tmpraster, rows=region_settings['rows'], overwrite=True) RunCommand('r.to.vect', input=tmpraster, output=tmpvector, type='area', overwrite=True) RunCommand('v.to.rast', input=tmpvector, output=rasterName, value=1, use='val') wx.EndBusyCursor() grass.use_temp_region() grass.run_command('g.region', vector=tmpvector) region = grass.region() marea = MaskedArea(region, rasterName) RunCommand('g.remove', flags='f', type='raster', name=tmpraster) RunCommand('g.remove', flags='f', type='vector', name=tmpvector) os.unlink(polyfile.name) return marea def _onToolChanged(self): """Helper function to disconnect drawing""" try: self.mapWindow.mouseLeftUp.disconnect(self._rectangleDrawn) self.mapWindow.mouseLeftUp.disconnect(self._radiusDrawn) self.mapWindow.mouseMoving.disconnect(self._mouseMoving) self.mapWindow.mouseLeftDown.disconnect(self._mouseLeftDown) self.mapWindow.mouseDClick.disconnect(self._mouseDbClick) except DispatcherKeyError: pass def _radiusDrawn(self, x, y): """When drawing finished, get region values""" mouse = self.mapWindow.mouse item = self._registeredGraphics.GetItem(0) p1 = mouse['begin'] p2 = mouse['end'] dist, (north, east) = self.mapWindow.Distance(p1, p2, False) circle = Circle(p1, dist) self.mapWindow.ClearLines() self.mapWindow.pdcTmp.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT)) pen = wx.Pen(colour=wx.RED, width=2) self.mapWindow.pdcTmp.SetPen(pen) self.mapWindow.pdcTmp.DrawCircle(circle.point[0], circle.point[1], circle.radius) self._registeredGraphics.Draw() self.createCricle(circle) def createCricle(self, c): dlg = wx.TextEntryDialog(None, 'Name of sample circle region', 'Create circle region', 'circle' + str(self.catId)) ret = dlg.ShowModal() while True: if ret == wx.ID_OK: raster = dlg.GetValue() if checkMapExists(raster): GMessage( parent=self, message=_( "The raster file %s already" " exists, please change name") % raster) ret = dlg.ShowModal() else: dlg.Destroy() circle = self.writeCircle(c, raster) self.nextCircle(next=True, circle=circle) break else: self.nextCircle(next=False) break def nextCircle(self, next=True, circle=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) if next is True: self.afterCircleDrawn.emit(region=circle) else: gcmd.GMessage(parent=self.parent, message=_( "Raster map not created. redraw region again.")) def writeCircle(self, circle, rasterName): coords = self.mapWindow.Pixel2Cell(circle.point) RunCommand('r.circle', output=rasterName, max=circle.radius, coordinate=coords, flags="b") grass.use_temp_region() grass.run_command('g.region', zoom=rasterName) region = grass.region() marea = MaskedArea(region, rasterName, circle.radius) return marea def _rectangleDrawn(self): """When drawing finished, get region values""" mouse = self.mapWindow.mouse item = self._registeredGraphics.GetItem(0) p1 = self.mapWindow.Pixel2Cell(mouse['begin']) p2 = self.mapWindow.Pixel2Cell(mouse['end']) item.SetCoords([p1, p2]) region = {'n': max(p1[1], p2[1]), 's': min(p1[1], p2[1]), 'w': min(p1[0], p2[0]), 'e': max(p1[0], p2[0])} item.SetPropertyVal('hide', False) self.mapWindow.ClearLines() self._registeredGraphics.Draw() if self.samplingtype in [SamplingType.MUNITSR, SamplingType.MMVWINR]: dlg = wx.MessageDialog(self, "Is this area ok?", "select sampling unit", wx.YES_NO | wx.ICON_QUESTION) ret = dlg.ShowModal() if ret == wx.ID_YES: grass.use_temp_region() grass.run_command('g.region', n=region['n'], s=region['s'], e=region['e'], w=region['w']) tregion = grass.region() self.sampleFrameChanged.emit(region=tregion) self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) item.SetPropertyVal('hide', True) layers = self.map_.GetListOfLayers() self.mapWindow.ZoomToMap(layers=layers, ignoreNulls=False, render=True) else: self.nextRegion(next=False) dlg.Destroy() elif self.samplingtype != SamplingType.WHOLE: """When drawing finished, get region values""" self.sampleFrameChanged.emit(region=region)
class MapFrame(SingleMapFrame): """Main frame for map display window. Drawing takes place in child double buffered drawing window. """ def __init__( self, parent, giface, title=_( "GRASS GIS Manage Location of Tick Points on a Scanned Photo"), toolbars=["gcpdisp"], Map=None, auimgr=None, name='GCPMapWindow', **kwargs): """Main map display window with toolbars, statusbar and DrawWindow :param giface: GRASS interface instance :param title: window title :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] :param map: instance of render.Map :param auimgs: AUI manager :param kwargs: wx.Frame attribures """ SingleMapFrame.__init__(self, parent=parent, giface=giface, title=title, Map=Map, auimgr=auimgr, name=name, **kwargs) self._giface = giface # properties are shared in other objects, so defining here self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.alignExtent = True # # Add toolbars # for toolb in toolbars: self.AddToolbar(toolb) self.activemap = self.toolbars['gcpdisp'].togglemap self.activemap.SetSelection(0) self.SrcMap = self.grwiz.SrcMap # instance of render.Map self.TgtMap = self.grwiz.TgtMap # instance of render.Map self._mgr.SetDockSizeConstraint(0.5, 0.5) # # Add statusbar # # items for choice self.statusbarItems = [ sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbProjection, sbgcp.SbGoToGCP, sbgcp.SbRMSError ] # create statusbar and its manager statusbar = self.CreateStatusBar(number=4, style=0) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager(mapframe=self, statusbar=statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe=self, statusbar=statusbar) self.statusbarManager.AddStatusbarItem( sb.SbMask(self, statusbar=statusbar, position=2)) self.statusbarManager.AddStatusbarItem( sb.SbRender(self, statusbar=statusbar, position=3)) self.statusbarManager.SetMode(8) # goto GCP # # Init map display (buffered DC & set default cursor) # self.grwiz.SwitchEnv('source') self.SrcMapWindow = BufferedMapWindow( parent=self, giface=self._giface, id=wx.ID_ANY, properties=self.mapWindowProperties, Map=self.SrcMap) self.grwiz.SwitchEnv('target') self.TgtMapWindow = BufferedMapWindow( parent=self, giface=self._giface, id=wx.ID_ANY, properties=self.mapWindowProperties, Map=self.TgtMap) self.MapWindow = self.SrcMapWindow self.Map = self.SrcMap self._setUpMapWindow(self.SrcMapWindow) self._setUpMapWindow(self.TgtMapWindow) self.SrcMapWindow.SetNamedCursor('cross') self.TgtMapWindow.SetNamedCursor('cross') # used to switch current map (combo box in toolbar) self.SrcMapWindow.mouseEntered.connect( lambda: self._setActiveMapWindow(self.SrcMapWindow)) self.TgtMapWindow.mouseEntered.connect( lambda: self._setActiveMapWindow(self.TgtMapWindow)) # # initialize region values # self._initMap(Map=self.SrcMap) self._initMap(Map=self.TgtMap) self.GetMapToolbar().SelectDefault() # # Bind various events # self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive) self.Bind(wx.EVT_SIZE, self.OnSize) # # Update fancy gui style # # AuiManager wants a CentrePane, workaround to get two equally sized # windows self.list = self.CreateGCPList() #self.SrcMapWindow.SetSize((300, 300)) #self.TgtMapWindow.SetSize((300, 300)) self.list.SetSize((100, 150)) self._mgr.AddPane( self.list, wx.aui.AuiPaneInfo().Name("gcplist").Caption( _("GCP List")).LeftDockable(False).RightDockable( False).PinButton().FloatingSize((600, 200)).CloseButton( False).DestroyOnClose(True).Top().Layer(1).MinSize( (200, 100))) self._mgr.AddPane( self.SrcMapWindow, wx.aui.AuiPaneInfo().Name("source").Caption( _("Source Display")).Dockable(False).CloseButton( False).DestroyOnClose(True).Floatable(False).Centre()) self._mgr.AddPane( self.TgtMapWindow, wx.aui.AuiPaneInfo().Name("target").Caption( _("Target Display")).Dockable(False).CloseButton(False). DestroyOnClose(True).Floatable(False).Right().Layer(0)) srcwidth, srcheight = self.SrcMapWindow.GetSize() tgtwidth, tgtheight = self.TgtMapWindow.GetSize() srcwidth = (srcwidth + tgtwidth) / 2 self._mgr.GetPane("target").Hide() self._mgr.Update() self._mgr.GetPane("source").BestSize((srcwidth, srcheight)) self._mgr.GetPane("target").BestSize((srcwidth, srcheight)) if self.show_target: self._mgr.GetPane("target").Show() else: self.activemap.Enable(False) # needed by Mac OS, does not harm on Linux, breaks display on Windows if platform.system() != 'Windows': self._mgr.Update() # # Init print module and classes # self.printopt = PrintOptions(self, self.MapWindow) # # Initialization of digitization tool # self.digit = None # set active map self.MapWindow = self.SrcMapWindow self.Map = self.SrcMap # do not init zoom history here, that happens when zooming to map(s) # # Re-use dialogs # self.dialogs = {} self.dialogs['attributes'] = None self.dialogs['category'] = None self.dialogs['barscale'] = None self.dialogs['legend'] = None self.decorationDialog = None # decoration/overlays # doing nice things in statusbar when other things are ready self.statusbarManager.Update() def _setUpMapWindow(self, mapWindow): # TODO: almost the smae implementation as for MapFrameBase (only names differ) # enable or disable zoom history tool mapWindow.zoomHistoryAvailable.connect( lambda: self.GetMapToolbar().Enable('zoomback', enable=True)) mapWindow.zoomHistoryUnavailable.connect( lambda: self.GetMapToolbar().Enable('zoomback', enable=False)) mapWindow.mouseMoving.connect(self.CoordinatesChanged) def AddToolbar(self, name): """Add defined toolbar to the window Currently known toolbars are: - 'map' - basic map toolbar - 'gcpdisp' - GCP Manager, Display - 'gcpman' - GCP Manager, points management - 'nviz' - 3D view mode """ # default toolbar if name == "map": self.toolbars['map'] = MapToolbar(self, self._toolSwitcher) self._mgr.AddPane( self.toolbars['map'], wx.aui.AuiPaneInfo().Name("maptoolbar").Caption( _("Map Toolbar")).ToolbarPane().Top().LeftDockable(False). RightDockable(False).BottomDockable(False).TopDockable( True).CloseButton(False).Layer(2).BestSize( (self.toolbars['map'].GetSize()))) # GCP display elif name == "gcpdisp": self.toolbars['gcpdisp'] = GCPDisplayToolbar( self, self._toolSwitcher) self._mgr.AddPane( self.toolbars['gcpdisp'], wx.aui.AuiPaneInfo().Name("gcpdisplaytoolbar").Caption( _("GCP Display toolbar")).ToolbarPane().Top().LeftDockable( False).RightDockable(False).BottomDockable(False). TopDockable(True).CloseButton(False).Layer(2)) if self.show_target == False: self.toolbars['gcpdisp'].Enable('zoommenu', enable=False) self.toolbars['gcpman'] = GCPManToolbar(self) self._mgr.AddPane( self.toolbars['gcpman'], wx.aui.AuiPaneInfo().Name("gcpmanagertoolbar").Caption( _("GCP Manager toolbar")).ToolbarPane().Top().Row(1). LeftDockable(False).RightDockable(False).BottomDockable( False).TopDockable(True).CloseButton(False).Layer(2)) self._mgr.Update() def OnUpdateProgress(self, event): """ Update progress bar info """ self.GetProgressBar().UpdateProgress(event.layer, event.map) event.Skip() def OnFocus(self, event): """ Change choicebook page to match display. Or set display for georectifying """ # was in if layer manager but considering the state it was executed # always, moreover, there is no layer manager dependent code # in GCP Management, set focus to current MapWindow for mouse actions self.OnPointer(event) self.MapWindow.SetFocus() event.Skip() def OnDraw(self, event): """Re-display current map composition """ self.MapWindow.UpdateMap(render=False) def OnRender(self, event): """Re-render map composition (each map layer) """ # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame # delete tmp map layers (queries) qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER) for layer in qlayer: self.Map.DeleteLayer(layer) self.SrcMapWindow.UpdateMap(render=True) if self.show_target: self.TgtMapWindow.UpdateMap(render=True) # update statusbar self.StatusbarUpdate() def OnPointer(self, event): """Pointer button clicked """ self.SrcMapWindow.SetModePointer() self.TgtMapWindow.SetModePointer() # change the default cursor self.SrcMapWindow.SetNamedCursor('cross') self.TgtMapWindow.SetNamedCursor('cross') def OnZoomIn(self, event): """Zoom in the map.""" self.SrcMapWindow.SetModeZoomIn() self.TgtMapWindow.SetModeZoomIn() def OnZoomOut(self, event): """Zoom out the map.""" self.SrcMapWindow.SetModeZoomOut() self.TgtMapWindow.SetModeZoomOut() def OnPan(self, event): """Panning, set mouse to drag""" self.SrcMapWindow.SetModePan() self.TgtMapWindow.SetModePan() def OnErase(self, event): """ Erase the canvas """ self.MapWindow.EraseMap() if self.MapWindow == self.SrcMapWindow: win = self.TgtMapWindow elif self.MapWindow == self.TgtMapWindow: win = self.SrcMapWindow win.EraseMap() def SaveToFile(self, event): """Save map to image """ img = self.MapWindow.img if not img: GMessage(parent=self, message=_( "Nothing to render (empty map). Operation canceled.")) return filetype, ltype = GetImageHandlers(img) # get size dlg = ImageSizeDialog(self) dlg.CentreOnParent() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return width, height = dlg.GetValues() dlg.Destroy() # get filename dlg = wx.FileDialog(parent=self, message=_("Choose a file name to save the image " "(no need to add extension)"), wildcard=filetype, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() if not path: dlg.Destroy() return base, ext = os.path.splitext(path) fileType = ltype[dlg.GetFilterIndex()]['type'] extType = ltype[dlg.GetFilterIndex()]['ext'] if ext != extType: path = base + '.' + extType self.MapWindow.SaveToFile(path, fileType, width, height) dlg.Destroy() def PrintMenu(self, event): """ Print options and output menu for map display """ point = wx.GetMousePosition() printmenu = wx.Menu() # Add items to the menu setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup')) printmenu.AppendItem(setup) self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup) preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview')) printmenu.AppendItem(preview) self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview) doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display')) printmenu.AppendItem(doprint) self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(printmenu) printmenu.Destroy() def OnZoomToRaster(self, event): """ Set display extents to match selected raster map (ignore NULLs) """ self.MapWindow.ZoomToMap(ignoreNulls=True) def OnZoomToSaved(self, event): """Set display geometry to match extents in saved region file """ self.MapWindow.SetRegion(zoomOnly=True) def OnDisplayToWind(self, event): """Set computational region (WIND file) to match display extents """ self.MapWindow.DisplayToWind() def SaveDisplayRegion(self, event): """Save display extents to named region file. """ self.MapWindow.SaveDisplayRegion() def OnZoomMenu(self, event): """Popup Zoom menu """ point = wx.GetMousePosition() zoommenu = wx.Menu() # Add items to the menu zoomwind = wx.MenuItem( zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)')) zoommenu.AppendItem(zoomwind) self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind) zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region')) zoommenu.AppendItem(zoomdefault) self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault) zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region')) zoommenu.AppendItem(zoomsaved) self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved) savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display')) zoommenu.AppendItem(savewind) self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind) savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region')) zoommenu.AppendItem(savezoom) self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(zoommenu) zoommenu.Destroy() def IsStandalone(self): """Check if Map display is standalone""" # we do not know and we do not care, so always False return True def GetLayerManager(self): """Get reference to Layer Manager :return: always None """ return None def GetSrcWindow(self): return self.SrcMapWindow def GetTgtWindow(self): return self.TgtMapWindow def GetShowTarget(self): return self.show_target def GetMapToolbar(self): """Returns toolbar with zooming tools""" return self.toolbars['gcpdisp'] def _setActiveMapWindow(self, mapWindow): if not self.MapWindow == mapWindow: self.MapWindow = mapWindow self.Map = mapWindow.Map self.UpdateActive(mapWindow) # needed for wingrass self.SetFocus()
class ExampleMapFrame(SingleMapFrame): """! Main frame of example tool. Inherits from SingleMapFrame, so map is displayed in one map widow. In case two map windows are needed, use DoubleMapFrame from (gui_core.mapdisp). @see IClassMapFrame in iclass.frame """ def __init__( self, parent, giface, title=_("Example Tool"), toolbars=["MiscToolbar", "MapToolbar", "MainToolbar"], size=(800, 600), name="exampleWindow", **kwargs, ): """!Map Frame constructor @param parent (no parent is expected) @param title window title @param toolbars list of active toolbars (default value represents all toolbars) @param size default size """ SingleMapFrame.__init__( self, parent=parent, title=title, name=name, Map=Map(), **kwargs ) # Place debug message where appropriate # and set debug level from 1 to 5 (higher to lower level functions). # To enable debug mode write: # > g.gisenv set=WX_DEBUG=5 Debug.msg(1, "ExampleMapFrame.__init__()") # # Add toolbars to aui manager # toolbarsCopy = toolbars[:] # workaround to have the same toolbar order on all platforms if sys.platform == "win32": toolbarsCopy.reverse() for toolbar in toolbarsCopy: self.AddToolbar(toolbar) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.autoRenderChanged.connect( lambda value: self.OnRender(None) if value else None ) # # Add statusbar # # choose items in statusbar choice, which makes sense for your application self.statusbarItems = [ sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbAlignExtent, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbGoTo, sb.SbProjection, ] # create statusbar and its manager statusbar = self.CreateStatusBar(number=4, style=0) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager(mapframe=self, statusbar=statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass( self.statusbarItems, mapframe=self, statusbar=statusbar ) self.statusbarManager.AddStatusbarItem( sb.SbMask(self, statusbar=statusbar, position=2) ) self.statusbarManager.AddStatusbarItem( sb.SbRender(self, statusbar=statusbar, position=3) ) self.statusbarManager.Update() # create map window self.MapWindow = BufferedMapWindow( parent=self, Map=self.GetMap(), properties=self.mapWindowProperties, giface=self, ) self._setUpMapWindow(self.MapWindow) self.MapWindow.InitZoomHistory() # create whatever you want, here it is a widget for displaying raster info self.info = ExampleInfoTextManager(self) # add map window (and other widgets) to aui manager self._addPanes() self._mgr.Update() # initialize variables related to your application functionality self.InitVariables() # default action self.GetMapToolbar().SelectDefault() self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.SetSize(size) def __del__(self): """!Destructor deletes temporary region""" gcore.del_temp_region() def OnCloseWindow(self, event): """!Destroy frame""" self.Destroy() def IsStandalone(self): """!Check if application is standalone. Standalone application can work without parent. Parent can be e.g. Layer Manager. """ if self.parent: return False return True def InitVariables(self): """!Initialize any variables nneded by application""" self.currentRaster = None self.statitistics = dict() # use WIND_OVERRIDE region not to affect current region gcore.use_temp_region() def _addPanes(self): """!Add mapwindow (and other widgets) to aui manager""" window = self.GetWindow() name = "mainWindow" self._mgr.AddPane( window, wx.aui.AuiPaneInfo() .Name(name) .CentrePane() .Dockable(False) .CloseButton(False) .DestroyOnClose(True) .Layer(0), ) window = self.info.GetControl() name = "infoText" self._mgr.AddPane( window, wx.aui.AuiPaneInfo() .Name(name) .Caption(_("Raster Info")) .MinSize((250, -1)) .Dockable(True) .CloseButton(False) .Layer(0) .Left(), ) def AddToolbar(self, name): """!Add defined toolbar to the window Currently known toolbars are: - 'ExampleMapToolbar' - basic map toolbar - 'ExampleMainToolbar' - toolbar with application specific tools - 'ExampleMiscToolbar' - toolbar with common tools (help, quit, ...) """ # see wx.aui.AuiPaneInfo documentation for understanding all options if name == "MapToolbar": self.toolbars[name] = ExampleMapToolbar(self, self._toolSwitcher) self._mgr.AddPane( self.toolbars[name], wx.aui.AuiPaneInfo() .Name(name) .Caption(_("Map Toolbar")) .ToolbarPane() .Top() .LeftDockable(False) .RightDockable(False) .BottomDockable(False) .TopDockable(True) .CloseButton(False) .Layer(1) .Row(1) .BestSize((self.toolbars[name].GetBestSize())), ) if name == "MiscToolbar": self.toolbars[name] = ExampleMiscToolbar(self) self._mgr.AddPane( self.toolbars[name], wx.aui.AuiPaneInfo() .Name(name) .Caption(_("Misc Toolbar")) .ToolbarPane() .Top() .LeftDockable(False) .RightDockable(False) .BottomDockable(False) .TopDockable(True) .CloseButton(False) .Layer(1) .Row(1) .BestSize((self.toolbars[name].GetBestSize())), ) if name == "MainToolbar": self.toolbars[name] = ExampleMainToolbar(self) self._mgr.AddPane( self.toolbars[name], wx.aui.AuiPaneInfo() .Name(name) .Caption(_("Main Toolbar")) .ToolbarPane() .Top() .LeftDockable(False) .RightDockable(False) .BottomDockable(False) .TopDockable(True) .CloseButton(False) .Layer(1) .Row(1) .BestSize((self.toolbars[name].GetBestSize())), ) def GetMapToolbar(self): """!Returns toolbar with zooming tools""" return self.toolbars["MapToolbar"] def OnHelp(self, event): """!Show help page""" RunCommand("g.manual", entry="wxGUI.Example") def OnSelectRaster(self, event): """!Opens dialog to select raster map""" dlg = ExampleMapDialog(self) if dlg.ShowModal() == wx.ID_OK: raster = gcore.find_file(name=dlg.GetRasterMap(), element="cell") if raster["fullname"]: self.SetLayer(name=raster["fullname"]) else: # show user that the map name is incorrect GError( parent=self, message=_("Raster map <{raster}> not found").format( raster=dlg.GetRasterMap() ), ) dlg.Destroy() def SetLayer(self, name): """!Sets layer in Map and updates statistics. @param name layer (raster) name """ Debug.msg(3, "ExampleMapFrame.SetLayer(): name=%s" % name) # this simple application enables to keep only one raster self.GetMap().DeleteAllLayers() cmdlist = ["d.rast", "map=%s" % name] # add layer to Map instance (core.render) newLayer = self.GetMap().AddLayer( ltype="raster", command=cmdlist, active=True, name=name, hidden=False, opacity=1.0, render=True, ) self.GetWindow().ZoomToMap( layers=[ newLayer, ], render=True, ) self.currentRaster = name # change comp. region to match new raster, so that the statistics # are computed for the entire raster RunCommand("g.region", rast=self.currentRaster, parent=self) self.UpdateStatistics() def ComputeStatitistics(self): """!Computes statistics for raster map using 'r.univar' module. @return statistic in form of dictionary """ # RunCommand enables to run GRASS module res = RunCommand( "r.univar", # module name flags="g", # command flags map=self.currentRaster, # module parameters read=True, ) # get command output return gcore.parse_key_val(res, val_type=float) def UpdateStatistics(self): """!Upadate statistic information. Called after changing raster map. """ stats = self.ComputeStatitistics() self.info.WriteStatistics(name=self.currentRaster, statDict=stats)
class ExampleMapFrame(SingleMapFrame): """! Main frame of example tool. Inherits from SingleMapFrame, so map is displayed in one map widow. In case two map windows are needed, use DoubleMapFrame from (gui_core.mapdisp). @see IClassMapFrame in iclass.frame """ def __init__(self, parent, giface, title=_("Example Tool"), toolbars=["MiscToolbar", "MapToolbar", "MainToolbar"], size=(800, 600), name='exampleWindow', **kwargs): """!Map Frame constructor @param parent (no parent is expected) @param title window title @param toolbars list of active toolbars (default value represents all toolbars) @param size default size """ SingleMapFrame.__init__(self, parent=parent, title=title, name=name, Map=Map(), **kwargs) # Place debug message where appropriate # and set debug level from 1 to 5 (higher to lower level functions). # To enable debug mode write: # > g.gisenv set=WX_DEBUG=5 Debug.msg(1, "ExampleMapFrame.__init__()") # # Add toolbars to aui manager # toolbarsCopy = toolbars[:] # workaround to have the same toolbar order on all platforms if sys.platform == 'win32': toolbarsCopy.reverse() for toolbar in toolbarsCopy: self.AddToolbar(toolbar) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.autoRenderChanged.connect( lambda value: self.OnRender(None) if value else None) # # Add statusbar # # choose items in statusbar choice, which makes sense for your application self.statusbarItems = [sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbAlignExtent, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbGoTo, sb.SbProjection] # create statusbar and its manager statusbar = self.CreateStatusBar(number=4, style=0) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager(mapframe=self, statusbar=statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe=self, statusbar=statusbar) self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar=statusbar, position=2)) self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar=statusbar, position=3)) self.statusbarManager.Update() # create map window self.MapWindow = BufferedMapWindow(parent=self, Map=self.GetMap(), properties=self.mapWindowProperties, giface=self) self._setUpMapWindow(self.MapWindow) self.MapWindow.InitZoomHistory() # create whatever you want, here it is a widget for displaying raster info self.info = ExampleInfoTextManager(self) # add map window (and other widgets) to aui manager self._addPanes() self._mgr.Update() # initialize variables related to your application functionality self.InitVariables() # default action self.GetMapToolbar().SelectDefault() self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.SetSize(size) def __del__(self): """!Destructor deletes temporary region""" gcore.del_temp_region() def OnCloseWindow(self, event): """!Destroy frame""" self.Destroy() def IsStandalone(self): """!Check if application is standalone. Standalone application can work without parent. Parent can be e.g. Layer Manager. """ if self.parent: return False return True def InitVariables(self): """!Initialize any variables nneded by application""" self.currentRaster = None self.statitistics = dict() # use WIND_OVERRIDE region not to affect current region gcore.use_temp_region() def _addPanes(self): """!Add mapwindow (and other widgets) to aui manager""" window = self.GetWindow() name = "mainWindow" self._mgr.AddPane(window, wx.aui.AuiPaneInfo(). Name(name).CentrePane(). Dockable(False).CloseButton(False).DestroyOnClose(True). Layer(0)) window = self.info.GetControl() name = "infoText" self._mgr.AddPane(window, wx.aui.AuiPaneInfo(). Name(name).Caption(_("Raster Info")).MinSize((250, -1)). Dockable(True).CloseButton(False). Layer(0).Left()) def AddToolbar(self, name): """!Add defined toolbar to the window Currently known toolbars are: - 'ExampleMapToolbar' - basic map toolbar - 'ExampleMainToolbar' - toolbar with application specific tools - 'ExampleMiscToolbar' - toolbar with common tools (help, quit, ...) """ # see wx.aui.AuiPaneInfo documentation for understanding all options if name == "MapToolbar": self.toolbars[name] = ExampleMapToolbar(self, self._toolSwitcher) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Map Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(1).Row(1). BestSize((self.toolbars[name].GetBestSize()))) if name == "MiscToolbar": self.toolbars[name] = ExampleMiscToolbar(self) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Misc Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(1).Row(1). BestSize((self.toolbars[name].GetBestSize()))) if name == "MainToolbar": self.toolbars[name] = ExampleMainToolbar(self) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Main Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(1).Row(1). BestSize((self.toolbars[name].GetBestSize()))) def GetMapToolbar(self): """!Returns toolbar with zooming tools""" return self.toolbars['MapToolbar'] def OnHelp(self, event): """!Show help page""" RunCommand('g.manual', entry='wxGUI.Example') def OnSelectRaster(self, event): """!Opens dialog to select raster map""" dlg = ExampleMapDialog(self) if dlg.ShowModal() == wx.ID_OK: raster = gcore.find_file(name=dlg.GetRasterMap(), element='cell') if raster['fullname']: self.SetLayer(name=raster['fullname']) else: # show user that the map name is incorrect GError(parent=self, message=_("Raster map <{raster}> not found").format(raster=dlg.GetRasterMap())) dlg.Destroy() def SetLayer(self, name): """!Sets layer in Map and updates statistics. @param name layer (raster) name """ Debug.msg (3, "ExampleMapFrame.SetLayer(): name=%s" % name) # this simple application enables to keep only one raster self.GetMap().DeleteAllLayers() cmdlist = ['d.rast', 'map=%s' % name] # add layer to Map instance (core.render) newLayer = self.GetMap().AddLayer(ltype='raster', command=cmdlist, active=True, name=name, hidden=False, opacity=1.0, render=True) self.GetWindow().ZoomToMap(layers=[newLayer, ], render=True) self.currentRaster = name # change comp. region to match new raster, so that the statistics # are computed for the entire raster RunCommand('g.region', rast=self.currentRaster, parent=self) self.UpdateStatistics() def ComputeStatitistics(self): """!Computes statistics for raster map using 'r.univar' module. @return statistic in form of dictionary """ # RunCommand enables to run GRASS module res = RunCommand('r.univar', # module name flags='g', # command flags map=self.currentRaster, # module parameters read=True) # get command output return gcore.parse_key_val(res, val_type=float) def UpdateStatistics(self): """!Upadate statistic information. Called after changing raster map. """ stats = self.ComputeStatitistics() self.info.WriteStatistics(name=self.currentRaster, statDict=stats)
class SwipeMapFrame(DoubleMapFrame): def __init__(self, parent = None, giface = None, title = _("GRASS GIS Map Swipe"), name = "swipe", **kwargs): DoubleMapFrame.__init__(self, parent = parent, title = title, name = name, firstMap = Map(), secondMap = Map(), **kwargs) Debug.msg (1, "SwipeMapFrame.__init__()") # # Add toolbars # toolbars = ['swipeMisc', 'swipeMap', 'swipeMain'] if sys.platform == 'win32': self.AddToolbar(toolbars.pop(1)) toolbars.reverse() else: self.AddToolbar(toolbars.pop(0)) for toolb in toolbars: self.AddToolbar(toolb) self._giface = giface # # create widgets # self.splitter = MapSplitter(parent = self, id = wx.ID_ANY) self.sliderH = wx.Slider(self, id = wx.ID_ANY, style = wx.SL_HORIZONTAL) self.sliderV = wx.Slider(self, id = wx.ID_ANY, style = wx.SL_VERTICAL) self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.autoRenderChanged.connect(self.OnAutoRenderChanged) self.firstMapWindow = SwipeBufferedWindow(parent = self.splitter, giface = self._giface, properties=self.mapWindowProperties, Map = self.firstMap) self.secondMapWindow = SwipeBufferedWindow(parent = self.splitter, giface = self._giface, properties=self.mapWindowProperties, Map = self.secondMap) # bind query signal self.firstMapWindow.mapQueried.connect(self.Query) self.secondMapWindow.mapQueried.connect(self.Query) # bind tracking cursosr to mirror it self.firstMapWindow.Bind(wx.EVT_MOTION, lambda evt: self.TrackCursor(evt)) self.secondMapWindow.Bind(wx.EVT_MOTION, lambda evt: self.TrackCursor(evt)) self.MapWindow = self.firstMapWindow # current by default self.firstMapWindow.zoomhistory = self.secondMapWindow.zoomhistory self.SetBindRegions(True) self._mode = 'swipe' self._addPanes() self._bindWindowsActivation() self._setUpMapWindow(self.firstMapWindow) self._setUpMapWindow(self.secondMapWindow) self._mgr.GetPane('sliderV').Hide() self._mgr.GetPane('sliderH').Show() self.slider = self.sliderH self.InitStatusbar() self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.SetSize((800, 600)) self._mgr.Update() self.rasters = {'first': None, 'second': None} self._inputDialog = None self._preferencesDialog = None self._queryDialog = None # default action in map toolbar self.GetMapToolbar().SelectDefault() self.resize = False wx.CallAfter(self.CallAfterInit) def TrackCursor(self, event): """Track cursor in one window and show cross in the other. Only for mirror mode. """ if self._mode == 'swipe': event.Skip() return coords = event.GetPosition() if event.GetId() == self.secondMapWindow.GetId(): self.firstMapWindow.DrawMouseCursor(coords=coords) else: self.secondMapWindow.DrawMouseCursor(coords=coords) event.Skip() def ActivateFirstMap(self, event = None): """Switch tracking direction""" super(SwipeMapFrame, self).ActivateFirstMap(event) self.firstMapWindow.ClearLines() self.firstMapWindow.Refresh() def ActivateSecondMap(self, event = None): """Switch tracking direction""" super(SwipeMapFrame, self).ActivateSecondMap(event) self.secondMapWindow.ClearLines() self.secondMapWindow.Refresh() def CallAfterInit(self): self.InitSliderBindings() self.splitter.SplitVertically(self.firstMapWindow, self.secondMapWindow, 0) self.splitter.Init() if not (self.rasters['first'] and self.rasters['second']): self.OnSelectLayers(event=None) def InitStatusbar(self): """Init statusbar (default items).""" # items for choice self.statusbarItems = [sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbAlignExtent, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbGoTo, sb.SbProjection] # create statusbar and its manager statusbar = self.CreateStatusBar(number = 4, style = 0) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar) self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2)) sbRender = sb.SbRender(self, statusbar = statusbar, position = 3) self.statusbarManager.AddStatusbarItem(sbRender) self.statusbarManager.Update() def ResetSlider(self): if self.splitter.GetSplitMode() == wx.SPLIT_VERTICAL: size = self.splitter.GetSize()[0] else: size = self.splitter.GetSize()[1] self.slider.SetRange(0, size) self.slider.SetValue(self.splitter.GetSashPosition()) def InitSliderBindings(self): self.sliderH.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging) self.sliderH.Bind(wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged) self.sliderV.Bind(wx.EVT_SPIN, self.OnSliderPositionChanging) self.sliderV.Bind(wx.EVT_SCROLL_THUMBRELEASE, self.OnSliderPositionChanged) self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.OnSashChanging) self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged) def OnSliderPositionChanging(self, event): """Slider changes its position, sash must be moved too.""" Debug.msg (5, "SwipeMapFrame.OnSliderPositionChanging()") self.GetFirstWindow().movingSash = True self.GetSecondWindow().movingSash = True pos = event.GetPosition() if pos > 0: self.splitter.SetSashPosition(pos) self.splitter.OnSashChanging(None) def OnSliderPositionChanged(self, event): """Slider position changed, sash must be moved too.""" Debug.msg (5, "SwipeMapFrame.OnSliderPositionChanged()") self.splitter.SetSashPosition(event.GetPosition()) self.splitter.OnSashChanged(None) def OnSashChanging(self, event): """Sash position is changing, slider must be moved too.""" Debug.msg (5, "SwipeMapFrame.OnSashChanging()") self.slider.SetValue(self.splitter.GetSashPosition()) event.Skip() def OnSashChanged(self, event): """Sash position changed, slider must be moved too.""" Debug.msg (5, "SwipeMapFrame.OnSashChanged()") self.OnSashChanging(event) event.Skip() def OnSize(self, event): Debug.msg (4, "SwipeMapFrame.OnSize()") self.resize = time.clock() super(SwipeMapFrame, self).OnSize(event) def OnIdle(self, event): if self.resize and time.clock() - self.resize > 0.2: w1 = self.GetFirstWindow() w2 = self.GetSecondWindow() sizeAll = self.splitter.GetSize() w1.SetClientSize(sizeAll) w2.SetClientSize(sizeAll) w1.OnSize(event) w2.OnSize(event) self.ResetSlider() self.resize = False def OnAutoRenderChanged(self, value): """Auto rendering state changed.""" style = self.splitter.GetWindowStyle() style ^= wx.SP_LIVE_UPDATE self.splitter.SetWindowStyle(style) def AddToolbar(self, name): """Add defined toolbar to the window Currently known toolbars are: - 'swipeMap' - basic map toolbar - 'swipeMain' - swipe functionality """ if name == "swipeMap": self.toolbars[name] = SwipeMapToolbar(self, self._toolSwitcher) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Map Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1). BestSize((self.toolbars[name].GetBestSize()))) if name == "swipeMain": self.toolbars[name] = SwipeMainToolbar(self) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Main Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1). BestSize((self.toolbars[name].GetBestSize()))) if name == "swipeMisc": self.toolbars[name] = SwipeMiscToolbar(self) self._mgr.AddPane(self.toolbars[name], wx.aui.AuiPaneInfo(). Name(name).Caption(_("Misc Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2).Row(1). BestSize((self.toolbars[name].GetBestSize()))) def _addPanes(self): """Add splitter window and sliders to aui manager""" # splitter window self._mgr.AddPane(self.splitter, wx.aui.AuiPaneInfo(). Name('splitter').CaptionVisible(False).PaneBorder(True). Dockable(False).Floatable(False).CloseButton(False). Center().Layer(1).BestSize((self.splitter.GetBestSize()))) # sliders self._mgr.AddPane(self.sliderH, wx.aui.AuiPaneInfo(). Name('sliderH').CaptionVisible(False).PaneBorder(False). CloseButton(False).Gripper(True).GripperTop(False). BottomDockable(True).TopDockable(True). LeftDockable(False).RightDockable(False). Bottom().Layer(1).BestSize((self.sliderH.GetBestSize()))) self._mgr.AddPane(self.sliderV, wx.aui.AuiPaneInfo(). Name('sliderV').CaptionVisible(False).PaneBorder(False). CloseButton(False).Gripper(True).GripperTop(True). BottomDockable(False).TopDockable(False). LeftDockable(True).RightDockable(True). Right().Layer(1).BestSize((self.sliderV.GetBestSize()))) def ZoomToMap(self): """ Set display extents to match selected raster (including NULLs) or vector map. """ layers = [] if self.rasters['first']: layers += self.firstMap.GetListOfLayers() if self.rasters['second']: layers += self.secondMap.GetListOfLayers() if layers: self.GetFirstWindow().ZoomToMap(layers=layers) self.GetSecondWindow().ZoomToMap(layers=layers) def OnZoomToMap(self, event): """Zoom to map""" self.ZoomToMap() def OnZoomBack(self, event): self.GetFirstWindow().ZoomBack() self.secondMap.region = self.firstMap.region self.Render(self.GetSecondWindow()) def OnSelectLayers(self, event): if self._inputDialog is None: dlg = SwipeMapDialog(self, first=self.rasters['first'], second=self.rasters['second'], firstLayerList=None, secondLayerList=None) dlg.applyChanges.connect(self.OnApplyInputChanges) # connect to convertor object to convert to Map # store reference to convertor is needed otherwise it would be discarded self._firstConverter = self._connectSimpleLmgr(dlg.GetFirstSimpleLmgr(), self.GetFirstMap()) self._secondConverter = self._connectSimpleLmgr(dlg.GetSecondSimpleLmgr(), self.GetSecondMap()) self._inputDialog = dlg dlg.CentreOnParent() dlg.Show() else: if self._inputDialog.IsShown(): self._inputDialog.Raise() self._inputDialog.SetFocus() else: self._inputDialog.Show() def _connectSimpleLmgr(self, lmgr, renderer): converter = LayerListToRendererConverter(renderer) lmgr.opacityChanged.connect(converter.ChangeLayerOpacity) lmgr.cmdChanged.connect(converter.ChangeLayerCmd) lmgr.layerAdded.connect(converter.AddLayer) lmgr.layerRemoved.connect(converter.RemoveLayer) lmgr.layerActivated.connect(converter.ChangeLayerActive) lmgr.layerMovedUp.connect(converter.MoveLayerUp) lmgr.layerMovedDown.connect(converter.MoveLayerDown) lmgr.anyChange.connect(self._simpleLmgrChanged) return converter def _simpleLmgrChanged(self): if self.IsAutoRendered(): self.OnRender(event=None) def OnApplyInputChanges(self): first, second = self._inputDialog.GetValues() if self._inputDialog.IsSimpleMode(): self.rasters['first'], self.rasters['second'] = first, second res1 = self.SetFirstRaster(name=self.rasters['first']) res2 = self.SetSecondRaster(name=self.rasters['second']) if not (res1 and res2) and first and second: message = '' if not res1: message += _("Map <%s> not found. ") % self.rasters['first'] if not res2: message += _("Map <%s> not found.") % self.rasters['second'] GError(parent = self, message = message) return self.ZoomToMap() else: LayerListToRendererConverter(self.GetFirstMap()).ConvertAll(first) LayerListToRendererConverter(self.GetSecondMap()).ConvertAll(second) self.SetRasterNames() if self.IsAutoRendered(): self.OnRender(event=None) def SetFirstRaster(self, name): """Set raster map to first Map""" raster = grass.find_file(name = name, element = 'cell') if raster['fullname']: self.rasters['first'] = raster['fullname'] self.SetLayer(name = raster['fullname'], mapInstance = self.GetFirstMap()) return True return False def SetSecondRaster(self, name): """Set raster map to second Map""" raster = grass.find_file(name = name, element = 'cell') if raster['fullname']: self.rasters['second'] = raster['fullname'] self.SetLayer(name = raster['fullname'], mapInstance = self.GetSecondMap()) return True return False def SetLayer(self, name, mapInstance): """Sets layer in Map. :param name: layer (raster) name """ Debug.msg (3, "SwipeMapFrame.SetLayer(): name=%s" % name) # this simple application enables to keep only one raster mapInstance.DeleteAllLayers() cmdlist = ['d.rast', 'map=%s' % name] # add layer to Map instance (core.render) newLayer = mapInstance.AddLayer(ltype = 'raster', command = cmdlist, active = True, name = name, hidden = False, opacity = 1.0, render = True) def OnSwitchWindows(self, event): """Switch windows position.""" Debug.msg(3, "SwipeMapFrame.OnSwitchWindows()") splitter = self.splitter w1, w2 = splitter.GetWindow1(), splitter.GetWindow2() splitter.ReplaceWindow(w1, w2) splitter.ReplaceWindow(w2, w1) # self.OnSize(None) splitter.OnSashChanged(None) def _saveToFile(self, fileName, fileType): """Creates composite image by rendering both images and pasting them into the new one. .. todo:: specify size of the new image (problem is inaccurate scaling) .. todo:: make dividing line width and color optional """ w1 = self.splitter.GetWindow1() w2 = self.splitter.GetWindow2() lineWidth = 1 # render to temporary files filename1 = grass.tempfile(False) + '1' filename2 = grass.tempfile(False) + '2' width, height = self.splitter.GetClientSize() if self._mode == 'swipe': x, y = w2.GetImageCoords() w1.SaveToFile(filename1, fileType, width, height) w2.SaveToFile(filename2, fileType, width, height) else: fw, fh = w1.GetClientSize() w1.SaveToFile(filename1, fileType, fw, fh) sw, sh = w2.GetClientSize() w2.SaveToFile(filename2, fileType, sw, sh) # create empty white image - needed for line im = wx.EmptyImage(width, height) im.Replace(0, 0, 0, 255, 255, 255) # paste images if self._mode == 'swipe': if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: im1 = wx.Image(filename1).GetSubImage((0, 0, width, -y)) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), -x, -y + lineWidth) else: im1 = wx.Image(filename1).GetSubImage((0, 0, -x, height)) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), -x + lineWidth, -y) else: if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: im1 = wx.Image(filename1) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), 0, fh + lineWidth) else: im1 = wx.Image(filename1) im.Paste(im1, 0, 0) im.Paste(wx.Image(filename2), fw + lineWidth, 0) im.SaveFile(fileName, fileType) # remove temporary files grass.try_remove(filename1) grass.try_remove(filename2) def SaveToFile(self, event): """Save map to image """ img = self.firstMapWindow.img or self.secondMapWindow.img if not img: GMessage(parent = self, message = _("Nothing to render (empty map). Operation canceled.")) return filetype, ltype = GetImageHandlers(img) # get filename dlg = wx.FileDialog(parent = self, message = _("Choose a file name to save the image " "(no need to add extension)"), wildcard = filetype, style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() if not path: dlg.Destroy() return base, ext = os.path.splitext(path) fileType = ltype[dlg.GetFilterIndex()]['type'] extType = ltype[dlg.GetFilterIndex()]['ext'] if ext != extType: path = base + '.' + extType self._saveToFile(path, fileType) dlg.Destroy() def OnSwitchOrientation(self, event): """Switch orientation of the sash.""" Debug.msg(3, "SwipeMapFrame.OnSwitchOrientation()") splitter = self.splitter splitter.Unsplit() if splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: splitter.SplitVertically(self.firstMapWindow, self.secondMapWindow, 0) self.slider = self.sliderH if self._mode == 'swipe': self._mgr.GetPane('sliderH').Show() self._mgr.GetPane('sliderV').Hide() else: splitter.SplitHorizontally(self.firstMapWindow, self.secondMapWindow, 0) self.slider = self.sliderV if self._mode == 'swipe': self._mgr.GetPane('sliderV').Show() self._mgr.GetPane('sliderH').Hide() self._mgr.Update() splitter.OnSashChanged(None) self.OnSize(None) self.SetRasterNames() def OnAddText(self, event): """Double click on text overlay So far not implemented. """ pass def SetViewMode(self, mode): """Sets view mode. :param mode: view mode ('swipe', 'mirror') """ if self._mode == mode: return self._mode = mode self.toolbars['swipeMain'].SetMode(mode) # set window mode self.GetFirstWindow().SetMode(mode) self.GetSecondWindow().SetMode(mode) # hide/show slider if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL: self._mgr.GetPane('sliderV').Show(mode == 'swipe') size = self.splitter.GetSize()[1] / 2 else: self._mgr.GetPane('sliderH').Show(mode == 'swipe') size = self.splitter.GetSize()[0] / 2 # set sash in the middle self.splitter.SetSashPosition(size) self.slider.SetValue(size) self._mgr.Update() # enable / disable sash self.splitter.EnableSash(mode == 'swipe') # hack to make it work self.splitter.OnSashChanged(None) self.SendSizeEvent() def SetRasterNames(self): if not self._inputDialog or self._inputDialog.IsSimpleMode(): if self.rasters['first']: self.GetFirstWindow().SetRasterNameText(self.rasters['first'], 101) if self.rasters['second']: self.GetSecondWindow().SetRasterNameText(self.rasters['second'], 102) else: self.GetFirstWindow().SetRasterNameText('', 101) self.GetSecondWindow().SetRasterNameText('', 102) def Query(self, x, y): """Query active layers from both mapwindows. :param x,y: coordinates """ rasters = ([layer.GetName() for layer in self.GetFirstMap().GetListOfLayers(ltype='raster', active=True)], [layer.GetName() for layer in self.GetSecondMap().GetListOfLayers(ltype='raster', active=True)]) vectors = ([layer.GetName() for layer in self.GetFirstMap().GetListOfLayers(ltype='vector', active=True)], [layer.GetName() for layer in self.GetSecondMap().GetListOfLayers(ltype='vector', active=True)]) if not (rasters[0] + rasters[1] + vectors[0] + vectors[1]): GMessage(parent=self, message=_('No raster or vector map layer selected for querying.')) return # set query snap distance for v.what at map unit equivalent of 10 pixels qdist = 10.0 * ((self.GetFirstMap().region['e'] - self.GetFirstMap().region['w']) / self.GetFirstMap().width) east, north = self.GetFirstWindow().Pixel2Cell((x, y)) # use display region settings instead of computation region settings self.tmpreg = os.getenv("GRASS_REGION") os.environ["GRASS_REGION"] = self.GetFirstMap().SetRegion(windres=False) result = [] if rasters[0]: result.extend(grass.raster_what(map=rasters[0], coord=(east, north), localized=True)) if vectors[0]: result.extend(grass.vector_what(map=vectors[0], coord=(east, north), distance=qdist)) if rasters[1]: result.extend(grass.raster_what(map=rasters[1], coord=(east, north), localized=True)) if vectors[1]: result.extend(grass.vector_what(map=vectors[1], coord=(east, north), distance=qdist)) self._QueryMapDone() result = PrepareQueryResults(coordinates=(east, north), result=result) if self._queryDialog: self._queryDialog.Raise() self._queryDialog.SetData(result) else: self._queryDialog = QueryDialog(parent=self, data=result) self._queryDialog.Bind(wx.EVT_CLOSE, self._oncloseQueryDialog) self._queryDialog.redirectOutput.connect(lambda output: self._giface.WriteLog(output)) self._queryDialog.Show() def _oncloseQueryDialog(self, event): self._queryDialog = None event.Skip() def _QueryMapDone(self): """Restore settings after querying (restore GRASS_REGION) """ if hasattr(self, "tmpreg"): if self.tmpreg: os.environ["GRASS_REGION"] = self.tmpreg elif 'GRASS_REGION' in os.environ: del os.environ["GRASS_REGION"] elif 'GRASS_REGION' in os.environ: del os.environ["GRASS_REGION"] if hasattr(self, "tmpreg"): del self.tmpreg def GetMapToolbar(self): """Returns toolbar with zooming tools""" return self.toolbars['swipeMap'] def IsStandalone(self): """Since we do not need layer manager, we are standalone""" return True def OnHelp(self, event): self._giface.Help(entry = 'wxGUI.mapswipe') def OnPreferences(self, event): if not self._preferencesDialog: dlg = PreferencesDialog(parent=self, giface=self._giface) self._preferencesDialog = dlg self._preferencesDialog.CenterOnParent() self._preferencesDialog.ShowModal() def OnCloseWindow(self, event): self.GetFirstMap().Clean() self.GetSecondMap().Clean() self.Destroy()
class MapFrame(SingleMapFrame): """Main frame for map display window. Drawing takes place in child double buffered drawing window. """ def __init__(self, parent, giface, title=_("GRASS GIS Manage Ground Control Points"), toolbars=["gcpdisp"], Map=None, auimgr=None, name='GCPMapWindow', **kwargs): """Main map display window with toolbars, statusbar and DrawWindow :param giface: GRASS interface instance :param title: window title :param toolbars: array of activated toolbars, e.g. ['map', 'digit'] :param map: instance of render.Map :param auimgs: AUI manager :param kwargs: wx.Frame attribures """ SingleMapFrame.__init__(self, parent = parent, giface = giface, title = title, Map = Map, auimgr = auimgr, name = name, **kwargs) self._giface = giface # properties are shared in other objects, so defining here self.mapWindowProperties = MapWindowProperties() self.mapWindowProperties.setValuesFromUserSettings() self.mapWindowProperties.alignExtent = True # # Add toolbars # for toolb in toolbars: self.AddToolbar(toolb) self.activemap = self.toolbars['gcpdisp'].togglemap self.activemap.SetSelection(0) self.SrcMap = self.grwiz.SrcMap # instance of render.Map self.TgtMap = self.grwiz.TgtMap # instance of render.Map self._mgr.SetDockSizeConstraint(0.5, 0.5) # # Add statusbar # # items for choice self.statusbarItems = [sb.SbCoordinates, sb.SbRegionExtent, sb.SbCompRegionExtent, sb.SbShowRegion, sb.SbResolution, sb.SbDisplayGeometry, sb.SbMapScale, sb.SbProjection, sbgcp.SbGoToGCP, sbgcp.SbRMSError] # create statusbar and its manager statusbar = self.CreateStatusBar(number = 4, style = 0) statusbar.SetStatusWidths([-5, -2, -1, -1]) self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar) # fill statusbar manager self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar) self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2)) self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3)) self.statusbarManager.SetMode(8) # goto GCP # # Init map display (buffered DC & set default cursor) # self.grwiz.SwitchEnv('source') self.SrcMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY, properties=self.mapWindowProperties, Map=self.SrcMap) self.grwiz.SwitchEnv('target') self.TgtMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY, properties=self.mapWindowProperties, Map=self.TgtMap) self.MapWindow = self.SrcMapWindow self.Map = self.SrcMap self._setUpMapWindow(self.SrcMapWindow) self._setUpMapWindow(self.TgtMapWindow) self.SrcMapWindow.SetNamedCursor('cross') self.TgtMapWindow.SetNamedCursor('cross') # used to switch current map (combo box in toolbar) self.SrcMapWindow.mouseEntered.connect( lambda: self._setActiveMapWindow(self.SrcMapWindow)) self.TgtMapWindow.mouseEntered.connect( lambda: self._setActiveMapWindow(self.TgtMapWindow)) # # initialize region values # self._initMap(Map = self.SrcMap) self._initMap(Map = self.TgtMap) self.GetMapToolbar().SelectDefault() # # Bind various events # self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive) self.Bind(wx.EVT_SIZE, self.OnSize) # # Update fancy gui style # # AuiManager wants a CentrePane, workaround to get two equally sized windows self.list = self.CreateGCPList() #self.SrcMapWindow.SetSize((300, 300)) #self.TgtMapWindow.SetSize((300, 300)) self.list.SetSize((100, 150)) self._mgr.AddPane(self.list, wx.aui.AuiPaneInfo(). Name("gcplist").Caption(_("GCP List")).LeftDockable(False). RightDockable(False).PinButton().FloatingSize((600,200)). CloseButton(False).DestroyOnClose(True). Top().Layer(1).MinSize((200,100))) self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo(). Name("source").Caption(_("Source Display")).Dockable(False). CloseButton(False).DestroyOnClose(True).Floatable(False). Centre()) self._mgr.AddPane(self.TgtMapWindow, wx.aui.AuiPaneInfo(). Name("target").Caption(_("Target Display")).Dockable(False). CloseButton(False).DestroyOnClose(True).Floatable(False). Right().Layer(0)) srcwidth, srcheight = self.SrcMapWindow.GetSize() tgtwidth, tgtheight = self.TgtMapWindow.GetSize() srcwidth = (srcwidth + tgtwidth) / 2 self._mgr.GetPane("target").Hide() self._mgr.Update() self._mgr.GetPane("source").BestSize((srcwidth, srcheight)) self._mgr.GetPane("target").BestSize((srcwidth, srcheight)) if self.show_target: self._mgr.GetPane("target").Show() else: self.activemap.Enable(False) # needed by Mac OS, does not harm on Linux, breaks display on Windows if platform.system() != 'Windows': self._mgr.Update() # # Init print module and classes # self.printopt = PrintOptions(self, self.MapWindow) # # Initialization of digitization tool # self.digit = None # set active map self.MapWindow = self.SrcMapWindow self.Map = self.SrcMap # do not init zoom history here, that happens when zooming to map(s) # # Re-use dialogs # self.dialogs = {} self.dialogs['attributes'] = None self.dialogs['category'] = None self.dialogs['barscale'] = None self.dialogs['legend'] = None self.decorationDialog = None # decoration/overlays # doing nice things in statusbar when other things are ready self.statusbarManager.Update() def _setUpMapWindow(self, mapWindow): # TODO: almost the smae implementation as for MapFrameBase (only names differ) # enable or disable zoom history tool mapWindow.zoomHistoryAvailable.connect( lambda: self.GetMapToolbar().Enable('zoomback', enable=True)) mapWindow.zoomHistoryUnavailable.connect( lambda: self.GetMapToolbar().Enable('zoomback', enable=False)) mapWindow.mouseMoving.connect(self.CoordinatesChanged) def AddToolbar(self, name): """Add defined toolbar to the window Currently known toolbars are: - 'map' - basic map toolbar - 'vdigit' - vector digitizer - 'gcpdisp' - GCP Manager, Display - 'gcpman' - GCP Manager, points management - 'nviz' - 3D view mode """ # default toolbar if name == "map": self.toolbars['map'] = MapToolbar(self, self._toolSwitcher) self._mgr.AddPane(self.toolbars['map'], wx.aui.AuiPaneInfo(). Name("maptoolbar").Caption(_("Map Toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2). BestSize((self.toolbars['map'].GetSize()))) # GCP display elif name == "gcpdisp": self.toolbars['gcpdisp'] = GCPDisplayToolbar(self, self._toolSwitcher) self._mgr.AddPane(self.toolbars['gcpdisp'], wx.aui.AuiPaneInfo(). Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")). ToolbarPane().Top(). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2)) if self.show_target == False: self.toolbars['gcpdisp'].Enable('zoommenu', enable = False) self.toolbars['gcpman'] = GCPManToolbar(self) self._mgr.AddPane(self.toolbars['gcpman'], wx.aui.AuiPaneInfo(). Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")). ToolbarPane().Top().Row(1). LeftDockable(False).RightDockable(False). BottomDockable(False).TopDockable(True). CloseButton(False).Layer(2)) self._mgr.Update() def OnUpdateProgress(self, event): """ Update progress bar info """ self.GetProgressBar().UpdateProgress(event.layer, event.map) event.Skip() def OnFocus(self, event): """ Change choicebook page to match display. Or set display for georectifying """ # was in if layer manager but considering the state it was executed # always, moreover, there is no layer manager dependent code # in GCP Management, set focus to current MapWindow for mouse actions self.OnPointer(event) self.MapWindow.SetFocus() event.Skip() def OnDraw(self, event): """Re-display current map composition """ self.MapWindow.UpdateMap(render = False) def OnRender(self, event): """Re-render map composition (each map layer) """ # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame # delete tmp map layers (queries) qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER) for layer in qlayer: self.Map.DeleteLayer(layer) self.SrcMapWindow.UpdateMap(render=True) if self.show_target: self.TgtMapWindow.UpdateMap(render=True) # update statusbar self.StatusbarUpdate() def OnPointer(self, event): """Pointer button clicked """ self.SrcMapWindow.SetModePointer() self.TgtMapWindow.SetModePointer() # change the default cursor self.SrcMapWindow.SetNamedCursor('cross') self.TgtMapWindow.SetNamedCursor('cross') def OnZoomIn(self, event): """Zoom in the map.""" self.SrcMapWindow.SetModeZoomIn() self.TgtMapWindow.SetModeZoomIn() def OnZoomOut(self, event): """Zoom out the map.""" self.SrcMapWindow.SetModeZoomOut() self.TgtMapWindow.SetModeZoomOut() def OnPan(self, event): """Panning, set mouse to drag""" self.SrcMapWindow.SetModePan() self.TgtMapWindow.SetModePan() def OnErase(self, event): """ Erase the canvas """ self.MapWindow.EraseMap() if self.MapWindow == self.SrcMapWindow: win = self.TgtMapWindow elif self.MapWindow == self.TgtMapWindow: win = self.SrcMapWindow win.EraseMap() def SaveToFile(self, event): """Save map to image """ img = self.MapWindow.img if not img: GMessage(parent = self, message = _("Nothing to render (empty map). Operation canceled.")) return filetype, ltype = GetImageHandlers(img) # get size dlg = ImageSizeDialog(self) dlg.CentreOnParent() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return width, height = dlg.GetValues() dlg.Destroy() # get filename dlg = wx.FileDialog(parent = self, message = _("Choose a file name to save the image " "(no need to add extension)"), wildcard = filetype, style=wx.SAVE | wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() if not path: dlg.Destroy() return base, ext = os.path.splitext(path) fileType = ltype[dlg.GetFilterIndex()]['type'] extType = ltype[dlg.GetFilterIndex()]['ext'] if ext != extType: path = base + '.' + extType self.MapWindow.SaveToFile(path, fileType, width, height) dlg.Destroy() def PrintMenu(self, event): """ Print options and output menu for map display """ point = wx.GetMousePosition() printmenu = wx.Menu() # Add items to the menu setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup')) printmenu.AppendItem(setup) self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup) preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview')) printmenu.AppendItem(preview) self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview) doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display')) printmenu.AppendItem(doprint) self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(printmenu) printmenu.Destroy() def OnZoomToRaster(self, event): """ Set display extents to match selected raster map (ignore NULLs) """ self.MapWindow.ZoomToMap(ignoreNulls = True) def OnZoomToSaved(self, event): """Set display geometry to match extents in saved region file """ self.MapWindow.SetRegion(zoomOnly=True) def OnDisplayToWind(self, event): """Set computational region (WIND file) to match display extents """ self.MapWindow.DisplayToWind() def SaveDisplayRegion(self, event): """Save display extents to named region file. """ self.MapWindow.SaveDisplayRegion() def OnZoomMenu(self, event): """Popup Zoom menu """ point = wx.GetMousePosition() zoommenu = wx.Menu() # Add items to the menu zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)')) zoommenu.AppendItem(zoomwind) self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind) zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region')) zoommenu.AppendItem(zoomdefault) self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault) zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region')) zoommenu.AppendItem(zoomsaved) self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved) savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display')) zoommenu.AppendItem(savewind) self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind) savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region')) zoommenu.AppendItem(savezoom) self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(zoommenu) zoommenu.Destroy() def IsStandalone(self): """Check if Map display is standalone""" # we do not know and we do not care, so always False return True def GetLayerManager(self): """Get reference to Layer Manager :return: always None """ return None def GetSrcWindow(self): return self.SrcMapWindow def GetTgtWindow(self): return self.TgtMapWindow def GetShowTarget(self): return self.show_target def GetMapToolbar(self): """Returns toolbar with zooming tools""" return self.toolbars['gcpdisp'] def _setActiveMapWindow(self, mapWindow): if not self.MapWindow == mapWindow: self.MapWindow = mapWindow self.Map = mapWindow.Map self.UpdateActive(mapWindow) # needed for wingrass self.SetFocus()