[GRASS-SVN] r40794 - grass-addons/gui/wxpython/data_catalog
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Feb 3 11:29:52 EST 2010
Author: rashadkm
Date: 2010-02-03 11:29:51 -0500 (Wed, 03 Feb 2010)
New Revision: 40794
Added:
grass-addons/gui/wxpython/data_catalog/LayerTree.py
grass-addons/gui/wxpython/data_catalog/gmconsole.py
grass-addons/gui/wxpython/data_catalog/mapdisplay.py
grass-addons/gui/wxpython/data_catalog/newprompt.py
grass-addons/gui/wxpython/data_catalog/wx_utils.py
Modified:
grass-addons/gui/wxpython/data_catalog/catalog.py
grass-addons/gui/wxpython/data_catalog/mapwindow.py
Log:
data catalog; new features added
Added: grass-addons/gui/wxpython/data_catalog/LayerTree.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/LayerTree.py (rev 0)
+++ grass-addons/gui/wxpython/data_catalog/LayerTree.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -0,0 +1,317 @@
+"""
+ at package layertree.py
+
+ at brief Tree widget for listing maps raster, vector and DBF.
+
+Classes:
+ - LayerTree
+
+
+(C) 2006-2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Michael Barton (Arizona State University)
+ at author Jachym Cepicky (Mendel University of Agriculture)
+ at author Martin Landa <landa.martin gmail.com>
+ at author Mohammed Rashad K.M <rashadkm at gmail dot com> (modified for DataCatalog)
+"""
+
+import os
+import sys
+import wx
+import glob
+import render
+
+
+
+#To run DataCatalog from any directory set this pathname for access to gui_modules
+gbase = os.getenv("GISBASE")
+pypath = os.path.join(gbase,'etc','wxpython','gui_modules')
+sys.path.append(pypath)
+
+
+import globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+ globalvar.CheckForWx()
+import gcmd
+
+
+
+
+class LayerTree(wx.TreeCtrl):
+
+ def __init__(self, parent, id,
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style= wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS,gisdbase=None):
+
+ wx.TreeCtrl.__init__(self, parent, id, pos, size, style)
+ self.itemFont = wx.Font(pointSize=9,weight=0, family=wx.FONTFAMILY_DEFAULT ,style=wx.FONTSTYLE_ITALIC)
+
+ self.gisdbase = gisdbase
+ self.Map = None
+ if self.Map is not None:
+ print self.Map.width
+
+ self.ID_REN= wx.NewId()
+ self.ID_COPY = wx.NewId()
+ self.ID_DEL = wx.NewId()
+
+ acel = wx.AcceleratorTable([
+ (wx.ACCEL_CTRL, ord('R'), self.ID_REN ) ,
+ (wx.ACCEL_CTRL, ord('C'), self.ID_COPY) ,
+ (wx.ACCEL_NORMAL, wx.WXK_DELETE, self.ID_DEL) ])
+
+
+ self.SetAcceleratorTable(acel)
+
+
+
+
+ def AddTreeNodes(self,location,mapset):
+ """
+ Adds tree nodes. raster,vector and dbf files are identified using
+ their directory structure.
+ """
+
+ root = self.AddRoot('root')
+ node_raster = self.AppendItem(root, "Raster Map")
+ node_vector = self.AppendItem(root, "Vector Map")
+ node_dbf = self.AppendItem(root, "DBF")
+ treeNodes = [node_raster,node_vector,node_dbf]
+
+ glocs = glob.glob(os.path.join(self.gisdbase,location, mapset,"*"))
+ for gloc in glocs:
+ if not os.path.isfile(gloc) and os.path.isdir(gloc):
+ if(os.path.basename(gloc)=='cats'):
+ for rast in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
+ self.AppendItem(node_raster, os.path.basename(rast))
+ elif(os.path.basename(gloc)=='vector'):
+ for vect in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
+ self.AppendItem(node_vector, os.path.basename(vect))
+ elif(os.path.basename(gloc)=='dbf'):
+ for dfile in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
+ self.AppendItem(node_dbf, os.path.basename(dfile))
+
+ #Nodes with no children are given an italic type font
+ for node in treeNodes:
+ if not self.ItemHasChildren(node):
+ if self.GetItemText(node) == 'Raster Map':
+ tmp_item = self.AppendItem(node, "No raster maps found.")
+ elif self.GetItemText(node) == 'Vector Map':
+ tmp_item = self.AppendItem(node, "No vector maps found.")
+ elif self.GetItemText(node) == 'DBF':
+ tmp_item = self.AppendItem(node, "No DBF files found.")
+ self.SetItemFont(tmp_item,self.itemFont)
+
+
+
+
+ def OnToggleExpand(self,event):
+ if self.treeExpand.GetValue() == True:
+ self.ExpandAll()
+ else:
+ self.CollapseAll()
+
+
+ def OnBeginRename(self,event):
+
+ item = self.GetItemText(event.GetItem())
+ if type(item) == str and item in ("Raster Map", "Vector Map" , "DBF"):
+ event.Veto() #disable editing of parent items
+
+ def OnEndRename(self,event):
+ """
+ Rename mapset using grass commands
+ """
+ item = event.GetItem()
+ oldName = self.GetItemText(item)
+ try:
+ newName = self.GetEditControl().GetValue()
+ except:
+ return
+ parent =self.GetItemParent(item)
+ if self.GetItemText(parent) == "Raster Map" :
+ cmdflag = 'rast=' + oldName + ',' + newName
+ elif self.GetItemText(parent) == "Vector Map" :
+ cmdflag = 'vect=' + oldName + ',' + newName
+
+ if cmdflag:
+ command = ["g.rename", cmdflag]
+ gcmd.CommandThread(command,stdout=None,stderr=None).run()
+
+
+
+ def OnTreePopUp(self,event):
+ """
+ Display a popupMenu for copy,rename & delete operations
+ """
+ item = event.GetItem()
+ if not self.ItemHasChildren(item) and \
+ self.GetItemFont(item) != self.itemFont:
+
+ self.popupmenu = wx.Menu()
+ mnuCopy = self.popupmenu.Append(self.ID_COPY,'&Copy\tCtrl+C')
+ mnuRename = self.popupmenu.Append(self.ID_REN,'&Rename\tCtrl-R')
+ mnuDel = self.popupmenu.Append(self.ID_DEL,'&Delete\tDEL')
+ self.PopupMenu(self.popupmenu)
+
+
+ def OnCopy( self,event ):
+ #print "copy"
+ item = self.GetSelection()
+ parent = self.GetItemParent(item)
+ pText = self.GetItemText(parent)
+ name = self.GetCopyName(item)
+ if pText == "Raster Map" :
+ cmdflag = 'rast=' + self.GetItemText(item) + ',' + name
+ self.InsertItem(parent,item, name)
+ elif pText == "Vector Map" :
+ cmdflag = 'vect=' + self.GetItemText(item) + ',' + name
+ self.InsertItem(parent,item, name)
+
+ if cmdflag:
+ command = ["g.copy", cmdflag]
+ gcmd.CommandThread(command,stdout=None,stderr=None).run()
+
+
+ def GetCopyName(self, item):
+ """
+ Returns unique name depending on the mapname to be copied.
+ """
+
+ def GetPrefix(prefix):
+ """
+ This returns a prefix to the given map name
+ prefix applied here is _copy_x.
+ """
+
+ prefix = "_copy_" + str(self.count)
+ self.count = self.count + 1
+ return prefix
+
+ #end of GetPrefix
+
+ def CheckName(parent,prefix,name):
+ """
+ Checks all silbings of the parent wheather the name
+ already exists.
+ """
+ ncount = self.GetChildrenCount(parent, False)
+ ck = 1
+ current , ck = self.GetFirstChild(parent)
+ for i in range(ncount):
+ if str(self.GetItemText(current)) == str(name + prefix):
+ return False
+ else:
+ current,ck = self.GetNextChild(parent,ck)
+ return True
+
+ #End of CheckName
+
+ #GetCopyName function starts here
+ ext = None
+ self.count = 1
+ ext = GetPrefix(ext)
+ name = str(self.GetItemText(item))
+ parent = self.GetItemParent(item)
+ while CheckName(parent,ext,name) == False:
+ ext = GetPrefix(ext)
+ CheckName(parent,ext,name)
+
+ name = str(name + ext)
+ return name
+
+
+ def OnRename( self,event ):
+
+ item = self.GetSelection()
+ self.EditLabel( self.GetSelection())
+
+
+ def OnDelete( self,event ):
+ """
+ Performs grass command for deleting a map
+ """
+ item = self.GetSelection()
+ dlg = wx.MessageDialog(self, message=_( "Do you want to delete selected map ?"),
+ caption=_("Delete Map"),
+ style=wx.YES_NO | wx.YES_DEFAULT | \
+ wx.CANCEL | wx.ICON_QUESTION)
+ ret = dlg.ShowModal()
+ if ret == wx.ID_YES:
+ dlg.Destroy()
+ parent =self.GetItemParent(item)
+ if self.GetItemText(parent) == "Raster Map" :
+ cmdflag = 'rast=' + str(self.GetItemText(item))
+ elif self.tree.GetItemText(parent) == "Vector Map" :
+ cmdflag = 'vect=' + str(self.GetItemText(item))
+
+ if cmdflag:
+ command = ["g.remove", cmdflag]
+ gcmd.CommandThread(command,stdout=None,stderr=None).run()
+ select = self.GetPrevSibling(item)
+ self.Delete(item)
+ self.SelectItem(select)
+
+ elif ret == wx.ID_CANCEL:
+ dlg.Destroy()
+ return
+
+
+
+ def OnCloseWindow(self,event):
+
+ if self.gisrc['LOCATION_NAME'] != self.iLocation or \
+ self.gisrc['MAPSET'] != self.iMapset:
+ self.gisrc['LOCATION_NAME'] = self.iLocation
+ self.gisrc['MAPSET'] = self.iMapset
+ self.update_grassrc(self.gisrc)
+
+ self.Map.Clean()
+ event.Skip()
+ #self.Destroy()
+
+
+ def OnDisplay(self, event):
+ item = event.GetItem()
+ pText = self.GetItemText(self.GetItemParent(item))
+
+ leftpanel=self.GetParent()
+ splitter = leftpanel.GetParent()
+ frame = splitter.GetParent()
+ window2 = splitter.GetWindow2()
+
+ winlist = window2.GetChildren()
+ for win in winlist:
+ if type(win) == wx.lib.flatnotebook.FlatNotebook:
+ child=win.GetChildren()
+ for panel in child:
+ if panel.GetName() == "pg_panel":
+ ss = panel.GetName()
+
+
+
+ if not self.ItemHasChildren(item):
+ self.mapname = "map=" + self.GetItemText(item) + "@" + frame.cmbMapset.GetValue()
+ #self.mapname = "map=" + self.GetItemText(item) + "@PERMANENT"
+ if pText == "Raster Map" :
+ self.cmd= ['d.rast', str(self.mapname)]
+ self.infocmd = ["r.info", str(self.mapname)]
+ elif pText == "Vector Map" :
+ self.cmd= ['d.vect', str(self.mapname)]
+ self.infocmd = ["v.info", str(self.mapname)]
+
+ if self.cmd:
+ panel.Map.Clean()
+ panel.Map.__init__() #to update projection and region
+ panel.Map.AddLayer(type='raster', name='layer1', command=self.cmd)
+ panel.Map.region = panel.Map.GetRegion()
+ panel.MapWindow2D.flag = True
+ panel.MapWindow2D.UpdateMap(render=True)
+
+
+
+
Modified: grass-addons/gui/wxpython/data_catalog/catalog.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/catalog.py 2010-02-03 10:46:47 UTC (rev 40793)
+++ grass-addons/gui/wxpython/data_catalog/catalog.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -19,8 +19,40 @@
"""
+import sys
import os
-import sys
+import time
+import traceback
+import re
+import string
+import getopt
+import platform
+
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ import elementtree.ElementTree as etree
+
+
+gbase = os.getenv("GISBASE")
+pypath = os.path.join(gbase,'etc','wxpython')
+sys.path.append(pypath)
+
+
+
+import gui_modules
+gmpath = gui_modules.__path__[0]
+sys.path.append(gmpath)
+
+import images
+imagepath = images.__path__[0]
+sys.path.append(imagepath)
+
+import icons
+gmpath = icons.__path__[0]
+sys.path.append(gmpath)
+
+
#To run DataCatalog from any directory set this pathname for access to gui_modules
gbase = os.getenv("GISBASE")
pypath = os.path.join(gbase,'etc','wxpython','gui_modules')
@@ -34,469 +66,1603 @@
import gcmd
import glob
import render
-from mapwindow import BufferedWindow
+import gui_modules.gdialogs as gdialogs
+import gui_modules.goutput as goutput
+import gui_modules.histogram as histogram
+from gui_modules.debug import Debug
+import gui_modules.menuform as menuform
+import gui_modules.menudata as menudata
+import gui_modules.utils as utils
+import gui_modules.preferences as preferences
+import gui_modules.mapdisp as mapdisp
+import gui_modules.histogram as histogram
+import gui_modules.profile as profile
+import gui_modules.rules as rules
+import gui_modules.mcalc_builder as mapcalculator
+import gui_modules.gcmd as gcmd
+import gui_modules.georect as georect
+import gui_modules.dbm as dbm
+import gui_modules.workspace as workspace
+import gui_modules.colorrules as colorrules
+import gui_modules.ogc_services as ogc_services
+import newprompt as prompt
+from gui_modules.help import MenuTreeWindow
+from gui_modules.help import AboutWindow
+from icons.icon import Icons
+from gmconsole import GLog
+from mapdisplay import MapFrame
+from LayerTree import LayerTree
+import wx.lib.flatnotebook as FN
+from icons.icon import Icons
+import wx_utils as wx_utils
+from preferences import globalSettings as UserSettings
+
+
class DataCatalog(wx.Frame):
- def __init__(self,size=wx.DefaultSize):
- wx.Frame.__init__(self, None, wx.ID_ANY, "Data Catalog", wx.DefaultPosition, wx.DefaultSize)
- self.Maximize()
- self.gisbase = os.getenv("GISBASE")
- self.gisrc = self.read_gisrc()
- self.viewInfo = True #to display v/r.info on mapdisplay
- self.gisdbase = self.gisrc['GISDBASE']
+ def __init__(self, parent=None, id=wx.ID_ANY, title=_("Data Catalog"),
+ workspace=None,size=wx.DefaultSize,pos=wx.DefaultPosition):
+ self.iconsize = (16, 16)
+ self.baseTitle = title
+
+ wx.Frame.__init__(self, parent, id, title, pos=pos, size=size)
+
+
+ #self.Maximize()
+
+
+ self.gisbase = os.getenv("GISBASE")
+ self.gisrc = self.read_gisrc()
+ self.viewInfo = True #to display v/r.info on mapdisplay
+ self.gisdbase = self.gisrc['GISDBASE']
+
#backup location and mapset from gisrc which may be modified by datacatalog
- self.iLocation = self.gisrc['LOCATION_NAME']
- self.iMapset = self.gisrc['MAPSET']
+ self.iLocation = self.gisrc['LOCATION_NAME']
+ self.iMapset = self.gisrc['MAPSET']
+
- self.ID_REN= wx.NewId()
- self.ID_COPY = wx.NewId()
- self.ID_DEL = wx.NewId()
+ #self.Map = render.Map()
- acel = wx.AcceleratorTable([
- (wx.ACCEL_CTRL, ord('R'), self.ID_REN ) ,
- (wx.ACCEL_CTRL, ord('C'), self.ID_COPY) ,
- (wx.ACCEL_NORMAL, wx.WXK_DELETE, self.ID_DEL) ])
+ self.curr_pagenum = -1 # currently selected page number for layer tree notebook
+ self.encoding = 'ISO-8859-1' # default encoding for display fonts
+ self.workspaceFile = workspace # workspace file
+ self.menucmd = dict() # menuId / cmd
+ self.georectifying = None # reference to GCP class or None
+ self.dialogs = dict()
+ self.dialogs['preferences'] = None
+ self.dialogs['atm'] = list()
- self.SetAcceleratorTable(acel)
- #creating sizers
- self.cmbSizer = wx.GridBagSizer(hgap=5, vgap=0)
- self.mSizer = wx.BoxSizer(wx.VERTICAL)
+ self.g_catalog=None
- #these two sizers are applied to splitter window
- self.leftSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.rightSizer = wx.BoxSizer(wx.VERTICAL)
- #populate location combobox
- self.loclist = self.GetLocations()
+ self.ID_REN= wx.NewId()
+ self.ID_COPY = wx.NewId()
+ self.ID_DEL = wx.NewId()
- #setting splitter window
- self.win = wx.SplitterWindow(self)
- self.pLeft = wx.Panel(self.win, style=wx.SUNKEN_BORDER)
- self.pRight = wx.Panel(self.win, style=wx.SUNKEN_BORDER)
- self.cmbPanel = wx.Panel(self)
- self.pRight.SetBackgroundColour("white")
- self.pLeft.Hide()
- self.pRight.Hide()
- self.win.Initialize(self.pLeft)
- self.win.SplitVertically(self.pLeft, self.pRight, 310)
+ acel = wx.AcceleratorTable([
+ (wx.ACCEL_CTRL, ord('R'), self.ID_REN ) ,
+ (wx.ACCEL_CTRL, ord('C'), self.ID_COPY) ,
+ (wx.ACCEL_NORMAL, wx.WXK_DELETE, self.ID_DEL) ])
- #creating controls
- self.mInfo = wx.TextCtrl(self.pRight, wx.ID_ANY, style = wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY)
- self.chkInfo = wx.CheckBox(self.cmbPanel, wx.ID_ANY,"display Info", wx.DefaultPosition, wx.DefaultSize)
- self.treeExpand = wx.CheckBox(self.cmbPanel, wx.ID_ANY,"Expand All", wx.DefaultPosition, wx.DefaultSize)
- self.lbLocation = wx.StaticText(self.cmbPanel, wx.ID_ANY, "Location")
- self.lbMapset = wx.StaticText(self.cmbPanel, wx.ID_ANY, "Mapset")
- self.cmbLocation = wx.ComboBox(self.cmbPanel, value = "Select Location",size=wx.DefaultSize, choices=self.loclist)
- self.cmbMapset = wx.ComboBox(self.cmbPanel, value = "Select Mapset", size=wx.DefaultSize)
- self.tree = wx.TreeCtrl(self.pLeft, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS|wx.TR_EDIT_LABELS)
- self.itemFont = wx.Font(pointSize=9,weight=0, family=wx.FONTFAMILY_DEFAULT ,style=wx.FONTSTYLE_ITALIC)
- #self.redir = wx.TextCtrl(self, wx.ID_ANY)
+ self.SetAcceleratorTable(acel)
+ self.menucmd = dict()
- self.Map = render.Map()
- self.MapWindow = BufferedWindow(self.pRight, wx.ID_ANY,wx.DefaultPosition, size=(640,480), Map=self.Map)
- self.Map.Clean()
+ #creating sizers
+ self.cmbSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.mSizer = wx.BoxSizer(wx.VERTICAL)
- #By default v/r.info will be displayed
- self.chkInfo.SetValue(True)
- self.treeExpand.SetValue(False)
+ #these two sizers are applied to splitter window
+ self.leftSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.rightSizer = wx.BoxSizer(wx.HORIZONTAL)
- #apply bindings and setting layouts
- self.doBindings()
- self.doLayout()
- self.Centre()
+ #populate location combobox
+ self.loclist = self.GetLocations()
- def OnToggleExpand(self,event):
- if self.treeExpand.GetValue() == True:
- self.tree.ExpandAll()
- else:
- self.tree.CollapseAll()
+ #self.pg_panel4 = None
+ self.menubar, self.menudata = self.__createMenuBar()
+ #self.statusbar = self.CreateStatusBar(number=1)
+ #self.cmdprompt, self.cmdinput = self.__createCommandPrompt()
+ self.toolbar = self.__createToolBar()
+
+ #setting splitter window
+ self.win = wx.SplitterWindow(self)
+ self.pLeft = wx.Panel(self.win, style=wx.SUNKEN_BORDER)
+ self.pRight = wx.Panel(self.win, style=wx.SUNKEN_BORDER,name="rightpanel")
+ self.cmbPanel = wx.Panel(self)
+ self.rightPanel = wx.Panel(self.pRight)
+ self.pRight.SetBackgroundColour("white")
+ self.pLeft.Hide()
+ self.pRight.Hide()
+ self.win.Initialize(self.pLeft)
+ self.win.SplitVertically(self.pLeft, self.pRight, 310)
+
+ self.maptree = None
+ self.pg_panel = None
+
+ #creating controls
+ #self.mInfo = wx.TextCtrl(self.pRight, wx.ID_ANY, style = wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY)
+ #self.chkInfo = wx.CheckBox(self.cmbPanel, wx.ID_ANY,"display Info", wx.DefaultPosition, wx.DefaultSize)
+ self.treeExpand = wx.CheckBox(self.cmbPanel, wx.ID_ANY,"Expand All", wx.DefaultPosition, wx.DefaultSize)
+ self.cmbLocation = wx.ComboBox(self.cmbPanel, value = "Select Location",size=wx.DefaultSize, choices=self.loclist)
+ self.cmbMapset = wx.ComboBox(self.cmbPanel, value = "Select Mapset", size=wx.DefaultSize)
+ #self.tree = wx.TreeCtrl(self.pLeft, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS|wx.TR_EDIT_LABELS)
+
+ self.ltree = LayerTree(self.pLeft,wx.ID_ANY,gisdbase=self.gisdbase)
+
+ self.itemFont = wx.Font(pointSize=9,weight=0, family=wx.FONTFAMILY_DEFAULT ,style=wx.FONTSTYLE_ITALIC)
+
+
+ self.notebook = self.__createNoteBook()
+ self.cmdprompt, self.cmdinput = self.__createCommandPrompt()
+
+ # self._mgr = self.pg_panel._layerManager
+
+# self._mgr.AddPane(self.cmdprompt, wx.aui.AuiPaneInfo().CentrePane().Dockable(False).BestSize((-1,-1)).CloseButton(False).DestroyOnClose(True). Layer(0))
+
+ self.current = self.notebook.GetCurrentPage()
+
- def OnToggleInfo(self,event):
- if self.chkInfo.GetValue() == True:
- self.viewInfo = True
- self.mInfo.Show()
- else:
- self.viewInfo = False
- self.mInfo.Hide()
- def OnBeginRename(self,event):
- item = self.tree.GetItemText(event.GetItem())
- if type(item) == str and item in ("Raster Map", "Vector Map" , "DBF"):
- event.Veto() #disable editing of parent items
-
- def OnEndRename(self,event):
- """
- Rename mapset using grass commands
- """
- item = event.GetItem()
- oldName = self.tree.GetItemText(item)
- try:
- newName = self.tree.GetEditControl().GetValue()
- except:
- return
- parent =self.tree.GetItemParent(item)
- if self.tree.GetItemText(parent) == "Raster Map" :
- cmdflag = 'rast=' + oldName + ',' + newName
- elif self.tree.GetItemText(parent) == "Vector Map" :
- cmdflag = 'vect=' + oldName + ',' + newName
+ self.doBindings()
+ self.doLayout()
- if cmdflag:
- command = ["g.rename", cmdflag]
- gcmd.CommandThread(command,stdout=None,stderr=None).run()
+ self.cmbSizer.Add(self.cmdprompt)
+ self.Map = self.GetMapDisplay()
- def OnTreePopUp(self,event):
- """
- Display a popupMenu for copy,rename & delete operations
- """
- item = event.GetItem()
- if not self.tree.ItemHasChildren(item) and \
- self.tree.GetItemFont(item) != self.itemFont:
- self.popupmenu = wx.Menu()
- mnuCopy = self.popupmenu.Append(self.ID_COPY,'&Copy\tCtrl+C')
- mnuRename = self.popupmenu.Append(self.ID_REN,'&Rename\tCtrl-R')
- mnuDel = self.popupmenu.Append(self.ID_DEL,'&Delete\tDEL')
- self.tree.PopupMenu(self.popupmenu)
+ def GetMapDisplay(self):
+ self.winlist = self.GetChildren()
+ for win in self.winlist:
+ if win.GetName()== "splitter":
+ self.splitter = win.GetWindow2()
+
+ self.books = self.splitter.GetChildren()
+ for self.book in self.books:
+ if type(self.book) == wx.lib.flatnotebook.FlatNotebook:
+ self.panel = self.book.GetChildren()
+ for self.subpanel in self.panel:
+ if self.subpanel.GetName() == "pg_panel":
+ self.mapnew = self.subpanel.Map
+ return self.mapnew
+
- def OnCopy( self,event ):
- #print "copy"
- item = self.tree.GetSelection()
- parent = self.tree.GetItemParent(item)
- pText = self.tree.GetItemText(parent)
- name = self.GetCopyName(item)
- if pText == "Raster Map" :
- cmdflag = 'rast=' + self.tree.GetItemText(item) + ',' + name
- self.tree.InsertItem(parent,item, name)
- elif pText == "Vector Map" :
- cmdflag = 'vect=' + self.tree.GetItemText(item) + ',' + name
- self.tree.InsertItem(parent,item, name)
+ def __createMenuBar(self):
+ """!Creates menubar"""
- if cmdflag:
- command = ["g.copy", cmdflag]
- gcmd.CommandThread(command,stdout=None,stderr=None).run()
+ self.menubar = wx.MenuBar()
+ self.menudata = menudata.Data()
+ for eachMenuData in self.menudata.GetMenu():
+ for eachHeading in eachMenuData:
+ menuLabel = eachHeading[0]
+ menuItems = eachHeading[1]
+ self.menubar.Append(self.__createMenu(menuItems), menuLabel)
-
- def GetCopyName(self, item):
- """
- Returns unique name depending on the mapname to be copied.
- """
+ self.SetMenuBar(self.menubar)
- def GetPrefix(prefix):
- """
- This returns a prefix to the given map name
- prefix applied here is _copy_x.
- """
+ return (self.menubar, self.menudata)
- prefix = "_copy_" + str(self.count)
- self.count = self.count + 1
- return prefix
+ def __createCommandPrompt(self):
+ """!Creates command-line input area"""
+ p = prompt.GPrompt(parent=self.cmbPanel)
+
+ return p.GetPanel(), p.GetInput()
+
+ def __createMenu(self, menuData):
+ """!Creates menu"""
+
+ menu = wx.Menu()
+ for eachItem in menuData:
+ if len(eachItem) == 2:
+ label = eachItem[0]
+ subMenu = self.__createMenu(eachItem[1])
+ menu.AppendMenu(wx.ID_ANY, label, subMenu)
+ else:
+ self.__createMenuItem(menu, *eachItem)
+ self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
+ return menu
+
+ def __createMenuItem(self, menu, label, help, handler, gcmd, keywords, shortcut = '', kind = wx.ITEM_NORMAL):
+ """!Creates menu items"""
+
+ if not label:
+ menu.AppendSeparator()
+ return
+
+ if len(gcmd) > 0:
+ helpString = gcmd + ' -- ' + help
+ else:
+ helpString = help
- #end of GetPrefix
+ if shortcut:
+ label += '\t' + shortcut
+
+ menuItem = menu.Append(wx.ID_ANY, label, helpString, kind)
+
+ self.menucmd[menuItem.GetId()] = gcmd
- def CheckName(parent,prefix,name):
- """
- Checks all silbings of the parent wheather the name
- already exists.
- """
- ncount = self.tree.GetChildrenCount(parent, False)
- ck = 1
- current , ck = self.tree.GetFirstChild(parent)
- for i in range(ncount):
- if str(self.tree.GetItemText(current)) == str(name + prefix):
- return False
- else:
- current,ck = self.tree.GetNextChild(parent,ck)
- return True
+ if len(gcmd) > 0 and \
+ gcmd.split()[0] not in globalvar.grassCmd['all']:
+ menuItem.Enable (False)
+
+ rhandler = eval(handler)
+
+ self.Bind(wx.EVT_MENU, rhandler, menuItem)
+
+
+
+ def __createToolBar(self):
+ """!Creates toolbar"""
+
+ self.toolbar = self.CreateToolBar()
+ self.toolbar.SetToolBitmapSize(globalvar.toolbarSize)
+
+ for each in self.ToolbarData():
+ self.AddToolbarButton(self.toolbar, *each)
+ self.toolbar.Realize()
+
+ return self.toolbar
+
+ def OnMenuHighlight(self, event):
+ """
+ Default menu help handler
+ """
+ # Show how to get menu item info from this event handler
+ id = event.GetMenuId()
+ item = self.GetMenuBar().FindItemById(id)
+ if item:
+ text = item.GetText()
+ help = item.GetHelp()
+
+ # but in this case just call Skip so the default is done
+ event.Skip()
+
+
+ def __createNoteBook(self):
+ """!Creates notebook widgets"""
+
+ #create main notebook widget
+ nbStyle = FN.FNB_FANCY_TABS | \
+ FN.FNB_BOTTOM | \
+ FN.FNB_NO_NAV_BUTTONS | \
+ FN.FNB_NO_X_BUTTON
+
+
+ self.disp_idx = -1
+
+
+ # create displays notebook widget and add it to main notebook page
+ cbStyle = globalvar.FNPageStyle
+ self.notebook = FN.FlatNotebook(parent=self.pRight, id=wx.ID_ANY, style=cbStyle,name="mynotebook")
+
+ self.notebook.SetTabAreaColour(globalvar.FNPageColor)
+
+
+ self.pg_panel = MapFrame(parent=self.notebook, id=wx.ID_ANY, Map=render.Map(), size=globalvar.MAP_WINDOW_SIZE,frame=self,flag=True)
+
+ self.disp_idx = self.disp_idx + 1
+ self.notebook.AddPage(self.pg_panel, text="Display "+ str(self.disp_idx), select = True)
+
+
+ self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+ self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosed)
+
+
+ return self.notebook
+
+
+ def OnGeorectify(self, event):
+ """
+ Launch georectifier module
+ """
+ georect.GeorectWizard(self)
+
+ def OnMapsets(self, event):
+ """
+ Launch mapset access dialog
+ """
+ dlg = preferences.MapsetAccess(parent=self, id=wx.ID_ANY)
+ dlg.CenterOnScreen()
+
+ # if OK is pressed...
+ if dlg.ShowModal() == wx.ID_OK:
+ ms = dlg.GetMapsets()
+ # run g.mapsets with string of accessible mapsets
+ gcmd.RunCommand('g.mapsets',
+ parent = self,
+ mapset = '%s' % ','.join(ms))
- #End of CheckName
+ def OnRDigit(self, event):
+ """
+ Launch raster digitizing module
+ """
+ pass
- #GetCopyName function starts here
- ext = None
- self.count = 1
- ext = GetPrefix(ext)
- name = str(self.tree.GetItemText(item))
- parent = self.tree.GetItemParent(item)
- while CheckName(parent,ext,name) == False:
- ext = GetPrefix(ext)
- CheckName(parent,ext,name)
+ def OnPageChanged(self,event):
+ self.current = event.GetSelection()
+ event.Skip()
- name = str(name + ext)
- return name
- def OnRename( self,event ):
+ def OnPageClosed(self, event):
+ """
+ Page of notebook closed
+ Also close associated map display
+ """
- item = self.tree.GetSelection()
- self.tree.EditLabel( self.tree.GetSelection())
+# if UserSettings.Get(group='manager', key='askOnQuit', subkey='enabled'):
+# maptree = self.current.maptree
+#
+# if self.workspaceFile:
+# message = _("Do you want to save changes in the workspace?")
+# else:
+# message = _("Do you want to store current settings "
+# "to workspace file?")
+#
+# # ask user to save current settings
+# if maptree.GetCount() > 0:
+# dlg = wx.MessageDialog(self,
+# message=message,
+# caption=_("Close Map Display %d") % (self.disp_idx),
+# style=wx.YES_NO | wx.YES_DEFAULT |
+# wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
+# ret = dlg.ShowModal()
+# if ret == wx.ID_YES:
+# if not self.workspaceFile:
+# self.OnWorkspaceSaveAs()
+# else:
+# self.SaveToWorkspaceFile(self.workspaceFile)
+# elif ret == wx.ID_CANCEL:
+#
+# event.Veto()
+# dlg.Destroy()
+# return
+# dlg.Destroy()
- def OnDelete( self,event ):
- """
- Performs grass command for deleting a map
- """
- item = self.tree.GetSelection()
- parent =self.tree.GetItemParent(item)
- if self.tree.GetItemText(parent) == "Raster Map" :
- cmdflag = 'rast=' + str(self.tree.GetItemText(item))
- elif self.tree.GetItemText(parent) == "Vector Map" :
- cmdflag = 'vect=' + str(self.tree.GetItemText(item))
- if cmdflag:
- command = ["g.remove", cmdflag]
- gcmd.CommandThread(command,stdout=None,stderr=None).run()
- select = self.tree.GetPrevSibling(item)
- self.tree.Delete(item)
- self.tree.SelectItem(select)
+ self.notebook.GetPage(event.GetSelection()).maptree.Map.Clean()
+ self.disp_idx = self.disp_idx - 1
+ self.notebook.DeletePage(self.notebook.GetCurrentPage())
+ self.current = self.notebook.GetCurrentPage()
+ self.current.Map.Clean()
+ event.Skip()
+
+ def GetLogWindow(self):
+ """!Get widget for command output"""
+ return self.gmconsole.goutput
+
+ def GetMenuCmd(self, event):
+ """!Get GRASS command from menu item
- def OnCloseWindow(self,event):
+ Return command as a list"""
+ layer = None
+
+ if event:
+ cmd = self.menucmd[event.GetId()]
+
+ try:
+ cmdlist = cmd.split(' ')
+ except: # already list?
+ cmdlist = cmd
+
+ # check list of dummy commands for GUI modules that do not have GRASS
+ # bin modules or scripts.
+ if cmd in ['vcolors']:
+ return cmdlist
- if self.gisrc['LOCATION_NAME'] != self.iLocation or \
- self.gisrc['MAPSET'] != self.iMapset:
- self.gisrc['LOCATION_NAME'] = self.iLocation
- self.gisrc['MAPSET'] = self.iMapset
- self.update_grassrc(self.gisrc)
-
- self.Map.Clean()
- event.Skip()
- #self.Destroy()
-
+ try:
+ layer = self.current.maptree.layer_selected
+ name = self.current.maptree.GetPyData(layer)[0]['maplayer'].name
+ type = self.current.maptree.GetPyData(layer)[0]['type']
+ except:
+ layer = None
+ if layer and len(cmdlist) == 1: # only if no paramaters given
+ if (type == 'raster' and cmdlist[0][0] == 'r' and cmdlist[0][1] != '3') or \
+ (type == 'vector' and cmdlist[0][0] == 'v'):
+ input = menuform.GUI().GetCommandInputMapParamKey(cmdlist[0])
+ if input:
+ cmdlist.append("%s=%s" % (input, name))
- def OnDisplay(self, event):
- item = event.GetItem()
- pText = self.tree.GetItemText(self.tree.GetItemParent(item))
+ return cmdlist
- if not self.tree.ItemHasChildren(item):
- self.mapname = "map=" + self.tree.GetItemText(item) + "@" +self.cmbMapset.GetValue()
- if pText == "Raster Map" :
- self.cmd= ['d.rast', str(self.mapname)]
- self.infocmd = ["r.info", str(self.mapname)]
- elif pText == "Vector Map" :
- self.cmd= ['d.vect', str(self.mapname)]
- self.infocmd = ["v.info", str(self.mapname)]
+ def RunMenuCmd(self, event):
+ """!Run command selected from menu"""
+ print "asdf"
+ #cmd = self.GetMenuCmd(event)
+ #goutput.GMConsole(self, pageid=1).RunCmd(cmd, switchPage=True)
- if self.cmd:
- self.Map.Clean()
- self.Map.__init__() #to update projection and region
- self.Map.AddLayer(type='raster', name='layer1', command=self.cmd)
- self.Map.region = self.Map.GetRegion()
- self.MapWindow.flag = True
- self.MapWindow.Map = self.Map
- self.MapWindow.UpdateMap(render=True)
+ def OnMenuCmd(self, event, cmd = ''):
+ """!Parse command selected from menu"""
+ if event:
+ cmd = self.GetMenuCmd(event)
+ menuform.GUI().ParseCommand(cmd, parentframe=self)
- if self.viewInfo is True:
- gcmd.CommandThread(self.infocmd, stdout=self.mInfo).run()
- lines = self.mInfo.GetValue()
- lines = lines.replace('|','')
- lines =lines.replace('+','')
- lines =lines.replace('-','')
- #lines =lines.replace('-+','-------------------------------+')
- #lines =lines.replace('-\n','---------------------------------')
- #lines = lines.replace('+','----+')
- self.mInfo.SetValue(lines)
+ def OnChangeLocation(self, event):
+ """Change current location"""
+ print "asdf"
+
+ def OnChangeMapset(self, event):
+ """Change current mapset"""
+ print "asdf"
+
+ def OnNewVector(self, event):
+ """!Create new vector map layer"""
+ name, add = gdialogs.CreateNewVector(self, cmd = (('v.edit', { 'tool' : 'create' }, 'map')))
+
+ if name and add:
+ # add layer to map layer tree
+ self.current.maptree.AddLayer(ltype='vector',
+ lname=name,
+ lchecked=True,
+ lopacity=1.0,
+ lcmd=['d.vect', 'map=%s' % name])
+
+ def OnMenuTree(self, event):
+ """!Show dialog with menu tree"""
+ dlg = MenuTreeWindow(self)
+ dlg.CentreOnScreen()
+ dlg.Show()
+
+ def OnAboutGRASS(self, event):
+ """!Display 'About GRASS' dialog"""
+ win = AboutWindow(self)
+ win.Centre()
+ win.Show(True)
+
+ def OnWorkspace(self, event):
+ """!Workspace menu (new, load)"""
+ point = wx.GetMousePosition()
+ menu = wx.Menu()
- def OnMapsetChange(self,event):
- """
- Create the tree nodes based on selected location and mapset.
- Also update gisrc and grassrc files.
- """
- self.tree.DeleteAllItems()
- self.AddTreeNodes(self.cmbLocation.GetValue(),self.cmbMapset.GetValue())
- self.gisrc['LOCATION_NAME'] = str(self.cmbLocation.GetValue())
- self.gisrc['MAPSET'] = str(self.cmbMapset.GetValue())
- self.update_grassrc(self.gisrc)
- #gcmd.RunCommand("g.gisenv", set = "MAPSET=%s" % str(self.cmbMapset.GetValue()))
+ # Add items to the menu
+ new = wx.MenuItem(menu, wx.ID_ANY, Icons["workspaceNew"].GetLabel())
+ new.SetBitmap(Icons["workspaceNew"].GetBitmap(self.iconsize))
+ menu.AppendItem(new)
+ self.Bind(wx.EVT_MENU, self.OnWorkspaceNew, new)
+ load = wx.MenuItem(menu, wx.ID_ANY, Icons["workspaceLoad"].GetLabel())
+ load.SetBitmap(Icons["workspaceLoad"].GetBitmap(self.iconsize))
+ menu.AppendItem(load)
+ self.Bind(wx.EVT_MENU, self.OnWorkspaceLoad, load)
- def OnLocationChange(self,event):
- """
- Populate mapset combobox with selected location.
- """
+ # create menu
+ self.PopupMenu(menu)
+ menu.Destroy()
- self.cmbMapset.Clear()
- self.cmbMapset.SetValue("Select Mapset")
- self.tree.DeleteAllItems()
+ def OnWorkspaceNew(self, event=None):
+ """!Create new workspace file
- maplists = self.GetMapsets(self.cmbLocation.GetValue())
- for mapsets in maplists:
- self.cmbMapset.Append(str(mapsets))
+ Erase current workspace settings first"""
+ Debug.msg(4, "GMFrame.OnWorkspaceNew():")
+
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
+
+ maptree = self.current.maptree
+
+ # ask user to save current settings
+ if maptree.GetCount() > 0:
+ dlg = wx.MessageDialog(self, message=_("Current workspace is not empty. "
+ "Do you want to store current settings "
+ "to workspace file?"),
+ caption=_("Create new workspace?"),
+ style=wx.YES_NO | wx.YES_DEFAULT | \
+ wx.CANCEL | wx.ICON_QUESTION)
+ ret = dlg.ShowModal()
+ if ret == wx.ID_YES:
+ self.OnWorkspaceSaveAs()
+ elif ret == wx.ID_CANCEL:
+ dlg.Destroy()
+ return
+
+ dlg.Destroy()
+
+ # delete all items
+ maptree.DeleteAllItems()
+
+ # add new root element
+ maptree.root = maptree.AddRoot("Map Layers")
+ self.current.maptree.SetPyData(maptree.root, (None,None))
+
+ # no workspace file loaded
+ self.workspaceFile = None
+ self.SetTitle(self.baseTitle)
+
+ def OnWorkspaceOpen(self, event=None):
+ """!Open file with workspace definition"""
+ dlg = wx.FileDialog(parent=self, message=_("Choose workspace file"),
+ defaultDir=os.getcwd(), wildcard="*.gxw")
- def AddTreeNodes(self,location,mapset):
- """
- Adds tree nodes. raster,vector and dbf files are identified using
- their directory structure.
- """
+ filename = ''
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
- root = self.tree.AddRoot('root')
- node_raster = self.tree.AppendItem(root, "Raster Map")
- node_vector = self.tree.AppendItem(root, "Vector Map")
- node_dbf = self.tree.AppendItem(root, "DBF")
- treeNodes = [node_raster,node_vector,node_dbf]
+ if filename == '':
+ return
- glocs = glob.glob(os.path.join(self.gisdbase,location, mapset,"*"))
- for gloc in glocs:
- if not os.path.isfile(gloc) and os.path.isdir(gloc):
- if(os.path.basename(gloc)=='cats'):
- for rast in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
- self.tree.AppendItem(node_raster, os.path.basename(rast))
- elif(os.path.basename(gloc)=='vector'):
- for vect in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
- self.tree.AppendItem(node_vector, os.path.basename(vect))
- elif(os.path.basename(gloc)=='dbf'):
- for dfile in glob.glob(os.path.join(self.gisdbase,location, mapset,gloc, "*")):
- self.tree.AppendItem(node_dbf, os.path.basename(dfile))
+ Debug.msg(4, "GMFrame.OnWorkspaceOpen(): filename=%s" % filename)
- #Nodes with no children are given an italic type font
- for node in treeNodes:
- if not self.tree.ItemHasChildren(node):
- if self.tree.GetItemText(node) == 'Raster Map':
- tmp_item = self.tree.AppendItem(node, "No raster maps found.")
- elif self.tree.GetItemText(node) == 'Vector Map':
- tmp_item = self.tree.AppendItem(node, "No vector maps found.")
- elif self.tree.GetItemText(node) == 'DBF':
- tmp_item = self.tree.AppendItem(node, "No DBF files found.")
- self.tree.SetItemFont(tmp_item,self.itemFont)
+ # delete current layer tree content
+ self.OnWorkspaceClose()
+
+ self.LoadWorkspaceFile(filename)
- def GetMapsets(self,location):
- """
- Read and returns all mapset int GRASS data directory.
- """
-
- maplist = []
- for mapset in glob.glob(os.path.join(self.gisdbase, location, "*")):
- if os.path.isdir(mapset) and os.path.isfile(os.path.join(self.gisdbase, location, mapset, "WIND")):
- maplist.append(os.path.basename(mapset))
- return maplist
+ self.workspaceFile = filename
+ self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
- def GetLocations(self):
- """
- Read and returns all locations int GRASS data directory.
- """
- loclist = []
- for location in glob.glob(os.path.join(self.gisdbase, "*")):
- if os.path.join(location, "PERMANENT") in glob.glob(os.path.join(location, "*")):
- loclist.append(os.path.basename(location))
- return loclist
+ def LoadWorkspaceFile(self, filename):
+ """!Load layer tree definition stored in GRASS Workspace XML file (gxw)
+ @todo Validate against DTD
+
+ @return True on success
+ @return False on error
+ """
+ # dtd
+ dtdFilename = os.path.join(globalvar.ETCWXDIR, "xml", "grass-gxw.dtd")
+
+ # parse workspace file
+ try:
+ gxwXml = workspace.ProcessWorkspaceFile(etree.parse(filename))
+ except Exception, err:
+ raise gcmd.GStdError(_("Reading workspace file <%(file)s> failed.\n"
+ "Invalid file, unable to parse XML document."
+ "\n\n%(err)s") % { 'file' : filename, 'err': err},
+ parent = self)
+
+ busy = wx.BusyInfo(message=_("Please wait, loading workspace..."),
+ parent=self)
+ wx.Yield()
- def doBindings(self):
+ #
+ # load layer manager window properties
+ #
+ if UserSettings.Get(group='workspace', key='posManager', subkey='enabled') is False:
+ if gxwXml.layerManager['pos']:
+ self.SetPosition(gxwXml.layerManager['pos'])
+ if gxwXml.layerManager['size']:
+ self.SetSize(gxwXml.layerManager['size'])
- #Event bindings for combo boxes
- self.Bind(wx.EVT_COMBOBOX,self.OnMapsetChange,self.cmbMapset)
- self.Bind(wx.EVT_COMBOBOX,self.OnLocationChange,self.cmbLocation)
+ #
+ # start map displays first (list of layers can be empty)
+ #
+ displayId = 0
+ mapdisplay = []
+ for display in gxwXml.displays:
+ mapdisplay.append(self.NewDisplay())
+ maptree = self.notebook.GetPage(displayId).maptree
+
+ # set windows properties
+ mapdisplay[-1].SetProperties(render=display['render'],
+ mode=display['mode'],
+ showCompExtent=display['showCompExtent'],
+ constrainRes=display['constrainRes'],
+ projection=display['projection']['enabled'])
- #Event bindings for tree -(display,popup,label edit.)
- self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnDisplay,self.tree)
- self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,self.OnTreePopUp,self.tree)
- self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndRename,self.tree)
- self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginRename,self.tree)
+ if display['projection']['enabled']:
+ if display['projection']['epsg']:
+ UserSettings.Set(group = 'display', key = 'projection', subkey = 'epsg',
+ value = display['projection']['epsg'])
+ if display['projection']['proj']:
+ UserSettings.Set(group = 'display', key = 'projection', subkey = 'proj4',
+ value = display['projection']['proj'])
+
+ # set position and size of map display
+ if UserSettings.Get(group='workspace', key='posDisplay', subkey='enabled') is False:
+ if display['pos']:
+ mapdisplay[-1].SetPosition(display['pos'])
+ if display['size']:
+ mapdisplay[-1].SetSize(display['size'])
+
+ # set extent if defined
+ if display['extent']:
+ w, s, e, n = display['extent']
+ maptree.Map.region = maptree.Map.GetRegion(w=w, s=s, e=e, n=n)
+
+ mapdisplay[-1].Show()
+
+ displayId += 1
+
+ maptree = None
+ selected = [] # list of selected layers
+ #
+ # load list of map layers
+ #
+ for layer in gxwXml.layers:
+ display = layer['display']
+ maptree = self.notebook.GetPage(display).maptree
+
+ newItem = maptree.AddLayer(ltype=layer['type'],
+ lname=layer['name'],
+ lchecked=layer['checked'],
+ lopacity=layer['opacity'],
+ lcmd=layer['cmd'],
+ lgroup=layer['group'],
+ lnviz=layer['nviz'],
+ lvdigit=layer['vdigit'])
+
+ if layer.has_key('selected'):
+ if layer['selected']:
+ selected.append((maptree, newItem))
+ else:
+ maptree.SelectItem(newItem, select=False)
+
+ for maptree, layer in selected:
+ if not maptree.IsSelected(layer):
+ maptree.SelectItem(layer, select=True)
+ maptree.layer_selected = layer
+
+ busy.Destroy()
+
+ if maptree:
+ # reverse list of map layers
+ maptree.Map.ReverseListOfLayers()
- #Event bindings for tree menu
- self.Bind(wx.EVT_MENU,self.OnCopy,id=self.ID_COPY)
- self.Bind(wx.EVT_MENU,self.OnRename,id=self.ID_REN)
- self.Bind(wx.EVT_MENU,self.OnDelete,id=self.ID_DEL)
+ for mdisp in mapdisplay:
+ mdisp.MapWindow2D.UpdateMap()
+ return True
- self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ def OnWorkspaceLoad(self, event=None):
+ """!Load given map layers into layer tree"""
+ dialog = gdialogs.LoadMapLayersDialog(parent=self, title=_("Load map layers into layer tree"))
- #Event bindings for v/r.info checkbox
- self.Bind(wx.EVT_CHECKBOX, self.OnToggleInfo,self.chkInfo)
- self.Bind(wx.EVT_CHECKBOX, self.OnToggleExpand,self.treeExpand)
+ if dialog.ShowModal() == wx.ID_OK:
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
- def doLayout(self):
+ maptree = self.current.maptree
+ busy = wx.BusyInfo(message=_("Please wait, loading workspace..."),
+ parent=self)
+ wx.Yield()
- #combo panel sizers
- self.cmbSizer.Add(self.lbLocation,pos=(1,0),flag=wx.ALL,border=2)
- self.cmbSizer.Add(self.lbMapset,pos=(1,1),flag=wx.ALL,border=2)
- self.cmbSizer.Add(self.cmbLocation,pos=(2,0),flag=wx.ALL)
- self.cmbSizer.Add(self.cmbMapset,pos=(2,1),flag=wx.ALL)
- self.cmbSizer.Add(self.chkInfo,pos=(2,2),flag=wx.ALL)
- self.cmbSizer.Add(self.treeExpand,pos=(2,3),flag=wx.ALL)
- self.cmbPanel.SetSizer(self.cmbSizer)
+ for layerName in dialog.GetMapLayers():
+ if dialog.GetLayerType() == 'raster':
+ cmd = ['d.rast', 'map=%s' % layerName]
+ elif dialog.GetLayerType() == 'vector':
+ cmd = ['d.vect', 'map=%s' % layerName]
+ newItem = maptree.AddLayer(ltype=dialog.GetLayerType(),
+ lname=layerName,
+ lchecked=True,
+ lopacity=1.0,
+ lcmd=cmd,
+ lgroup=None)
- #splitter window sizers
- self.mSizer.Add(self.cmbPanel,flag=wx.EXPAND)
- self.mSizer.Add(self.win, 1, wx.EXPAND)
- self.SetSizer(self.mSizer)
+ busy.Destroy()
- #sizers for splitter window panels
- self.leftSizer.Add(self.tree,1,wx.EXPAND)
- self.rightSizer.Add(self.MapWindow)
- self.rightSizer.Add(self.mInfo,1,wx.EXPAND)
- self.pLeft.SetSizer(self.leftSizer)
- self.pRight.SetSizer(self.rightSizer)
+ def OnWorkspaceLoadGrcFile(self, event):
+ """!Load map layers from GRC file (Tcl/Tk GUI) into map layer tree"""
+ dlg = wx.FileDialog(parent=self, message=_("Choose GRC file to load"),
+ defaultDir=os.getcwd(), wildcard="*.grc")
+ filename = ''
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
+ if filename == '':
+ return
- def read_gisrc(self):
- """
- Read variables from $HOME/.grassrc7 file
- """
+ Debug.msg(4, "GMFrame.OnWorkspaceLoadGrcFile(): filename=%s" % filename)
- rc = {}
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
- gisrc = os.getenv("GISRC")
+ busy = wx.BusyInfo(message=_("Please wait, loading workspace..."),
+ parent=self)
+ wx.Yield()
- if gisrc and os.path.isfile(gisrc):
- try:
- f = open(gisrc, "r")
- for line in f.readlines():
- key, val = line.split(":", 1)
- rc[key.strip()] = val.strip()
- finally:
- f.close()
+ maptree = None
+ for layer in workspace.ProcessGrcFile(filename).read(self):
+ maptree = self.gm_cb.GetPage(layer['display']).maptree
+ newItem = maptree.AddLayer(ltype=layer['type'],
+ lname=layer['name'],
+ lchecked=layer['checked'],
+ lopacity=layer['opacity'],
+ lcmd=layer['cmd'],
+ lgroup=layer['group'])
- return rc
+ busy.Destroy()
+
+ if maptree:
+ # reverse list of map layers
+ maptree.Map.ReverseListOfLayers()
- def update_grassrc(self,gisrc):
- """
- Update $HOME/.grassrc7 and gisrc files
- """
+ def OnWorkspaceSaveAs(self, event=None):
+ """!Save workspace definition to selected file"""
- rc = os.getenv("GISRC")
- grassrc = os.path.join(os.getenv('HOME'), ".grassrc7.%s" % os.uname()[1])
- if not os.access(grassrc, os.R_OK):
- grassrc = os.path.join(os.getenv('HOME'), ".grassrc7")
- if rc and os.path.isfile(rc):
- try:
- f = open(rc, 'w')
- for key, val in gisrc.iteritems():
- f.write("%s: %s\n" % (key, val))
- finally:
- f.close()
+ dlg = wx.FileDialog(parent=self, message=_("Choose file to save current workspace"),
+ defaultDir=os.getcwd(), wildcard="*.gxw", style=wx.FD_SAVE)
- if grassrc and os.path.isfile(grassrc):
- try:
- g = open(grassrc, 'w')
- for key, val in gisrc.iteritems():
- g.write("%s: %s\n" % (key, val))
- finally:
- g.close()
+ filename = ''
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
+ if filename == '':
+ return False
+
+ # check for extension
+ if filename[-4:] != ".gxw":
+ filename += ".gxw"
+
+ if os.path.exists(filename):
+ dlg = wx.MessageDialog(self, message=_("Workspace file <%s> already exists. "
+ "Do you want to overwrite this file?") % filename,
+ caption=_("Save workspace"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+ if dlg.ShowModal() != wx.ID_YES:
+ dlg.Destroy()
+ return False
+
+ Debug.msg(4, "GMFrame.OnWorkspaceSaveAs(): filename=%s" % filename)
+
+ self.SaveToWorkspaceFile(filename)
+ self.workspaceFile = filename
+ self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
+
+ def OnWorkspaceSave(self, event=None):
+ """!Save file with workspace definition"""
+
+ if self.workspaceFile:
+ dlg = wx.MessageDialog(self, message=_("Workspace file <%s> already exists. "
+ "Do you want to overwrite this file?") % \
+ self.workspaceFile,
+ caption=_("Save workspace"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+ if dlg.ShowModal() == wx.ID_NO:
+ dlg.Destroy()
+ else:
+ Debug.msg(4, "GMFrame.OnWorkspaceSave(): filename=%s" % self.workspaceFile)
+ self.SaveToWorkspaceFile(self.workspaceFile)
+ else:
+ self.OnWorkspaceSaveAs()
+
+ def SaveToWorkspaceFile(self, filename):
+ """!Save layer tree layout to workspace file
+
+ Return True on success, False on error
+ """
+
+ try:
+ file = open(filename, "w")
+ except IOError:
+ wx.MessageBox(parent=self,
+ message=_("Unable to open workspace file <%s> for writing.") % filename,
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return False
+
+ try:
+ workspace.WriteWorkspaceFile(lmgr=self, file=file)
+ except StandardError, e:
+ file.close()
+ wx.MessageBox(parent=self,
+ message=_("Writing current settings to workspace file failed (%s)." % e),
+ caption=_("Error"),
+ style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return False
+
+ file.close()
+
+ return True
+
+ def OnWorkspaceClose(self, event=None):
+ """!Close file with workspace definition
+
+ If workspace has been modified ask user to save the changes.
+ """
+
+ Debug.msg(4, "GMFrame.OnWorkspaceClose(): file=%s" % self.workspaceFile)
+ self.workspaceFile = None
+ self.SetTitle(self.baseTitle)
+
+ displays = []
+ for page in range(0, self.notebook.GetPageCount()):
+ displays.append(self.notebook.GetPage(page).maptree.mapdisplay)
+
+ for display in displays:
+ display.OnCloseWindow(event)
+
+ self.disp_idx = 0
+ self.curr_page = None
+
+
+ def RulesCmd(self, event, cmd = ''):
+ """
+ Launches dialog for commands that need rules
+ input and processes rules
+ """
+ if event:
+ cmd = self.GetMenuCmd(event)
+
+ if cmd[0] == 'r.colors' or cmd[0] == 'vcolors':
+ ctable = colorrules.ColorTable(self, cmd=cmd[0])
+ ctable.Show()
+ else:
+ dlg = rules.RulesText(self, cmd=cmd)
+ dlg.CenterOnScreen()
+ if dlg.ShowModal() == wx.ID_OK:
+ gtemp = utils.GetTempfile()
+ output = open(gtemp, "w")
+ try:
+ output.write(dlg.rules)
+ finally:
+ output.close()
+
+ cmdlist = [cmd[0],
+ 'input=%s' % dlg.inmap,
+ 'output=%s' % dlg.outmap,
+ 'rules=%s' % gtemp]
+
+ if dlg.overwrite == True:
+ cmdlist.append('--o')
+
+ dlg.Destroy()
+
+ self.goutput.RunCmd(cmdlist)
+
+ def OnPreferences(self, event):
+ """!General GUI preferences/settings"""
+ if not self.dialogs['preferences']:
+ dlg = preferences.PreferencesDialog(parent=self)
+ self.dialogs['preferences'] = dlg
+ self.dialogs['preferences'].CenterOnScreen()
+
+ self.dialogs['preferences'].ShowModal()
+
+ def DispHistogram(self, event):
+ """
+ Init histogram display canvas and tools
+ """
+ self.histogram = histogram.HistFrame(self,
+ id=wx.ID_ANY, pos=wx.DefaultPosition, size=(400,300),
+ style=wx.DEFAULT_FRAME_STYLE)
+
+ #show new display
+ self.histogram.Show()
+ self.histogram.Refresh()
+ self.histogram.Update()
+
+ def DispProfile(self, event):
+ """
+ Init profile canvas and tools
+ """
+ self.profile = profile.ProfileFrame(self,
+ id=wx.ID_ANY, pos=wx.DefaultPosition, size=(400,300),
+ style=wx.DEFAULT_FRAME_STYLE)
+ self.profile.Show()
+ self.profile.Refresh()
+ self.profile.Update()
+
+ def DispMapCalculator(self, event):
+ """
+ Init map calculator for interactive creation of mapcalc statements
+ """
+
+ self.mapcalculator = mapcalculator.MapCalcFrame(self, wx.ID_ANY, title='',
+ dimension=2)
+
+ def Disp3DMapCalculator(self, event):
+ """
+ Init map calculator for interactive creation of mapcalc statements
+ """
+
+ self.mapcalculator = mapcalculator.MapCalcFrame(self, wx.ID_ANY, title='',
+ dimension=3)
+
+ def AddToolbarButton(self, toolbar, label, icon, help, handler):
+ """!Adds button to the given toolbar"""
+
+ if not label:
+ toolbar.AddSeparator()
+ return
+ tool = toolbar.AddLabelTool(id=wx.ID_ANY, label=label, bitmap=icon, shortHelp=help)
+ self.Bind(wx.EVT_TOOL, handler, tool)
+
+ def ToolbarData(self):
+
+ return (
+ ('newdisplay', Icons["newdisplay"].GetBitmap(),
+ Icons["newdisplay"].GetLabel(), self.OnNewDisplay),
+ ('', '', '', ''),
+ ('workspaceLoad', Icons["workspaceLoad"].GetBitmap(),
+ Icons["workspaceLoad"].GetLabel(), self.OnWorkspace),
+ ('workspaceOpen', Icons["workspaceOpen"].GetBitmap(),
+ Icons["workspaceOpen"].GetLabel(), self.OnWorkspaceOpen),
+ ('workspaceSave', Icons["workspaceSave"].GetBitmap(),
+ Icons["workspaceSave"].GetLabel(), self.OnWorkspaceSave),
+ ('', '', '', ''),
+ ('addrast', Icons["addrast"].GetBitmap(),
+ Icons["addrast"].GetLabel(), self.OnAddRaster),
+ ('addshaded', Icons["addshaded"].GetBitmap(),
+ _("Add various raster-based map layers"), self.OnAddRasterMisc),
+ ('addvect', Icons["addvect"].GetBitmap(),
+ Icons["addvect"].GetLabel(), self.OnAddVector),
+ ('addthematic', Icons["addthematic"].GetBitmap(),
+ _("Add various vector-based map layer"), self.OnAddVectorMisc),
+ ('addcmd', Icons["addcmd"].GetBitmap(),
+ Icons["addcmd"].GetLabel(), self.OnAddCommand),
+ ('addgrp', Icons["addgrp"].GetBitmap(),
+ Icons["addgrp"].GetLabel(), self.OnAddGroup),
+ ('addovl', Icons["addovl"].GetBitmap(),
+ Icons["addovl"].GetLabel(), self.OnAddOverlay),
+ ('delcmd', Icons["delcmd"].GetBitmap(),
+ Icons["delcmd"].GetLabel(), self.OnDeleteLayer),
+ ('', '', '', ''),
+ ('attrtable', Icons["attrtable"].GetBitmap(),
+ Icons["attrtable"].GetLabel(), self.OnShowAttributeTable)
+ )
+
+ def OnImportDxfFile(self, event):
+ """!Convert multiple DXF layers to GRASS vector map layers"""
+ dlg = gdialogs.MultiImportDialog(parent=self, type='dxf',
+ title=_("Import DXF layers"))
+ dlg.ShowModal()
+
+ def OnImportGdalLayers(self, event):
+ """!Convert multiple GDAL layers to GRASS raster map layers"""
+ dlg = gdialogs.MultiImportDialog(parent=self, type='gdal',
+ title=_("Import GDAL layers"))
+ dlg.ShowModal()
+
+ def OnLinkGdalLayers(self, event):
+ """!Link multiple GDAL layers to GRASS raster map layers"""
+ dlg = gdialogs.MultiImportDialog(parent=self, type='gdal',
+ title=_("Link GDAL layers"),
+ link = True)
+ dlg.ShowModal()
+
+ def OnImportOgrLayers(self, event):
+ """!Convert multiple OGR layers to GRASS vector map layers"""
+ dlg = gdialogs.MultiImportDialog(parent=self, type='ogr',
+ title=_("Import OGR layers"))
+ dlg.ShowModal()
+
+ def OnLinkOgrLayers(self, event):
+ """!Links multiple OGR layers to GRASS vector map layers"""
+ dlg = gdialogs.MultiImportDialog(parent=self, type='ogr',
+ title=_("Link OGR layers"),
+ link = True)
+ dlg.ShowModal()
+
+ def OnImportWMS(self, event):
+ """!Import data from OGC WMS server"""
+ dlg = ogc_services.WMSDialog(parent = self, service = 'wms')
+ dlg.CenterOnScreen()
+
+ if dlg.ShowModal() == wx.ID_OK: # -> import layers
+ layers = dlg.GetLayers()
+
+ if len(layers.keys()) > 0:
+ for layer in layers.keys():
+ cmd = ['r.in.wms',
+ 'mapserver=%s' % dlg.GetSettings()['server'],
+ 'layers=%s' % layer,
+ 'output=%s' % layer]
+ styles = ','.join(layers[layer])
+ if styles:
+ cmd.append('styles=%s' % styles)
+ self.goutput.RunCmd(cmd, switchPage = True)
+ else:
+ self.goutput.WriteWarning(_("Nothing to import. No WMS layer selected."))
+
+ dlg.Destroy()
+
+ def OnShowAttributeTable(self, event):
+ """
+ Show attribute table of the given vector map layer
+ """
+ if not self.current:
+ self.MsgNoLayerSelected()
+ return
+
+ layer = self.current.maptree.layer_selected
+ # no map layer selected
+ if not layer:
+ self.MsgNoLayerSelected()
+ return
+
+ # available only for vector map layers
+ try:
+ maptype = self.current.maptree.GetPyData(layer)[0]['maplayer'].type
+ except:
+ maptype = None
+
+ if not maptype or maptype != 'vector':
+ wx.MessageBox(parent=self,
+ message=_("Attribute management is available only "
+ "for vector maps."),
+ caption=_("Message"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ return
+
+ if not self.current.maptree.GetPyData(layer)[0]:
+ return
+ dcmd = self.current.maptree.GetPyData(layer)[0]['cmd']
+ if not dcmd:
+ return
+
+ busy = wx.BusyInfo(message=_("Please wait, loading attribute data..."),
+ parent=self)
+ wx.Yield()
+
+ dbmanager = dbm.AttributeManager(parent=self, id=wx.ID_ANY,
+ size=wx.Size(500, 300),
+ item=layer, log=self.goutput)
+
+ busy.Destroy()
+
+ # register ATM dialog
+ self.dialogs['atm'].append(dbmanager)
+
+ # show ATM window
+ dbmanager.Show()
+
+ def OnNewDisplay(self, event=None):
+ """!Create new layer tree and map display instance"""
+ self.NewDisplay()
+
+ def NewDisplay(self):
+ """!Create new layer tree, which will
+ create an associated map display frame
+
+ @param show show map display window if True
+
+ @return reference to mapdisplay intance
+ """
+ Debug.msg(1, "GMFrame.NewDisplay(): idx=%d" % self.disp_idx)
+
+ # make a new page in the bookcontrol for the layer tree (on page 0 of the notebook)
+
+ self.disp_idx = self.disp_idx + 1
+# self.curr_pagenum = self.disp_idx
+
+ self.page = MapFrame(parent=self.notebook, id=wx.ID_ANY, Map=render.Map(), size=globalvar.MAP_WINDOW_SIZE,frame=self)
+ self.notebook.AddPage(self.page, text="Display "+ str(self.disp_idx), select = True)
+
+ self.current = self.notebook.GetCurrentPage()
+
+
+
+ # toolBar button handlers
+ def OnAddRaster(self, event):
+ """!Add raster map layer"""
+ #create image list to use with layer tree
+ il = wx.ImageList(16, 16, mask=False)
+
+ trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16))
+ self.folder_open = il.Add(trart)
+ trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
+ self.folder = il.Add(trart)
+
+ bmpsize = (16, 16)
+ trgif = Icons["addrast"].GetBitmap(bmpsize)
+ self.rast_icon = il.Add(trgif)
+
+ trgif = Icons["addrast3d"].GetBitmap(bmpsize)
+ self.rast3d_icon = il.Add(trgif)
+
+ trgif = Icons["addrgb"].GetBitmap(bmpsize)
+ self.rgb_icon = il.Add(trgif)
+
+ trgif = Icons["addhis"].GetBitmap(bmpsize)
+ self.his_icon = il.Add(trgif)
+
+ trgif = Icons["addshaded"].GetBitmap(bmpsize)
+ self.shaded_icon = il.Add(trgif)
+
+ trgif = Icons["addrarrow"].GetBitmap(bmpsize)
+ self.rarrow_icon = il.Add(trgif)
+
+ trgif = Icons["addrnum"].GetBitmap(bmpsize)
+ self.rnum_icon = il.Add(trgif)
+
+ trgif = Icons["addvect"].GetBitmap(bmpsize)
+ self.vect_icon = il.Add(trgif)
+
+ trgif = Icons["addthematic"].GetBitmap(bmpsize)
+ self.theme_icon = il.Add(trgif)
+
+ trgif = Icons["addchart"].GetBitmap(bmpsize)
+ self.chart_icon = il.Add(trgif)
+
+ trgif = Icons["addgrid"].GetBitmap(bmpsize)
+ self.grid_icon = il.Add(trgif)
+
+ trgif = Icons["addgeodesic"].GetBitmap(bmpsize)
+ self.geodesic_icon = il.Add(trgif)
+
+ trgif = Icons["addrhumb"].GetBitmap(bmpsize)
+ self.rhumb_icon = il.Add(trgif)
+
+ trgif = Icons["addlabels"].GetBitmap(bmpsize)
+ self.labels_icon = il.Add(trgif)
+
+ trgif = Icons["addcmd"].GetBitmap(bmpsize)
+ self.cmd_icon = il.Add(trgif)
+
+# self.current.maptree.AssignImageList(il)
+
+
+ self.AddRaster(event)
+
+ def OnAddRasterMisc(self, event):
+ """!Add raster menu"""
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
+
+ point = wx.GetMousePosition()
+ rastmenu = wx.Menu()
+
+ # add items to the menu
+ if self.current.maptree.mapdisplay.toolbars['nviz']:
+ addrast3d = wx.MenuItem(rastmenu, -1, Icons ["addrast3d"].GetLabel())
+ addrast3d.SetBitmap(Icons["addrast3d"].GetBitmap (self.iconsize))
+ rastmenu.AppendItem(addrast3d)
+ self.Bind(wx.EVT_MENU, self.AddRaster3d, addrast3d)
+
+ addshaded = wx.MenuItem(rastmenu, -1, Icons ["addshaded"].GetLabel())
+ addshaded.SetBitmap(Icons["addshaded"].GetBitmap (self.iconsize))
+ rastmenu.AppendItem(addshaded)
+ self.Bind(wx.EVT_MENU, self.AddShaded, addshaded)
+
+ addrgb = wx.MenuItem(rastmenu, -1, Icons["addrgb"].GetLabel())
+ addrgb.SetBitmap(Icons["addrgb"].GetBitmap(self.iconsize))
+ rastmenu.AppendItem(addrgb)
+ self.Bind(wx.EVT_MENU, self.AddRGB, addrgb)
+
+ addhis = wx.MenuItem(rastmenu, -1, Icons ["addhis"].GetLabel())
+ addhis.SetBitmap(Icons["addhis"].GetBitmap (self.iconsize))
+ rastmenu.AppendItem(addhis)
+ self.Bind(wx.EVT_MENU, self.AddHIS, addhis)
+
+ addrastarrow = wx.MenuItem(rastmenu, -1, Icons ["addrarrow"].GetLabel())
+ addrastarrow.SetBitmap(Icons["addrarrow"].GetBitmap (self.iconsize))
+ rastmenu.AppendItem(addrastarrow)
+ self.Bind(wx.EVT_MENU, self.AddRastarrow, addrastarrow)
+
+ addrastnums = wx.MenuItem(rastmenu, -1, Icons ["addrnum"].GetLabel())
+ addrastnums.SetBitmap(Icons["addrnum"].GetBitmap (self.iconsize))
+ rastmenu.AppendItem(addrastnums)
+ self.Bind(wx.EVT_MENU, self.AddRastnum, addrastnums)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(rastmenu)
+ rastmenu.Destroy()
+
+ # show map display
+ #self.curr_page.maptree.mapdisplay.Show()
+
+ def OnAddVector(self, event):
+ """!Add vector map layer"""
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
+
+ self.AddVector(event)
+
+ def OnAddVectorMisc(self, event):
+ """!Add vector menu"""
+ # start new map display if no display is available
+ if not self.current:
+ self.NewDisplay()
+
+ point = wx.GetMousePosition()
+ vectmenu = wx.Menu()
+
+ addtheme = wx.MenuItem(vectmenu, -1, Icons["addthematic"].GetLabel())
+ addtheme.SetBitmap(Icons["addthematic"].GetBitmap(self.iconsize))
+ vectmenu.AppendItem(addtheme)
+ self.Bind(wx.EVT_MENU, self.AddThemeMap, addtheme)
+
+ addchart = wx.MenuItem(vectmenu, -1, Icons["addchart"].GetLabel())
+ addchart.SetBitmap(Icons["addchart"].GetBitmap(self.iconsize))
+ vectmenu.AppendItem(addchart)
+ self.Bind(wx.EVT_MENU, self.AddThemeChart, addchart)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(vectmenu)
+ vectmenu.Destroy()
+
+ # show map display
+ #self.curr_page.maptree.mapdisplay.Show()
+
+ def OnAddOverlay(self, event):
+ """!Add overlay menu"""
+ # start new map display if no display is available
+ if not self.curent:
+ self.NewDisplay()
+
+ point = wx.GetMousePosition()
+ ovlmenu = wx.Menu()
+
+ addgrid = wx.MenuItem(ovlmenu, wx.ID_ANY, Icons["addgrid"].GetLabel())
+ addgrid.SetBitmap(Icons["addgrid"].GetBitmap(self.iconsize))
+ ovlmenu.AppendItem(addgrid)
+ self.Bind(wx.EVT_MENU, self.AddGrid, addgrid)
+
+ addlabels = wx.MenuItem(ovlmenu, wx.ID_ANY, Icons["addlabels"].GetLabel())
+ addlabels.SetBitmap(Icons["addlabels"].GetBitmap(self.iconsize))
+ ovlmenu.AppendItem(addlabels)
+ self.Bind(wx.EVT_MENU, self.OnAddLabels, addlabels)
+
+ addgeodesic = wx.MenuItem(ovlmenu, wx.ID_ANY, Icons["addgeodesic"].GetLabel())
+ addgeodesic.SetBitmap(Icons["addgeodesic"].GetBitmap(self.iconsize))
+ ovlmenu.AppendItem(addgeodesic)
+ self.Bind(wx.EVT_MENU, self.AddGeodesic, addgeodesic)
+
+ addrhumb = wx.MenuItem(ovlmenu, wx.ID_ANY, Icons["addrhumb"].GetLabel())
+ addrhumb.SetBitmap(Icons["addrhumb"].GetBitmap(self.iconsize))
+ ovlmenu.AppendItem(addrhumb)
+ self.Bind(wx.EVT_MENU, self.AddRhumb, addrhumb)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(ovlmenu)
+ ovlmenu.Destroy()
+
+ # show map display
+ self.curr_page.maptree.mapdisplay.Show()
+
+ def AddRaster(self, event):
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('raster')
+
+ def AddRaster3d(self, event):
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('3d-raster')
+
+ def AddRGB(self, event):
+ """!Add RGB layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('rgb')
+
+ def AddHIS(self, event):
+ """!Add HIS layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('his')
+
+ def AddShaded(self, event):
+ """!Add shaded relief map layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('shaded')
+
+ def AddRastarrow(self, event):
+ """!Add raster flow arrows map"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('rastarrow')
+
+ def AddRastnum(self, event):
+ """!Add raster map with cell numbers"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('rastnum')
+
+ def AddVector(self, event):
+ """!Add vector layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('vector')
+
+ def AddThemeMap(self, event):
+ """!Add thematic map layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('thememap')
+
+ def AddThemeChart(self, event):
+ """!Add thematic chart layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('themechart')
+
+ def OnAddCommand(self, event):
+ """!Add command line layer"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('command')
+
+ def OnAddGroup(self, event):
+ """!Add layer group"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('group')
+
+ def AddGrid(self, event):
+ """!Add layer grid"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('grid')
+
+ def AddGeodesic(self, event):
+ """!Add layer geodesic"""
+ self.curr_page.maptree.AddLayer('geodesic')
+
+ def AddRhumb(self, event):
+ """!Add layer rhumb"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('rhumb')
+
+ def OnAddLabels(self, event):
+ """!Add layer vector labels"""
+ if not self.current:
+ self.NewDisplay()
+
+ self.current.maptree.AddLayer('labels')
+
+ def OnDeleteLayer(self, event):
+ """
+ Delete selected map display layer in GIS Manager tree widget
+ """
+ if UserSettings.Get(group='manager', key='askOnRemoveLayer', subkey='enabled'):
+ layerName = ''
+ for item in self.current.maptree.GetSelections():
+ name = str(self.current.maptree.GetItemText(item))
+ idx = name.find('(opacity')
+ if idx > -1:
+ layerName += '<' + name[:idx].strip(' ') + '>,\n'
+ else:
+ layerName += '<' + name + '>,\n'
+ layerName = layerName.rstrip(',\n')
+
+ if len(layerName) > 2: # <>
+ message = _("Do you want to remove map layer(s)\n%s\n"
+ "from layer tree?") % layerName
+ else:
+ message = _("Do you want to remove selected map layer(s) "
+ "from layer tree?")
+
+ dlg = wx.MessageDialog (parent=self, message=message,
+ caption=_("Remove map layer"),
+ style=wx.YES_NO | wx.YES_DEFAULT | wx.CANCEL | wx.ICON_QUESTION)
+
+ if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
+ dlg.Destroy()
+ return
+
+ dlg.Destroy()
+
+ for layer in self.current.maptree.GetSelections():
+ if self.current.maptree.GetPyData(layer)[0]['type'] == 'group':
+ self.current.maptree.DeleteChildren(layer)
+ self.current.maptree.Delete(layer)
+
+ def OnKey(self, event):
+ """!Check hotkey"""
+ try:
+ kc = chr(event.GetKeyCode())
+ except ValueError:
+ event.Skip()
+ return
+
+ if event.AltDown():
+ if kc == 'R':
+ self.OnAddRaster(None)
+ elif kc == 'V':
+ self.OnAddVector(None)
+
+ event.Skip()
+
+ def OnCloseWindow(self, event):
+ """!Cleanup when wxGUI is quit"""
+ count = self.notebook.GetPageCount()
+ index = 0
+ while index < count:
+ self.current = self.notebook.GetPage(index)
+ self.current.Map.Clean()
+ index = index+1
+
+ self.notebook.DeleteAllPages()
+ self.Destroy()
+
+
+ def MsgNoLayerSelected(self):
+ """!Show dialog message 'No layer selected'"""
+ wx.MessageBox(parent=self,
+ message=_("No map layer selected. Operation cancelled."),
+ caption=_("Message"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+
+
+
+ def OnMapsetChange(self,event):
+ """
+ Create the tree nodes based on selected location and mapset.
+ Also update gisrc and grassrc files.
+ """
+ self.ltree.DeleteAllItems()
+ self.ltree.AddTreeNodes(self.cmbLocation.GetValue(),self.cmbMapset.GetValue())
+ self.gisrc['LOCATION_NAME'] = str(self.cmbLocation.GetValue())
+ self.gisrc['MAPSET'] = str(self.cmbMapset.GetValue())
+ self.update_grassrc(self.gisrc)
+ #gcmd.RunCommand("g.gisenv", set = "MAPSET=%s" % str(self.cmbMapset.GetValue()))
+
+
+ def OnLocationChange(self,event):
+ """
+ Populate mapset combobox with selected location.
+ """
+
+ self.cmbMapset.Clear()
+ self.cmbMapset.SetValue("Select Mapset")
+ self.ltree.DeleteAllItems()
+
+ maplists = self.GetMapsets(self.cmbLocation.GetValue())
+ for mapsets in maplists:
+ self.cmbMapset.Append(str(mapsets))
+
+ def GetMapsets(self,location):
+ """
+ Read and returns all mapset int GRASS data directory.
+ """
+
+ maplist = []
+ for mapset in glob.glob(os.path.join(self.gisdbase, location, "*")):
+ if os.path.isdir(mapset) and os.path.isfile(os.path.join(self.gisdbase, location, mapset, "WIND")):
+ maplist.append(os.path.basename(mapset))
+ return maplist
+
+ def GetLocations(self):
+ """
+ Read and returns all locations int GRASS data directory.
+ """
+ loclist = []
+ for location in glob.glob(os.path.join(self.gisdbase, "*")):
+ if os.path.join(location, "PERMANENT") in glob.glob(os.path.join(location, "*")):
+ loclist.append(os.path.basename(location))
+ return loclist
+
+
+ def doBindings(self):
+
+ #Event bindings for combo boxes
+ self.Bind(wx.EVT_COMBOBOX,self.OnMapsetChange,self.cmbMapset)
+ self.Bind(wx.EVT_COMBOBOX,self.OnLocationChange,self.cmbLocation)
+
+ #Event bindings for tree -(display,popup,label edit.)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.ltree.OnDisplay,self.ltree)
+ self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,self.ltree.OnTreePopUp,self.ltree)
+ self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.ltree.OnEndRename,self.ltree)
+ self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.ltree.OnBeginRename,self.ltree)
+
+ #Event bindings for tree menu
+ self.Bind(wx.EVT_MENU,self.ltree.OnCopy,id=self.ltree.ID_COPY)
+ self.Bind(wx.EVT_MENU,self.ltree.OnRename,id=self.ltree.ID_REN)
+ self.Bind(wx.EVT_MENU,self.ltree.OnDelete,id=self.ltree.ID_DEL)
+
+
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ #Event bindings for v/r.info checkbox
+ #self.Bind(wx.EVT_CHECKBOX, self.OnToggleInfo,self.chkInfo)
+ #self.Bind(wx.EVT_CHECKBOX, self.OnToggleExpand,self.treeExpand)
+
+ def OnToggleExpand(self,event):
+ if self.treeExpand.IsChecked():
+ if not self.gmconsole:
+ self.gmconsole = GLog(parent=self)
+ # self.gmconsole.show()
+# sys.exit(0)
+ else:
+ self.gmconsole.Raise()
+ else:
+ self.gmconsole.Destroy()
+
+ def doLayout(self):
+
+ #combo panel sizers
+ self.cmbSizer.Add(self.cmbLocation)
+ self.cmbSizer.Add(self.cmbMapset)
+ self.cmbSizer.Add(self.treeExpand)
+ #splitter window sizers
+ self.mSizer.Add(self.cmbPanel,flag=wx.EXPAND)
+ self.mSizer.Add(self.win, 1, wx.EXPAND)
+ self.leftSizer.Add(self.ltree,1,wx.EXPAND)
+ self.rightSizer.Add(self.notebook,1,wx.EXPAND)
+
+ self.cmbPanel.SetSizer(self.cmbSizer)
+ self.SetSizer(self.mSizer)
+ self.pLeft.SetSizer(self.leftSizer)
+ self.pRight.SetSizer(self.rightSizer)
+
+
+
+ def read_gisrc(self):
+ """
+ Read variables from $HOME/.grassrc7 file
+ """
+
+ rc = {}
+
+ gisrc = os.getenv("GISRC")
+
+ if gisrc and os.path.isfile(gisrc):
+ try:
+ f = open(gisrc, "r")
+ for line in f.readlines():
+ key, val = line.split(":", 1)
+ rc[key.strip()] = val.strip()
+ finally:
+ f.close()
+
+ return rc
+
+ def update_grassrc(self,gisrc):
+ """
+ Update $HOME/.grassrc7 and gisrc files
+ """
+
+ rc = os.getenv("GISRC")
+ grassrc = os.path.join(os.getenv('HOME'), ".grassrc7.%s" % os.uname()[1])
+ if not os.access(grassrc, os.R_OK):
+ grassrc = os.path.join(os.getenv('HOME'), ".grassrc7")
+ if rc and os.path.isfile(rc):
+ try:
+ f = open(rc, 'w')
+ for key, val in gisrc.iteritems():
+ f.write("%s: %s\n" % (key, val))
+ finally:
+ f.close()
+
+ if grassrc and os.path.isfile(grassrc):
+ try:
+ g = open(grassrc, 'w')
+ for key, val in gisrc.iteritems():
+ g.write("%s: %s\n" % (key, val))
+ finally:
+ g.close()
+
+
+
#End of DataCatalog class
+
+
class CatalogApp(wx.App):
def OnInit(self):
- wx.InitAllImageHandlers()
self.catalog = DataCatalog()
self.catalog.Show()
- #self.catalog.Maximize()
+ self.catalog.Maximize()
return 1
Added: grass-addons/gui/wxpython/data_catalog/gmconsole.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/gmconsole.py (rev 0)
+++ grass-addons/gui/wxpython/data_catalog/gmconsole.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -0,0 +1,120 @@
+"""
+ at package gmconsole.py
+
+ at brief window to ouptut grass command ouput.
+
+Classes:
+ - GLog
+
+
+(C) 2006-2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Michael Barton (Arizona State University)
+ at author Jachym Cepicky (Mendel University of Agriculture)
+ at author Martin Landa <landa.martin gmail.com>
+ at author Mohammed Rashad K.M <rashadkm at gmail dot com> (modified for DataCatalog)
+"""
+
+import sys
+import os
+import time
+import traceback
+import re
+import string
+import getopt
+import platform
+
+### XML
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ import elementtree.ElementTree as etree # Python <= 2.4
+
+### i18N
+import gettext
+gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
+
+pypath = "/usr/local/grass-7.0.svn/etc/wxpython"
+sys.path.append(pypath)
+
+import gui_modules
+gmpath = gui_modules.__path__[0]
+sys.path.append(gmpath)
+
+import images
+imagepath = images.__path__[0]
+sys.path.append(imagepath)
+
+import icons
+gmpath = icons.__path__[0]
+sys.path.append(gmpath)
+
+import gui_modules.globalvar as globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+ globalvar.CheckForWx()
+
+import wx
+import wx.aui
+import wx.combo
+import wx.html
+import wx.stc
+import wx.lib.customtreectrl as CT
+import wx.lib.flatnotebook as FN
+
+grassPath = os.path.join(globalvar.ETCDIR, "python")
+sys.path.append(grassPath)
+
+import gui_modules.preferences as preferences
+
+
+UserSettings = preferences.globalSettings
+
+class GLog(wx.Frame):
+ """
+ GIS Manager frame with notebook widget for controlling
+ GRASS GIS. Includes command console page for typing GRASS
+ (and other) commands, tree widget page for managing GIS map layers.
+ """
+ def __init__(self, parent=None, id=wx.ID_ANY, title=_("Command Output")):
+
+
+ wx.Frame.__init__(self, parent=parent, id=id, size=(550, 450),
+ style=wx.DEFAULT_FRAME_STYLE,title="Command Output")
+
+
+ self.SetName("LayerManager")
+ self.notebook = self.__createNoteBook()
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Show()
+ self.SetBackgroundColour("white")
+ self.goutput.Redirect()
+
+
+ def OnCloseWindow(self,event):
+ self.Destroy()
+
+ def __createNoteBook(self):
+ """!Creates notebook widgets"""
+ nbStyle = FN.FNB_FANCY_TABS | \
+ FN.FNB_BOTTOM | \
+ FN.FNB_NO_NAV_BUTTONS | \
+ FN.FNB_NO_X_BUTTON
+
+ self.notebook = FN.FlatNotebook(parent=self, id=wx.ID_ANY, style=nbStyle)
+ self.goutput = goutput.GMConsole(self, pageid=1)
+ self.outpage = self.notebook.AddPage(self.goutput, text=_("Command output"))
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self.notebook.SetSize(wx.Size(600,600))
+ sizer.Add(item=self.goutput, proportion=1,flag=wx.EXPAND | wx.ALL, border=10)
+ self.SetSizer(sizer)
+ self.Layout()
+ self.Centre()
+ return self.notebook
+
+
+
+
+
Added: grass-addons/gui/wxpython/data_catalog/mapdisplay.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/mapdisplay.py (rev 0)
+++ grass-addons/gui/wxpython/data_catalog/mapdisplay.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -0,0 +1,2089 @@
+"""!
+ at package mapdisp.py
+
+ at brief GIS map display canvas, with toolbar for various display
+management functions, and additional toolbars (vector digitizer, 3d
+view).
+
+Can be used either from Layer Manager or as p.mon backend.
+
+Classes:
+- MapFrame
+- MapApp
+
+Usage:
+python mapdisp.py monitor-identifier /path/to/command/file
+
+(C) 2006-2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Martin Landa <landa.martin gmail.com>
+ at author Mohammed Rashad K.M <rashadkm at gmail dot com> (modified for DataCatalog)
+"""
+
+import os
+import sys
+import glob
+import math
+import tempfile
+import copy
+
+gbase = os.getenv("GISBASE")
+pypath = os.path.join(gbase,'etc','wxpython','gui_modules')
+sys.path.append(pypath)
+
+import globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+ globalvar.CheckForWx()
+import wx
+import wx.aui
+import wx_utils as wx_utils
+
+try:
+ import subprocess
+except:
+ CompatPath = os.path.join(globalvar.ETCWXDIR)
+ sys.path.append(CompatPath)
+ from compat import subprocess
+
+gmpath = os.path.join(globalvar.ETCWXDIR, "icons")
+sys.path.append(gmpath)
+
+grassPath = os.path.join(globalvar.ETCDIR, "python")
+sys.path.append(grassPath)
+
+import render
+import toolbars
+import menuform
+import gselect
+import disp_print
+import gcmd
+import dbm
+import dbm_dialogs
+import histogram
+import profile
+import globalvar
+import utils
+import gdialogs
+from grass.script import core as grass
+from debug import Debug
+from preferences import globalSettings as UserSettings
+
+
+from mapdisp_window import BufferedWindow
+
+
+
+import images
+imagepath = images.__path__[0]
+sys.path.append(imagepath)
+
+###
+### global variables
+###
+# for standalone app
+cmdfilename = None
+
+class MapFrame(wx.Panel):
+ """
+ Main frame for map display window. Drawing takes place in child double buffered
+ drawing window.
+ """
+
+ def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS GIS - Map display"),
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE, toolbars=["map"],
+ tree=None, notebook=None, lmgr=None, page=None,
+ Map=None, auimgr=None,frame=None,flag=False):
+ """
+ Main map display window with toolbars, statusbar and
+ DrawWindow
+
+ @param toolbars array of activated toolbars, e.g. ['map', 'digit']
+ @param tree reference to layer tree
+ @param notebook control book ID in Layer Manager
+ @param mgr Layer Manager
+ @param page notebook page with layer tree
+ @param Map instance of render.Map
+ """
+ self._layerManager = lmgr # Layer Manager object
+ self.Map = Map # instance of render.Map
+ self.tree = tree # Layer Manager layer tree object
+ self.page = page # Notebook page holding the layer tree
+ self.layerbook = notebook # Layer Manager layer tree notebook
+ self.parent = parent
+ self.frame = frame
+ self.statusFlag = flag
+ self.statusbar = None
+
+
+ #
+ # available cursors
+ #
+ self.cursors = {
+ # default: cross
+ # "default" : wx.StockCursor(wx.CURSOR_DEFAULT),
+ "default" : wx.StockCursor(wx.CURSOR_ARROW),
+ "cross" : wx.StockCursor(wx.CURSOR_CROSS),
+ "hand" : wx.StockCursor(wx.CURSOR_HAND),
+ "pencil" : wx.StockCursor(wx.CURSOR_PENCIL),
+ "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE)
+ }
+
+ #wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+
+ wx.Panel.__init__(self, parent, id, pos, size, style,name="pg_panel")
+ #self.SetName("MapWindow")
+
+ #
+ # set the size & system icon
+ #
+ #self.SetClientSize(size)
+ self.iconsize = (16, 16)
+
+
+
+
+ #self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
+
+ #
+ # Fancy gui
+ #
+ # self._mgr = auimgr
+ self._mgr = wx.aui.AuiManager(self)
+
+ #
+ # Add toolbars
+ #
+ self.toolbars = { 'map' : None,
+ 'vdigit' : None,
+ 'georect' : None,
+ 'nviz' : None }
+ for toolb in toolbars:
+ self.AddToolbar(toolb)
+
+ #
+ # Add statusbar
+ #
+ if self.statusFlag:
+ self.statusbar = self.frame.CreateStatusBar(number=4, style=0)
+ self.statusbar.SetStatusWidths([-5, -2, -1, -1])
+ else:
+ self.statusbar = self.frame.GetStatusBar()
+
+
+
+ self.statusbarWin = dict()
+ self.statusbarWin['toggle'] = wx.Choice(self.statusbar, wx.ID_ANY,
+ choices = globalvar.MAP_DISPLAY_STATUSBAR_MODE)
+ self.statusbarWin['toggle'].SetSelection(UserSettings.Get(group='display',
+ key='statusbarMode',
+ subkey='selection'))
+
+ self.statusbar.Bind(wx.EVT_CHOICE, self.OnToggleStatus, self.statusbarWin['toggle'])
+
+ # auto-rendering checkbox
+ self.statusbarWin['render'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Render"))
+
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleRender, self.statusbarWin['render'])
+
+ self.statusbarWin['render'].SetValue(UserSettings.Get(group='display',
+ key='autoRendering',
+ subkey='enabled'))
+ self.statusbarWin['render'].SetToolTip(wx.ToolTip (_("Enable/disable auto-rendering")))
+ # show region
+ self.statusbarWin['region'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Show computational extent"))
+
+
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleShowRegion, self.statusbarWin['region'])
+
+ self.statusbarWin['region'].SetValue(False)
+ self.statusbarWin['region'].Hide()
+ self.statusbarWin['region'].SetToolTip(wx.ToolTip (_("Show/hide computational "
+ "region extent (set with g.region). "
+ "Display region drawn as a blue box inside the "
+ "computational region, "
+ "computational region inside a display region "
+ "as a red box).")))
+ # set resolution
+ self.statusbarWin['resolution'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Constrain display resolution to computational settings"))
+ self.statusbar.Bind(wx.EVT_CHECKBOX, self.OnToggleResolution, self.statusbarWin['resolution'])
+ self.statusbarWin['resolution'].SetValue(UserSettings.Get(group='display', key='compResolution', subkey='enabled'))
+ self.statusbarWin['resolution'].Hide()
+ self.statusbarWin['resolution'].SetToolTip(wx.ToolTip (_("Constrain display resolution "
+ "to computational region settings. "
+ "Default value for new map displays can "
+ "be set up in 'User GUI settings' dialog.")))
+ # map scale
+ self.statusbarWin['mapscale'] = wx.TextCtrl(parent=self.statusbar, id=wx.ID_ANY,
+ value="", style=wx.TE_PROCESS_ENTER,
+ size=(150, -1))
+ self.statusbarWin['mapscale'].Hide()
+ self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale, self.statusbarWin['mapscale'])
+
+ # go to
+ self.statusbarWin['goto'] = wx.TextCtrl(parent=self.statusbar, id=wx.ID_ANY,
+ value="", style=wx.TE_PROCESS_ENTER,
+ size=(300, -1))
+ self.statusbarWin['goto'].Hide()
+ self.statusbar.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo, self.statusbarWin['goto'])
+
+ # projection
+ self.statusbarWin['projection'] = wx.CheckBox(parent=self.statusbar, id=wx.ID_ANY,
+ label=_("Use defined projection"))
+ self.statusbarWin['projection'].SetValue(False)
+ size = self.statusbarWin['projection'].GetSize()
+ self.statusbarWin['projection'].SetMinSize((size[0] + 150, size[1]))
+ self.statusbarWin['projection'].SetToolTip(wx.ToolTip (_("Reproject coordinates displayed "
+ "in the statusbar. Projection can be "
+ "defined in GUI preferences dialog "
+ "(tab 'Display')")))
+ self.statusbarWin['projection'].Hide()
+
+ # mask
+ self.statusbarWin['mask'] = wx.StaticText(parent = self.statusbar, id = wx.ID_ANY,
+ label = '')
+ self.statusbarWin['mask'].SetForegroundColour(wx.Colour(255, 0, 0))
+
+ # on-render gauge
+ self.statusbarWin['progress'] = wx.Gauge(parent=self.statusbar, id=wx.ID_ANY,
+ range=0, style=wx.GA_HORIZONTAL)
+ self.statusbarWin['progress'].Hide()
+
+ self.StatusbarReposition() # reposition statusbar
+
+ #
+ # Init map display (buffered DC & set default cursor)
+ #
+ self.MapWindow2D = BufferedWindow(self, id=wx.ID_ANY,
+ Map=self.Map, tree=self.tree, lmgr=self._layerManager)
+ # default is 2D display mode
+ self.MapWindow = self.MapWindow2D
+ #self.MapWindow.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.MapWindow.SetCursor(self.cursors["default"])
+ # used by Nviz (3D display mode)
+ self.MapWindow3D = None
+
+ #
+ # initialize region values
+ #
+ self.__InitDisplay()
+
+ #
+ # Bind various events
+ #
+ self.Bind(wx.EVT_ACTIVATE, self.OnFocus)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(render.EVT_UPDATE_PRGBAR, self.OnUpdateProgress)
+
+ #
+ # Update fancy gui style
+ #
+ self._mgr.AddPane(self.MapWindow, wx.aui.AuiPaneInfo().CentrePane().
+ Dockable(False).BestSize((-1,-1)).
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0))
+
+
+ self._mgr.Update()
+
+ #
+ # Init print module and classes
+ #
+ self.printopt = disp_print.PrintOptions(self, self.MapWindow)
+
+ #
+ # Initialization of digitization tool
+ #
+ self.digit = None
+
+ #
+ # Init zoom history
+ #
+ self.MapWindow.ZoomHistory(self.Map.region['n'],
+ self.Map.region['s'],
+ self.Map.region['e'],
+ self.Map.region['w'])
+
+ #
+ # 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
+
+ pos = wx.Point(700,10)
+
+
+
+ parent1 = self.GetParent()
+ rightpanel = parent1.GetParent()
+ splitter= rightpanel.GetParent()
+ self.lmgr= splitter.GetParent()
+
+
+ self.maptree = wx_utils.AddLayerTree(self, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.TR_HAS_BUTTONS
+ |wx.TR_LINES_AT_ROOT|wx.TR_HIDE_ROOT
+ |wx.TR_DEFAULT_STYLE|wx.NO_BORDER|wx.FULL_REPAINT_ON_RESIZE,
+ frame=parent,Map=self.Map,lmgr=self.lmgr)
+ #self.maptree.SetBackgroundColour("red")
+
+ self._mgr.AddPane(self.maptree, wx.aui.AuiPaneInfo().Right().
+ Dockable(False).BestSize((-1,-1)).
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0).Caption("Layers"))
+
+ self._mgr.Update()
+
+ #r.rightSizer.Add(self.maptree)
+
+ def AddToolbar(self, name):
+ """
+ Add defined toolbar to the window
+
+ Currently known toolbars are:
+ - map basic map toolbar
+ - digit vector digitizer
+ - georect georectifier
+ """
+ # default toolbar
+ if name == "map":
+ self.toolbars['map'] = toolbars.MapToolbar(self, self.Map)
+
+ self._mgr.AddPane(self.toolbars['map'].toolbar,
+ 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'].GetToolbar().GetSize())))
+
+ # vector digitizer
+ elif name == "vdigit":
+ from vdigit import haveVDigit
+ if not haveVDigit:
+ from vdigit import errorMsg
+ msg = _("Unable to start vector digitizer.\nThe VDigit python extension "
+ "was not found or loaded properly.\n"
+ "Switching back to 2D display mode.\n\nDetails: %s" % errorMsg)
+
+ self.toolbars['map'].combo.SetValue (_("2D view"))
+ wx.MessageBox(parent=self,
+ message=msg,
+ caption=_("Error"),
+ style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ if self._layerManager:
+ log = self._layerManager.goutput
+ else:
+ log = None
+ self.toolbars['vdigit'] = toolbars.VDigitToolbar(parent=self, map=self.Map,
+ layerTree=self.tree,
+ log=log)
+
+ for toolRow in range(0, self.toolbars['vdigit'].numOfRows):
+ self._mgr.AddPane(self.toolbars['vdigit'].toolbar[toolRow],
+ wx.aui.AuiPaneInfo().
+ Name("vdigittoolbar" + str(toolRow)).Caption(_("Vector digitizer toolbar")).
+ ToolbarPane().Top().Row(toolRow + 1).
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2).
+ BestSize((self.toolbars['vdigit'].GetToolbar().GetSize())))
+
+ # change mouse to draw digitized line
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.zoomtype = 0
+ self.MapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SOLID)
+ self.MapWindow.polypen = wx.Pen(colour='green', width=2, style=wx.SOLID)
+ # georectifier
+ elif name == "georect":
+ self.toolbars['georect'] = toolbars.GRToolbar(self, self.Map)
+
+ self._mgr.AddPane(self.toolbars['georect'].toolbar,
+ wx.aui.AuiPaneInfo().
+ Name("georecttoolbar").Caption(_("Georectification toolbar")).
+ ToolbarPane().Top().
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2))
+ # nviz
+ elif name == "nviz":
+ import nviz
+
+ # check for GLCanvas and OpenGL
+ msg = None
+ if not nviz.haveGLCanvas:
+ msg = _("Unable to switch to 3D display mode.\nThe GLCanvas class has not been "
+ "included with this build "
+ "of wxPython!\nSwitching back to "
+ "2D display mode.\n\nDetails: %s" % nviz.errorMsg)
+ if not nviz.haveNviz:
+ msg = _("Unable to switch to 3D display mode.\nThe Nviz python extension "
+ "was not found or loaded properly.\n"
+ "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg)
+
+ if msg:
+ self.toolbars['map'].combo.SetValue (_("2D view"))
+ wx.MessageBox(parent=self,
+ message=msg,
+ caption=_("Error"),
+ style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ #
+ # add Nviz toolbar and disable 2D display mode tools
+ #
+ self.toolbars['nviz'] = toolbars.NvizToolbar(self, self.Map)
+ self.toolbars['map'].Enable2D(False)
+
+ #
+ # update layer tree (-> enable 3d-rasters)
+ #
+ if self.tree:
+ self.tree.EnableItemType(type='3d-raster', enable=True)
+
+ #
+ # update status bar
+ #
+ self.statusbarWin['toggle'].Enable(False)
+
+ #
+ # erase map window
+ #
+ self.MapWindow.EraseMap()
+
+ self.statusbar.SetStatusText(_("Please wait, loading data..."), 0)
+
+ #
+ # create GL window & NVIZ toolbar
+ #
+ if not self.MapWindow3D:
+ self.MapWindow3D = nviz.GLWindow(self, id=wx.ID_ANY,
+ Map=self.Map, tree=self.tree, lmgr=self._layerManager)
+ # -> show after paint
+ self.nvizToolWin = nviz.NvizToolWindow(self, id=wx.ID_ANY,
+ mapWindow=self.MapWindow3D)
+ self.MapWindow3D.OnPaint(None) # -> LoadData
+ self.MapWindow3D.Show()
+ self.MapWindow3D.UpdateView(None)
+
+ self.nvizToolWin.Show()
+
+ #
+ # switch from MapWindow to MapWindowGL
+ # add nviz toolbar
+ #
+ self._mgr.DetachPane(self.MapWindow2D)
+ self.MapWindow2D.Hide()
+ self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane().
+ Dockable(False).BestSize((-1,-1)).
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0))
+ self._mgr.AddPane(self.toolbars['nviz'].toolbar,
+ wx.aui.AuiPaneInfo().
+ Name("nviztoolbar").Caption(_("Nviz toolbar")).
+ ToolbarPane().Top().Row(1).
+ LeftDockable(False).RightDockable(False).
+ BottomDockable(False).TopDockable(True).
+ CloseButton(False).Layer(2))
+
+ self.MapWindow = self.MapWindow3D
+ self.frame.SetStatusText("", 0)
+
+ self._mgr.Update()
+
+ def RemoveToolbar (self, name):
+ """
+ Removes toolbar from the window
+
+ TODO: Only hide, activate by calling AddToolbar()
+ """
+
+ # cannot hide main toolbar
+ if name == "map":
+ return
+ elif name == "vdigit":
+ # TODO: not destroy only hide
+ for toolRow in range(0, self.toolbars['vdigit'].numOfRows):
+ self._mgr.DetachPane (self.toolbars['vdigit'].toolbar[toolRow])
+ self.toolbars['vdigit'].toolbar[toolRow].Destroy()
+ else:
+ self._mgr.DetachPane (self.toolbars[name].toolbar)
+ self.toolbars[name].toolbar.Destroy()
+
+ self.toolbars[name] = None
+
+ if name == 'nviz':
+ # hide nviz tools
+ self.nvizToolWin.Hide()
+ # unload data
+ # self.MapWindow3D.Reset()
+ # switch from MapWindowGL to MapWindow
+ self._mgr.DetachPane(self.MapWindow3D)
+ self.MapWindow3D.Hide()
+ self.MapWindow2D.Show()
+ self._mgr.AddPane(self.MapWindow2D, wx.aui.AuiPaneInfo().CentrePane().
+ Dockable(False).BestSize((-1,-1)).
+ CloseButton(False).DestroyOnClose(True).
+ Layer(0))
+ self.MapWindow = self.MapWindow2D
+
+ #
+ # update layer tree (-> disable 3d-rasters)
+ #
+ if self.tree:
+ self.tree.EnableItemType(type='3d-raster', enable=False)
+ self.MapWindow.UpdateMap()
+
+ self.toolbars['map'].combo.SetValue (_("2D view"))
+ self.toolbars['map'].Enable2D(True)
+ self.statusbarWin['toggle'].Enable(True)
+
+ self._mgr.Update()
+
+ def __InitDisplay(self):
+ """
+ Initialize map display, set dimensions and map region
+ """
+ self.width, self.height = self.GetClientSize()
+
+ Debug.msg(2, "MapFrame.__InitDisplay():")
+ self.Map.ChangeMapSize(self.GetClientSize())
+ self.Map.region = self.Map.GetRegion() # g.region -upgc
+ # self.Map.SetRegion() # adjust region to match display window
+
+ def OnUpdateProgress(self, event):
+ """
+ Update progress bar info
+ """
+ self.statusbarWin['progress'].SetValue(event.value)
+
+ event.Skip()
+
+ def OnFocus(self, event):
+ """
+ Change choicebook page to match display.
+ Or set display for georectifying
+ """
+ if self._layerManager and \
+ self._layerManager.georectifying:
+ # in georectifying session; display used to get get geographic
+ # coordinates for GCPs
+ self.OnPointer(event)
+ else:
+ # change bookcontrol page to page associated with display
+ if self.page:
+ pgnum = self.layerbook.GetPageIndex(self.page)
+ if pgnum > -1:
+ self.layerbook.SetSelection(pgnum)
+
+ event.Skip()
+
+ def OnMotion(self, event):
+ """
+ Mouse moved
+ Track mouse motion and update status bar
+ """
+ # update statusbar if required
+ if self.statusbarWin['toggle'].GetSelection() == 0: # Coordinates
+ precision = int(UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'precision'))
+ format = UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'll')
+ e, n = self.MapWindow.Pixel2Cell(event.GetPositionTuple())
+ if self.toolbars['vdigit'] and \
+ self.toolbars['vdigit'].GetAction() == 'addLine' and \
+ self.toolbars['vdigit'].GetAction('type') in ('line', 'boundary') and \
+ len(self.MapWindow.polycoords) > 0:
+ # for linear feature show segment and total length
+ distance_seg = self.MapWindow.Distance(self.MapWindow.polycoords[-1],
+ (e, n), screen=False)[0]
+ distance_tot = distance_seg
+ for idx in range(1, len(self.MapWindow.polycoords)):
+ distance_tot += self.MapWindow.Distance(self.MapWindow.polycoords[idx-1],
+ self.MapWindow.polycoords[idx],
+ screen=False )[0]
+ self.statusbar.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
+ (precision, e, precision, n,
+ precision, distance_seg,
+ precision, distance_tot), 0)
+ else:
+ if self.statusbarWin['projection'].IsChecked():
+ if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'):
+ self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
+ else:
+ proj, coord = utils.ReprojectCoordinates(coord = (e, n),
+ projOut = UserSettings.Get(group='projection',
+ key='statusbar',
+ subkey='proj4'),
+ flags = 'd')
+
+ if coord:
+ e, n = coord
+ if proj in ('ll', 'latlong', 'longlat') and format == 'DMS':
+ self.statusbar.SetStatusText("%s" % \
+ utils.Deg2DMS(e, n, precision = precision),
+ 0)
+ else:
+ self.statusbar.SetStatusText("%.*f; %.*f" % \
+ (precision, e, precision, n), 0)
+ else:
+ self.statusbar.SetStatusText(_("Error in projection (check the settings)"), 0)
+ else:
+ if self.Map.projinfo['proj'] == 'll' and format == 'DMS':
+ self.statusbar.SetStatusText("%s" % \
+ utils.Deg2DMS(e, n, precision = precision),
+ 0)
+ else:
+ self.statusbar.SetStatusText("%.*f; %.*f" % \
+ (precision, e, precision, n), 0)
+
+ 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)
+ """
+ # delete tmp map layers (queries)
+ qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER)
+ for layer in qlayer:
+ self.Map.DeleteLayer(layer)
+
+ # delete tmp lines
+ if self.MapWindow.mouse["use"] in ("measure",
+ "profile"):
+ self.MapWindow.polycoords = []
+ self.MapWindow.ClearLines()
+
+ # deselect features in vdigit
+ if self.toolbars['vdigit'] and self.digit:
+ self.digit.driver.SetSelected([])
+ self.MapWindow.UpdateMap(render=True, renderVector=True)
+ else:
+ self.MapWindow.UpdateMap(render=True)
+
+ # update statusbar
+ self.StatusbarUpdate()
+
+ def OnPointer(self, event):
+ """
+ Pointer button clicked
+ """
+ if self.toolbars['map']:
+ if event:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "pointer"
+ self.MapWindow.mouse['box'] = "point"
+
+ # change the cursor
+ if self.toolbars['vdigit']:
+ # digitization tool activated
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ # reset mouse['box'] if needed
+ if self.toolbars['vdigit'].GetAction() in ['addLine']:
+ if self.toolbars['vdigit'].GetAction('type') in ['point', 'centroid']:
+ self.MapWindow.mouse['box'] = 'point'
+ else: # line, boundary
+ self.MapWindow.mouse['box'] = 'line'
+ elif self.toolbars['vdigit'].GetAction() in ['addVertex', 'removeVertex', 'splitLine',
+ 'editLine', 'displayCats', 'displayAttrs',
+ 'copyCats']:
+ self.MapWindow.mouse['box'] = 'point'
+ else: # moveLine, deleteLine
+ self.MapWindow.mouse['box'] = 'box'
+
+ elif self._layerManager and self._layerManager.georectifying:
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ else:
+ self.MapWindow.SetCursor(self.cursors["default"])
+
+ def OnZoomIn(self, event):
+ """
+ Zoom in the map.
+ Set mouse cursor, zoombox attributes, and zoom direction
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "zoom"
+ self.MapWindow.mouse['box'] = "box"
+ self.MapWindow.zoomtype = 1
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def OnZoomOut(self, event):
+ """
+ Zoom out the map.
+ Set mouse cursor, zoombox attributes, and zoom direction
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "zoom"
+ self.MapWindow.mouse['box'] = "box"
+ self.MapWindow.zoomtype = -1
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def OnZoomBack(self, event):
+ """
+ Zoom last (previously stored position)
+ """
+ self.MapWindow.ZoomBack()
+
+ def OnPan(self, event):
+ """
+ Panning, set mouse to drag
+ """
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ self.toolbars['map'].action['desc'] = ''
+
+ self.MapWindow.mouse['use'] = "pan"
+ self.MapWindow.mouse['box'] = "pan"
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["hand"])
+
+ def OnErase(self, event):
+ """
+ Erase the canvas
+ """
+ self.MapWindow.EraseMap()
+
+ def OnZoomRegion(self, event):
+ """
+ Zoom to region
+ """
+ self.Map.getRegion()
+ self.Map.getResolution()
+ self.UpdateMap()
+ # event.Skip()
+
+ def OnAlignRegion(self, event):
+ """
+ Align region
+ """
+ if not self.Map.alignRegion:
+ self.Map.alignRegion = True
+ else:
+ self.Map.alignRegion = False
+ # event.Skip()
+
+ def OnToggleRender(self, event):
+ """
+ Enable/disable auto-rendering
+ """
+ if self.statusbarWin['render'].GetValue():
+ self.OnRender(None)
+
+ def OnToggleShowRegion(self, event):
+ """
+ Show/Hide extent in map canvas
+ """
+ if self.statusbarWin['region'].GetValue():
+ # show extent
+ self.MapWindow.regionCoords = []
+ else:
+ del self.MapWindow.regionCoords
+
+ # redraw map if auto-rendering is enabled
+ if self.statusbarWin['render'].GetValue():
+ self.OnRender(None)
+
+ def OnToggleResolution(self, event):
+ """
+ Use resolution of computation region settings
+ for redering image instead of display resolution
+ """
+ # redraw map if auto-rendering is enabled
+ if self.statusbarWin['render'].GetValue():
+ self.OnRender(None)
+
+ def OnToggleStatus(self, event):
+ """
+ Toggle status text
+ """
+ self.StatusbarUpdate()
+
+ def OnChangeMapScale(self, event):
+ """
+ Map scale changed by user
+ """
+ scale = event.GetString()
+
+ try:
+ if scale[:2] != '1:':
+ raise ValueError
+ value = int(scale[2:])
+ except ValueError:
+ self.statusbarWin['mapscale'].SetValue('1:%ld' % int(self.mapScaleValue))
+ return
+
+ dEW = value * (self.Map.region['cols'] / self.ppm[0])
+ dNS = value * (self.Map.region['rows'] / self.ppm[1])
+ self.Map.region['n'] = self.Map.region['center_northing'] + dNS / 2.
+ self.Map.region['s'] = self.Map.region['center_northing'] - dNS / 2.
+ self.Map.region['w'] = self.Map.region['center_easting'] - dEW / 2.
+ self.Map.region['e'] = self.Map.region['center_easting'] + dEW / 2.
+
+ # add to zoom history
+ self.MapWindow.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ # redraw a map
+ self.MapWindow.UpdateMap()
+ self.statusbarWin['mapscale'].SetFocus()
+
+ def OnGoTo(self, event):
+ """
+ Go to position
+ """
+ try:
+ if self.statusbarWin['projection'].IsChecked():
+ if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'):
+ self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
+ else:
+ # reproject values
+ projIn = UserSettings.Get(group='projection',
+ key='statusbar',
+ subkey='proj4')
+ projOut = gcmd.RunCommand('g.proj',
+ flags = 'jf',
+ read = True)
+ proj = projIn.split(' ')[0].split('=')[1]
+ if proj in ('ll', 'latlong', 'longlat'):
+ e, n = self.statusbarWin['goto'].GetValue().split(';')
+ e, n = utils.DMS2Deg(e, n)
+ proj, coord1 = utils.ReprojectCoordinates(coord = (e, n),
+ projIn = projIn,
+ projOut = projOut, flags = 'd')
+ e, n = coord1
+ else:
+ e, n = map(float, self.statusbarWin['goto'].GetValue().split(';'))
+ proj, coord1 = utils.ReprojectCoordinates(coord = (e, n),
+ projIn = projIn,
+ projOut = projOut, flags = 'd')
+ e, n = coord1
+ else:
+ if self.Map.projinfo['proj'] == 'll':
+ e, n = self.statusbarWin['goto'].GetValue().split(';')
+ else:
+ e, n = map(float, self.statusbarWin['goto'].GetValue().split(';'))
+
+ region = self.Map.GetCurrentRegion()
+ if self.statusbarWin['projection'].IsChecked():
+ if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'):
+ self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
+ else:
+ region['center_easting'], region['center_northing'] = e, n
+ else:
+ if self.Map.projinfo['proj'] == 'll':
+ region['center_easting'], region['center_northing'] = utils.DMS2Deg(e, n)
+ else:
+ region['center_easting'], region['center_northing'] = e, n
+ except ValueError:
+ region = self.Map.GetCurrentRegion()
+ precision = int(UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'precision'))
+ format = UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'll')
+ if self.Map.projinfo['proj'] == 'll' and format == 'DMS':
+ self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(region['center_easting'],
+ region['center_northing'],
+ precision = precision))
+ else:
+ self.statusbarWin['goto'].SetValue("%.*f; %.*f" % \
+ (precision, region['center_easting'],
+ precision, region['center_northing']))
+ return
+
+
+ dn = (region['nsres'] * region['rows']) / 2.
+ region['n'] = region['center_northing'] + dn
+ region['s'] = region['center_northing'] - dn
+ de = (region['ewres'] * region['cols']) / 2.
+ region['e'] = region['center_easting'] + de
+ region['w'] = region['center_easting'] - de
+
+ self.Map.AdjustRegion()
+
+ # add to zoom history
+ self.MapWindow.ZoomHistory(region['n'], region['s'],
+ region['e'], region['w'])
+
+ # redraw a map
+ self.MapWindow.UpdateMap()
+ self.statusbarWin['goto'].SetFocus()
+
+ def StatusbarUpdate(self):
+ """!Update statusbar content"""
+
+ self.statusbarWin['region'].Hide()
+ self.statusbarWin['resolution'].Hide()
+ self.statusbarWin['mapscale'].Hide()
+ self.statusbarWin['goto'].Hide()
+ self.statusbarWin['projection'].Hide()
+ self.mapScaleValue = self.ppm = None
+
+ if self.statusbarWin['toggle'].GetSelection() == 0: # Coordinates
+ self.statusbar.SetStatusText("", 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.statusbarWin['toggle'].GetSelection() in (1, 2): # Extent
+ sel = self.statusbarWin['toggle'].GetSelection()
+ if sel == 1:
+ region = self.Map.region
+ else:
+ region = self.Map.GetRegion() # computation region
+
+ precision = int(UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'precision'))
+ format = UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'll')
+
+ if self.statusbarWin['projection'].IsChecked():
+ if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'):
+ self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
+ else:
+ projOut = UserSettings.Get(group='projection',
+ key='statusbar',
+ subkey='proj4')
+ proj, coord1 = utils.ReprojectCoordinates(coord = (region["w"], region["s"]),
+ projOut = projOut, flags = 'd')
+ proj, coord2 = utils.ReprojectCoordinates(coord = (region["e"], region["n"]),
+ projOut = projOut, flags = 'd')
+ if sel == 2:
+ proj, coord3 = utils.ReprojectCoordinates(coord = (0.0, 0.0),
+ projOut = projOut, flags = 'd')
+ proj, coord4 = utils.ReprojectCoordinates(coord = (region["ewres"], region["nsres"]),
+ projOut = projOut, flags = 'd')
+ if coord1 and coord2:
+ if proj in ('ll', 'latlong', 'longlat') and format == 'DMS':
+ w, s = utils.Deg2DMS(coord1[0], coord1[1], string = False,
+ precision = precision)
+ e, n = utils.Deg2DMS(coord2[0], coord2[1], string = False,
+ precision = precision)
+ if sel == 1:
+ self.statusbar.SetStatusText("%s - %s, %s - %s" %
+ (w, e, s, n), 0)
+ else:
+ ewres, nsres = utils.Deg2DMS(abs(coord3[0]) - abs(coord4[0]),
+ abs(coord3[1]) - abs(coord4[1]),
+ string = False, hemisphere = False,
+ precision = precision)
+ self.statusbar.SetStatusText("%s - %s, %s - %s (%s, %s)" %
+ (w, e, s, n, ewres, nsres), 0)
+ else:
+ w, s = coord1
+ e, n = coord2
+ if sel == 1:
+ self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f" %
+ (precision, w, precision, e,
+ precision, s, precision, n), 0)
+ else:
+ ewres, nsres = coord3
+ self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" %
+ (precision, w, precision, e,
+ precision, s, precision, n,
+ precision, ewres, precision, nsres), 0)
+ else:
+ self.statusbar.SetStatusText(_("Error in projection (check the settings)"), 0)
+ else:
+ if self.Map.projinfo['proj'] == 'll' and format == 'DMS':
+ w, s = utils.Deg2DMS(region["w"], region["s"],
+ string = False, precision = precision)
+ e, n = utils.Deg2DMS(region["e"], region["n"],
+ string = False, precision = precision)
+ if sel == 1:
+ self.statusbar.SetStatusText("%s - %s, %s - %s" %
+ (w, e, s, n), 0)
+ else:
+ ewres, nsres = utils.Deg2DMS(region['ewres'], region['nsres'],
+ string = False, precision = precision)
+ self.statusbar.SetStatusText("%s - %s, %s - %s (%s, %s)" %
+ (w, e, s, n, ewres, nsres), 0)
+ else:
+ w, s = region["w"], region["s"]
+ e, n = region["e"], region["n"]
+ if sel == 1:
+ self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f" %
+ (precision, w, precision, e,
+ precision, s, precision, n), 0)
+ else:
+ ewres, nsres = region['ewres'], region['nsres']
+ self.statusbar.SetStatusText("%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" %
+ (precision, w, precision, e,
+ precision, s, precision, n,
+ precision, ewres, precision, nsres), 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.statusbarWin['toggle'].GetSelection() == 3: # Show comp. extent
+ self.statusbar.SetStatusText("", 0)
+ self.statusbarWin['region'].Show()
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.statusbarWin['toggle'].GetSelection() == 4: # Display mode
+ self.statusbar.SetStatusText("", 0)
+ self.statusbarWin['resolution'].Show()
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.statusbarWin['toggle'].GetSelection() == 5: # Display geometry
+ self.statusbar.SetStatusText("rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" %
+ (self.Map.region["rows"], self.Map.region["cols"],
+ self.Map.region["nsres"], self.Map.region["ewres"]), 0)
+ # enable long help
+ self.StatusbarEnableLongHelp()
+
+ elif self.statusbarWin['toggle'].GetSelection() == 6: # Map scale
+ # 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
+ self.ppm = ((ppi[0] / 2.54) * 100, # pixel per meter
+ (ppi[1] / 2.54) * 100)
+
+ Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): 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],
+ self.ppm[0], self.ppm[1]))
+
+ region = self.Map.region
+
+ heightCm = region['rows'] / self.ppm[1] * 100
+ widthCm = region['cols'] / self.ppm[0] * 100
+
+ Debug.msg(4, "MapFrame.StatusbarUpdate(mapscale): width_cm=%f, height_cm=%f" %
+ (widthCm, heightCm))
+
+ xscale = (region['e'] - region['w']) / (region['cols'] / self.ppm[0])
+ yscale = (region['n'] - region['s']) / (region['rows'] / self.ppm[1])
+ scale = (xscale + yscale) / 2.
+
+ Debug.msg(3, "MapFrame.StatusbarUpdate(mapscale): xscale=%f, yscale=%f -> scale=%f" % \
+ (xscale, yscale, scale))
+
+ self.statusbar.SetStatusText("")
+ try:
+ self.statusbarWin['mapscale'].SetValue("1:%ld" % (scale + 0.5))
+ except TypeError:
+ pass
+ self.mapScaleValue = scale
+ self.statusbarWin['mapscale'].Show()
+
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.statusbarWin['toggle'].GetSelection() == 7: # go to
+ self.statusbar.SetStatusText("")
+ region = self.Map.GetCurrentRegion()
+ precision = int(UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'precision'))
+ format = UserSettings.Get(group = 'projection', key = 'format',
+ subkey = 'll')
+
+ if self.statusbarWin['projection'].IsChecked():
+ if not UserSettings.Get(group='projection', key='statusbar', subkey='proj4'):
+ self.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
+ else:
+ proj, coord = utils.ReprojectCoordinates(coord = (region['center_easting'],
+ region['center_northing']),
+ projOut = UserSettings.Get(group='projection',
+ key='statusbar',
+ subkey='proj4'),
+ flags = 'd')
+ if coord:
+ if proj in ('ll', 'latlong', 'longlat') and format == 'DMS':
+ self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(coord[0],
+ coord[1],
+ precision = precision))
+ else:
+ self.statusbarWin['goto'].SetValue("%.*f; %.*f" % (precision, coord[0],
+ precision, coord[1]))
+ else:
+ self.statusbar.SetStatusText(_("Error in projection (check the settings)"), 0)
+ else:
+ if self.Map.projinfo['proj'] == 'll' and format == 'DMS':
+ self.statusbarWin['goto'].SetValue("%s" % utils.Deg2DMS(region['center_easting'],
+ region['center_northing'],
+ precision = precision))
+ else:
+ self.statusbarWin['goto'].SetValue("%.*f; %.*f" % (precision, region['center_easting'],
+ precision, region['center_northing']))
+ self.statusbarWin['goto'].Show()
+
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ elif self.statusbarWin['toggle'].GetSelection() == 8: # projection
+ self.statusbar.SetStatusText("")
+ epsg = UserSettings.Get(group='projection', key='statusbar', subkey='epsg')
+ if epsg:
+ label = '%s (EPSG: %s)' % (_("Use defined projection"), epsg)
+ self.statusbarWin['projection'].SetLabel(label)
+ else:
+ self.statusbarWin['projection'].SetLabel(_("Use defined projection"))
+ self.statusbarWin['projection'].Show()
+
+ # disable long help
+ self.StatusbarEnableLongHelp(False)
+
+ else:
+ self.statusbar.SetStatusText("", 1)
+
+ def StatusbarEnableLongHelp(self, enable=True):
+ """!Enable/disable toolbars long help"""
+ for toolbar in self.toolbars.itervalues():
+ if toolbar:
+ toolbar.EnableLongHelp(enable)
+
+ def StatusbarReposition(self):
+ """!Reposition checkbox in statusbar"""
+ # reposition checkbox
+ widgets = [(0, self.statusbarWin['region']),
+ (0, self.statusbarWin['resolution']),
+ (0, self.statusbarWin['mapscale']),
+ (0, self.statusbarWin['progress']),
+ (0, self.statusbarWin['projection']),
+ (1, self.statusbarWin['toggle']),
+ (2, self.statusbarWin['mask']),
+ (3, self.statusbarWin['render'])]
+ for idx, win in widgets:
+ rect = self.statusbar.GetFieldRect(idx)
+ if idx == 0: # show region / mapscale / process bar
+ # -> size
+ wWin, hWin = win.GetBestSize()
+ if win == self.statusbarWin['progress']:
+ wWin = rect.width - 6
+ # -> position
+ # if win == self.statusbarWin['region']:
+ # x, y = rect.x + rect.width - wWin, rect.y - 1
+ # align left
+ # else:
+ x, y = rect.x + 3, rect.y - 1
+ w, h = wWin, rect.height + 2
+ else: # choice || auto-rendering
+ x, y = rect.x, rect.y - 1
+ w, h = rect.width, rect.height + 2
+ if idx == 2: # mask
+ x += 5
+ y += 4
+ elif idx == 3: # render
+ x += 5
+ win.SetPosition((x, y))
+ win.SetSize((w, h))
+
+ def SaveToFile(self, event):
+ """
+ Save image to file
+ """
+ lext = []
+ for h in self.MapWindow.img.GetHandlers():
+ lext.append(h.GetExtension())
+
+ filetype = "BMP file (*.bmp)|*.bmp|"
+ if 'gif' in lext:
+ filetype += "GIF file (*.gif)|*.gif|"
+ if 'jpg' in lext:
+ filetype += "JPG file (*.jpg)|*.jpg|"
+ if 'pcx' in lext:
+ filetype += "PCX file (*.pcx)|*.pcx|"
+ if 'png' in lext:
+ filetype += "PNG file (*.png)|*.png|"
+ if 'pnm' in lext:
+ filetype += "PNM file (*.pnm)|*.pnm|"
+ if 'tif' in lext:
+ filetype += "TIF file (*.tif)|*.tif|"
+ if 'xpm' in lext:
+ filetype += "XPM file (*.xpm)|*.xpm"
+
+ dlg = wx.FileDialog(self, _("Choose a file name to save the image (no need to add extension)"),
+ defaultDir = "",
+ defaultFile = "",
+ wildcard = filetype,
+ style=wx.SAVE|wx.FD_OVERWRITE_PROMPT)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if path == None: return
+ base = os.path.splitext(dlg.GetPath())[0]
+ ext = os.path.splitext(dlg.GetPath())[1]
+ if dlg.GetFilterIndex() == 0:
+ type = wx.BITMAP_TYPE_BMP
+ if ext != '.bmp': path = base+'.bmp'
+ if dlg.GetFilterIndex() == 1:
+ type = wx.BITMAP_TYPE_GIF
+ if ext != '.gif': path = base+'.gif'
+ elif dlg.GetFilterIndex() == 2:
+ type = wx.BITMAP_TYPE_JPEG
+ if ext != '.jpg': path = base+'.jpg'
+ elif dlg.GetFilterIndex() == 3:
+ type = wx.BITMAP_TYPE_GIF
+ if ext != '.pcx': path = base+'.pcx'
+ elif dlg.GetFilterIndex() == 4:
+ type = wx.BITMAP_TYPE_PNG
+ if ext != '.png': path = base+'.png'
+ elif dlg.GetFilterIndex() == 5:
+ type = wx.BITMAP_TYPE_PNM
+ if ext != '.pnm': path = base+'.pnm'
+ elif dlg.GetFilterIndex() == 6:
+ type = wx.BITMAP_TYPE_TIF
+ if ext != '.tif': path = base+'.tif'
+ elif dlg.GetFilterIndex() == 7:
+ type = wx.BITMAP_TYPE_XPM
+ if ext != '.xpm': path = base+'.xpm'
+ self.MapWindow.SaveToFile(path, type)
+
+ 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 OnCloseWindow(self, event):
+ """
+ Window closed.
+ Also close associated layer tree page
+ """
+ pgnum = None
+ self.Map.Clean()
+
+ # close edited map and 3D tools properly
+ if self.toolbars['vdigit']:
+ maplayer = self.toolbars['vdigit'].GetLayer()
+ if maplayer:
+ self.toolbars['vdigit'].OnExit()
+ self.imgVectorMap = None
+
+ if self.toolbars['nviz']:
+ self.toolbars['nviz'].OnExit()
+
+ if not self._layerManager:
+ self.Destroy()
+ elif self.page:
+ pgnum = self.layerbook.GetPageIndex(self.page)
+ if pgnum > -1:
+ self.layerbook.DeletePage(pgnum)
+
+ def GetRender(self):
+ """
+ Returns the current instance of render.Map()
+ """
+ return self.Map
+
+ def OnQueryDisplay(self, event):
+ """
+ Query currrent raster/vector map layers (display mode)
+ """
+ if self.toolbars['map'].GetAction() == 'displayAttrb': # select previous action
+ self.toolbars['map'].SelectDefault(event)
+ return
+
+ self.toolbars['map'].action['desc'] = 'displayAttrb'
+
+ # switch GIS Manager to output console to show query results
+ self._layerManager.notebook.SetSelection(1)
+
+ self.MapWindow.mouse['use'] = "query"
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def OnQueryModify(self, event):
+ """
+ Query vector map layer (edit mode)
+ """
+ if self.toolbars['map'].GetAction() == 'modifyAttrb': # select previous action
+ self.toolbars['map'].SelectDefault(event)
+ return
+
+ self.toolbars['map'].action['desc'] = 'modifyAttrb'
+
+ self.MapWindow.mouse['use'] = "queryVector"
+ self.MapWindow.mouse['box'] = "point"
+ self.MapWindow.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+ self.MapWindow.zoomtype = 0
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["cross"])
+
+ def QueryMap(self, x, y):
+ """!Query map layer features
+
+ Currently only raster and vector map layers are supported.
+
+ @param x,y coordinates
+ """
+ #set query snap distance for v.what at mapunit equivalent of 10 pixels
+ qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width)
+ east, north = self.MapWindow.Pixel2Cell((x, y))
+
+ num = 0
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ if type in ('raster', 'rgb', 'his',
+ 'vector', 'thememap', 'themechart'):
+ num += 1
+
+ if num < 1:
+ dlg = wx.MessageDialog(parent=self,
+ message=_('No raster or vector map layer selected for querying.'),
+ caption=_('No map layer selected'),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ mapname = None
+ raststr = ''
+ vectstr = ''
+ rcmd = ['r.what', '--q']
+ vcmd = ['v.what', '--q']
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ dcmd = self.tree.GetPyData(layer)[0]['cmd']
+ name = utils.GetLayerNameFromCmd(dcmd)
+ if name == '':
+ continue
+ if type in ('raster', 'rgb', 'his'):
+ raststr += "%s," % name
+ elif type in ('vector', 'thememap', 'themechart'):
+ vectstr += "%s," % name
+
+ # use display region settings instead of computation region settings
+ self.tmpreg = os.getenv("GRASS_REGION")
+ os.environ["GRASS_REGION"] = self.Map.SetRegion(windres=False)
+
+ # build query commands for any selected rasters and vectors
+ if raststr != '':
+ rcmd.append('-f')
+ rcmd.append('input=%s' % raststr.rstrip(','))
+ rcmd.append('east_north=%f,%f' % (float(east), float(north)))
+
+ if vectstr != '':
+ # check for vector maps open to be edited
+ digitToolbar = self.toolbars['vdigit']
+ if digitToolbar:
+ map = digitToolbar.GetLayer().GetName()
+ vect = []
+ for vector in vectstr.split(','):
+ if map == vector:
+ self._layerManager.goutput.WriteWarning("Vector map <%s> "
+ "opened for editing - skipped." % map)
+ continue
+ vect.append(vector)
+ vectstr = ','.join(vect)
+
+ if len(vectstr) <= 1:
+ self._layerManager.goutput.WriteCmdLog("Nothing to query.")
+ return
+
+ vcmd.append('-a')
+ vcmd.append('map=%s' % vectstr.rstrip(','))
+ vcmd.append('east_north=%f,%f' % (float(east), float(north)))
+ vcmd.append('distance=%f' % float(qdist))
+
+ # parse query command(s)
+ if self._layerManager:
+ if raststr:
+ self._layerManager.goutput.RunCmd(rcmd,
+ compReg=False,
+ onDone = self._QueryMapDone)
+ if vectstr:
+ self._layerManager.goutput.RunCmd(vcmd,
+ onDone = self._QueryMapDone)
+ else:
+ if raststr:
+ gcmd.RunCommand(rcmd)
+ if vectstr:
+ gcmd.RunCommand(vcmd)
+
+ def _QueryMapDone(self, returncode):
+ """!Restore settings after querying (restore GRASS_REGION)
+
+ @param returncode command return code
+ """
+ if hasattr(self, "tmpreg"):
+ if self.tmpreg:
+ os.environ["GRASS_REGION"] = self.tmpreg
+ elif os.environ.has_key('GRASS_REGION'):
+ del os.environ["GRASS_REGION"]
+ elif os.environ.has_key('GRASS_REGION'):
+ del os.environ["GRASS_REGION"]
+
+ if hasattr(self, "tmpreg"):
+ del self.tmpreg
+
+ def QueryVector(self, x, y):
+ """
+ Query vector map layer features
+
+ Attribute data of selected vector object are displayed in GUI dialog.
+ Data can be modified (On Submit)
+ """
+ if not self.tree.layer_selected or \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] != 'vector':
+ wx.MessageBox(parent=self,
+ message=_("No vector map selected for querying."),
+ caption=_("Vector querying"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ return
+
+ if self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetMapset() != \
+ grass.gisenv()['MAPSET']:
+ wx.MessageBox(parent=self,
+ message=_("Only vector map from the current mapset can be modified."),
+ caption=_("Vector querying"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ return
+
+ posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset,
+ y + self.MapWindow.dialogOffset))
+
+ qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) /
+ self.Map.width)
+
+ east, north = self.MapWindow.Pixel2Cell((x, y))
+
+ mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name
+
+ if self.dialogs['attributes'] is None:
+ self.dialogs['attributes'] = \
+ dbm_dialogs.DisplayAttributesDialog(parent=self.MapWindow,
+ map=mapName,
+ query=((east, north), qdist),
+ pos=posWindow,
+ action="update")
+ else:
+ # selection changed?
+ if not self.dialogs['attributes'].mapDBInfo or \
+ self.dialogs['attributes'].mapDBInfo.map != mapName:
+ self.dialogs['attributes'].UpdateDialog(map=mapName, query=((east, north), qdist))
+ else:
+ self.dialogs['attributes'].UpdateDialog(query=((east, north), qdist))
+
+ cats = self.dialogs['attributes'].GetCats()
+
+ try:
+ qlayer = self.Map.GetListOfLayers(l_name=globalvar.QUERYLAYER)[0]
+ except IndexError:
+ qlayer = None
+
+ if self.dialogs['attributes'].mapDBInfo and cats:
+ # highlight feature & re-draw map
+ if qlayer:
+ qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats,
+ useId=False,
+ addLayer=False))
+ else:
+ qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId=False)
+
+ # set opacity based on queried layer
+ opacity = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetOpacity(float=True)
+ qlayer.SetOpacity(opacity)
+
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+ if not self.dialogs['attributes'].IsShown():
+ self.dialogs['attributes'].Show()
+ else:
+ if qlayer:
+ self.Map.DeleteLayer(qlayer)
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+ if self.dialogs['attributes'].IsShown():
+ self.dialogs['attributes'].Hide()
+
+ def OnQuery(self, event):
+ """!Query tools menu"""
+ if self.toolbars['map']:
+ self.toolbars['map'].OnTool(event)
+ action = self.toolbars['map'].GetAction()
+
+ point = wx.GetMousePosition()
+ toolsmenu = wx.Menu()
+ # Add items to the menu
+ display = wx.MenuItem(parentMenu=toolsmenu, id=wx.ID_ANY,
+ text=_("Query raster/vector map(s) (display mode)"),
+ kind=wx.ITEM_CHECK)
+ toolsmenu.AppendItem(display)
+ self.Bind(wx.EVT_MENU, self.OnQueryDisplay, display)
+ numLayers = 0
+ for layer in self.tree.GetSelections():
+ type = self.tree.GetPyData(layer)[0]['maplayer'].GetType()
+ if type in ('raster', 'rgb', 'his',
+ 'vector', 'thememap', 'themechart'):
+ numLayers += 1
+ if numLayers < 1:
+ display.Enable(False)
+
+ if action == "displayAttrb":
+ display.Check(True)
+
+ modify = wx.MenuItem(parentMenu=toolsmenu, id=wx.ID_ANY,
+ text=_("Query vector map (edit mode)"),
+ kind=wx.ITEM_CHECK)
+ toolsmenu.AppendItem(modify)
+ self.Bind(wx.EVT_MENU, self.OnQueryModify, modify)
+ digitToolbar = self.toolbars['vdigit']
+ if self.tree.layer_selected:
+ layer_selected = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer']
+ if layer_selected.GetType() != 'vector' or \
+ (digitToolbar and \
+ digitToolbar.GetLayer() == layer_selected):
+ modify.Enable(False)
+ else:
+ if action == "modifyAttrb":
+ modify.Check(True)
+
+ self.PopupMenu(toolsmenu)
+ toolsmenu.Destroy()
+
+ def AddTmpVectorMapLayer(self, name, cats, useId=False, addLayer=True):
+ """
+ Add temporal vector map layer to map composition
+
+ @param name name of map layer
+ @param useId use feature id instead of category
+ """
+ # color settings from ATM
+ color = UserSettings.Get(group='atm', key='highlight', subkey='color')
+ colorStr = str(color[0]) + ":" + \
+ str(color[1]) + ":" + \
+ str(color[2])
+
+ pattern = ["d.vect",
+ "map=%s" % name,
+ "color=%s" % colorStr,
+ "fcolor=%s" % colorStr,
+ "width=%d" % UserSettings.Get(group='atm', key='highlight', subkey='width')]
+
+ if useId:
+ cmd = pattern
+ cmd.append('-i')
+ cmd.append('cats=%s' % str(cats))
+ else:
+ cmd = []
+ for layer in cats.keys():
+ cmd.append(copy.copy(pattern))
+ lcats = cats[layer]
+ cmd[-1].append("layer=%d" % layer)
+ cmd[-1].append("cats=%s" % utils.ListOfCatsToRange(lcats))
+
+ # if self.icon:
+ # cmd.append("icon=%s" % (self.icon))
+ # if self.pointsize:
+ # cmd.append("size=%s" % (self.pointsize))
+
+ if addLayer:
+ if useId:
+ return self.Map.AddLayer(type='vector', name=globalvar.QUERYLAYER, command=cmd,
+ l_active=True, l_hidden=True, l_opacity=1.0)
+ else:
+ return self.Map.AddLayer(type='command', name=globalvar.QUERYLAYER, command=cmd,
+ l_active=True, l_hidden=True, l_opacity=1.0)
+ else:
+ return cmd
+
+ def OnAnalyze(self, event):
+ """
+ Analysis tools menu
+ """
+ point = wx.GetMousePosition()
+ toolsmenu = wx.Menu()
+ # Add items to the menu
+ measure = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["measure"].GetLabel())
+ measure.SetBitmap(Icons["measure"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(measure)
+ self.Bind(wx.EVT_MENU, self.OnMeasure, measure)
+
+ profile = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["profile"].GetLabel())
+ profile.SetBitmap(Icons["profile"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(profile)
+ self.Bind(wx.EVT_MENU, self.Profile, profile)
+
+ histogram = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["histogram"].GetLabel())
+ histogram.SetBitmap(Icons["histogram"].GetBitmap(self.iconsize))
+ toolsmenu.AppendItem(histogram)
+ self.Bind(wx.EVT_MENU, self.Histogram, histogram)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(toolsmenu)
+ toolsmenu.Destroy()
+
+ def OnMeasure(self, event):
+ """
+ Init measurement routine that calculates
+ map distance along transect drawn on
+ map display
+ """
+
+ self.totaldist = 0.0 # total measured distance
+
+ # switch GIS Manager to output console to show measure results
+ self._layerManager.notebook.SetSelection(1)
+
+ # change mouse to draw line for measurement
+ self.MapWindow.mouse['use'] = "measure"
+ self.MapWindow.mouse['box'] = "line"
+ self.MapWindow.zoomtype = 0
+ self.MapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SHORT_DASH)
+ self.MapWindow.polypen = wx.Pen(colour='green', width=2, style=wx.SHORT_DASH)
+
+ # change the cursor
+ self.MapWindow.SetCursor(self.cursors["pencil"])
+
+ # initiating output
+ style = self._layerManager.goutput.cmd_output.StyleWarning
+ self._layerManager.goutput.WriteLog(_('Click and drag with left mouse button '
+ 'to measure.%s'
+ 'Double click with left button to clear.') % \
+ (os.linesep), style)
+ if self.Map.projinfo['proj'] != 'xy':
+ units = self.Map.projinfo['units']
+ style = self._layerManager.goutput.cmd_output.StyleCommand
+ self._layerManager.goutput.WriteLog(_('Measuring distance') + ' ('
+ + units + '):',
+ style)
+ else:
+ self._layerManager.goutput.WriteLog(_('Measuring distance:'),
+ style)
+
+ def MeasureDist(self, beginpt, endpt):
+ """
+ Calculate map distance from screen distance
+ and print to output window
+ """
+
+ if self._layerManager.notebook.GetSelection() != 1:
+ self._layerManager.notebook.SetSelection(1)
+
+ dist, (north, east) = self.MapWindow.Distance(beginpt, endpt)
+
+ dist = round(dist, 3)
+ d, dunits = self.FormatDist(dist)
+
+ self.totaldist += dist
+ td, tdunits = self.FormatDist(self.totaldist)
+
+ strdist = str(d)
+ strtotdist = str(td)
+
+ if self.Map.projinfo['proj'] == 'xy' or 'degree' not in self.Map.projinfo['unit']:
+ angle = int(math.degrees(math.atan2(north,east)) + 0.5)
+ angle = 180 - angle
+ if angle < 0:
+ angle = 360+angle
+
+ mstring = 'segment = %s %s\ttotal distance = %s %s\tbearing = %d deg' \
+ % (strdist,dunits,strtotdist,tdunits,angle)
+ else:
+ mstring = 'segment = %s %s\ttotal distance = %s %s' \
+ % (strdist,dunits,strtotdist,tdunits)
+
+ self._layerManager.goutput.WriteLog(mstring)
+
+ return dist
+
+ def Profile(self, event):
+ """
+ Init profile canvas and tools
+ """
+ raster = []
+ if self.tree.layer_selected and \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
+ raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
+
+ self.profile = profile.ProfileFrame(self,
+ id=wx.ID_ANY, pos=wx.DefaultPosition, size=(700,300),
+ style=wx.DEFAULT_FRAME_STYLE, rasterList=raster)
+ self.profile.Show()
+ # Open raster select dialog to make sure that a raster (and the desired raster)
+ # is selected to be profiled
+ self.profile.OnSelectRaster(None)
+
+ def FormatDist(self, dist):
+ """!Format length numbers and units in a nice way,
+ as a function of length. From code by Hamish Bowman
+ Grass Development Team 2006"""
+
+ mapunits = self.Map.projinfo['units']
+ if mapunits == 'metres': mapunits = 'meters'
+ outunits = mapunits
+ dist = float(dist)
+ divisor = 1.0
+
+ # figure out which units to use
+ if mapunits == 'meters':
+ if dist > 2500.0:
+ outunits = 'km'
+ divisor = 1000.0
+ else: outunits = 'm'
+ elif mapunits == 'feet':
+ # nano-bug: we match any "feet", but US Survey feet is really
+ # 5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
+ # miles the tick markers are rounded to the nearest 10th of a
+ # mile (528'), the difference in foot flavours is ignored.
+ if dist > 5280.0:
+ outunits = 'miles'
+ divisor = 5280.0
+ else:
+ outunits = 'ft'
+ elif 'degree' in mapunits:
+ if dist < 1:
+ outunits = 'min'
+ divisor = (1/60.0)
+ else:
+ outunits = 'deg'
+
+ # format numbers in a nice way
+ if (dist/divisor) >= 2500.0:
+ outdist = round(dist/divisor)
+ elif (dist/divisor) >= 1000.0:
+ outdist = round(dist/divisor,1)
+ elif (dist/divisor) > 0.0:
+ outdist = round(dist/divisor,int(math.ceil(3-math.log10(dist/divisor))))
+ else:
+ outdist = float(dist/divisor)
+
+ return (outdist, outunits)
+
+
+ def Histogram(self, event):
+ """
+ Init histogram display canvas and tools
+ """
+ self.histogram = histogram.HistFrame(self,
+ id=wx.ID_ANY, size=globalvar.HIST_WINDOW_SIZE,
+ style=wx.DEFAULT_FRAME_STYLE)
+
+ #show new display
+ self.histogram.Show()
+ self.histogram.Refresh()
+ self.histogram.Update()
+
+
+ def OnDecoration(self, event):
+ """
+ Decorations overlay menu
+ """
+ point = wx.GetMousePosition()
+ decmenu = wx.Menu()
+ # Add items to the menu
+ AddScale = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addbarscale"].GetLabel())
+ AddScale.SetBitmap(Icons["addbarscale"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddScale)
+ self.Bind(wx.EVT_MENU, self.OnAddBarscale, AddScale)
+
+ AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addlegend"].GetLabel())
+ AddLegend.SetBitmap(Icons["addlegend"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddLegend)
+ self.Bind(wx.EVT_MENU, self.OnAddLegend, AddLegend)
+
+ AddText = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addtext"].GetLabel())
+ AddText.SetBitmap(Icons["addtext"].GetBitmap(self.iconsize))
+ decmenu.AppendItem(AddText)
+ self.Bind(wx.EVT_MENU, self.OnAddText, AddText)
+
+ # Popup the menu. If an item is selected then its handler
+ # will be called before PopupMenu returns.
+ self.PopupMenu(decmenu)
+ decmenu.Destroy()
+
+ def OnAddBarscale(self, event):
+ """
+ Handler for scale/arrow map decoration menu selection.
+ """
+ if self.dialogs['barscale']:
+ return
+
+ id = 0 # unique index for overlay layer
+
+ # If location is latlon, only display north arrow (scale won't work)
+ # proj = self.Map.projinfo['proj']
+ # if proj == 'll':
+ # barcmd = 'd.barscale -n'
+ # else:
+ # barcmd = 'd.barscale'
+
+ # decoration overlay control dialog
+ self.dialogs['barscale'] = \
+ gdialogs.DecorationDialog(parent=self, title=_('Scale and North arrow'),
+ size=(350, 200),
+ style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
+ cmd=['d.barscale', 'at=0,5'],
+ ovlId=id,
+ name='barscale',
+ checktxt = _("Show/hide scale and North arrow"),
+ ctrltxt = _("scale object"))
+
+ self.dialogs['barscale'].CentreOnParent()
+ ### dialog cannot be show as modal - in the result d.barscale is not selectable
+ ### self.dialogs['barscale'].ShowModal()
+ self.dialogs['barscale'].Show()
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def OnAddLegend(self, event):
+ """
+ Handler for legend map decoration menu selection.
+ """
+ if self.dialogs['legend']:
+ return
+
+ id = 1 # index for overlay layer in render
+
+ cmd = ['d.legend', 'at=5,50,2,5']
+ if self.tree.layer_selected and \
+ self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
+ cmd.append('map=%s' % self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
+
+ # Decoration overlay control dialog
+ self.dialogs['legend'] = \
+ gdialogs.DecorationDialog(parent=self, title=('Legend'),
+ size=(350, 200),
+ style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE,
+ cmd=cmd,
+ ovlId=id,
+ name='legend',
+ checktxt = _("Show/hide legend"),
+ ctrltxt = _("legend object"))
+
+ self.dialogs['legend'].CentreOnParent()
+ ### dialog cannot be show as modal - in the result d.legend is not selectable
+ ### self.dialogs['legend'].ShowModal()
+ self.dialogs['legend'].Show()
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def OnAddText(self, event):
+ """
+ Handler for text decoration menu selection.
+ """
+ if self.MapWindow.dragid > -1:
+ id = self.MapWindow.dragid
+ else:
+ # index for overlay layer in render
+ if len(self.MapWindow.textdict.keys()) > 0:
+ id = self.MapWindow.textdict.keys()[-1] + 1
+ else:
+ id = 101
+
+ self.dialogs['text'] = gdialogs.TextLayerDialog(parent=self, ovlId=id,
+ title=_('Add text layer'),
+ size=(400, 200))
+ self.dialogs['text'].CenterOnParent()
+
+ # If OK button pressed in decoration control dialog
+ if self.dialogs['text'].ShowModal() == wx.ID_OK:
+ text = self.dialogs['text'].GetValues()['text']
+ active = self.dialogs['text'].GetValues()['active']
+ coords, w, h = self.MapWindow.TextBounds(self.dialogs['text'].GetValues())
+
+ # delete object if it has no text or is not active
+ if text == '' or active == False:
+ try:
+ self.MapWindow.pdc.ClearId(id)
+ self.MapWindow.pdc.RemoveId(id)
+ del self.MapWindow.textdict[id]
+ except:
+ pass
+ return
+
+ self.MapWindow.pdc.ClearId(id)
+ self.MapWindow.pdc.SetId(id)
+ self.MapWindow.textdict[id] = self.dialogs['text'].GetValues()
+
+ self.MapWindow.Draw(self.MapWindow.pdcDec, img=self.MapWindow.textdict[id],
+ drawid=id, pdctype='text', coords=coords)
+
+ self.MapWindow.UpdateMap(render=False, renderVector=False)
+
+ self.MapWindow.mouse['use'] = 'pointer'
+
+ def GetOptData(self, dcmd, type, params, propwin):
+ """
+ Callback method for decoration overlay command generated by
+ dialog created in menuform.py
+ """
+ # Reset comand and rendering options in render.Map. Always render decoration.
+ # Showing/hiding handled by PseudoDC
+ self.Map.ChangeOverlay(ovltype=type, type='overlay', name='', command=dcmd,
+ l_active=True, l_render=False)
+ self.params[type] = params
+ self.propwin[type] = propwin
+
+ def OnZoomMenu(self, event):
+ """
+ Zoom menu
+ """
+ point = wx.GetMousePosition()
+ zoommenu = wx.Menu()
+ # Add items to the menu
+ zoommap = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to selected map(s)'))
+ zoommenu.AppendItem(zoommap)
+ self.Bind(wx.EVT_MENU, self.MapWindow.OnZoomToMap, zoommap)
+
+ zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)'))
+ zoommenu.AppendItem(zoomwind)
+ self.Bind(wx.EVT_MENU, self.MapWindow.ZoomToWind, zoomwind)
+
+ zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region'))
+ zoommenu.AppendItem(zoomdefault)
+ self.Bind(wx.EVT_MENU, self.MapWindow.ZoomToDefault, zoomdefault)
+
+ zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region'))
+ zoommenu.AppendItem(zoomsaved)
+ self.Bind(wx.EVT_MENU, self.MapWindow.ZoomToSaved, zoomsaved)
+
+ savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display'))
+ zoommenu.AppendItem(savewind)
+ self.Bind(wx.EVT_MENU, self.MapWindow.DisplayToWind, savewind)
+
+ savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region'))
+ zoommenu.AppendItem(savezoom)
+ self.Bind(wx.EVT_MENU, self.MapWindow.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 SetProperties(self, render=False, mode=0, showCompExtent=False,
+ constrainRes=False, projection=False):
+ """!Set properies of map display window"""
+ self.statusbarWin['render'].SetValue(render)
+ self.statusbarWin['toggle'].SetSelection(mode)
+ self.StatusbarUpdate()
+ self.statusbarWin['region'].SetValue(showCompExtent)
+ self.statusbarWin['resolution'].SetValue(constrainRes)
+ self.statusbarWin['projection'].SetValue(projection)
+ if showCompExtent:
+ self.MapWindow.regionCoords = []
+
+ def IsStandalone(self):
+ """!Check if Map display is standalone"""
+ if self._layerManager:
+ return False
+
+ return True
+
+ def GetLayerManager(self):
+ """!Get reference to Layer Manager
+
+ @return window reference
+ @return None (if standalone)
+ """
+ return self._layerManager
+
+# end of class MapFrame
+
+class MapApp(wx.App):
+ """
+ MapApp class
+ """
+
+ def OnInit(self):
+
+ wx.InitAllImageHandlers()
+ if __name__ == "__main__":
+ Map = render.Map() # instance of Map class to render GRASS display output to PPM file
+ else:
+ Map = None
+
+ self.mapFrm = MapFrame(parent=None, id=wx.ID_ANY, Map=Map,
+ size=globalvar.MAP_WINDOW_SIZE)
+ #self.SetTopWindow(Map)
+ self.mapFrm.Show()
+
+ if __name__ == "__main__":
+ # redraw map, if new command appears
+ self.redraw = False
+
+
+ return 1
+
+
+# end of class MapApp
+
+if __name__ == "__main__":
+
+ ###### SET command variable
+
+
+ title = "title"
+ cmdfilename = "cmdfilename"
+
+
+
+ gm_map = MapApp(0)
+ # set title
+ gm_map.mapFrm.SetTitle(_("GRASS GIS Map Display: " + title + " - Location: " + grass.gisenv()["LOCATION_NAME"]))
+
+ gm_map.MainLoop()
+ sys.exit(0)
Modified: grass-addons/gui/wxpython/data_catalog/mapwindow.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/mapwindow.py 2010-02-03 10:46:47 UTC (rev 40793)
+++ grass-addons/gui/wxpython/data_catalog/mapwindow.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -1,11 +1,10 @@
"""!
- at package mapwindow.py
+ at package mapdisp_window.py
- at brief buffered window, map display for DataCatalog.
-orginal code from wxGUI module mapdisp_window.py.
-Modified for map display in DataCatalog.
+ at brief GIS map display canvas, buffered window.
Classes:
+ - MapWindow
- BufferedWindow
(C) 2006-2009 by the GRASS Development Team
@@ -13,10 +12,10 @@
License (>=v2). Read the file COPYING that comes with GRASS
for details.
- at author Michael Barton (original author)
- at author Jachym Cepicky (original author)
- at author Martin Landa <landa.martin gmail.com> (original author)
- at author Mohammed Rashad K.M (modified for DataCatalog)
+ at author Michael Barton
+ at author Jachym Cepicky
+ at author Martin Landa <landa.martin gmail.com>
+
"""
import os
@@ -24,55 +23,316 @@
import math
import sys
import tempfile
+
+gbase = os.getenv("GISBASE")
+pypath = os.path.join(gbase,'etc','wxpython','gui_modules')
+sys.path.append(pypath)
+
+import globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+ globalvar.CheckForWx()
+
import wx
+
+import grass.script as grass
+
+import dbm
+
+
+import dbm_dialogs
+import gdialogs
+import gcmd
+import utils
import globalvar
import gselect
from debug import Debug
+from preferences import globalSettings as UserSettings
+from units import ConvertValue as UnitsConvertValue
+from vdigit import GV_LINES as VDigit_Lines_Type
+from vdigit import VDigitCategoryDialog
+from vdigit import VDigitZBulkDialog
+from vdigit import VDigitDuplicatesDialog
+from vdigit import PseudoDC as VDigitPseudoDC
+class MapWindow(object):
+ """!
+ Abstract map window class
+ Parent for BufferedWindow class (2D display mode) and
+ GLWindow (3D display mode)
+ """
+ def __init__(self, parent, id=wx.ID_ANY,
+ pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.NO_FULL_REPAINT_ON_RESIZE,
+ Map=None, tree=None, lmgr=None):
+ self.parent = parent # MapFrame
+
+ #
+ # mouse attributes -- position on the screen, begin and end of
+ # dragging, and type of drawing
+ #
+ self.mouse = {
+ 'begin': [0, 0], # screen coordinates
+ 'end' : [0, 0],
+ 'use' : "pointer",
+ 'box' : "point"
+ }
+
+ def EraseMap(self):
+ """!
+ Erase the canvas (virtual method)
+ """
+ pass
+ def UpdateMap(self):
+ """!
+ Updates the canvas anytime there is a change to the
+ underlaying images or to the geometry of the canvas.
+ """
+ pass
+
+ def OnLeftDown(self, event):
+ pass
+
+ def OnLeftUp(self, event):
+ pass
+
+ def OnMouseMotion(self, event):
+ pass
+
+ def OnZoomToMap(self, event):
+ pass
+
+ def OnZoomToRaster(self, event):
+ pass
-class BufferedWindow(wx.Window):
+ def GetSelectedLayer(self, type = 'layer', multi = False):
+ """!
+ Get selected layer from layer tree
+ @param type 'item' / 'layer' / 'nviz'
+ @param multi return first selected layer or all
+
+ @return layer / map layer properties / nviz properties
+ @return None / [] on failure
+ """
+ ret = []
+ if not self.tree or \
+ not self.tree.GetSelection():
+ if multi:
+ return []
+ else:
+ return None
+
+ if multi and \
+ type == 'item':
+ return self.tree.GetSelections()
+
+ for item in self.tree.GetSelections():
+ if not item.IsChecked():
+ if multi:
+ continue
+ else:
+ return None
+
+ if type == 'item': # -> multi = False
+ return item
+
+ try:
+ if type == 'nviz':
+ layer = self.tree.GetPyData(item)[0]['nviz']
+ else:
+ layer = self.tree.GetPyData(item)[0]['maplayer']
+ except:
+ layer = None
+
+ if multi:
+ ret.append(layer)
+ else:
+ return layer
+
+ return ret
+
+class BufferedWindow(MapWindow, wx.Window):
+ """!
+ A Buffered window class.
+
+ When the drawing needs to change, you app needs to call the
+ UpdateMap() method. Since the drawing is stored in a bitmap, you
+ can also save the drawing to file by calling the
+ SaveToFile(self,file_name,file_type) method.
+ """
+
def __init__(self, parent, id,
pos = wx.DefaultPosition,
size = wx.DefaultSize,
- style=wx.NO_FULL_REPAINT_ON_RESIZE,Map=None):
+ style=wx.NO_FULL_REPAINT_ON_RESIZE,
+ Map=None, tree=None, lmgr=None):
- wx.Window.__init__(self, parent, id, pos, size, style)
- Debug.msg(4, "BufferedWindow.__init(): Map=%s" % Map)
- self.Map = Map
-
- self.Bind(wx.EVT_PAINT, self.OnPaint)
- self.buffer = wx.EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height))
- self.mapfile = None
- self.img = ""
+ MapWindow.__init__(self, parent, id, pos, size, style,
+ Map, tree, lmgr)
+ wx.Window.__init__(self, parent, id, pos, size, style)
- self.imagedict = {}
- self.select = {}
- self.pdc = wx.PseudoDC()
+ self.Map = Map
+ self.tree = tree
+ self.lmgr = lmgr # Layer Manager
+
+ #
+ # Flags
+ #
+ self.resize = False # indicates whether or not a resize event has taken place
+ self.dragimg = None # initialize variable for map panning
+ #
+ # Variable for drawing on DC
+ #
+ self.pen = None # pen for drawing zoom boxes, etc.
+ self.polypen = None # pen for drawing polylines (measurements, profiles, etc)
+ # List of wx.Point tuples defining a polyline (geographical coordinates)
+ self.polycoords = []
+ # ID of rubber band line
+ self.lineid = None
+ # ID of poly line resulting from cumulative rubber band lines (e.g. measurement)
+ self.plineid = None
+
+ #
+ # Event bindings
+ #
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ #self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.Bind(wx.EVT_MOTION, self.MouseActions)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.MouseActions)
+ self.processMouse = True
+
+ #
+ # Render output objects
+ #
+ self.mapfile = None # image file to be rendered
+ self.img = "" # wx.Image object (self.mapfile)
+ # used in digitization tool (do not redraw vector map)
+ self.imgVectorMap = None
+ # decoration overlays
+ self.overlays = {}
+ # images and their PseudoDC ID's for painting and dragging
+ self.imagedict = {}
+ self.select = {} # selecting/unselecting decorations for dragging
+ self.textdict = {} # text, font, and color indexed by id
+ self.currtxtid = None # PseudoDC id for currently selected text
+ #
+ # Zoom objects
+ #
+ self.zoomhistory = [] # list of past zoom extents
+ self.currzoom = 0 # current set of extents in zoom history being used
+
+ self.zoomtype = 1 # 1 zoom in, 0 no zoom, -1 zoom out
+ self.hitradius = 10 # distance for selecting map decorations
+ self.dialogOffset = 5 # offset for dialog (e.g. DisplayAttributesDialog)
+
+ # OnSize called to make sure the buffer is initialized.
+ # This might result in OnSize getting called twice on some
+ # platforms at initialization, but little harm done.
+ ### self.OnSize(None)
+
+ self.DefinePseudoDC()
+ # redraw all pdc's, pdcTmp layer is redrawn always (speed issue)
+ self.redrawAll = True
+
+ # will store an off screen empty bitmap for saving to file
+ self._buffer = ''
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
+
+ # vars for handling mouse clicks
+ self.dragid = -1
+ self.lastpos = (0, 0)
+
+ def DefinePseudoDC(self, vdigit = False):
+ """!Define PseudoDC class to use
+
+ @vdigit True to use PseudoDC from vdigit
+ """
+ # create PseudoDC used for background map, map decorations like scales and legends
+ self.pdc = self.PseudoDC(vdigit)
+ # used for digitization tool
+ self.pdcVector = None
+ # decorations (region box, etc.)
+ self.pdcDec = self.PseudoDC(vdigit)
+ # pseudoDC for temporal objects (select box, measurement tool, etc.)
+ self.pdcTmp = self.PseudoDC(vdigit)
+
+ def PseudoDC(self, vdigit = False):
+ """!Create PseudoDC instance"""
+ if vdigit:
+ PseudoDC = VDigitPseudoDC
+ else:
+ PseudoDC = wx.PseudoDC
+
+ return PseudoDC()
+
+ def CheckPseudoDC(self):
+ """!Try to draw background
+
+ @return True on success
+ @return False on failure
+ """
+ try:
+ self.pdc.BeginDrawing()
+ self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ self.pdc.BeginDrawing()
+ except:
+ return False
+
+ return True
+
def Draw(self, pdc, img=None, drawid=None, pdctype='image', coords=[0, 0, 0, 0]):
-
+ """!
+ Draws map and overlay decorations
+ """
if drawid == None:
if pdctype == 'image' and img:
drawid = self.imagedict[img]
+ elif pdctype == 'clear':
+ drawid == None
else:
drawid = wx.NewId()
if img and pdctype == 'image':
+ # self.imagedict[img]['coords'] = coords
self.select[self.imagedict[img]['id']] = False # ?
pdc.BeginDrawing()
+
+ if drawid != 99:
+ bg = wx.TRANSPARENT_BRUSH
+ else:
+ bg = wx.Brush(self.GetBackgroundColour())
+
+ pdc.SetBackground(bg)
+
+ ### pdc.Clear()
+
Debug.msg (5, "BufferedWindow.Draw(): id=%s, pdctype=%s, coord=%s" % \
(drawid, pdctype, coords))
# set PseudoDC id
if drawid is not None:
pdc.SetId(drawid)
+
+ if pdctype == 'clear': # erase the display
+ bg = wx.WHITE_BRUSH
+ # bg = wx.Brush(self.GetBackgroundColour())
+ pdc.SetBackground(bg)
+ pdc.RemoveAll()
+ pdc.Clear()
+ pdc.EndDrawing()
+
+ self.Refresh()
+ return
if pdctype == 'image': # draw selected image
bitmap = wx.BitmapFromImage(img)
@@ -80,33 +340,295 @@
pdc.DrawBitmap(bitmap, coords[0], coords[1], True) # draw the composite map
pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
+ elif pdctype == 'box': # draw a box on top of the map
+ if self.pen:
+ pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+ pdc.SetPen(self.pen)
+ x2 = max(coords[0],coords[2])
+ x1 = min(coords[0],coords[2])
+ y2 = max(coords[1],coords[3])
+ y1 = min(coords[1],coords[3])
+ rwidth = x2-x1
+ rheight = y2-y1
+ rect = wx.Rect(x1, y1, rwidth, rheight)
+ pdc.DrawRectangleRect(rect)
+ pdc.SetIdBounds(drawid, rect)
+
+ elif pdctype == 'line': # draw a line on top of the map
+ if self.pen:
+ pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+ pdc.SetPen(self.pen)
+ pdc.DrawLine(wx.Point(coords[0], coords[1]),
+ wx.Point(coords[2], coords[3]))
+ pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], coords[2], coords[3]))
+ # self.ovlcoords[drawid] = coords
+ elif pdctype == 'polyline': # draw a polyline on top of the map
+ if self.polypen:
+ pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+ pdc.SetPen(self.polypen)
+ ### pdc.DrawLines(coords)
+ if (len(coords) < 2):
+ return
+ i = 1
+ while i < len(coords):
+ pdc.DrawLinePoint(wx.Point(coords[i-1][0], coords[i-1][1]),
+ wx.Point(coords[i][0], coords[i][1]))
+ i += 1
+
+ # get bounding rectangle for polyline
+ xlist = []
+ ylist = []
+ if len(coords) > 0:
+ for point in coords:
+ x,y = point
+ xlist.append(x)
+ ylist.append(y)
+ x1=min(xlist)
+ x2=max(xlist)
+ y1=min(ylist)
+ y2=max(ylist)
+ pdc.SetIdBounds(drawid, wx.Rect(x1,y1,x2,y2))
+ # self.ovlcoords[drawid] = [x1,y1,x2,y2]
+
+ elif pdctype == 'point': # draw point
+ if self.pen:
+ pdc.SetPen(self.pen)
+ pdc.DrawPoint(coords[0], coords[1])
+ coordsBound = (coords[0] - 5,
+ coords[1] - 5,
+ coords[0] + 5,
+ coords[1] + 5)
+ pdc.SetIdBounds(drawid, wx.Rect(coordsBound))
+ # self.ovlcoords[drawid] = coords
+
+ elif pdctype == 'text': # draw text on top of map
+ if not img['active']:
+ return #only draw active text
+ if img.has_key('rotation'):
+ rotation = float(img['rotation'])
+ else:
+ rotation = 0.0
+ w, h = self.GetFullTextExtent(img['text'])[0:2]
+ pdc.SetFont(img['font'])
+ pdc.SetTextForeground(img['color'])
+ coords, w, h = self.TextBounds(img)
+ if rotation == 0:
+ pdc.DrawText(img['text'], coords[0], coords[1])
+ else:
+ pdc.DrawRotatedText(img['text'], coords[0], coords[1], rotation)
+ pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], w, h))
+
pdc.EndDrawing()
+
self.Refresh()
return drawid
+ def TextBounds(self, textinfo):
+ """!
+ Return text boundary data
- def OnPaint(self,event):
- #Debug.msg(4, "BufferedWindow.OnPaint(): redrawAll=%s" % self.redrawAll)
+ @param textinfo text metadata (text, font, color, rotation)
+ @param coords reference point
+ """
+ if textinfo.has_key('rotation'):
+ rotation = float(textinfo['rotation'])
+ else:
+ rotation = 0.0
+
+ coords = textinfo['coords']
+
+ Debug.msg (4, "BufferedWindow.TextBounds(): text=%s, rotation=%f" % \
+ (textinfo['text'], rotation))
+
+ self.Update()
+ ### self.Refresh()
+
+ self.SetFont(textinfo['font'])
+
+ w, h = self.GetTextExtent(textinfo['text'])
+
+ if rotation == 0:
+ coords[2], coords[3] = coords[0] + w, coords[1] + h
+ return coords, w, h
+
+ boxh = math.fabs(math.sin(math.radians(rotation)) * w) + h
+ boxw = math.fabs(math.cos(math.radians(rotation)) * w) + h
+ coords[2] = coords[0] + boxw
+ coords[3] = coords[1] + boxh
+
+ return coords, boxw, boxh
+
+ def OnPaint(self, event):
+ """!
+ Draw PseudoDC's to buffered paint DC
+
+ self.pdc for background and decorations
+ self.pdcVector for vector map which is edited
+ self.pdcTmp for temporaly drawn objects (self.polycoords)
+
+ If self.redrawAll is False on self.pdcTmp content is re-drawn
+ """
+ Debug.msg(4, "BufferedWindow.OnPaint(): redrawAll=%s" % self.redrawAll)
+
dc = wx.BufferedPaintDC(self, self.buffer)
+
+ ### dc.SetBackground(wx.Brush("White"))
dc.Clear()
+
+ # use PrepareDC to set position correctly
self.PrepareDC(dc)
- self.bufferLast = None
+
+ # create a clipping rect from our position and size
+ # and update region
+ rgn = self.GetUpdateRegion().GetBox()
+ dc.SetClippingRect(rgn)
+
+ switchDraw = False
+ if self.redrawAll is None:
+ self.redrawAll = True
+ switchDraw = True
+
+ if self.redrawAll: # redraw pdc and pdcVector
+ # draw to the dc using the calculated clipping rect
+ self.pdc.DrawToDCClipped(dc, rgn)
+
+ # draw vector map layer
+ if self.pdcVector:
+ # decorate with GDDC (transparency)
+ try:
+ gcdc = wx.GCDC(dc)
+ self.pdcVector.DrawToDCClipped(gcdc, rgn)
+ except NotImplementedError, e:
+ print >> sys.stderr, e
+ self.pdcVector.DrawToDCClipped(dc, rgn)
+
+ self.bufferLast = None
+ else: # do not redraw pdc and pdcVector
+ if self.bufferLast is None:
+ # draw to the dc
+ self.pdc.DrawToDC(dc)
+
+ if self.pdcVector:
+ # decorate with GDDC (transparency)
+ try:
+ gcdc = wx.GCDC(dc)
+ self.pdcVector.DrawToDC(gcdc)
+ except NotImplementedError, e:
+ print >> sys.stderr, e
+ self.pdcVector.DrawToDC(dc)
+
+ # store buffered image
+ # self.bufferLast = wx.BitmapFromImage(self.buffer.ConvertToImage())
+ self.bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
+
+ pdcLast = self.PseudoDC(vdigit = False)
+ pdcLast.DrawBitmap(self.bufferLast, 0, 0, False)
+ pdcLast.DrawToDC(dc)
+
+ # draw decorations (e.g. region box)
+ try:
+ gcdc = wx.GCDC(dc)
+ self.pdcDec.DrawToDC(gcdc)
+ except NotImplementedError, e:
+ print >> sys.stderr, e
+ self.pdcDec.DrawToDC(dc)
+
+ # draw temporary object on the foreground
+ ### self.pdcTmp.DrawToDCClipped(dc, rgn)
+ self.pdcTmp.DrawToDC(dc)
+
+ if switchDraw:
+ self.redrawAll = False
+
+ def OnSize(self, event):
+ """!
+ Scale map image so that it is
+ the same size as the Window
+ """
+ Debug.msg(3, "BufferedWindow.OnSize():")
+
+ # set size of the input image
+ self.Map.ChangeMapSize(self.GetClientSize())
+ # align extent based on center point and display resolution
+ # this causes that image is not resized when display windows is resized
+ # self.Map.AlignExtentFromDisplay()
+
+ # Make new off screen bitmap: this bitmap will always have the
+ # current drawing in it, so it can be used to save the image to
+ # a file, or whatever.
+ self.buffer = wx.EmptyBitmap(max(1, self.Map.width), max(1, self.Map.height))
+
+ # get the image to be rendered
+ self.img = self.GetImage()
+
+ # update map display
+ if self.img and self.Map.width + self.Map.height > 0: # scale image during resize
+ self.img = self.img.Scale(self.Map.width, self.Map.height)
+ if len(self.Map.GetListOfLayers()) > 0:
+ self.UpdateMap()
+
+ # re-render image on idle
+ self.resize = True
+
+ # reposition checkbox in statusbar
+ #self.parent.StatusbarReposition()
+
+ # update statusbar
+ #self.parent.StatusbarUpdate()
+
+ def OnIdle(self, event):
+ """!
+ Only re-render a composite map image from GRASS during
+ idle time instead of multiple times during resizing.
+ """
+ if self.resize:
+ self.UpdateMap(render=True)
+
+ event.Skip()
+
+ def SaveToFile(self, FileName, FileType):
+ """!
+ This draws the psuedo DC to a buffer that
+ can be saved to a file.
+ """
+ dc = wx.BufferedPaintDC(self, self.buffer)
self.pdc.DrawToDC(dc)
- self.bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
- pdcLast = wx.PseudoDC()
- pdcLast.DrawBitmap(self.bufferLast, 0, 0, False)
- pdcLast.DrawToDC(dc)
+ if self.pdcVector:
+ self.pdcVector.DrawToDC(dc)
+ self.buffer.SaveFile(FileName, FileType)
+ def GetOverlay(self):
+ """!
+ Converts rendered overlay files to wx.Image
+ Updates self.imagedict
+ @return list of images
+ """
+ imgs = []
+ for overlay in self.Map.GetListOfLayers(l_type="overlay", l_active=True):
+ if os.path.isfile(overlay.mapfile) and os.path.getsize(overlay.mapfile):
+ img = wx.Image(overlay.mapfile, wx.BITMAP_TYPE_ANY)
+ self.imagedict[img] = { 'id' : overlay.id,
+ 'layer' : overlay }
+ imgs.append(img)
+
+ return imgs
+
def GetImage(self):
+ """!
+ Converts redered map files to wx.Image
+
+ Updates self.imagedict (id=99)
+
+ @return wx.Image instance (map composition)
+ """
imgId = 99
if self.Map.mapfile and os.path.isfile(self.Map.mapfile) and \
os.path.getsize(self.Map.mapfile):
img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY)
- #print self.Map.mapfile
else:
img = None
@@ -115,31 +637,2137 @@
return img
def UpdateMap(self, render=True, renderVector=True):
+ """!
+ Updates the canvas anytime there is a change to the
+ underlaying images or to the geometry of the canvas.
- if self.img is None:
- render = True
+ @param render re-render map composition
+ @param renderVector re-render vector map layer enabled for editing (used for digitizer)
+ """
+ start = time.clock()
+
+ self.resize = False
- if render:
- # update display size
- self.Map.ChangeMapSize(self.GetClientSize())
- self.mapfile = self.Map.Render(force=True, windres=False)
- else:
- self.mapfile = self.Map.Render(force=False)
+ # if len(self.Map.GetListOfLayers()) == 0:
+ # return False
+
+ if self.img is None:
+ render = True
- self.img = self.GetImage() # id=99
- self.pdc.Clear()
- self.pdc.RemoveAll()
+ #
+ # initialize process bar (only on 'render')
+ #
+ if render is True or renderVector is True:
+ self.parent.statusbarWin['progress'].Show()
+ if self.parent.statusbarWin['progress'].GetRange() > 0:
+ self.parent.statusbarWin['progress'].SetValue(1)
- if not self.img:
- self.Draw(self.pdc, pdctype='clear')
- else:
- try:
- id = self.imagedict[self.img]['id']
- except:
- return False
+ #
+ # render background image if needed
+ #
+
+ # update layer dictionary if there has been a change in layers
+ if self.tree and self.tree.reorder == True:
+ self.tree.ReorderLayers()
+
+ # reset flag for auto-rendering
+ if self.tree:
+ self.tree.rerender = False
+
+ if render:
+ # update display size
+ self.Map.ChangeMapSize(self.GetClientSize())
+ if self.parent.statusbarWin['resolution'].IsChecked():
+ # use computation region resolution for rendering
+ windres = True
+ else:
+ windres = False
+ self.mapfile = self.Map.Render(force=True, mapWindow=self.parent,
+ windres=windres)
+ else:
+ self.mapfile = self.Map.Render(force=False, mapWindow=self.parent)
+
+ self.img = self.GetImage() # id=99
+
+ #
+ # clear pseudoDcs
+ #
+ for pdc in (self.pdc,
+ self.pdcDec,
+ self.pdcTmp):
+ pdc.Clear()
+ pdc.RemoveAll()
+
+ #
+ # draw background map image to PseudoDC
+ #
+ if not self.img:
+ self.Draw(self.pdc, pdctype='clear')
+ else:
+ try:
+ id = self.imagedict[self.img]['id']
+ except:
+ return False
- self.Draw(self.pdc, self.img, drawid=id)
-
- return True
+ self.Draw(self.pdc, self.img, drawid=id)
+
+ #
+ # render vector map layer
+ #
+ digitToolbar = self.parent.toolbars['vdigit']
+ if renderVector and digitToolbar and \
+ digitToolbar.GetLayer():
+ # set region
+ self.parent.digit.driver.UpdateRegion()
+ # re-calculate threshold for digitization tool
+ self.parent.digit.driver.GetThreshold()
+ # draw map
+ if self.pdcVector:
+ self.pdcVector.Clear()
+ self.pdcVector.RemoveAll()
+ try:
+ item = self.tree.FindItemByData('maplayer', digitToolbar.GetLayer())
+ except TypeError:
+ item = None
+
+ if item and self.tree.IsItemChecked(item):
+ self.parent.digit.driver.DrawMap()
+ # translate tmp objects (pointer position)
+ if digitToolbar.GetAction() == 'moveLine':
+ if hasattr(self, "vdigitMove") and \
+ self.vdigitMove.has_key('beginDiff'):
+ # move line
+ for id in self.vdigitMove['id']:
+ self.pdcTmp.TranslateId(id,
+ self.vdigitMove['beginDiff'][0],
+ self.vdigitMove['beginDiff'][1])
+ del self.vdigitMove['beginDiff']
+
+ #
+ # render overlays
+ #
+ for img in self.GetOverlay():
+ # draw any active and defined overlays
+ if self.imagedict[img]['layer'].IsActive():
+ id = self.imagedict[img]['id']
+ self.Draw(self.pdc, img=img, drawid=id,
+ pdctype=self.overlays[id]['pdcType'], coords=self.overlays[id]['coords'])
+ for id in self.textdict.keys():
+ self.Draw(self.pdc, img=self.textdict[id], drawid=id,
+ pdctype='text', coords=[10, 10, 10, 10])
+
+ # optionally draw computational extent box
+ self.DrawCompRegionExtent()
+
+ #
+ # redraw pdcTmp if needed
+ #
+ if len(self.polycoords) > 0:
+ self.DrawLines(self.pdcTmp)
+
+ if not self.parent.IsStandalone() and \
+ self.parent.GetLayerManager().georectifying:
+ # -> georectifier (redraw GCPs)
+ if self.parent.toolbars['georect']:
+ coordtype = 'gcpcoord'
+ else:
+ coordtype = 'mapcoord'
+ self.parent.GetLayerManager().georectifying.DrawGCP(coordtype)
+
+ #
+ # clear measurement
+ #
+ if self.mouse["use"] == "measure":
+ self.ClearLines(pdc=self.pdcTmp)
+ self.polycoords = []
+ self.mouse['use'] = 'pointer'
+ self.mouse['box'] = 'point'
+ self.mouse['end'] = [0, 0]
+ self.SetCursor(self.parent.cursors["default"])
+
+ stop = time.clock()
+
+ #
+ # hide process bar
+ #
+ self.parent.statusbarWin['progress'].Hide()
+
+ #
+ # update statusbar
+ #
+ ### self.Map.SetRegion()
+ self.parent.StatusbarUpdate()
+ if grass.find_file(name = 'MASK', element = 'cell')['name']:
+ # mask found
+ self.parent.statusbarWin['mask'].SetLabel(_('MASK'))
+ else:
+ self.parent.statusbarWin['mask'].SetLabel('')
+
+ Debug.msg (2, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
+ (render, renderVector, (stop-start)))
+
+ return True
+
+ def DrawCompRegionExtent(self):
+ """!
+ Draw computational region extent in the display
+
+ Display region is drawn as a blue box inside the computational region,
+ computational region inside a display region as a red box).
+ """
+ if hasattr(self, "regionCoords"):
+ compReg = self.Map.GetRegion()
+ dispReg = self.Map.GetCurrentRegion()
+ reg = None
+ if self.IsInRegion(dispReg, compReg):
+ self.polypen = wx.Pen(colour=wx.Colour(0, 0, 255, 128), width=3, style=wx.SOLID)
+ reg = dispReg
+ else:
+ self.polypen = wx.Pen(colour=wx.Colour(255, 0, 0, 128),
+ width=3, style=wx.SOLID)
+ reg = compReg
+
+ self.regionCoords = []
+ self.regionCoords.append((reg['w'], reg['n']))
+ self.regionCoords.append((reg['e'], reg['n']))
+ self.regionCoords.append((reg['e'], reg['s']))
+ self.regionCoords.append((reg['w'], reg['s']))
+ self.regionCoords.append((reg['w'], reg['n']))
+ # draw region extent
+ self.DrawLines(pdc=self.pdcDec, polycoords=self.regionCoords)
+
+ def IsInRegion(self, region, refRegion):
+ """!
+ Test if 'region' is inside of 'refRegion'
+
+ @param region input region
+ @param refRegion reference region (e.g. computational region)
+
+ @return True if region is inside of refRegion
+ @return False
+ """
+ if region['s'] >= refRegion['s'] and \
+ region['n'] <= refRegion['n'] and \
+ region['w'] >= refRegion['w'] and \
+ region['e'] <= refRegion['e']:
+ return True
+
+ return False
+
+ def EraseMap(self):
+ """!
+ Erase the canvas
+ """
+ self.Draw(self.pdc, pdctype='clear')
+
+ if self.pdcVector:
+ self.Draw(self.pdcVector, pdctype='clear')
+
+ self.Draw(self.pdcDec, pdctype='clear')
+ self.Draw(self.pdcTmp, pdctype='clear')
+
+ def DragMap(self, moveto):
+ """!
+ Drag the entire map image for panning.
+ """
+
+ dc = wx.BufferedDC(wx.ClientDC(self))
+ dc.SetBackground(wx.Brush("White"))
+ dc.Clear()
+
+ self.dragimg = wx.DragImage(self.buffer)
+ self.dragimg.BeginDrag((0, 0), self)
+ self.dragimg.GetImageRect(moveto)
+ self.dragimg.Move(moveto)
+
+ self.dragimg.DoDrawImage(dc, moveto)
+ self.dragimg.EndDrag()
+
+ return True
+
+ def DragItem(self, id, event):
+ """!
+ Drag an overlay decoration item
+ """
+ if id == 99 or id == '' or id == None: return
+ Debug.msg (5, "BufferedWindow.DragItem(): id=%d" % id)
+ x, y = self.lastpos
+ dx = event.GetX() - x
+ dy = event.GetY() - y
+ self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ r = self.pdc.GetIdBounds(id)
+ ### FIXME in vdigit/pseudodc.i
+ if type(r) is list:
+ r = wx.Rect(r[0], r[1], r[2], r[3])
+ if id > 100: # text dragging
+ rtop = (r[0],r[1]-r[3],r[2],r[3])
+ r = r.Union(rtop)
+ rleft = (r[0]-r[2],r[1],r[2],r[3])
+ r = r.Union(rleft)
+ self.pdc.TranslateId(id, dx, dy)
+
+ r2 = self.pdc.GetIdBounds(id)
+ if type(r2) is list:
+ r2 = wx.Rect(r[0], r[1], r[2], r[3])
+ if id > 100: # text
+ self.textdict[id]['coords'] = r2
+ r = r.Union(r2)
+ r.Inflate(4,4)
+ self.RefreshRect(r, False)
+ self.lastpos = (event.GetX(), event.GetY())
+
+ def MouseDraw(self, pdc=None, begin=None, end=None):
+ """!
+ Mouse box or line from 'begin' to 'end'
+
+ If not given from self.mouse['begin'] to self.mouse['end'].
+
+ """
+ self.redrawAll = False
+
+ if not pdc:
+ return
+
+ if begin is None:
+ begin = self.mouse['begin']
+ if end is None:
+ end = self.mouse['end']
+
+ Debug.msg (5, "BufferedWindow.MouseDraw(): use=%s, box=%s, begin=%f,%f, end=%f,%f" % \
+ (self.mouse['use'], self.mouse['box'],
+ begin[0], begin[1], end[0], end[1]))
+
+ if self.mouse['box'] == "box":
+ boxid = wx.ID_NEW
+ mousecoords = [begin[0], begin[1],
+ end[0], end[1]]
+ r = pdc.GetIdBounds(boxid)
+ if type(r) is list:
+ r = wx.Rect(r[0], r[1], r[2], r[3])
+ r.Inflate(4, 4)
+ try:
+ pdc.ClearId(boxid)
+ except:
+ pass
+ self.RefreshRect(r, False)
+ pdc.SetId(boxid)
+ self.Draw(pdc, drawid=boxid, pdctype='box', coords=mousecoords)
+ elif self.mouse['box'] == "line" or self.mouse['box'] == 'point':
+ self.lineid = wx.ID_NEW
+ mousecoords = [begin[0], begin[1], \
+ end[0], end[1]]
+ x1=min(begin[0],end[0])
+ x2=max(begin[0],end[0])
+ y1=min(begin[1],end[1])
+ y2=max(begin[1],end[1])
+ r = wx.Rect(x1,y1,x2-x1,y2-y1)
+ r.Inflate(4,4)
+ try:
+ pdc.ClearId(self.lineid)
+ except:
+ pass
+ self.RefreshRect(r, False)
+ pdc.SetId(self.lineid)
+ self.Draw(pdc, drawid=self.lineid, pdctype='line', coords=mousecoords)
+
+ def DrawLines(self, pdc=None, polycoords=None):
+ """!
+ Draw polyline in PseudoDC
+
+ Set self.pline to wx.NEW_ID + 1
+
+ polycoords - list of polyline vertices, geographical coordinates
+ (if not given, self.polycoords is used)
+
+ """
+ if not pdc:
+ pdc = self.pdcTmp
+
+ if not polycoords:
+ polycoords = self.polycoords
+
+ if len(polycoords) > 0:
+ self.plineid = wx.ID_NEW + 1
+ # convert from EN to XY
+ coords = []
+ for p in polycoords:
+ coords.append(self.Cell2Pixel(p))
+
+ self.Draw(pdc, drawid=self.plineid, pdctype='polyline', coords=coords)
+
+ Debug.msg (4, "BufferedWindow.DrawLines(): coords=%s, id=%s" % \
+ (coords, self.plineid))
+
+ return self.plineid
+
+ return -1
+
+ def DrawCross(self, pdc, coords, size, rotation=0,
+ text=None, textAlign='lr', textOffset=(5, 5)):
+ """!Draw cross in PseudoDC
+
+ @todo implement rotation
+
+ @param pdc PseudoDC
+ @param coord center coordinates
+ @param rotation rotate symbol
+ @param text draw also text (text, font, color, rotation)
+ @param textAlign alignment (default 'lower-right')
+ @textOffset offset for text (from center point)
+ """
+ Debug.msg(4, "BufferedWindow.DrawCross(): pdc=%s, coords=%s, size=%d" % \
+ (pdc, coords, size))
+ coordsCross = ((coords[0] - size, coords[1], coords[0] + size, coords[1]),
+ (coords[0], coords[1] - size, coords[0], coords[1] + size))
+
+ self.lineid = wx.NewId()
+ for lineCoords in coordsCross:
+ self.Draw(pdc, drawid=self.lineid, pdctype='line', coords=lineCoords)
+
+ if not text:
+ return self.lineid
+
+ if textAlign == 'ul':
+ coord = [coords[0] - textOffset[0], coords[1] - textOffset[1], 0, 0]
+ elif textAlign == 'ur':
+ coord = [coords[0] + textOffset[0], coords[1] - textOffset[1], 0, 0]
+ elif textAlign == 'lr':
+ coord = [coords[0] + textOffset[0], coords[1] + textOffset[1], 0, 0]
+ else:
+ coord = [coords[0] - textOffset[0], coords[1] + textOffset[1], 0, 0]
+
+ self.Draw(pdc, img=text,
+ pdctype='text', coords=coord)
+
+ return self.lineid
+
+ def MouseActions(self, event):
+ """!
+ Mouse motion and button click notifier
+ """
+ if not self.processMouse:
+ return
+
+ ### if self.redrawAll is False:
+ ### self.redrawAll = True
+
+ # zoom with mouse wheel
+ if event.GetWheelRotation() != 0:
+ self.OnMouseWheel(event)
+
+ # left mouse button pressed
+ elif event.LeftDown():
+ self.OnLeftDown(event)
+
+ # left mouse button released
+ elif event.LeftUp():
+ self.OnLeftUp(event)
+
+ # dragging
+ elif event.Dragging():
+ self.OnDragging(event)
+
+ # double click
+ elif event.ButtonDClick():
+ self.OnButtonDClick(event)
+
+ # middle mouse button pressed
+ elif event.MiddleDown():
+ self.OnMiddleDown(event)
+
+ # right mouse button pressed
+ elif event.RightDown():
+ self.OnRightDown(event)
+
+ # right mouse button released
+ elif event.RightUp():
+ self.OnRightUp(event)
+
+ elif event.Moving():
+ self.OnMouseMoving(event)
+
+# event.Skip()
+
+ def OnMouseWheel(self, event):
+ """!
+ Mouse wheel moved
+ """
+ self.processMouse = False
+ current = event.GetPositionTuple()[:]
+ wheel = event.GetWheelRotation()
+ Debug.msg (5, "BufferedWindow.MouseAction(): wheel=%d" % wheel)
+ # zoom 1/2 of the screen, centered to current mouse position (TODO: settings)
+ begin = (current[0] - self.Map.width / 4,
+ current[1] - self.Map.height / 4)
+ end = (current[0] + self.Map.width / 4,
+ current[1] + self.Map.height / 4)
+
+ if wheel > 0:
+ zoomtype = 1
+ else:
+ zoomtype = -1
+
+ # zoom
+ self.Zoom(begin, end, zoomtype)
+
+ # redraw map
+ self.UpdateMap()
+
+ ### self.OnPaint(None)
+
+ # update statusbar
+ self.parent.StatusbarUpdate()
+
+ self.Refresh()
+ self.processMouse = True
+# event.Skip()
+
+ def OnDragging(self, event):
+ """!
+ Mouse dragging with left button down
+ """
+ Debug.msg (5, "BufferedWindow.MouseAction(): Dragging")
+ current = event.GetPositionTuple()[:]
+ previous = self.mouse['begin']
+ move = (current[0] - previous[0],
+ current[1] - previous[1])
+
+ digitToolbar = self.parent.toolbars['vdigit']
+
+ # dragging or drawing box with left button
+ if self.mouse['use'] == 'pan':
+ self.DragMap(move)
+
+ # dragging decoration overlay item
+ elif (self.mouse['use'] == 'pointer' and
+ not digitToolbar and
+ self.dragid != None):
+ self.DragItem(self.dragid, event)
+
+ # dragging anything else - rubber band box or line
+ else:
+ if (self.mouse['use'] == 'pointer' and
+ not digitToolbar): return
+ self.mouse['end'] = event.GetPositionTuple()[:]
+ digitClass = self.parent.digit
+ if (event.LeftIsDown() and
+ not (digitToolbar and
+ digitToolbar.GetAction() in ("moveLine",) and
+ digitClass.driver.GetSelected() > 0)):
+ # draw box only when left mouse button is pressed
+ self.MouseDraw(pdc=self.pdcTmp)
+
+# event.Skip()
+
+ def OnLeftDownVDigitAddLine(self, event):
+ """!
+ Left mouse button down - vector digitizer add new line
+ action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ try:
+ mapLayer = digitToolbar.GetLayer().GetName()
+ except:
+ return
+
+ if digitToolbar.GetAction('type') in ["point", "centroid"]:
+ # add new point
+ if digitToolbar.GetAction('type') == 'point':
+ point = True
+ else:
+ point = False
+
+ east, north = self.Pixel2Cell(self.mouse['begin'])
+ fid = digitClass.AddPoint(mapLayer, point, east, north)
+ if fid < 0:
+ return
+
+ self.UpdateMap(render=False) # redraw map
+
+ # add new record into atribute table
+ if UserSettings.Get(group='vdigit', key="addRecord", subkey='enabled') is True:
+ # select attributes based on layer and category
+ cats = { fid : {
+ UserSettings.Get(group='vdigit', key="layer", subkey='value') :
+ (UserSettings.Get(group='vdigit', key="category", subkey='value'), )
+ }}
+
+ posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+ self.mouse['end'][1] + self.dialogOffset))
+
+ addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent=self, map=mapLayer,
+ cats=cats,
+ pos=posWindow,
+ action="add")
+
+ if not point:
+ self.__geomAttrb(fid, addRecordDlg, 'area', digitClass,
+ digitToolbar.GetLayer())
+ self.__geomAttrb(fid, addRecordDlg, 'perimeter', digitClass,
+ digitToolbar.GetLayer())
+
+ if addRecordDlg.mapDBInfo and \
+ addRecordDlg.ShowModal() == wx.ID_OK:
+ sqlfile = tempfile.NamedTemporaryFile(mode="w")
+ for sql in addRecordDlg.GetSQLString():
+ sqlfile.file.write(sql + ";\n")
+ sqlfile.file.flush()
+
+ gcmd.RunCommand('db.execute',
+ parent = self,
+ quiet = True,
+ input = sqlfile.name)
+
+ if addRecordDlg.mapDBInfo:
+ self.__updateATM()
+
+ elif digitToolbar.GetAction('type') in ["line", "boundary"]:
+ # add new point to the line
+ self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+ self.DrawLines(pdc=self.pdcTmp)
+
+ def __geomAttrb(self, fid, dialog, attrb, digit, mapLayer):
+ """!Trac geometry attributes?"""
+ item = self.tree.FindItemByData('maplayer', mapLayer)
+ vdigit = self.tree.GetPyData(item)[0]['vdigit']
+ if vdigit and \
+ vdigit.has_key('geomAttr') and \
+ vdigit['geomAttr'].has_key(attrb):
+ val = -1
+ if attrb == 'length':
+ val = digit.GetLineLength(fid)
+ type = attrb
+ elif attrb == 'area':
+ val = digit.GetAreaSize(fid)
+ type = attrb
+ elif attrb == 'perimeter':
+ val = digit.GetAreaPerimeter(fid)
+ type = 'length'
+
+ if val > 0:
+ layer = int(UserSettings.Get(group='vdigit', key="layer", subkey='value'))
+ column = vdigit['geomAttr'][attrb]['column']
+ val = UnitsConvertValue(val, type, vdigit['geomAttr'][attrb]['units'])
+ dialog.SetColumnValue(layer, column, val)
+ dialog.OnReset()
+
+ def __geomAttrbUpdate(self, fids):
+ """!Update geometry atrributes of currently selected features
+
+ @param fid list feature id
+ """
+ mapLayer = self.parent.toolbars['vdigit'].GetLayer()
+ vectorName = mapLayer.GetName()
+ digit = self.parent.digit
+ item = self.tree.FindItemByData('maplayer', mapLayer)
+ vdigit = self.tree.GetPyData(item)[0]['vdigit']
+
+ if vdigit is None or not vdigit.has_key('geomAttr'):
+ return
+
+ dbInfo = gselect.VectorDBInfo(vectorName)
+ sqlfile = tempfile.NamedTemporaryFile(mode="w")
+ for fid in fids:
+ for layer, cats in digit.GetLineCats(fid).iteritems():
+ table = dbInfo.GetTable(layer)
+ for attrb, item in vdigit['geomAttr'].iteritems():
+ val = -1
+ if attrb == 'length':
+ val = digit.GetLineLength(fid)
+ type = attrb
+ elif attrb == 'area':
+ val = digit.GetAreaSize(fid)
+ type = attrb
+ elif attrb == 'perimeter':
+ val = digit.GetAreaPerimeter(fid)
+ type = 'length'
+
+ if val < 0:
+ continue
+ val = UnitsConvertValue(val, type, item['units'])
+
+ for cat in cats:
+ sqlfile.write('UPDATE %s SET %s = %f WHERE %s = %d;\n' % \
+ (table, item['column'], val,
+ dbInfo.GetKeyColumn(layer), cat))
+ sqlfile.file.flush()
+ gcmd.RunCommand('db.execute',
+ parent = True,
+ quiet = True,
+ input = sqlfile.name)
+
+ def __updateATM(self):
+ """!Update open Attribute Table Manager
+
+ @todo: use AddDataRow() instead
+ """
+ # update ATM
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitVector = digitToolbar.GetLayer().GetName()
+
+ for atm in self.lmgr.dialogs['atm']:
+ atmVector = atm.GetVectorName()
+ if atmVector == digitVector:
+ layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
+ # TODO: use AddDataRow instead
+ atm.LoadData(layer)
+
+ def OnLeftDownVDigitEditLine(self, event):
+ """!
+ Left mouse button down - vector digitizer edit linear feature
+ - add new vertex.
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ self.polycoords.append(self.Pixel2Cell(self.mouse['begin']))
+ self.vdigitMove['id'].append(wx.NewId())
+ self.DrawLines(pdc=self.pdcTmp)
+
+ def OnLeftDownVDigitMoveLine(self, event):
+ """!
+ Left mouse button down - vector digitizer move feature/vertex,
+ edit linear feature
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ self.vdigitMove = {}
+ # geographic coordinates of initial position (left-down)
+ self.vdigitMove['begin'] = None
+ # list of ids to modify
+ self.vdigitMove['id'] = []
+ # ids geographic coordinates
+ self.vdigitMove['coord'] = {}
+
+ if digitToolbar.GetAction() in ["moveVertex", "editLine"]:
+ # set pen
+ pcolor = UserSettings.Get(group='vdigit', key="symbol",
+ subkey=["highlight", "color"])
+ self.pen = self.polypen = wx.Pen(colour=pcolor,
+ width=2, style=wx.SHORT_DASH)
+ self.pdcTmp.SetPen(self.polypen)
+
+ def OnLeftDownVDigitDisplayCA(self, event):
+ """!
+ Left mouse button down - vector digitizer display categories
+ or attributes action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ try:
+ mapLayer = digitToolbar.GetLayer().GetName()
+ except:
+ return
+
+ coords = self.Pixel2Cell(self.mouse['begin'])
+
+ # unselect
+ digitClass.driver.SetSelected([])
+
+ # select feature by point
+ cats = {}
+ if digitClass.driver.SelectLineByPoint(coords,
+ digitClass.GetSelectType()) is None:
+ return
+
+ if UserSettings.Get(group='vdigit', key='checkForDupl',
+ subkey='enabled'):
+ lines = digitClass.driver.GetSelected()
+ else:
+ lines = (digitClass.driver.GetSelected()[0],) # only first found
+
+ for line in lines:
+ cats[line] = digitClass.GetLineCats(line)
+
+ posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+ self.mouse['end'][1] + self.dialogOffset))
+
+ if digitToolbar.GetAction() == "displayAttrs":
+ # select attributes based on coordinates (all layers)
+ if self.parent.dialogs['attributes'] is None:
+ self.parent.dialogs['attributes'] = \
+ dbm_dialogs.DisplayAttributesDialog(parent=self, map=mapLayer,
+ cats=cats,
+ action="update")
+ else:
+ # upgrade dialog
+ self.parent.dialogs['attributes'].UpdateDialog(cats=cats)
+
+ if self.parent.dialogs['attributes']:
+ if len(cats.keys()) > 0:
+ # highlight feature & re-draw map
+ if not self.parent.dialogs['attributes'].IsShown():
+ self.parent.dialogs['attributes'].Show()
+ else:
+ if self.parent.dialogs['attributes'] and \
+ self.parent.dialogs['attributes'].IsShown():
+ self.parent.dialogs['attributes'].Hide()
+
+ else: # displayCats
+ if self.parent.dialogs['category'] is None:
+ # open new dialog
+ dlg = VDigitCategoryDialog(parent=self,
+ map=mapLayer,
+ cats=cats,
+ pos=posWindow,
+ title=_("Update categories"))
+ self.parent.dialogs['category'] = dlg
+ else:
+ # update currently open dialog
+ self.parent.dialogs['category'].UpdateDialog(cats=cats)
+
+ if self.parent.dialogs['category']:
+ if len(cats.keys()) > 0:
+ # highlight feature & re-draw map
+ if not self.parent.dialogs['category'].IsShown():
+ self.parent.dialogs['category'].Show()
+ else:
+ if self.parent.dialogs['category'].IsShown():
+ self.parent.dialogs['category'].Hide()
+
+ self.UpdateMap(render=False)
+
+ def OnLeftDownVDigitCopyCA(self, event):
+ """!
+ Left mouse button down - vector digitizer copy categories
+ or attributes action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ if not hasattr(self, "copyCatsList"):
+ self.copyCatsList = []
+ else:
+ self.copyCatsIds = []
+ self.mouse['box'] = 'box'
+
+ def OnLeftDownVDigitCopyLine(self, event):
+ """!
+ Left mouse button down - vector digitizer copy lines action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ if not hasattr(self, "copyIds"):
+ self.copyIds = []
+ self.layerTmp = None
+
+ def OnLeftDownVDigitBulkLine(self, event):
+ """!
+ Left mouse button down - vector digitizer label 3d vector
+ lines
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ if len(self.polycoords) > 1: # start new line
+ self.polycoords = []
+ self.ClearLines(pdc=self.pdcTmp)
+ self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+ if len(self.polycoords) == 1:
+ begin = self.Pixel2Cell(self.polycoords[-1])
+ end = self.Pixel2Cell(self.mouse['end'])
+ else:
+ end = self.Pixel2Cell(self.polycoords[-1])
+ begin = self.Pixel2Cell(self.mouse['begin'])
+
+ self.DrawLines(self.pdcTmp, polycoords = (begin, end))
+
+ def OnLeftDown(self, event):
+ """!
+ Left mouse button pressed
+ """
+ Debug.msg (5, "BufferedWindow.OnLeftDown(): use=%s" % \
+ self.mouse["use"])
+
+ self.mouse['begin'] = event.GetPositionTuple()[:]
+
+ if self.mouse["use"] in ["measure", "profile"]:
+ # measure or profile
+ if len(self.polycoords) == 0:
+ self.mouse['end'] = self.mouse['begin']
+ self.polycoords.append(self.Pixel2Cell(self.mouse['begin']))
+ self.ClearLines(pdc=self.pdcTmp)
+ else:
+ self.mouse['begin'] = self.mouse['end']
+ elif self.mouse['use'] == 'zoom':
+ pass
+
+ #
+ # vector digizer
+ #
+ elif self.mouse["use"] == "pointer" and \
+ self.parent.toolbars['vdigit']:
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ try:
+ mapLayer = digitToolbar.GetLayer().GetName()
+ except:
+ wx.MessageBox(parent=self,
+ message=_("No vector map selected for editing."),
+ caption=_("Vector digitizer"),
+ style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+ event.Skip()
+ return
+
+ if digitToolbar.GetAction() not in ("moveVertex",
+ "addVertex",
+ "removeVertex",
+ "editLine"):
+ # set pen
+ self.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
+ self.polypen = wx.Pen(colour='dark green', width=2, style=wx.SOLID)
+
+ if digitToolbar.GetAction() in ("addVertex",
+ "removeVertex",
+ "splitLines"):
+ # unselect
+ digitClass.driver.SetSelected([])
+
+ if digitToolbar.GetAction() == "addLine":
+ self.OnLeftDownVDigitAddLine(event)
+
+ elif digitToolbar.GetAction() == "editLine" and \
+ hasattr(self, "vdigitMove"):
+ self.OnLeftDownVDigitEditLine(event)
+
+ elif digitToolbar.GetAction() in ("moveLine",
+ "moveVertex",
+ "editLine") and \
+ not hasattr(self, "vdigitMove"):
+ self.OnLeftDownVDigitMoveLine(event)
+
+ elif digitToolbar.GetAction() in ("displayAttrs"
+ "displayCats"):
+ self.OnLeftDownVDigitDisplayCA(event)
+
+ elif digitToolbar.GetAction() in ("copyCats",
+ "copyAttrs"):
+ self.OnLeftDownVDigitCopyCA(event)
+
+ elif digitToolbar.GetAction() == "copyLine":
+ self.OnLeftDownVDigitCopyLine(event)
+
+ elif digitToolbar.GetAction() == "zbulkLine":
+ self.OnLeftDownVDigitBulkLine(event)
+
+ elif self.mouse['use'] == 'pointer':
+ # get decoration or text id
+ self.idlist = []
+ self.dragid = ''
+ self.lastpos = self.mouse['begin']
+ idlist = self.pdc.FindObjects(self.lastpos[0], self.lastpos[1],
+ self.hitradius)
+ if 99 in idlist:
+ idlist.remove(99)
+ if idlist != []:
+ self.dragid = idlist[0] #drag whatever is on top
+ else:
+ pass
+
+ event.Skip()
+
+ def OnLeftUpVDigitVarious(self, event):
+ """!
+ Left mouse button up - vector digitizer various actions
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ pos1 = self.Pixel2Cell(self.mouse['begin'])
+ pos2 = self.Pixel2Cell(self.mouse['end'])
+
+ nselected = 0
+ # -> delete line || move line || move vertex
+ if digitToolbar.GetAction() in ("moveVertex",
+ "editLine"):
+ if len(digitClass.driver.GetSelected()) == 0:
+ nselected = digitClass.driver.SelectLineByPoint(pos1, type=VDigit_Lines_Type)
+
+ if digitToolbar.GetAction() == "editLine":
+ try:
+ selVertex = digitClass.driver.GetSelectedVertex(pos1)[0]
+ except IndexError:
+ selVertex = None
+
+ if selVertex:
+ # self.UpdateMap(render=False)
+ ids = digitClass.driver.GetSelected(grassId=False)
+ # move this line to tmp layer
+ self.polycoords = []
+ for id in ids:
+ if id % 2: # register only vertices
+ e, n = self.Pixel2Cell(self.pdcVector.GetIdBounds(id)[0:2])
+ self.polycoords.append((e, n))
+ digitClass.driver.DrawSelected(False)
+
+ if selVertex < ids[-1] / 2:
+ # choose first or last node of line
+ self.vdigitMove['id'].reverse()
+ self.polycoords.reverse()
+ else:
+ # unselect
+ digitClass.driver.SetSelected([])
+ del self.vdigitMove
+
+ self.UpdateMap(render=False)
+
+ elif digitToolbar.GetAction() in ("copyCats",
+ "copyAttrs"):
+ if not hasattr(self, "copyCatsIds"):
+ # 'from' -> select by point
+ nselected = digitClass.driver.SelectLineByPoint(pos1, digitClass.GetSelectType())
+ if nselected:
+ self.copyCatsList = digitClass.driver.GetSelected()
+ else:
+ # -> 'to' -> select by bbox
+ digitClass.driver.SetSelected([])
+ # return number of selected features (by box/point)
+ nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+ digitClass.GetSelectType())
+ if nselected == 0:
+ if digitClass.driver.SelectLineByPoint(pos1,
+ digitClass.GetSelectType()) is not None:
+ nselected = 1
+
+ if nselected > 0:
+ self.copyCatsIds = digitClass.driver.GetSelected()
+
+ elif digitToolbar.GetAction() == "queryLine":
+ selected = digitClass.SelectLinesByQuery(pos1, pos2)
+ nselected = len(selected)
+ if nselected > 0:
+ digitClass.driver.SetSelected(selected)
+
+ else:
+ # -> moveLine || deleteLine, etc. (select by point/box)
+ if digitToolbar.GetAction() == 'moveLine' and \
+ len(digitClass.driver.GetSelected()) > 0:
+ nselected = 0
+ else:
+ if digitToolbar.GetAction() == 'moveLine':
+ drawSeg = True
+ else:
+ drawSeg = False
+
+ nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+ digitClass.GetSelectType(),
+ drawSeg)
+
+ if nselected == 0:
+ if digitClass.driver.SelectLineByPoint(pos1,
+ digitClass.GetSelectType()) is not None:
+ nselected = 1
+
+ if nselected > 0:
+ if digitToolbar.GetAction() in ("moveLine",
+ "moveVertex"):
+ # get pseudoDC id of objects which should be redrawn
+ if digitToolbar.GetAction() == "moveLine":
+ # -> move line
+ self.vdigitMove['id'] = digitClass.driver.GetSelected(grassId=False)
+ self.vdigitMove['coord'] = digitClass.driver.GetSelectedCoord()
+ else: # moveVertex
+ self.vdigitMove['id'] = digitClass.driver.GetSelectedVertex(pos1)
+ if len(self.vdigitMove['id']) == 0: # no vertex found
+ digitClass.driver.SetSelected([])
+
+ #
+ # check for duplicates
+ #
+ if UserSettings.Get(group='vdigit', key='checkForDupl', subkey='enabled') is True:
+ dupl = digitClass.driver.GetDuplicates()
+ self.UpdateMap(render=False)
+
+ if dupl:
+ posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+ self.mouse['end'][1] + self.dialogOffset))
+
+ dlg = VDigitDuplicatesDialog(parent=self, data=dupl, pos=posWindow)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ digitClass.driver.UnSelect(dlg.GetUnSelected())
+ # update selected
+ self.UpdateMap(render=False)
+
+ if digitToolbar.GetAction() != "editLine":
+ # -> move line || move vertex
+ self.UpdateMap(render=False)
+
+ else: # no vector object found
+ if not (digitToolbar.GetAction() in ("moveLine",
+ "moveVertex") and \
+ len(self.vdigitMove['id']) > 0):
+ # avoid left-click when features are already selected
+ self.UpdateMap(render=False, renderVector=False)
+
+ def OnLeftUpVDigitModifyLine(self, event):
+ """!
+ Left mouse button up - vector digitizer split line, add/remove
+ vertex action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ pos1 = self.Pixel2Cell(self.mouse['begin'])
+
+ pointOnLine = digitClass.driver.SelectLineByPoint(pos1,
+ type=VDigit_Lines_Type)
+
+ if not pointOnLine:
+ return
+
+ if digitToolbar.GetAction() in ["splitLine", "addVertex"]:
+ self.UpdateMap(render=False) # highlight object
+ self.DrawCross(pdc=self.pdcTmp, coords=self.Cell2Pixel(pointOnLine),
+ size=5)
+ else: # removeVertex
+ # get only id of vertex
+ try:
+ id = digitClass.driver.GetSelectedVertex(pos1)[0]
+ except IndexError:
+ id = None
+
+ if id:
+ x, y = self.pdcVector.GetIdBounds(id)[0:2]
+ self.pdcVector.RemoveId(id)
+ self.UpdateMap(render=False) # highlight object
+ self.DrawCross(pdc=self.pdcTmp, coords=(x, y),
+ size=5)
+ else:
+ # unselect
+ digitClass.driver.SetSelected([])
+ self.UpdateMap(render=False)
+
+ def OnLeftUpVDigitCopyLine(self, event):
+ """!
+ Left mouse button up - vector digitizer copy feature action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ pos1 = self.Pixel2Cell(self.mouse['begin'])
+ pos2 = self.Pixel2Cell(self.mouse['end'])
+
+ if UserSettings.Get(group='vdigit', key='bgmap',
+ subkey='value', internal=True) == '':
+ # no background map -> copy from current vector map layer
+ nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+ digitClass.GetSelectType())
+
+ if nselected > 0:
+ # highlight selected features
+ self.UpdateMap(render=False)
+ else:
+ self.UpdateMap(render=False, renderVector=False)
+ else:
+ # copy features from background map
+ self.copyIds += digitClass.SelectLinesFromBackgroundMap(pos1, pos2)
+ if len(self.copyIds) > 0:
+ color = UserSettings.Get(group='vdigit', key='symbol',
+ subkey=['highlight', 'color'])
+ colorStr = str(color[0]) + ":" + \
+ str(color[1]) + ":" + \
+ str(color[2])
+ dVectTmp = ['d.vect',
+ 'map=%s' % UserSettings.Get(group='vdigit', key='bgmap',
+ subkey='value', internal=True),
+ 'cats=%s' % utils.ListOfCatsToRange(self.copyIds),
+ '-i',
+ 'color=%s' % colorStr,
+ 'fcolor=%s' % colorStr,
+ 'type=point,line,boundary,centroid',
+ 'width=2']
+
+ if not self.layerTmp:
+ self.layerTmp = self.Map.AddLayer(type='vector',
+ name=globalvar.QUERYLAYER,
+ command=dVectTmp)
+ else:
+ self.layerTmp.SetCmd(dVectTmp)
+
+ self.UpdateMap(render=True, renderVector=False)
+ else:
+ self.UpdateMap(render=False, renderVector=False)
+
+ self.redrawAll = None
+
+ def OnLeftUpVDigitBulkLine(self, event):
+ """!
+ Left mouse button up - vector digitizer z-bulk line action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ # select lines to be labeled
+ pos1 = self.polycoords[0]
+ pos2 = self.polycoords[1]
+ nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
+ digitClass.GetSelectType())
+
+ if nselected > 0:
+ # highlight selected features
+ self.UpdateMap(render=False)
+ self.DrawLines(pdc=self.pdcTmp) # redraw temp line
+ else:
+ self.UpdateMap(render=False, renderVector=False)
+
+ def OnLeftUpVDigitConnectLine(self, event):
+ """!
+ Left mouse button up - vector digitizer connect line action
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ if len(digitClass.driver.GetSelected()) > 0:
+ self.UpdateMap(render=False)
+
+ def OnLeftUp(self, event):
+ """!
+ Left mouse button released
+ """
+ Debug.msg (5, "BufferedWindow.OnLeftUp(): use=%s" % \
+ self.mouse["use"])
+
+ self.mouse['end'] = event.GetPositionTuple()[:]
+
+ if self.mouse['use'] in ["zoom", "pan"]:
+ # set region in zoom or pan
+ begin = self.mouse['begin']
+ end = self.mouse['end']
+ if self.mouse['use'] == 'zoom':
+ # set region for click (zero-width box)
+ if begin[0] - end[0] == 0 or \
+ begin[1] - end[1] == 0:
+ # zoom 1/2 of the screen (TODO: settings)
+ begin = (end[0] - self.Map.width / 4,
+ end[1] - self.Map.height / 4)
+ end = (end[0] + self.Map.width / 4,
+ end[1] + self.Map.height / 4)
+
+ self.Zoom(begin, end, self.zoomtype)
+
+ # redraw map
+ self.UpdateMap(render=True)
+
+ # update statusbar
+ self.parent.StatusbarUpdate()
+
+ elif self.mouse["use"] == "query":
+ # querying
+ self.parent.QueryMap(self.mouse['begin'][0],self.mouse['begin'][1])
+
+ elif self.mouse["use"] == "queryVector":
+ # editable mode for vector map layers
+ self.parent.QueryVector(self.mouse['begin'][0], self.mouse['begin'][1])
+
+ # clear temp canvas
+ self.UpdateMap(render=False, renderVector=False)
+
+ elif self.mouse["use"] in ["measure", "profile"]:
+ # measure or profile
+ if self.mouse["use"] == "measure":
+ self.parent.MeasureDist(self.mouse['begin'], self.mouse['end'])
+
+ self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
+ self.ClearLines(pdc=self.pdcTmp)
+ self.DrawLines(pdc=self.pdcTmp)
+
+ elif self.mouse["use"] == "pointer" and \
+ self.parent.GetLayerManager().georectifying:
+ # -> georectifying
+ coord = self.Pixel2Cell(self.mouse['end'])
+ if self.parent.toolbars['georect']:
+ coordtype = 'gcpcoord'
+ else:
+ coordtype = 'mapcoord'
+
+ self.parent.GetLayerManager().georectifying.SetGCPData(coordtype, coord, self)
+ self.UpdateMap(render=False, renderVector=False)
+
+ elif self.mouse["use"] == "pointer" and self.parent.toolbars['vdigit']:
+ # digitization tool active
+ digitToolbar = self.parent.toolbars['vdigit']
+ digitClass = self.parent.digit
+
+ if hasattr(self, "vdigitMove"):
+ if len(digitClass.driver.GetSelected()) == 0:
+ self.vdigitMove['begin'] = self.Pixel2Cell(self.mouse['begin']) # left down
+
+ # eliminate initial mouse moving efect
+ self.mouse['begin'] = self.mouse['end']
+
+ if digitToolbar.GetAction() in ("deleteLine",
+ "moveLine",
+ "moveVertex",
+ "copyCats",
+ "copyAttrs",
+ "editLine",
+ "flipLine",
+ "mergeLine",
+ "snapLine",
+ "queryLine",
+ "breakLine",
+ "typeConv",
+ "connectLine"):
+ self.OnLeftUpVDigitVarious(event)
+
+ elif digitToolbar.GetAction() in ("splitLine",
+ "addVertex",
+ "removeVertex"):
+ self.OnLeftUpVDigitModifyLine(event)
+
+ elif digitToolbar.GetAction() == "copyLine":
+ self.OnLeftUpVDigitCopyLine(event)
+
+ elif digitToolbar.GetAction() == "zbulkLine" and \
+ len(self.polycoords) == 2:
+ self.OnLeftUpVDigitBulkLine(event)
+
+ elif digitToolbar.GetAction() == "connectLine":
+ self.OnLeftUpConnectLine(event)
+
+ if len(digitClass.driver.GetSelected()) > 0:
+ self.redrawAll = None
+
+ elif (self.mouse['use'] == 'pointer' and
+ self.dragid >= 0):
+ # end drag of overlay decoration
+
+ if self.dragid < 99 and self.overlays.has_key(self.dragid):
+ self.overlays[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
+ elif self.dragid > 100 and self.textdict.has_key(self.dragid):
+ self.textdict[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
+ else:
+ pass
+ self.dragid = None
+ self.currtxtid = None
+
+ def OnButtonDClick(self, event):
+ """!
+ Mouse button double click
+ """
+ Debug.msg (5, "BufferedWindow.OnButtonDClick(): use=%s" % \
+ self.mouse["use"])
+
+ if self.mouse["use"] == "measure":
+ # measure
+ self.ClearLines(pdc=self.pdcTmp)
+ self.polycoords = []
+ self.mouse['use'] = 'pointer'
+ self.mouse['box'] = 'point'
+ self.mouse['end'] = [0, 0]
+ self.Refresh()
+ self.SetCursor(self.parent.cursors["default"])
+
+ elif self.mouse["use"] == "profile":
+ pass
+
+ elif self.mouse['use'] == 'pointer' and \
+ self.parent.toolbars['vdigit']:
+ # vector digitizer
+ pass
+
+ else:
+ # select overlay decoration options dialog
+ clickposition = event.GetPositionTuple()[:]
+ idlist = self.pdc.FindObjects(clickposition[0], clickposition[1], self.hitradius)
+ if idlist == []:
+ return
+ self.dragid = idlist[0]
+
+ # self.ovlcoords[self.dragid] = self.pdc.GetIdBounds(self.dragid)
+ if self.dragid > 100:
+ self.currtxtid = self.dragid
+ self.parent.OnAddText(None)
+ elif self.dragid == 0:
+ self.parent.OnAddBarscale(None)
+ elif self.dragid == 1:
+ self.parent.OnAddLegend(None)
+
+ def OnRightDown(self, event):
+ """!
+ Right mouse button pressed
+ """
+ Debug.msg (5, "BufferedWindow.OnRightDown(): use=%s" % \
+ self.mouse["use"])
+
+ digitToolbar = self.parent.toolbars['vdigit']
+ if digitToolbar:
+ digitClass = self.parent.digit
+ # digitization tool (confirm action)
+ if digitToolbar.GetAction() in ("moveLine",
+ "moveVertex") and \
+ hasattr(self, "vdigitMove"):
+
+ pFrom = self.vdigitMove['begin']
+ pTo = self.Pixel2Cell(event.GetPositionTuple())
+
+ move = (pTo[0] - pFrom[0],
+ pTo[1] - pFrom[1])
+
+ if digitToolbar.GetAction() == "moveLine":
+ # move line
+ if digitClass.MoveSelectedLines(move) < 0:
+ return
+ elif digitToolbar.GetAction() == "moveVertex":
+ # move vertex
+ fid = digitClass.MoveSelectedVertex(pFrom, move)
+ if fid < 0:
+ return
+
+ self.__geomAttrbUpdate([fid,])
+
+ del self.vdigitMove
+
+ event.Skip()
+
+ def OnRightUp(self, event):
+ """!
+ Right mouse button released
+ """
+ Debug.msg (5, "BufferedWindow.OnRightUp(): use=%s" % \
+ self.mouse["use"])
+
+ digitToolbar = self.parent.toolbars['vdigit']
+ if digitToolbar:
+ digitClass = self.parent.digit
+ # digitization tool (confirm action)
+ if digitToolbar.GetAction() == "addLine" and \
+ digitToolbar.GetAction('type') in ["line", "boundary"]:
+ # -> add new line / boundary
+ try:
+ map = digitToolbar.GetLayer().GetName()
+ except:
+ map = None
+ wx.MessageBox(parent=self,
+ message=_("No vector map selected for editing."),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+
+ if map:
+ # mapcoords = []
+ # xy -> EN
+ # for coord in self.polycoords:
+ # mapcoords.append(self.Pixel2Cell(coord))
+ if digitToolbar.GetAction('type') == 'line':
+ line = True
+ else:
+ line = False
+
+ if len(self.polycoords) < 2: # ignore 'one-point' lines
+ return
+
+ fid = digitClass.AddLine(map, line, self.polycoords)
+ if fid < 0:
+ return
+
+ position = self.Cell2Pixel(self.polycoords[-1])
+ self.polycoords = []
+ self.UpdateMap(render=False)
+ self.redrawAll = True
+ self.Refresh()
+
+ # add new record into atribute table
+ if UserSettings.Get(group='vdigit', key="addRecord", subkey='enabled') and \
+ (line is True or \
+ (not line and fid > 0)):
+ posWindow = self.ClientToScreen((position[0] + self.dialogOffset,
+ position[1] + self.dialogOffset))
+
+ # select attributes based on layer and category
+ cats = { fid : {
+ UserSettings.Get(group='vdigit', key="layer", subkey='value') :
+ (UserSettings.Get(group='vdigit', key="category", subkey='value'), )
+ }}
+
+ addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent=self, map=map,
+ cats=cats,
+ pos=posWindow,
+ action="add")
+
+ self.__geomAttrb(fid, addRecordDlg, 'length', digitClass,
+ digitToolbar.GetLayer())
+ # auto-placing centroid
+ self.__geomAttrb(fid, addRecordDlg, 'area', digitClass,
+ digitToolbar.GetLayer())
+ self.__geomAttrb(fid, addRecordDlg, 'perimeter', digitClass,
+ digitToolbar.GetLayer())
+
+ if addRecordDlg.mapDBInfo and \
+ addRecordDlg.ShowModal() == wx.ID_OK:
+ sqlfile = tempfile.NamedTemporaryFile(mode="w")
+ for sql in addRecordDlg.GetSQLString():
+ sqlfile.file.write(sql + ";\n")
+ sqlfile.file.flush()
+ gcmd.RunCommand('db.execute',
+ parent = True,
+ quiet = True,
+ input = sqlfile.name)
+
+ if addRecordDlg.mapDBInfo:
+ self.__updateATM()
+
+ elif digitToolbar.GetAction() == "deleteLine":
+ # -> delete selected vector features
+ if digitClass.DeleteSelectedLines() < 0:
+ return
+ self.__updateATM()
+ elif digitToolbar.GetAction() == "splitLine":
+ # split line
+ if digitClass.SplitLine(self.Pixel2Cell(self.mouse['begin'])) < 0:
+ return
+ elif digitToolbar.GetAction() == "addVertex":
+ # add vertex
+ fid = digitClass.AddVertex(self.Pixel2Cell(self.mouse['begin']))
+ if fid < 0:
+ return
+ elif digitToolbar.GetAction() == "removeVertex":
+ # remove vertex
+ fid = digitClass.RemoveVertex(self.Pixel2Cell(self.mouse['begin']))
+ if fid < 0:
+ return
+ self.__geomAttrbUpdate([fid,])
+ elif digitToolbar.GetAction() in ("copyCats", "copyAttrs"):
+ try:
+ if digitToolbar.GetAction() == 'copyCats':
+ if digitClass.CopyCats(self.copyCatsList,
+ self.copyCatsIds, copyAttrb=False) < 0:
+ return
+ else:
+ if digitClass.CopyCats(self.copyCatsList,
+ self.copyCatsIds, copyAttrb=True) < 0:
+ return
+
+ del self.copyCatsList
+ del self.copyCatsIds
+ except AttributeError:
+ pass
+
+ self.__updateATM()
+
+ elif digitToolbar.GetAction() == "editLine" and \
+ hasattr(self, "vdigitMove"):
+ line = digitClass.driver.GetSelected()
+ if digitClass.EditLine(line, self.polycoords) < 0:
+ return
+
+ del self.vdigitMove
+
+ elif digitToolbar.GetAction() == "flipLine":
+ if digitClass.FlipLine() < 0:
+ return
+ elif digitToolbar.GetAction() == "mergeLine":
+ if digitClass.MergeLine() < 0:
+ return
+ elif digitToolbar.GetAction() == "breakLine":
+ if digitClass.BreakLine() < 0:
+ return
+ elif digitToolbar.GetAction() == "snapLine":
+ if digitClass.SnapLine() < 0:
+ return
+ elif digitToolbar.GetAction() == "connectLine":
+ if len(digitClass.driver.GetSelected()) > 1:
+ if digitClass.ConnectLine() < 0:
+ return
+ elif digitToolbar.GetAction() == "copyLine":
+ if digitClass.CopyLine(self.copyIds) < 0:
+ return
+ del self.copyIds
+ if self.layerTmp:
+ self.Map.DeleteLayer(self.layerTmp)
+ self.UpdateMap(render=True, renderVector=False)
+ del self.layerTmp
+
+ elif digitToolbar.GetAction() == "zbulkLine" and len(self.polycoords) == 2:
+ pos1 = self.polycoords[0]
+ pos2 = self.polycoords[1]
+
+ selected = digitClass.driver.GetSelected()
+ dlg = VDigitZBulkDialog(parent=self, title=_("Z bulk-labeling dialog"),
+ nselected=len(selected))
+ if dlg.ShowModal() == wx.ID_OK:
+ if digitClass.ZBulkLines(pos1, pos2, dlg.value.GetValue(),
+ dlg.step.GetValue()) < 0:
+ return
+ self.UpdateMap(render=False, renderVector=True)
+ elif digitToolbar.GetAction() == "typeConv":
+ # -> feature type conversion
+ # - point <-> centroid
+ # - line <-> boundary
+ if digitClass.TypeConvForSelectedLines() < 0:
+ return
+
+ if digitToolbar.GetAction() != "addLine":
+ # unselect and re-render
+ digitClass.driver.SetSelected([])
+ self.polycoords = []
+ self.UpdateMap(render=False)
+
+ self.redrawAll = True
+ self.Refresh()
+
+ event.Skip()
+
+ def OnMiddleDown(self, event):
+ """!
+ Middle mouse button pressed
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ # digitization tool
+ if self.mouse["use"] == "pointer" and digitToolbar:
+ digitClass = self.parent.digit
+ if (digitToolbar.GetAction() == "addLine" and \
+ digitToolbar.GetAction('type') in ["line", "boundary"]) or \
+ digitToolbar.GetAction() == "editLine":
+ # add line or boundary -> remove last point from the line
+ try:
+ removed = self.polycoords.pop()
+ Debug.msg(4, "BufferedWindow.OnMiddleDown(): polycoords_poped=%s" % \
+ [removed,])
+
+ self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1])
+ except:
+ pass
+
+ if digitToolbar.GetAction() == "editLine":
+ # remove last vertex & line
+ if len(self.vdigitMove['id']) > 1:
+ self.vdigitMove['id'].pop()
+
+ self.UpdateMap(render=False, renderVector=False)
+
+ elif digitToolbar.GetAction() in ["deleteLine", "moveLine", "splitLine",
+ "addVertex", "removeVertex", "moveVertex",
+ "copyCats", "flipLine", "mergeLine",
+ "snapLine", "connectLine", "copyLine",
+ "queryLine", "breakLine", "typeConv"]:
+ # varios tools -> unselected selected features
+ digitClass.driver.SetSelected([])
+ if digitToolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] and \
+ hasattr(self, "vdigitMove"):
+
+ del self.vdigitMove
+
+ elif digitToolbar.GetAction() == "copyCats":
+ try:
+ del self.copyCatsList
+ del self.copyCatsIds
+ except AttributeError:
+ pass
+
+ elif digitToolbar.GetAction() == "copyLine":
+ del self.copyIds
+ if self.layerTmp:
+ self.Map.DeleteLayer(self.layerTmp)
+ self.UpdateMap(render=True, renderVector=False)
+ del self.layerTmp
+
+ self.polycoords = []
+ self.UpdateMap(render=False) # render vector
+
+ elif digitToolbar.GetAction() == "zbulkLine":
+ # reset polyline
+ self.polycoords = []
+ digitClass.driver.SetSelected([])
+ self.UpdateMap(render=False)
+
+ self.redrawAll = True
+
+ def OnMouseMoving(self, event):
+ """!
+ Motion event and no mouse buttons were pressed
+ """
+ digitToolbar = self.parent.toolbars['vdigit']
+ if self.mouse["use"] == "pointer" and digitToolbar:
+ digitClass = self.parent.digit
+ self.mouse['end'] = event.GetPositionTuple()[:]
+ Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
+ (self.mouse['end'][0], self.mouse['end'][1]))
+ if digitToolbar.GetAction() == "addLine" and digitToolbar.GetAction('type') in ["line", "boundary"]:
+ if len(self.polycoords) > 0:
+ self.MouseDraw(pdc=self.pdcTmp, begin=self.Cell2Pixel(self.polycoords[-1]))
+ elif digitToolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] \
+ and hasattr(self, "vdigitMove"):
+ dx = self.mouse['end'][0] - self.mouse['begin'][0]
+ dy = self.mouse['end'][1] - self.mouse['begin'][1]
+
+ if len(self.vdigitMove['id']) > 0:
+ # draw lines on new position
+ if digitToolbar.GetAction() == "moveLine":
+ # move line
+ for id in self.vdigitMove['id']:
+ self.pdcTmp.TranslateId(id, dx, dy)
+ elif digitToolbar.GetAction() in ["moveVertex", "editLine"]:
+ # move vertex ->
+ # (vertex, left vertex, left line,
+ # right vertex, right line)
+
+ # do not draw static lines
+ if digitToolbar.GetAction() == "moveVertex":
+ self.polycoords = []
+ ### self.pdcTmp.TranslateId(self.vdigitMove['id'][0], dx, dy)
+ self.pdcTmp.RemoveId(self.vdigitMove['id'][0])
+ if self.vdigitMove['id'][1] > 0: # previous vertex
+ x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][1])[0:2])
+ self.pdcTmp.RemoveId(self.vdigitMove['id'][1]+1)
+ self.polycoords.append((x, y))
+ ### x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][0])[0:2])
+ self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
+ if self.vdigitMove['id'][2] > 0: # next vertex
+ x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][2])[0:2])
+ self.pdcTmp.RemoveId(self.vdigitMove['id'][2]-1)
+ self.polycoords.append((x, y))
+
+ self.ClearLines(pdc=self.pdcTmp)
+ self.DrawLines(pdc=self.pdcTmp)
+
+ else: # edit line
+ try:
+ if self.vdigitMove['id'][-1] > 0: # previous vertex
+ self.MouseDraw(pdc=self.pdcTmp,
+ begin=self.Cell2Pixel(self.polycoords[-1]))
+ except: # no line
+ self.vdigitMove['id'] = []
+ self.polycoords = []
+
+ self.Refresh() # TODO: use RefreshRect()
+ self.mouse['begin'] = self.mouse['end']
+
+ elif digitToolbar.GetAction() == "zbulkLine":
+ if len(self.polycoords) == 1:
+ # draw mouse moving
+ self.MouseDraw(self.pdcTmp)
+
+ event.Skip()
+
+ def ClearLines(self, pdc=None):
+ """!
+ Clears temporary drawn lines from PseudoDC
+ """
+ if not pdc:
+ pdc=self.pdcTmp
+ try:
+ pdc.ClearId(self.lineid)
+ pdc.RemoveId(self.lineid)
+ except:
+ pass
+
+ try:
+ pdc.ClearId(self.plineid)
+ pdc.RemoveId(self.plineid)
+ except:
+ pass
+
+ Debug.msg(4, "BufferedWindow.ClearLines(): lineid=%s, plineid=%s" %
+ (self.lineid, self.plineid))
+
+ ### self.Refresh()
+
+ return True
+
+ def Pixel2Cell(self, (x, y)):
+ """!
+ Convert image coordinates to real word coordinates
+
+ Input : int x, int y
+ Output: float x, float y
+ """
+
+ try:
+ x = int(x)
+ y = int(y)
+ except:
+ return None
+
+ if self.Map.region["ewres"] > self.Map.region["nsres"]:
+ res = self.Map.region["ewres"]
+ else:
+ res = self.Map.region["nsres"]
+
+ w = self.Map.region["center_easting"] - (self.Map.width / 2) * res
+ n = self.Map.region["center_northing"] + (self.Map.height / 2) * res
+
+ east = w + x * res
+ north = n - y * res
+
+ # extent does not correspond with whole map canvas area...
+ # east = self.Map.region['w'] + x * self.Map.region["ewres"]
+ # north = self.Map.region['n'] - y * self.Map.region["nsres"]
+
+ return (east, north)
+
+ def Cell2Pixel(self, (east, north)):
+ """!
+ Convert real word coordinates to image coordinates
+ """
+
+ try:
+ east = float(east)
+ north = float(north)
+ except:
+ return None
+
+ if self.Map.region["ewres"] > self.Map.region["nsres"]:
+ res = self.Map.region["ewres"]
+ else:
+ res = self.Map.region["nsres"]
+
+ w = self.Map.region["center_easting"] - (self.Map.width / 2) * res
+ n = self.Map.region["center_northing"] + (self.Map.height / 2) * res
+
+ # x = int((east - w) / res)
+ # y = int((n - north) / res)
+
+ x = (east - w) / res
+ y = (n - north) / res
+
+ return (x, y)
+
+ def Zoom(self, begin, end, zoomtype):
+ """!
+ Calculates new region while (un)zoom/pan-ing
+ """
+ x1, y1 = begin
+ x2, y2 = end
+ newreg = {}
+
+ # threshold - too small squares do not make sense
+ # can only zoom to windows of > 5x5 screen pixels
+ if abs(x2-x1) > 5 and abs(y2-y1) > 5 and zoomtype != 0:
+
+ if x1 > x2:
+ x1, x2 = x2, x1
+ if y1 > y2:
+ y1, y2 = y2, y1
+
+ # zoom in
+ if zoomtype > 0:
+ newreg['w'], newreg['n'] = self.Pixel2Cell((x1, y1))
+ newreg['e'], newreg['s'] = self.Pixel2Cell((x2, y2))
+
+ # zoom out
+ elif zoomtype < 0:
+ newreg['w'], newreg['n'] = self.Pixel2Cell((-x1 * 2, -y1 * 2))
+ newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width + 2 * \
+ (self.Map.width - x2),
+ self.Map.height + 2 * \
+ (self.Map.height - y2)))
+ # pan
+ elif zoomtype == 0:
+ dx = x1 - x2
+ dy = y1 - y2
+ newreg['w'], newreg['n'] = self.Pixel2Cell((dx, dy))
+ newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width + dx,
+ self.Map.height + dy))
+
+ # if new region has been calculated, set the values
+ if newreg != {}:
+ # LL locations
+ if self.parent.Map.projinfo['proj'] == 'll':
+ if newreg['n'] > 90.0:
+ newreg['n'] = 90.0
+ if newreg['s'] < -90.0:
+ newreg['s'] = -90.0
+
+ ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
+ cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
+
+ if hasattr(self, "vdigitMove"):
+ # xo = self.Cell2Pixel((self.Map.region['center_easting'], self.Map.region['center_northing']))
+ # xn = self.Cell2Pixel(ce, cn))
+ tmp = self.Pixel2Cell(self.mouse['end'])
+
+ # calculate new center point and display resolution
+ self.Map.region['center_easting'] = ce
+ self.Map.region['center_northing'] = cn
+ self.Map.region["ewres"] = (newreg['e'] - newreg['w']) / self.Map.width
+ self.Map.region["nsres"] = (newreg['n'] - newreg['s']) / self.Map.height
+ self.Map.AlignExtentFromDisplay()
+
+ if hasattr(self, "vdigitMove"):
+ tmp1 = self.mouse['end']
+ tmp2 = self.Cell2Pixel(self.vdigitMove['begin'])
+ dx = tmp1[0] - tmp2[0]
+ dy = tmp1[1] - tmp2[1]
+ self.vdigitMove['beginDiff'] = (dx, dy)
+ for id in self.vdigitMove['id']:
+ self.pdcTmp.RemoveId(id)
+
+ self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ if self.redrawAll is False:
+ self.redrawAll = True
+
+ def ZoomBack(self):
+ """!
+ Zoom to previous extents in zoomhistory list
+ """
+ zoom = list()
+
+ if len(self.zoomhistory) > 1:
+ self.zoomhistory.pop()
+ zoom = self.zoomhistory[-1]
+
+ if len(self.zoomhistory) < 2: # disable tool
+ self.parent.toolbars['map'].Enable('zoomback', enable = False)
+
+ # zoom to selected region
+ self.Map.GetRegion(n = zoom[0], s = zoom[1],
+ e = zoom[2], w = zoom[3],
+ update = True)
+ # update map
+ self.UpdateMap()
+
+ # update statusbar
+ self.parent.StatusbarUpdate()
+
+ def ZoomHistory(self, n, s, e, w):
+ """!
+ Manages a list of last 10 zoom extents
+
+ Return removed history item if exists
+ """
+ removed = None
+ self.zoomhistory.append((n,s,e,w))
+
+ if len(self.zoomhistory) > 10:
+ removed = self.zoomhistory.pop(0)
+
+ if removed:
+ Debug.msg(4, "BufferedWindow.ZoomHistory(): hist=%s, removed=%s" %
+ (self.zoomhistory, removed))
+ else:
+ Debug.msg(4, "BufferedWindow.ZoomHistory(): hist=%s" %
+ (self.zoomhistory))
+
+ if len(self.zoomhistory) > 1:
+ self.parent.toolbars['map'].Enable('zoomback')
+
+ return removed
+
+ def OnZoomToMap(self, event):
+ """!
+ Set display extents to match selected raster (including NULLs)
+ or vector map.
+ """
+ self.ZoomToMap()
+
+ def OnZoomToRaster(self, event):
+ """!
+ Set display extents to match selected raster map (ignore NULLs)
+ """
+ self.ZoomToMap(ignoreNulls = True)
+
+ def ZoomToMap(self, layers = None, ignoreNulls = False, render = True):
+ """!
+ Set display extents to match selected raster
+ or vector map(s).
+
+ @param layer list of layers to be zoom to
+ @param ignoreNulls True to ignore null-values
+ @param render True to re-render display
+ """
+ zoomreg = {}
+
+ if not layers:
+ layers = self.GetSelectedLayer(multi = True)
+
+ if not layers:
+ return
+
+ rast = []
+ vect = []
+ updated = False
+ for l in layers:
+ # only raster/vector layers are currently supported
+ if l.type == 'raster':
+ rast.append(l.name)
+ elif l.type == 'vector':
+ digitToolbar = self.parent.toolbars['vdigit']
+ if digitToolbar and digitToolbar.GetLayer() == l:
+ w, s, b, e, n, t = self.parent.digit.driver.GetMapBoundingBox()
+ self.Map.GetRegion(n=n, s=s, w=w, e=e,
+ update=True)
+ updated = True
+ else:
+ vect.append(l.name)
+
+ if not updated:
+ self.Map.GetRegion(rast = rast,
+ vect = vect,
+ update = True)
+
+ self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ if render:
+ self.UpdateMap()
+
+ self.parent.StatusbarUpdate()
+
+ def ZoomToWind(self, event):
+ """!
+ Set display geometry to match computational
+ region settings (set with g.region)
+ """
+ self.Map.region = self.Map.GetRegion()
+ ### self.Map.SetRegion(windres=True)
+
+ self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ self.UpdateMap()
+
+ self.parent.StatusbarUpdate()
+
+ def ZoomToDefault(self, event):
+ """!
+ Set display geometry to match default region settings
+ """
+ self.Map.region = self.Map.GetRegion(default=True)
+ self.Map.AdjustRegion() # aling region extent to the display
+
+ self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
+ self.Map.region['e'], self.Map.region['w'])
+
+ self.UpdateMap()
+
+ self.parent.StatusbarUpdate()
+
+ def DisplayToWind(self, event):
+ """!
+ Set computational region (WIND file) to
+ match display extents
+ """
+ tmpreg = os.getenv("GRASS_REGION")
+ if tmpreg:
+ del os.environ["GRASS_REGION"]
+
+ # We ONLY want to set extents here. Don't mess with resolution. Leave that
+ # for user to set explicitly with g.region
+ new = self.Map.AlignResolution()
+ gcmd.RunCommand('g.region',
+ parent = self,
+ overwrite = True,
+ n = new['n'],
+ s = new['s'],
+ e = new['e'],
+ w = new['w'],
+ rows = int(new['rows']),
+ cols = int(new['cols']))
+
+ if tmpreg:
+ os.environ["GRASS_REGION"] = tmpreg
+
+ def ZoomToSaved(self, event):
+ """!Set display geometry to match extents in
+ saved region file
+ """
+ dlg = gdialogs.SavedRegion(parent = self,
+ title = _("Zoom to saved region extents"),
+ loadsave='load')
+
+ if dlg.ShowModal() == wx.ID_CANCEL or not dlg.wind:
+ dlg.Destroy()
+ return
+
+ if not grass.find_file(name = dlg.wind, element = 'windows')['name']:
+ wx.MessageBox(parent = self,
+ message = _("Region <%s> not found. Operation canceled.") % dlg.wind,
+ caption = _("Error"), style = wx.ICON_ERROR | wx.OK | wx.CENTRE)
+ dlg.Destroy()
+ return
+
+ self.Map.GetRegion(regionName = dlg.wind,
+ update = True)
+
+ dlg.Destroy()
+
+ self.ZoomHistory(self.Map.region['n'],
+ self.Map.region['s'],
+ self.Map.region['e'],
+ self.Map.region['w'])
+
+ self.UpdateMap()
+
+ def SaveDisplayRegion(self, event):
+ """!
+ Save display extents to named region file.
+ """
+
+ dlg = gdialogs.SavedRegion(parent = self,
+ title = _("Save display extents to region file"),
+ loadsave='save')
+
+ if dlg.ShowModal() == wx.ID_CANCEL or not dlg.wind:
+ dlg.Destroy()
+ return
+
+ # test to see if it already exists and ask permission to overwrite
+ if grass.find_file(name = dlg.wind, element = 'windows')['name']:
+ overwrite = wx.MessageBox(parent = self,
+ message = _("Region file <%s> already exists. "
+ "Do you want to overwrite it?") % (dlg.wind),
+ caption = _("Warning"), style = wx.YES_NO | wx.CENTRE)
+ if (overwrite == wx.YES):
+ self.SaveRegion(dlg.wind)
+ else:
+ self.SaveRegion(dlg.wind)
+
+ dlg.Destroy()
+
+ def SaveRegion(self, wind):
+ """!Save region settings
+
+ @param wind region name
+ """
+ new = self.Map.GetCurrentRegion()
+
+ tmpreg = os.getenv("GRASS_REGION")
+ if tmpreg:
+ del os.environ["GRASS_REGION"]
+
+ gcmd.RunCommand('g.region',
+ overwrite = True,
+ parent = self,
+ flags = 'u',
+ n = new['n'],
+ s = new['s'],
+ e = new['e'],
+ w = new['w'],
+ rows = int(new['rows']),
+ cols = int(new['cols']),
+ save = wind)
+
+ if tmpreg:
+ os.environ["GRASS_REGION"] = tmpreg
+
+ def Distance(self, beginpt, endpt, screen=True):
+ """!Calculete distance
+
+ LL-locations not supported
+
+ @todo Use m.distance
+
+ @param beginpt first point
+ @param endpt second point
+ @param screen True for screen coordinates otherwise EN
+ """
+ x1, y1 = beginpt
+ x2, y2 = endpt
+ if screen:
+ dEast = (x2 - x1) * self.Map.region["ewres"]
+ dNorth = (y2 - y1) * self.Map.region["nsres"]
+ else:
+ dEast = (x2 - x1)
+ dNorth = (y2 - y1)
+
+ return (math.sqrt(math.pow((dEast),2) + math.pow((dNorth),2)), (dEast, dNorth))
Added: grass-addons/gui/wxpython/data_catalog/newprompt.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/newprompt.py (rev 0)
+++ grass-addons/gui/wxpython/data_catalog/newprompt.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -0,0 +1,604 @@
+"""!
+ at package prompt.py
+
+ at brief GRASS prompt
+
+Classes:
+ - GPrompt
+ - PromptListCtrl
+ - TextCtrlAutoComplete
+
+ at todo: fix TextCtrlAutoComplete to work also on Macs (missing
+wx.PopupWindow())
+
+(C) 2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+ at author Mohammed Rashad K.M <rashadkm at gmail dot com> (modified for DataCatalog)
+"""
+
+import os
+import sys
+import shlex
+
+import wx
+import wx.lib.mixins.listctrl as listmix
+
+from grass.script import core as grass
+
+import globalvar
+import utils
+import menuform
+import menudata
+import goutput
+
+class GPrompt:
+ """!Interactive GRASS prompt"""
+ def __init__(self, parent):
+ # self.parent = parent # GMFrame
+
+ # dictionary of modules (description, keywords, ...)
+
+
+
+ self.parent=parent.GetParent()
+ winlist = self.parent.GetChildren()
+ for win in winlist:
+ if type(win) == wx._windows.StatusBar:
+ self.statusbar=win
+ self.modules = self.parent.menudata.GetModules()
+
+ self.panel, self.input = self.__create()
+ #self.goutput = goutput
+ self.goutput = goutput.GMConsole(self.parent, pageid=1)
+ self.goutput.Hide()
+ self.goutput.Redirect()
+
+ def __create(self):
+ """!Create widget"""
+ cmdprompt = wx.Panel(self.parent)
+
+ #
+ # search
+ #
+ #searchTxt = wx.StaticText(parent = cmdprompt, id = wx.ID_ANY, label = _("Search:"))
+
+ #self.searchBy = wx.Choice(parent = cmdprompt, id = wx.ID_ANY, choices = [_("description"), _("keywords")])
+ winHeight =30
+
+ #self.search = wx.TextCtrl(parent = cmdprompt, id = wx.ID_ANY, value = "", size = (-1, 25))
+
+ label = wx.Button(parent = cmdprompt, id = wx.ID_ANY,
+ label = _("Cmd >"), size = (-1, winHeight))
+ label.SetToolTipString(_("Click for erasing command prompt"))
+
+ ### todo: fix TextCtrlAutoComplete to work also on Macs
+ ### reason: missing wx.PopupWindow()
+
+ try:
+ cmdinput = TextCtrlAutoComplete(parent = cmdprompt, id = wx.ID_ANY,
+ value = "",
+ style = wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
+ size = (-1, winHeight),
+ statusbar = self.statusbar)
+ except NotImplementedError:
+ # wx.PopupWindow may be not available in wxMac
+ # see http://trac.wxwidgets.org/ticket/9377
+ cmdinput = wx.TextCtrl(parent = cmdprompt, id = wx.ID_ANY,
+ value = "",
+ style=wx.TE_LINEWRAP | wx.TE_PROCESS_ENTER,
+ size = (-1, 25))
+# self.searchBy.Enable(False)
+ #self.search.Enable(False)
+
+ cmdinput.SetFont(wx.Font(10, wx.FONTFAMILY_MODERN, wx.NORMAL, wx.NORMAL, 0, ''))
+
+ wx.CallAfter(cmdinput.SetInsertionPoint, 0)
+
+ # bidnings
+ label.Bind(wx.EVT_BUTTON, self.OnCmdErase)
+ cmdinput.Bind(wx.EVT_TEXT_ENTER, self.OnRunCmd)
+ cmdinput.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
+ #self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
+
+ # layout
+ sizer = wx.GridBagSizer(hgap=5, vgap=5)
+ sizer.AddGrowableCol(2)
+
+
+
+ sizer.Add(item = label,
+ flag = wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER,
+ border = 5,
+ pos = (0, 1))
+
+ sizer.Add(item = cmdinput,
+ flag = wx.EXPAND | wx.RIGHT,
+ border = 5,
+ pos = (0, 2))
+
+ cmdprompt.SetSizer(sizer)
+ sizer.Fit(cmdprompt)
+ cmdprompt.Layout()
+
+ return cmdprompt, cmdinput
+
+ def __checkKey(self, text, keywords):
+ """!Check if text is in keywords"""
+ found = 0
+ keys = text.split(',')
+ if len(keys) > 1: # -> multiple keys
+ for k in keys[:-1]:
+ k = k.strip()
+ for key in keywords:
+ if k == key: # full match
+ found += 1
+ break
+ k = keys[-1].strip()
+ for key in keywords:
+ if k in key: # partial match
+ found +=1
+ break
+ else:
+ for key in keywords:
+ if text in key: # partial match
+ found +=1
+ break
+
+ if found == len(keys):
+ return True
+
+ return False
+
+ def GetPanel(self):
+ """!Get main widget panel"""
+ return self.panel
+
+ def GetInput(self):
+ """!Get main prompt widget"""
+ return self.input
+
+ def OnCmdErase(self, event):
+ """!Erase command prompt"""
+ self.input.SetValue('')
+
+ def OnRunCmd(self, event):
+ """!Run command"""
+ cmdString = event.GetString()
+
+ #if self.parent.GetName() != "LayerManager":
+ # return
+
+ if cmdString[:2] == 'd.' and not self.parent.current:
+ self.parent.NewDisplay()
+
+ cmd = shlex.split(str(cmdString))
+ if len(cmd) > 1:
+ self.goutput.RunCmd(cmd, switchPage = True)
+ else:
+ self.goutput.RunCmd(cmd, switchPage = False)
+
+ self.OnUpdateStatusBar(None)
+
+ def OnUpdateStatusBar(self, event):
+ """!Update Layer Manager status bar"""
+ if self.parent.GetName() != "LayerManager":
+ return
+
+ if event is None:
+ self.parent.statusbar.SetStatusText("")
+ else:
+ self.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
+ event.Skip()
+
+# def OnSearchModule(self, event):
+# """!Search module by metadata"""
+# print "here"
+# text = event.GetString()
+# if not text:
+# self.input.SetChoices(globalvar.grassCmd['all'])
+# return
+#
+# modules = []
+# for module, data in self.modules.iteritems():
+#
+# if self.searchBy.GetSelection() == 0: # -> description
+# if text in data['desc']:
+# modules.append(module)
+# else: # -> keywords
+# if self.__checkKey(text, data['keywords']):
+# modules.append(module)
+#
+# self.statusbar.SetStatusText(_("%d modules found") % len(modules))
+# self.input.SetChoices(modules)
+
+class PromptListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
+ def __init__(self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition,
+ size = wx.DefaultSize, style = 0):
+ wx.ListCtrl.__init__(self, parent, id, pos, size, style)
+ listmix.ListCtrlAutoWidthMixin.__init__(self)
+
+class TextCtrlAutoComplete(wx.ComboBox, listmix.ColumnSorterMixin):
+ def __init__ (self, parent, statusbar,
+ id = wx.ID_ANY, choices = [], **kwargs):
+ """!Constructor works just like wx.TextCtrl except you can pass in a
+ list of choices. You can also change the choice list at any time
+ by calling setChoices.
+
+ Inspired by http://wiki.wxpython.org/TextCtrlAutoComplete
+ """
+ self.statusbar = statusbar
+
+ if kwargs.has_key('style'):
+ kwargs['style'] = wx.TE_PROCESS_ENTER | kwargs['style']
+ else:
+ kwargs['style'] = wx.TE_PROCESS_ENTER
+
+ wx.ComboBox.__init__(self, parent, id, **kwargs)
+
+ # some variables
+ self._choices = choices
+ self._hideOnNoMatch = True
+ self._module = None # currently selected module
+ self._choiceType = None # type of choice (module, params, flags, raster, vector ...)
+ self._screenheight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
+
+ # sort variable needed by listmix
+ self.itemDataMap = dict()
+
+ # widgets
+ try:
+ self.dropdown = wx.PopupWindow(self)
+ except NotImplementedError:
+ self.Destroy()
+ raise NotImplementedError
+
+ # create the list and bind the events
+ self.dropdownlistbox = PromptListCtrl(parent = self.dropdown,
+ style = wx.LC_REPORT | wx.LC_SINGLE_SEL | \
+ wx.LC_SORT_ASCENDING | wx.LC_NO_HEADER,
+ pos = wx.Point(0, 0))
+
+ listmix.ColumnSorterMixin.__init__(self, 1)
+
+ # set choices (list of GRASS modules)
+ self._choicesCmd = globalvar.grassCmd['all']
+ self._choicesMap = dict()
+ for type in ('raster', 'vector'):
+ self._choicesMap[type] = grass.list_strings(type = type[:4])
+ # first search for GRASS module
+ self.SetChoices(self._choicesCmd)
+
+ self.SetMinSize(self.GetSize())
+ # read history
+ self.SetHistoryItems()
+
+ # bindings...
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnControlChanged)
+ self.Bind(wx.EVT_TEXT, self.OnEnteredText)
+ self.Bind(wx.EVT_KEY_DOWN , self.OnKeyDown)
+ ### self.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
+
+ # if need drop down on left click
+ self.dropdown.Bind(wx.EVT_LISTBOX , self.OnListItemSelected, self.dropdownlistbox)
+ self.dropdownlistbox.Bind(wx.EVT_LEFT_DOWN, self.OnListClick)
+ self.dropdownlistbox.Bind(wx.EVT_LEFT_DCLICK, self.OnListDClick)
+ self.dropdownlistbox.Bind(wx.EVT_LIST_COL_CLICK, self.OnListColClick)
+
+ self.Bind(wx.EVT_COMBOBOX, self.OnCommandSelect)
+
+ def _updateDataList(self, choices):
+ """!Update data list"""
+ # delete, if need, all the previous data
+ if self.dropdownlistbox.GetColumnCount() != 0:
+ self.dropdownlistbox.DeleteAllColumns()
+ self.dropdownlistbox.DeleteAllItems()
+ # and update the dict
+ if choices:
+ for numVal, data in enumerate(choices):
+ self.itemDataMap[numVal] = data
+ else:
+ numVal = 0
+ self.SetColumnCount(numVal)
+
+ def _setListSize(self):
+ """!Set list size"""
+ choices = self._choices
+ longest = 0
+ for choice in choices:
+ longest = max(len(choice), longest)
+ longest += 3
+ itemcount = min(len( choices ), 7) + 2
+ charheight = self.dropdownlistbox.GetCharHeight()
+ charwidth = self.dropdownlistbox.GetCharWidth()
+ self.popupsize = wx.Size(charwidth*longest, charheight*itemcount)
+ self.dropdownlistbox.SetSize(self.popupsize)
+ self.dropdown.SetClientSize(self.popupsize)
+
+ def _showDropDown(self, show = True):
+ """!Either display the drop down list (show = True) or hide it
+ (show = False).
+ """
+ if show:
+ size = self.dropdown.GetSize()
+ width, height = self.GetSizeTuple()
+ x, y = self.ClientToScreenXY(0, height)
+ if size.GetWidth() != width:
+ size.SetWidth(width)
+ self.dropdown.SetSize(size)
+ self.dropdownlistbox.SetSize(self.dropdown.GetClientSize())
+ if (y + size.GetHeight()) < self._screenheight:
+ self.dropdown.SetPosition(wx.Point(x, y))
+ else:
+ self.dropdown.SetPosition(wx.Point(x, y - height - size.GetHeight()))
+
+ self.dropdown.Show(show)
+
+ def _listItemVisible(self):
+ """!Moves the selected item to the top of the list ensuring it is
+ always visible.
+ """
+ toSel = self.dropdownlistbox.GetFirstSelected()
+ if toSel == -1:
+ return
+ self.dropdownlistbox.EnsureVisible(toSel)
+
+ def _setValueFromSelected(self):
+ """!Sets the wx.TextCtrl value from the selected wx.ListCtrl item.
+ Will do nothing if no item is selected in the wx.ListCtrl.
+ """
+ sel = self.dropdownlistbox.GetFirstSelected()
+ if sel > -1:
+ if self._colFetch != -1:
+ col = self._colFetch
+ else:
+ col = self._colSearch
+ itemtext = self.dropdownlistbox.GetItem(sel, col).GetText()
+
+ cmd = shlex.split(str(self.GetValue()))
+ if len(cmd) > 1:
+ # -> append text (skip last item)
+ if self._choiceType == 'param':
+ self.SetValue(' '.join(cmd[:-1]) + ' ' + itemtext + '=')
+ optType = self._module.get_param(itemtext)['prompt']
+ if optType in ('raster', 'vector'):
+ # -> raster/vector map
+ self.SetChoices(self._choicesMap[optType], optType)
+ elif self._choiceType == 'flag':
+ if len(itemtext) > 1:
+ prefix = '--'
+ else:
+ prefix = '-'
+ self.SetValue(' '.join(cmd[:-1]) + ' ' + prefix + itemtext)
+ elif self._choiceType in ('raster', 'vector'):
+ self.SetValue(' '.join(cmd[:-1]) + ' ' + cmd[-1].split('=', 1)[0] + '=' + itemtext)
+ else:
+ # -> reset text
+ self.SetValue(itemtext + ' ')
+ self.SetInsertionPointEnd()
+
+ self._showDropDown(False)
+
+ def GetListCtrl(self):
+ """!Method required by listmix.ColumnSorterMixin"""
+ return self.dropdownlistbox
+
+ def SetHistoryItems(self):
+ """!Read history file and update combobox items"""
+ env = grass.gisenv()
+ try:
+ fileHistory = open(os.path.join(env['GISDBASE'],
+ env['LOCATION_NAME'],
+ env['MAPSET'],
+ '.bash_history'), 'r')
+ except IOError:
+ self.SetItems([])
+ return
+
+ try:
+ hist = []
+ for line in fileHistory.readlines():
+ hist.append(line.replace('\n', ''))
+
+ self.SetItems(hist)
+ finally:
+ fileHistory.close()
+ return
+
+ self.SetItems([])
+
+ def SetChoices(self, choices, type = 'module'):
+ """!Sets the choices available in the popup wx.ListBox.
+ The items will be sorted case insensitively.
+ """
+ self._choices = choices
+ self._choiceType = type
+
+ self.dropdownlistbox.SetWindowStyleFlag(wx.LC_REPORT | wx.LC_SINGLE_SEL | \
+ wx.LC_SORT_ASCENDING | wx.LC_NO_HEADER)
+ if not isinstance(choices, list):
+ self._choices = [ x for x in choices ]
+ if self._choiceType not in ('raster', 'vector'):
+ # do not sort raster/vector maps
+ utils.ListSortLower(self._choices)
+
+ self._updateDataList(self._choices)
+
+ self.dropdownlistbox.InsertColumn(0, "")
+ for num, colVal in enumerate(self._choices):
+ index = self.dropdownlistbox.InsertImageStringItem(sys.maxint, colVal, -1)
+ self.dropdownlistbox.SetStringItem(index, 0, colVal)
+ self.dropdownlistbox.SetItemData(index, num)
+ self._setListSize()
+
+ # there is only one choice for both search and fetch if setting a single column:
+ self._colSearch = 0
+ self._colFetch = -1
+
+ def OnClick(self, event):
+ """Left mouse button pressed"""
+ sel = self.dropdownlistbox.GetFirstSelected()
+ if not self.dropdown.IsShown():
+ if sel > -1:
+ self.dropdownlistbox.Select(sel)
+ else:
+ self.dropdownlistbox.Select(0)
+ self._listItemVisible()
+ self._showDropDown()
+ else:
+ self.dropdown.Hide()
+
+ def OnCommandSelect(self, event):
+ """!Command selected from history"""
+ self.SetFocus()
+
+ def OnListClick(self, evt):
+ """!Left mouse button pressed"""
+ toSel, flag = self.dropdownlistbox.HitTest( evt.GetPosition() )
+ #no values on poition, return
+ if toSel == -1: return
+ self.dropdownlistbox.Select(toSel)
+
+ def OnListDClick(self, evt):
+ """!Mouse button double click"""
+ self._setValueFromSelected()
+
+ def OnListColClick(self, evt):
+ """!Left mouse button pressed on column"""
+ col = evt.GetColumn()
+ # reverse the sort
+ if col == self._colSearch:
+ self._ascending = not self._ascending
+ self.SortListItems( evt.GetColumn(), ascending=self._ascending )
+ self._colSearch = evt.GetColumn()
+ evt.Skip()
+
+ def OnListItemSelected(self, event):
+ """!Item selected"""
+ self._setValueFromSelected()
+ event.Skip()
+
+ def OnEnteredText(self, event):
+ """!Text entered"""
+ text = event.GetString()
+
+ if not text:
+ # control is empty; hide dropdown if shown:
+ if self.dropdown.IsShown():
+ self._showDropDown(False)
+ event.Skip()
+ return
+
+ try:
+ cmd = shlex.split(str(text))
+ except ValueError, e:
+ self.statusbar.SetStatusText(str(e))
+ cmd = text.split(' ')
+
+ pattern = str(text)
+ if len(cmd) > 1:
+ # search for module's options
+ if cmd[0] in self._choicesCmd and not self._module:
+ try:
+ self._module = menuform.GUI().ParseInterface(cmd = cmd)
+ except IOError:
+ self._module = None
+
+ if self._module:
+ if len(cmd[-1].split('=', 1)) == 1:
+ # new option
+ if cmd[-1][0] == '-':
+ # -> flags
+ self.SetChoices(self._module.get_list_flags(), type = 'flag')
+ pattern = cmd[-1].lstrip('-')
+ else:
+ # -> options
+ self.SetChoices(self._module.get_list_params(), type = 'param')
+ pattern = cmd[-1]
+ else:
+ # value
+ pattern = cmd[-1].split('=', 1)[1]
+ else:
+ # search for GRASS modules
+ if self._module:
+ # -> switch back to GRASS modules list
+ self.SetChoices(self._choicesCmd)
+ self._module = None
+ self._choiceType = None
+
+ found = False
+ choices = self._choices
+ for numCh, choice in enumerate(choices):
+ if choice.lower().startswith(pattern):
+ found = True
+ if found:
+ self._showDropDown(True)
+ item = self.dropdownlistbox.GetItem(numCh)
+ toSel = item.GetId()
+ self.dropdownlistbox.Select(toSel)
+ break
+
+ if not found:
+ self.dropdownlistbox.Select(self.dropdownlistbox.GetFirstSelected(), False)
+ if self._hideOnNoMatch:
+ self._showDropDown(False)
+ if self._module and '=' not in cmd[-1]:
+ message = ''
+ if cmd[-1][0] == '-': # flag
+ message = "Warning: flag <%s> not found in '%s'" % \
+ (cmd[-1][1:], self._module.name)
+ else: # option
+ message = "Warning: option <%s> not found in '%s'" % \
+ (cmd[-1], self._module.name)
+ self.statusbar.SetStatusText(message)
+
+ if self._module and len(cmd[-1]) == 2 and cmd[-1][-2] == '=':
+ optType = self._module.get_param(cmd[-1][:-2])['prompt']
+ if optType in ('raster', 'vector'):
+ # -> raster/vector map
+ self.SetChoices(self._choicesMap[optType], optType)
+
+ self._listItemVisible()
+
+ event.Skip()
+
+ def OnKeyDown (self, event):
+ """!Do some work when the user press on the keys: up and down:
+ move the cursor left and right: move the search
+ """
+ skip = True
+ sel = self.dropdownlistbox.GetFirstSelected()
+ visible = self.dropdown.IsShown()
+ KC = event.GetKeyCode()
+ if KC == wx.WXK_DOWN:
+ if sel < (self.dropdownlistbox.GetItemCount() - 1):
+ self.dropdownlistbox.Select(sel + 1)
+ self._listItemVisible()
+ self._showDropDown()
+ skip = False
+ elif KC == wx.WXK_UP:
+ if sel > 0:
+ self.dropdownlistbox.Select(sel - 1)
+ self._listItemVisible()
+ self._showDropDown()
+ skip = False
+
+ if visible:
+ if event.GetKeyCode() == wx.WXK_RETURN:
+ self._setValueFromSelected()
+ skip = False
+ if event.GetKeyCode() == wx.WXK_ESCAPE:
+ self._showDropDown(False)
+ skip = False
+ if skip:
+ event.Skip()
+
+ def OnControlChanged(self, event):
+ """!Control changed"""
+ if self.IsShown():
+ self._showDropDown(False)
+
+ event.Skip()
Added: grass-addons/gui/wxpython/data_catalog/wx_utils.py
===================================================================
--- grass-addons/gui/wxpython/data_catalog/wx_utils.py (rev 0)
+++ grass-addons/gui/wxpython/data_catalog/wx_utils.py 2010-02-03 16:29:51 UTC (rev 40794)
@@ -0,0 +1,1493 @@
+"""!
+ at package wx_utils.py
+
+ at brief Utility classes for GRASS wxPython GUI. Main functions include
+tree control for GIS map layer management, command console, and
+command parsing.
+
+Classes:
+ - LayerTree
+
+(C) 2007-2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Michael Barton (Arizona State University)
+ at author Jachym Cepicky (Mendel University of Agriculture)
+ at author Martin Landa <landa.martin gmail.com>
+ at author Mohammed Rashad K.M <rashadkm at gmail dot com> (modified for DataCatalog)
+"""
+
+import os
+import sys
+import string
+
+import wx
+import wx.lib.customtreectrl as CT
+import wx.combo
+import wx.lib.newevent
+import wx.lib.buttons as buttons
+
+from grass.script import core as grass
+
+import gdialogs
+import globalvar
+import menuform
+import toolbars
+import mapdisp
+import render
+import histogram
+import utils
+import profile
+from debug import Debug as Debug
+from icon import Icons as Icons
+from preferences import globalSettings as UserSettings
+from vdigit import haveVDigit
+
+
+
+
+
+try:
+ import subprocess
+except:
+ from compat import subprocess
+
+try:
+ import treemixin
+except ImportError:
+ from wx.lib.mixins import treemixin
+
+
+TREE_ITEM_HEIGHT = 25
+
+class AddLayerTree(treemixin.DragAndDrop, CT.CustomTreeCtrl):
+ """
+ Creates layer tree structure
+ """
+ def __init__(self, parent,
+ id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=(300,300), style=wx.SUNKEN_BORDER,
+ ctstyle=CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT |
+ CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT |
+ CT.TR_MULTIPLE,mapdisplay=None,frame=None,panel=None,Map=None,lmgr=None):
+ self.items = []
+ self.itemCounter = 0
+
+ super(AddLayerTree, self).__init__(parent, id, pos, size, style=style, ctstyle=ctstyle)
+ self.SetName("AddLayerTree")
+
+ ### SetAutoLayout() causes that no vertical scrollbar is displayed
+ ### when some layers are not visible in layer tree
+ # self.SetAutoLayout(True)
+ self.SetGradientStyle(1)
+ self.EnableSelectionGradient(True)
+ self.SetFirstGradientColour(wx.Colour(100, 100, 100))
+ self.SetSecondGradientColour(wx.Colour(150, 150, 150))
+
+
+
+
+ self.mapdisplay = self.GetParent()
+
+ if self.mapdisplay.toolbars['vdigit']:
+ self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool=True)
+
+ self.Map = Map # instance of render.Map to be associated with display
+
+ self.root = None # ID of layer tree root node
+ self.groupnode = 0 # index value for layers
+ self.optpage = {} # dictionary of notebook option pages for each map layer
+ self.layer_selected = None # ID of currently selected layer
+ self.saveitem = {} # dictionary to preserve layer attributes for drag and drop
+ self.first = True # indicates if a layer is just added or not
+ self.flag = '' # flag for drag and drop hittest
+ self.parent = parent
+ #self.disp_idx = kargs['idx']
+ self.lmgr = lmgr
+#FIX
+ # self.notebook = kargs['notebook'] # GIS Manager notebook for layer tree
+#FIX this
+ #self.treepg = parent # notebook page holding layer tree
+ #self.auimgr = kargs['auimgr'] # aui manager
+ self.rerender = False # layer change requires a rerendering if auto render
+ self.reorder = False # layer change requires a reordering
+
+ # init associated map display
+ # pos = wx.Point((self.disp_idx + 1) * 25, (self.disp_idx + 1) * 25)
+# self.mapdisplay = mapdisp.MapFrame(self, id=wx.ID_ANY, pos=pos, size=globalvar.MAP_WINDOW_SIZE,style=wx.DEFAULT_FRAME_STYLE, tree=self, notebook=self.notebook,
+
+
+ self.frame = frame
+ self.panel = panel
+
+ self.SetSize(wx.Size(340,640))
+ #lmgr=self.lmgr, page=self.treepg,Map=self.Map, auimgr=self.auimgr)
+
+ # title
+ # self.mapdisplay.SetTitle(_("GRASS GIS Map Display: %(id)d - Location: %(loc)s") % \
+ # { 'id' : self.disp_idx + 1,
+ # 'loc' : grass.gisenv()["LOCATION_NAME"] })
+
+ # show new display
+ # if kargs['showMapDisplay'] is True:
+ # self.mapdisplay.Show()
+ # self.mapdisplay.Refresh()
+ # self.mapdisplay.Update()
+
+ #self.SetSize(300,300)
+
+ self.root = self.AddRoot(_("Map Layers"))
+ self.SetPyData(self.root, (None,None))
+ self.items = []
+
+ #create image list to use with layer tree
+ il = wx.ImageList(16, 16, mask=False)
+
+ trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16))
+ self.folder_open = il.Add(trart)
+ trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
+ self.folder = il.Add(trart)
+
+ bmpsize = (16, 16)
+ trgif = Icons["addrast"].GetBitmap(bmpsize)
+ self.rast_icon = il.Add(trgif)
+
+ trgif = Icons["addrast3d"].GetBitmap(bmpsize)
+ self.rast3d_icon = il.Add(trgif)
+
+ trgif = Icons["addrgb"].GetBitmap(bmpsize)
+ self.rgb_icon = il.Add(trgif)
+
+ trgif = Icons["addhis"].GetBitmap(bmpsize)
+ self.his_icon = il.Add(trgif)
+
+ trgif = Icons["addshaded"].GetBitmap(bmpsize)
+ self.shaded_icon = il.Add(trgif)
+
+ trgif = Icons["addrarrow"].GetBitmap(bmpsize)
+ self.rarrow_icon = il.Add(trgif)
+
+ trgif = Icons["addrnum"].GetBitmap(bmpsize)
+ self.rnum_icon = il.Add(trgif)
+
+ trgif = Icons["addvect"].GetBitmap(bmpsize)
+ self.vect_icon = il.Add(trgif)
+
+ trgif = Icons["addthematic"].GetBitmap(bmpsize)
+ self.theme_icon = il.Add(trgif)
+
+ trgif = Icons["addchart"].GetBitmap(bmpsize)
+ self.chart_icon = il.Add(trgif)
+
+ trgif = Icons["addgrid"].GetBitmap(bmpsize)
+ self.grid_icon = il.Add(trgif)
+
+ trgif = Icons["addgeodesic"].GetBitmap(bmpsize)
+ self.geodesic_icon = il.Add(trgif)
+
+ trgif = Icons["addrhumb"].GetBitmap(bmpsize)
+ self.rhumb_icon = il.Add(trgif)
+
+ trgif = Icons["addlabels"].GetBitmap(bmpsize)
+ self.labels_icon = il.Add(trgif)
+
+ trgif = Icons["addcmd"].GetBitmap(bmpsize)
+ self.cmd_icon = il.Add(trgif)
+
+ self.AssignImageList(il)
+
+ # use when groups implemented
+ ## self.tree.SetItemImage(self.root, fldridx, wx.TreeItemIcon_Normal)
+ ## self.tree.SetItemImage(self.root, fldropenidx, wx.TreeItemIcon_Expanded)
+
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnExpandNode)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnCollapseNode)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateLayer)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnChangeSel)
+ self.Bind(CT.EVT_TREE_ITEM_CHECKED, self.OnLayerChecked)
+ self.Bind(wx.EVT_TREE_DELETE_ITEM, self.OnDeleteLayer)
+ self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnLayerContextMenu)
+ #self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnDrag)
+ self.Bind(wx.EVT_TREE_END_DRAG, self.OnEndDrag)
+ #self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnChangeLayerName)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ # self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+
+
+
+
+
+ def OnIdle(self, event):
+ """
+ Only re-order and re-render a composite map image from GRASS during
+ idle time instead of multiple times during layer changing.
+ """
+ if self.rerender:
+ if self.mapdisplay.toolbars['vdigit']:
+ self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool=True)
+ if self.mapdisplay.statusbarWin['render'].GetValue():
+ self.mapdisplay.MapWindow2D.UpdateMap(render=True)
+
+ event.Skip()
+
+ def OnKeyUp(self, event):
+ """!Key pressed"""
+ key = event.GetKeyCode()
+ if key == wx.WXK_DELETE and self.lmgr:
+ self.frame.OnDeleteLayer(None)
+
+ event.Skip()
+
+ #def OnChangeLayerName (self, event):
+ # """!Change layer name"""
+ # Debug.msg (3, "LayerTree.OnChangeLayerName: name=%s" % event.GetLabel())
+
+ def OnLayerContextMenu (self, event):
+ """!Contextual menu for item/layer"""
+ if not self.layer_selected:
+ event.Skip()
+ return
+
+ ltype = self.GetPyData(self.layer_selected)[0]['type']
+
+ Debug.msg (4, "LayerTree.OnContextMenu: layertype=%s" % \
+ ltype)
+
+ if not hasattr (self, "popupID1"):
+ self.popupID1 = wx.NewId()
+ self.popupID2 = wx.NewId()
+ self.popupID3 = wx.NewId()
+ self.popupID4 = wx.NewId()
+ self.popupID5 = wx.NewId()
+ self.popupID6 = wx.NewId()
+ self.popupID7 = wx.NewId()
+ self.popupID8 = wx.NewId()
+ self.popupID9 = wx.NewId()
+ self.popupID10 = wx.NewId()
+ self.popupID11 = wx.NewId() # nviz
+ self.popupID12 = wx.NewId()
+ self.popupID13 = wx.NewId()
+ self.popupID14 = wx.NewId()
+ self.popupID15 = wx.NewId()
+
+ self.popupMenu = wx.Menu()
+
+ numSelected = len(self.GetSelections())
+
+ # general item
+ self.popupMenu.Append(self.popupID1, text=_("Remove"))
+
+ p = self.parent.GetParent()
+ q= p.GetParent()
+ r= q.GetParent()
+ frame= r.GetParent()
+ self.Bind(wx.EVT_MENU, frame.OnDeleteLayer, id=self.popupID1)
+
+ if ltype != "command": # rename
+ self.popupMenu.Append(self.popupID2, text=_("Rename"))
+ self.Bind(wx.EVT_MENU, self.RenameLayer, id=self.popupID2)
+ if numSelected > 1:
+ self.popupMenu.Enable(self.popupID2, False)
+
+ # map layer items
+ if ltype != "group" and \
+ ltype != "command":
+ self.popupMenu.AppendSeparator()
+ self.popupMenu.Append(self.popupID8, text=_("Change opacity level"))
+ self.Bind(wx.EVT_MENU, self.OnPopupOpacityLevel, id=self.popupID8)
+ self.popupMenu.Append(self.popupID3, text=_("Properties"))
+ self.Bind(wx.EVT_MENU, self.OnPopupProperties, id=self.popupID3)
+ if ltype in ('raster', 'vector', 'rgb'):
+ self.popupMenu.Append(self.popupID9, text=_("Zoom to selected map(s)"))
+ self.Bind(wx.EVT_MENU, self.mapdisplay.MapWindow2D.OnZoomToMap, id=self.popupID9)
+ self.popupMenu.Append(self.popupID10, text=_("Set computational region from selected map(s)"))
+ self.Bind(wx.EVT_MENU, self.OnSetCompRegFromMap, id=self.popupID10)
+ if numSelected > 1:
+ self.popupMenu.Enable(self.popupID8, False)
+ self.popupMenu.Enable(self.popupID3, False)
+
+ # specific items
+ try:
+ mltype = self.GetPyData(self.layer_selected)[0]['type']
+ except:
+ mltype = None
+ #
+ # vector layers (specific items)
+ #
+ if mltype and mltype == "vector":
+ self.popupMenu.AppendSeparator()
+ self.popupMenu.Append(self.popupID4, text=_("Show attribute data"))
+ self.Bind (wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id=self.popupID4)
+
+ self.popupMenu.Append(self.popupID5, text=_("Start editing"))
+ self.popupMenu.Append(self.popupID6, text=_("Stop editing"))
+ self.popupMenu.Enable(self.popupID6, False)
+ self.Bind (wx.EVT_MENU, self.OnStartEditing, id=self.popupID5)
+ self.Bind (wx.EVT_MENU, self.OnStopEditing, id=self.popupID6)
+
+ layer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ # enable editing only for vector map layers available in the current mapset
+ digitToolbar = self.mapdisplay.toolbars['vdigit']
+ if digitToolbar:
+ # background vector map
+ self.popupMenu.Append(self.popupID14,
+ text=_("Use as background vector map"),
+ kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnSetBgMap, id=self.popupID14)
+ if UserSettings.Get(group='vdigit', key='bgmap', subkey='value',
+ internal=True) == layer.GetName():
+ self.popupMenu.Check(self.popupID14, True)
+
+ if layer.GetMapset() != grass.gisenv()['MAPSET']:
+ # only vector map in current mapset can be edited
+ self.popupMenu.Enable (self.popupID5, False)
+ self.popupMenu.Enable (self.popupID6, False)
+ elif digitToolbar and digitToolbar.GetLayer():
+ # vector map already edited
+ vdigitLayer = digitToolbar.GetLayer()
+ if vdigitLayer is layer:
+ # disable 'start editing'
+ self.popupMenu.Enable (self.popupID5, False)
+ # enable 'stop editing'
+ self.popupMenu.Enable(self.popupID6, True)
+ # disable 'remove'
+ self.popupMenu.Enable(self.popupID1, False)
+ # disable 'bgmap'
+ self.popupMenu.Enable(self.popupID14, False)
+ else:
+ # disable 'start editing'
+ self.popupMenu.Enable(self.popupID5, False)
+ # disable 'stop editing'
+ self.popupMenu.Enable(self.popupID6, False)
+ # enable 'bgmap'
+ self.popupMenu.Enable(self.popupID14, True)
+
+ self.popupMenu.Append(self.popupID7, _("Metadata"))
+ self.Bind (wx.EVT_MENU, self.OnMetadata, id=self.popupID7)
+ if numSelected > 1:
+ self.popupMenu.Enable(self.popupID4, False)
+ self.popupMenu.Enable(self.popupID5, False)
+ self.popupMenu.Enable(self.popupID6, False)
+ self.popupMenu.Enable(self.popupID7, False)
+ self.popupMenu.Enable(self.popupID14, False)
+
+ #
+ # raster layers (specific items)
+ #
+ elif mltype and mltype == "raster":
+ self.popupMenu.Append(self.popupID12, text=_("Zoom to selected map(s) (ignore NULLs)"))
+ self.Bind(wx.EVT_MENU, self.mapdisplay.MapWindow2D.OnZoomToRaster, id=self.popupID12)
+ self.popupMenu.Append(self.popupID13, text=_("Set computational region from selected map(s) (ignore NULLs)"))
+ self.Bind(wx.EVT_MENU, self.OnSetCompRegFromRaster, id=self.popupID13)
+ self.popupMenu.AppendSeparator()
+ self.popupMenu.Append(self.popupID15, _("Set color table"))
+ self.Bind (wx.EVT_MENU, self.OnColorTable, id=self.popupID15)
+ self.popupMenu.Append(self.popupID4, _("Histogram"))
+ self.Bind (wx.EVT_MENU, self.OnHistogram, id=self.popupID4)
+ self.popupMenu.Append(self.popupID5, _("Profile"))
+ self.Bind (wx.EVT_MENU, self.OnProfile, id=self.popupID5)
+ self.popupMenu.Append(self.popupID6, _("Metadata"))
+ self.Bind (wx.EVT_MENU, self.OnMetadata, id=self.popupID6)
+ if self.mapdisplay.toolbars['nviz']:
+ self.popupMenu.Append(self.popupID11, _("Nviz properties"))
+ self.Bind (wx.EVT_MENU, self.OnNvizProperties, id=self.popupID11)
+
+ if numSelected > 1:
+ self.popupMenu.Enable(self.popupID12, False)
+ self.popupMenu.Enable(self.popupID13, False)
+ self.popupMenu.Enable(self.popupID15, False)
+ self.popupMenu.Enable(self.popupID4, False)
+ self.popupMenu.Enable(self.popupID5, False)
+ self.popupMenu.Enable(self.popupID6, False)
+ self.popupMenu.Enable(self.popupID11, False)
+
+ ## self.PopupMenu(self.popupMenu, pos)
+ self.PopupMenu(self.popupMenu)
+ self.popupMenu.Destroy()
+
+ def OnMetadata(self, event):
+ """!Print metadata of raster/vector map layer
+ TODO: Dialog to modify metadata
+ """
+ mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ mltype = self.GetPyData(self.layer_selected)[0]['type']
+
+ if mltype == 'raster':
+ cmd = ['r.info']
+ elif mltype == 'vector':
+ cmd = ['v.info']
+ cmd.append('map=%s' % mapLayer.name)
+
+
+ # print output to command log area
+ self.lmgr.goutput.RunCmd(cmd, switchPage=True)
+
+ def OnSetCompRegFromRaster(self, event):
+ """!Set computational region from selected raster map (ignore NULLs)"""
+ mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+
+ cmd = ['g.region',
+ '-p',
+ 'zoom=%s' % mapLayer.name]
+
+ # print output to command log area
+ self.lmgr.goutput.RunCmd(cmd)
+
+ def OnSetCompRegFromMap(self, event):
+ """!Set computational region from selected raster/vector map"""
+ rast = []
+ vect = []
+ rast3d = []
+ for layer in self.GetSelections():
+ mapLayer = self.GetPyData(layer)[0]['maplayer']
+ mltype = self.GetPyData(layer)[0]['type']
+
+ if mltype == 'raster':
+ rast.append(mapLayer.name)
+ elif mltype == 'vector':
+ vect.append(mapLayer.name)
+ elif mltype == '3d-raster':
+ rast3d.append(mapLayer.name)
+
+ cmd = ['g.region']
+ if rast:
+ cmd.append('rast=%s' % ','.join(rast))
+ if vect:
+ cmd.append('vect=%s' % ','.join(vect))
+ if rast3d:
+ cmd.append('rast3d=%s' % ','.join(rast3d))
+
+ # print output to command log area
+ if len(cmd) > 1:
+ cmd.append('-p')
+ self.lmgr.goutput.RunCmd(cmd)
+
+ def OnProfile(self, event):
+ """!Plot profile of given raster map layer"""
+ mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ if not mapLayer.name:
+ wx.MessageBox(parent=self,
+ message=_("Unable to create profile of "
+ "raster map."),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return False
+
+ if not hasattr (self, "profileFrame"):
+ self.profileFrame = None
+
+ if hasattr (self.mapdisplay, "profile") and self.mapdisplay.profile:
+ self.profileFrame = self.mapdisplay.profile
+
+ if not self.profileFrame:
+ self.profileFrame = profile.ProfileFrame(self.mapdisplay,
+ id=wx.ID_ANY, pos=wx.DefaultPosition, size=(700,300),
+ style=wx.DEFAULT_FRAME_STYLE, rasterList=[mapLayer.name])
+ # show new display
+ self.profileFrame.Show()
+
+ def OnColorTable(self, event):
+ """!Set color table for raster map"""
+ name = self.GetPyData(self.layer_selected)[0]['maplayer'].name
+ menuform.GUI().ParseCommand(['r.colors',
+ 'map=%s' % name],
+ parentframe=self)
+
+ def OnHistogram(self, event):
+ """
+ Plot histogram for given raster map layer
+ """
+ mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ if not mapLayer.name:
+ wx.MessageBox(parent=self,
+ message=_("Unable to display histogram of "
+ "raster map."),
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return False
+
+ if not hasattr (self, "histogramFrame"):
+ self.histogramFrame = None
+
+ if hasattr (self.mapdisplay, "histogram") and self.mapdisplay.histogram:
+ self.histogramFrame = self.mapdisplay.histogram
+
+ if not self.histogramFrame:
+ self.histogramFrame = histogram.HistFrame(self,
+ id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=globalvar.HIST_WINDOW_SIZE,
+ style=wx.DEFAULT_FRAME_STYLE)
+ # show new display
+ self.histogramFrame.Show()
+
+ self.histogramFrame.SetHistLayer(mapLayer.name)
+ self.histogramFrame.HistWindow.UpdateHist()
+ self.histogramFrame.Refresh()
+ self.histogramFrame.Update()
+
+ return True
+
+ def OnStartEditing(self, event):
+ """
+ Start editing vector map layer requested by the user
+ """
+ if not haveVDigit:
+ from vdigit import errorMsg
+ msg = _("Unable to start vector digitizer.\nThe VDigit python extension "
+ "was not found or loaded properly.\n"
+ "Switching back to 2D display mode.\n\nDetails: %s" % errorMsg)
+
+ self.mapdisplay.toolbars['map'].combo.SetValue (_("2D view"))
+ wx.MessageBox(parent=self.mapdisplay,
+ message=msg,
+ caption=_("Error"),
+ style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ try:
+ maplayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ except:
+ event.Skip()
+ return
+
+ if not self.mapdisplay.toolbars['vdigit']: # enable tool
+ self.mapdisplay.AddToolbar('vdigit')
+ else: # tool already enabled
+ pass
+
+ # mark layer as 'edited'
+ self.mapdisplay.toolbars['vdigit'].StartEditing (maplayer)
+
+ def OnStopEditing(self, event):
+ """
+ Stop editing the current vector map layer
+ """
+ maplayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+
+ self.mapdisplay.toolbars['vdigit'].OnExit()
+ self.mapdisplay.imgVectorMap = None
+
+ def OnSetBgMap(self, event):
+ """!Set background vector map for editing sesstion"""
+ if event.IsChecked():
+ mapName = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName()
+ UserSettings.Set(group='vdigit', key='bgmap', subkey='value',
+ value=str(mapName), internal=True)
+ else:
+ UserSettings.Set(group='vdigit', key='bgmap', subkey='value',
+ value='', internal=True)
+
+ def OnPopupProperties (self, event):
+ """!Popup properties dialog"""
+ self.PropertiesDialog(self.layer_selected)
+
+ def OnPopupOpacityLevel(self, event):
+ """!Popup opacity level indicator"""
+ if not self.GetPyData(self.layer_selected)[0]['ctrl']:
+ return
+
+ #win = self.FindWindowById(self.GetPyData(self.layer_selected)[0]['ctrl'])
+ #type = win.GetName()
+ #
+ #self.layer_selected.DeleteWindow()
+
+ maplayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+ current_opacity = maplayer.GetOpacity()
+
+ dlg = gdialogs.SetOpacityDialog(self, opacity=current_opacity,
+ title=_("Set opacity <%s>") % maplayer.GetName())
+ dlg.CentreOnParent()
+
+ if dlg.ShowModal() == wx.ID_OK:
+ new_opacity = dlg.GetOpacity() # string
+ self.Map.ChangeOpacity(maplayer, new_opacity)
+ maplayer.SetOpacity(new_opacity)
+ opacity_pct = int(new_opacity * 100)
+ layername = self.GetItemText(self.layer_selected)
+ layerbase = layername.split('(')[0].strip()
+ self.SetItemText(self.layer_selected,
+ layerbase + ' (opacity: ' + str(opacity_pct) + '%)')
+
+ # vector layer currently edited
+ if self.mapdisplay.toolbars['vdigit'] and \
+ self.mapdisplay.toolbars['vdigit'].GetLayer() == maplayer:
+ alpha = int(new_opacity * 255)
+ self.mapdisplay.digit.driver.UpdateSettings(alpha)
+
+ # redraw map if auto-rendering is enabled
+ self.rerender = True
+ self.reorder = True
+ #if self.mapdisplay.statusbarWin['render'].GetValue():
+ # print "*** Opacity OnRender *****"
+ # self.mapdisplay.OnRender(None)
+
+ def OnNvizProperties(self, event):
+ """!Nviz-related properties (raster/vector/volume)
+
+ @todo vector/volume
+ """
+ if not self.mapdisplay.nvizToolWin.IsShown():
+ self.mapdisplay.nvizToolWin.Show()
+
+ self.mapdisplay.nvizToolWin.SetPage('surface')
+
+ def RenameLayer (self, event):
+ """!Rename layer"""
+ self.EditLabel(self.layer_selected)
+
+ def AddLayer(self, ltype, lname=None, lchecked=None,
+ lopacity=1.0, lcmd=None, lgroup=None, lvdigit=None, lnviz=None):
+ """!Add new item to the layer tree, create corresponding MapLayer instance.
+ Launch property dialog if needed (raster, vector, etc.)
+
+ @param ltype layer type (raster, vector, 3d-raster, ...)
+ @param lname layer name
+ @param lchecked if True layer is checked
+ @param lopacity layer opacity level
+ @param lcmd command (given as a list)
+ @param lgroup group name or None
+ @param lvdigit vector digitizer settings (eg. geometry attributes)
+ @param lnviz layer Nviz properties
+ """
+ self.first = True
+ params = {} # no initial options parameters
+
+ # deselect active item
+ if self.layer_selected:
+ self.SelectItem(self.layer_selected, select=False)
+
+ Debug.msg (3, "LayerTree().AddLayer(): ltype=%s" % (ltype))
+
+ if ltype == 'command':
+ # generic command item
+ ctrl = wx.TextCtrl(self, id=wx.ID_ANY, value='',
+ pos=wx.DefaultPosition, size=(self.GetSize()[0]-100,25),
+ # style=wx.TE_MULTILINE|wx.TE_WORDWRAP)
+ style=wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
+ ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged)
+ # ctrl.Bind(wx.EVT_TEXT, self.OnCmdChanged)
+ elif ltype == 'group':
+ # group item
+ ctrl = None
+ grouptext = _('Layer group:') + str(self.groupnode)
+ self.groupnode += 1
+ else:
+ btnbmp = Icons["layeropts"].GetBitmap((16,16))
+ ctrl = buttons.GenBitmapButton(self, id=wx.ID_ANY, bitmap=btnbmp, size=(24,24))
+ ctrl.SetToolTipString(_("Click to edit layer settings"))
+ self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, ctrl)
+ # add layer to the layer tree
+ if self.layer_selected and self.layer_selected != self.GetRootItem():
+ if self.GetPyData(self.layer_selected)[0]['type'] == 'group' \
+ and self.IsExpanded(self.layer_selected):
+ # add to group (first child of self.layer_selected) if group expanded
+ layer = self.PrependItem(parent=self.layer_selected,
+ text='', ct_type=1, wnd=ctrl)
+ else:
+ # prepend to individual layer or non-expanded group
+ if lgroup is False:
+ # -> last child of root (loading from workspace)
+ layer = self.AppendItem(parentId=self.root,
+ text='', ct_type=1, wnd=ctrl)
+ elif lgroup is True:
+ # -> last child of group (loading from workspace)
+ parent = self.GetItemParent(self.layer_selected)
+ if parent is self.root: # first item in group
+ parent=self.layer_selected
+ layer = self.AppendItem(parentId=parent,
+ text='', ct_type=1, wnd=ctrl)
+ elif lgroup is None:
+ # -> previous sibling of selected layer
+ parent = self.GetItemParent(self.layer_selected)
+ layer = self.InsertItem(parentId=parent,
+ input=self.GetPrevSibling(self.layer_selected),
+ text='', ct_type=1, wnd=ctrl)
+ else: # add first layer to the layer tree (first child of root)
+ layer = self.PrependItem(parent=self.root, text='', ct_type=1, wnd=ctrl)
+
+ # layer is initially unchecked as inactive (beside 'command')
+ # use predefined value if given
+ if lchecked is not None:
+ checked = lchecked
+ else:
+ checked = True
+
+ self.CheckItem(layer, checked=checked)
+
+ # select new item
+ self.SelectItem(layer, select=True)
+ self.layer_selected = layer
+
+ # add text and icons for each layer ltype
+ if ltype == 'raster':
+ self.SetItemImage(layer, self.rast_icon)
+ self.SetItemText(layer, '%s %s' % (_('raster'), _('(double click to set properties)')))
+ elif ltype == '3d-raster':
+ self.SetItemImage(layer, self.rast3d_icon)
+ self.SetItemText(layer, '%s %s' % (_('3d raster'), _('(double click to set properties)')))
+ elif ltype == 'rgb':
+ self.SetItemImage(layer, self.rgb_icon)
+ self.SetItemText(layer, '%s %s' % (_('RGB'), _('(double click to set properties)')))
+ elif ltype == 'his':
+ self.SetItemImage(layer, self.his_icon)
+ self.SetItemText(layer, '%s %s' % (_('HIS'), _('(double click to set properties)')))
+ elif ltype == 'shaded':
+ self.SetItemImage(layer, self.shaded_icon)
+ self.SetItemText(layer, '%s %s' % (_('Shaded relief'), _('(double click to set properties)')))
+ elif ltype == 'rastnum':
+ self.SetItemImage(layer, self.rnum_icon)
+ self.SetItemText(layer, '%s %s' % (_('raster cell numbers'), _('(double click to set properties)')))
+ elif ltype == 'rastarrow':
+ self.SetItemImage(layer, self.rarrow_icon)
+ self.SetItemText(layer, '%s %s' % (_('raster flow arrows'), _('(double click to set properties)')))
+ elif ltype == 'vector':
+ self.SetItemImage(layer, self.vect_icon)
+ self.SetItemText(layer, '%s %s' % (_('vector'), _('(double click to set properties)')))
+ elif ltype == 'thememap':
+ self.SetItemImage(layer, self.theme_icon)
+ self.SetItemText(layer, '%s %s' % (_('thematic map'), _('(double click to set properties)')))
+ elif ltype == 'themechart':
+ self.SetItemImage(layer, self.chart_icon)
+ self.SetItemText(layer, '%s %s' % (_('thematic charts'), _('(double click to set properties)')))
+ elif ltype == 'grid':
+ self.SetItemImage(layer, self.grid_icon)
+ self.SetItemText(layer, '%s %s' % (_('grid'), _('(double click to set properties)')))
+ elif ltype == 'geodesic':
+ self.SetItemImage(layer, self.geodesic_icon)
+ self.SetItemText(layer, '%s %s' % (_('geodesic line'), _('(double click to set properties)')))
+ elif ltype == 'rhumb':
+ self.SetItemImage(layer, self.rhumb_icon)
+ self.SetItemText(layer, '%s %s' % (_('rhumbline'), _('(double click to set properties)')))
+ elif ltype == 'labels':
+ self.SetItemImage(layer, self.labels_icon)
+ self.SetItemText(layer, '%s %s' % (_('vector labels'), _('(double click to set properties)')))
+ elif ltype == 'command':
+ self.SetItemImage(layer, self.cmd_icon)
+ elif ltype == 'group':
+ self.SetItemImage(layer, self.folder)
+ self.SetItemText(layer, grouptext)
+
+ self.first = False
+
+ if ltype != 'group':
+ if lcmd and len(lcmd) > 1:
+ cmd = lcmd
+ render = False
+ name = utils.GetLayerNameFromCmd(lcmd)
+ else:
+ cmd = []
+ if ltype == 'command' and lname:
+ for c in lname.split(';'):
+ cmd.append(c.split(' '))
+
+ render = False
+ name = None
+
+ if ctrl:
+ ctrlId = ctrl.GetId()
+ else:
+ ctrlId = None
+
+ # add a data object to hold the layer's command (does not apply to generic command layers)
+ self.SetPyData(layer, ({'cmd' : cmd,
+ 'type' : ltype,
+ 'ctrl' : ctrlId,
+ 'maplayer' : None,
+ 'vdigit' : lvdigit,
+ 'nviz' : lnviz,
+ 'propwin' : None},
+ None))
+
+ # find previous map layer instance
+ prevItem = self.GetFirstChild(self.root)[0]
+ prevMapLayer = None
+ pos = -1
+ while prevItem and prevItem.IsOk() and prevItem != layer:
+ if self.GetPyData(prevItem)[0]['maplayer']:
+ prevMapLayer = self.GetPyData(prevItem)[0]['maplayer']
+
+ prevItem = self.GetNextSibling(prevItem)
+
+ if prevMapLayer:
+ pos = self.Map.GetLayerIndex(prevMapLayer)
+ else:
+ pos = -1
+
+ maplayer = self.Map.AddLayer(pos=pos,
+ type=ltype, command=self.GetPyData(layer)[0]['cmd'], name=name,
+ l_active=checked, l_hidden=False,
+ l_opacity=lopacity, l_render=render)
+ self.GetPyData(layer)[0]['maplayer'] = maplayer
+
+ # run properties dialog if no properties given
+ if len(cmd) == 0:
+ self.PropertiesDialog(layer, show=True)
+
+ if ltype == '3d-raster' and \
+ not self.mapdisplay.toolbars['nviz']:
+ self.EnableItem(layer, False)
+
+ else: # group
+ self.SetPyData(layer, ({'cmd': None,
+ 'type' : ltype,
+ 'ctrl' : None,
+ 'maplayer' : None,
+ 'propwin' : None},
+ None))
+
+ # use predefined layer name if given
+ if lname:
+ if ltype == 'group':
+ self.SetItemText(layer, lname)
+ elif ltype == 'command':
+ ctrl.SetValue(lname)
+ else:
+ name = lname + ' (opacity: ' + \
+ str(self.GetPyData(layer)[0]['maplayer'].GetOpacity()) + '%)'
+ self.SetItemText(layer, name)
+
+ # updated progress bar range (mapwindow statusbar)
+ if checked is True:
+ self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+
+ # self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+
+ # layer.SetHeight(TREE_ITEM_HEIGHT)
+
+ return layer
+
+ def PropertiesDialog (self, layer, show=True):
+ """!Launch the properties dialog"""
+
+
+
+ if self.GetPyData(layer)[0].has_key('propwin') and self.GetPyData(layer)[0]['propwin']:
+ win = self.GetPyData(layer)[0]['propwin']
+ win.notebookpanel.OnUpdateSelection(None)
+ if win.IsShown():
+ win.SetFocus()
+ else:
+ win.Show()
+ return
+
+ completed = ''
+ params = self.GetPyData(layer)[1]
+ ltype = self.GetPyData(layer)[0]['type']
+
+ Debug.msg (3, "LayerTree.PropertiesDialog(): ltype=%s" % \
+ ltype)
+
+ if self.GetPyData(layer)[0]['cmd']:
+ cmdValidated = menuform.GUI().ParseCommand(self.GetPyData(layer)[0]['cmd'],
+ completed=(self.GetOptData,layer,params),
+ parentframe=self, show=show)
+ self.GetPyData(layer)[0]['cmd'] = cmdValidated
+ elif ltype == 'raster':
+ cmd = ['d.rast']
+
+ if UserSettings.Get(group='cmd', key='rasterOpaque', subkey='enabled'):
+ cmd.append('-n')
+ menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == '3d-raster':
+ cmd = ['d.rast3d']
+ menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'rgb':
+ menuform.GUI().ParseCommand(['d.rgb'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'his':
+ menuform.GUI().ParseCommand(['d.his'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'shaded':
+ menuform.GUI().ParseCommand(['d.shadedmap'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'rastarrow':
+ menuform.GUI().ParseCommand(['d.rast.arrow'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'rastnum':
+ menuform.GUI().ParseCommand(['d.rast.num'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'vector':
+ types = ''
+ for type in UserSettings.Get(group='cmd', key='showType').keys():
+ if UserSettings.Get(group='cmd', key='showType', subkey=[type, 'enabled']):
+ types += type + ','
+ types = types.rstrip(',')
+
+ menuform.GUI().ParseCommand(['d.vect', 'type=%s' % types],
+ completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'thememap':
+ # -s flag requested, otherwise only first thematic category is displayed
+ # should be fixed by C-based d.thematic.* modules
+ menuform.GUI().ParseCommand(['d.vect.thematic', '-s'],
+ completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'themechart':
+ menuform.GUI().ParseCommand(['d.vect.chart'],
+ completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'grid':
+ menuform.GUI().ParseCommand(['d.grid'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'geodesic':
+ menuform.GUI().ParseCommand(['d.geodesic'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'rhumb':
+ menuform.GUI().ParseCommand(['d.rhumbline'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'labels':
+ menuform.GUI().ParseCommand(['d.labels'], completed=(self.GetOptData,layer,params),
+ parentframe=self)
+ elif ltype == 'cmdlayer':
+ pass
+ elif ltype == 'group':
+ pass
+
+ def OnActivateLayer(self, event):
+ """!Double click on the layer item.
+ Launch property dialog, or expand/collapse group of items, etc."""
+
+ layer = event.GetItem()
+ self.layer_selected = layer
+
+ self.PropertiesDialog (layer)
+
+ if self.GetPyData(layer)[0]['type'] == 'group':
+ if self.IsExpanded(layer):
+ self.Collapse(layer)
+ else:
+ self.Expand(layer)
+
+ def OnDeleteLayer(self, event):
+ """!Remove selected layer item from the layer tree"""
+
+ item = event.GetItem()
+
+ try:
+ item.properties.Close(True)
+ except:
+ pass
+
+ if item != self.root:
+ Debug.msg (3, "LayerTree.OnDeleteLayer(): name=%s" % \
+ (self.GetItemText(item)))
+ else:
+ self.root = None
+
+ # unselect item
+ self.Unselect()
+ self.layer_selected = None
+
+ try:
+ if self.GetPyData(item)[0]['type'] != 'group':
+ self.Map.DeleteLayer( self.GetPyData(item)[0]['maplayer'])
+ except:
+ pass
+
+ # redraw map if auto-rendering is enabled
+ self.rerender = True
+ self.reorder = True
+ #if self.mapdisplay.statusbarWin['render'].GetValue():
+ # print "*** Delete OnRender *****"
+ # self.mapdisplay.OnRender(None)
+
+
+ if self.mapdisplay.toolbars['vdigit']:
+ self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers (updateTool=True)
+
+ # update progress bar range (mapwindow statusbar)
+ self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+
+ event.Skip()
+
+ def OnLayerChecked(self, event):
+ """!Enable/disable data layer"""
+ item = event.GetItem()
+ checked = item.IsChecked()
+
+ digitToolbar = self.mapdisplay.toolbars['vdigit']
+
+ if self.first == False:
+ # change active parameter for item in layers list in render.Map
+ if self.GetPyData(item)[0]['type'] == 'group':
+ child, cookie = self.GetFirstChild(item)
+ while child:
+ self.CheckItem(child, checked)
+ mapLayer = self.GetPyData(child)[0]['maplayer']
+ if not digitToolbar or \
+ (digitToolbar and digitToolbar.GetLayer() != mapLayer):
+ # ignore when map layer is edited
+ self.Map.ChangeLayerActive(mapLayer, checked)
+ child = self.GetNextSibling(child)
+ else:
+ mapLayer = self.GetPyData(item)[0]['maplayer']
+ if not digitToolbar or \
+ (digitToolbar and digitToolbar.GetLayer() != mapLayer):
+ # ignore when map layer is edited
+ self.Map.ChangeLayerActive(mapLayer, checked)
+
+ #
+ # update progress bar range (mapwindow statusbar)
+
+
+ self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+
+ #
+ # nviz
+ #
+ if self.mapdisplay.toolbars['nviz'] and \
+ self.GetPyData(item) is not None:
+ # nviz - load/unload data layer
+ mapLayer = self.GetPyData(item)[0]['maplayer']
+
+ self.mapdisplay.SetStatusText(_("Please wait, updating data..."), 0)
+
+ if checked: # enable
+ if mapLayer.type == 'raster':
+ self.mapdisplay.MapWindow.LoadRaster(item)
+ elif mapLayer.type == '3d-raster':
+ self.mapdisplay.MapWindow.LoadRaster3d(item)
+ elif mapLayer.type == 'vector':
+ self.mapdisplay.MapWindow.LoadVector(item)
+
+ else: # disable
+ data = self.GetPyData(item)[0]['nviz']
+
+ if mapLayer.type == 'raster':
+ self.mapdisplay.MapWindow.UnloadRaster(item)
+ elif mapLayer.type == '3d-raster':
+ self.mapdisplay.MapWindow.UnloadRaster3d(item)
+ elif mapLayer.type == 'vector':
+ self.mapdisplay.MapWindow.UnloadVector(item)
+
+ if hasattr(self.mapdisplay, "nvizToolWin"):
+ toolWin = self.mapdisplay.nvizToolWin
+ # remove vector page
+ if toolWin.notebook.GetSelection() == toolWin.page['vector']['id']:
+ toolWin.notebook.RemovePage(toolWin.page['vector']['id'])
+ toolWin.page['vector']['id'] = -1
+ toolWin.page['settings']['id'] = 1
+
+ self.mapdisplay.SetStatusText("", 0)
+
+ # redraw map if auto-rendering is enabled
+ self.rerender = True
+ self.reorder = True
+ #if self.mapdisplay.statusbarWin['render'].GetValue():
+ # print "*** Checked OnRender *****"
+ # self.mapdisplay.OnRender(None)
+
+ def OnCmdChanged(self, event):
+ """!Change command string"""
+ ctrl = event.GetEventObject().GetId()
+ cmd = event.GetString()
+
+ layer = self.GetFirstVisibleItem()
+
+ while layer and layer.IsOk():
+ if self.GetPyData(layer)[0]['ctrl'] == ctrl:
+ break
+
+ layer = self.GetNextVisible(layer)
+
+ # change parameters for item in layers list in render.Map
+ self.ChangeLayer(layer)
+
+ event.Skip()
+
+ def OnChangeSel(self, event):
+ """!Selection changed"""
+ oldlayer = event.GetOldItem()
+ layer = event.GetItem()
+ if layer == oldlayer:
+ event.Veto()
+ return
+
+ self.layer_selected = layer
+
+ try:
+ self.RefreshLine(oldlayer)
+ self.RefreshLine(layer)
+ except:
+ pass
+
+ #
+ # update statusbar -> show command string
+ #
+ if self.GetPyData(layer) and self.GetPyData(layer)[0]['maplayer']:
+ cmd = self.GetPyData(layer)[0]['maplayer'].GetCmd(string=True)
+ if len(cmd) > 0:
+ self.lmgr.SetStatusText(cmd)
+
+ # set region if auto-zooming is enabled
+ if self.GetPyData(layer) and self.GetPyData(layer)[0]['cmd'] and \
+ UserSettings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'):
+ mapLayer = self.GetPyData(layer)[0]['maplayer']
+ if mapLayer.GetType() in ('raster', 'vector'):
+ render = self.mapdisplay.statusbarWin['render'].IsChecked()
+ self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
+ render = render)
+
+ #
+ # update nviz tools
+ #
+
+
+ if self.mapdisplay.toolbars['nviz'] and \
+ self.GetPyData(self.layer_selected) is not None:
+
+ if self.layer_selected.IsChecked():
+ # update Nviz tool window
+ type = self.GetPyData(self.layer_selected)[0]['maplayer'].type
+
+ if type == 'raster':
+ self.mapdisplay.nvizToolWin.UpdatePage('surface')
+ self.mapdisplay.nvizToolWin.SetPage('surface')
+ elif type == 'vector':
+ self.mapdisplay.nvizToolWin.UpdatePage('vector')
+ self.mapdisplay.nvizToolWin.SetPage('vector')
+ elif type == '3d-raster':
+ self.mapdisplay.nvizToolWin.UpdatePage('volume')
+ self.mapdisplay.nvizToolWin.SetPage('volume')
+ else:
+ for page in ('surface', 'vector', 'volume'):
+ pageId = self.mapdisplay.nvizToolWin.page[page]['id']
+ if pageId > -1:
+ self.mapdisplay.nvizToolWin.notebook.RemovePage(pageId)
+ self.mapdisplay.nvizToolWin.page[page]['id'] = -1
+ self.mapdisplay.nvizToolWin.page['settings']['id'] = 1
+
+ def OnCollapseNode(self, event):
+ """
+ Collapse node
+ """
+ if self.GetPyData(self.layer_selected)[0]['type'] == 'group':
+ self.SetItemImage(self.layer_selected, self.folder)
+
+ def OnExpandNode(self, event):
+ """
+ Expand node
+ """
+ self.layer_selected = event.GetItem()
+ if self.GetPyData(self.layer_selected)[0]['type'] == 'group':
+ self.SetItemImage(self.layer_selected, self.folder_open)
+
+ def OnEndDrag(self, event):
+ self.StopDragging()
+ dropTarget = event.GetItem()
+ self.flag = self.HitTest(event.GetPoint())[1]
+ if self.IsValidDropTarget(dropTarget):
+ self.UnselectAll()
+ if dropTarget != None:
+ self.SelectItem(dropTarget)
+ self.OnDrop(dropTarget, self._dragItem)
+ elif dropTarget == None:
+ self.OnDrop(dropTarget, self._dragItem)
+
+ def OnDrop(self, dropTarget, dragItem):
+ # save everthing associated with item to drag
+ try:
+ old = dragItem # make sure this member exists
+ except:
+ return
+
+ Debug.msg (4, "LayerTree.OnDrop(): layer=%s" % \
+ (self.GetItemText(dragItem)))
+
+ # recreate data layer, insert copy of layer in new position, and delete original at old position
+ newItem = self.RecreateItem (dragItem, dropTarget)
+
+ # if recreated layer is a group, also recreate its children
+ if self.GetPyData(newItem)[0]['type'] == 'group':
+ (child, cookie) = self.GetFirstChild(dragItem)
+ if child:
+ while child:
+ self.RecreateItem(child, dropTarget, parent=newItem)
+ self.Delete(child)
+ child = self.GetNextChild(old, cookie)[0]
+ #self.Expand(newItem)
+
+ # delete layer at original position
+ try:
+ self.Delete(old) # entry in render.Map layers list automatically deleted by OnDeleteLayer handler
+ except AttributeError:
+ # FIXME being ugly (item.SetWindow(None))
+ pass
+
+ # reorder layers in render.Map to match new order after drag and drop
+ #self.ReorderLayers()
+
+ # redraw map if auto-rendering is enabled
+ self.rerender = True
+ self.reorder = True
+ #if self.mapdisplay.statusbarWin['render'].GetValue():
+ # print "*** Drop OnRender *****"
+ # self.mapdisplay.OnRender(None)
+
+ # select new item
+ self.SelectItem(newItem)
+
+ def RecreateItem (self, dragItem, dropTarget, parent=None):
+ """
+ Recreate item (needed for OnEndDrag())
+ """
+ Debug.msg (4, "LayerTree.RecreateItem(): layer=%s" % \
+ self.GetItemText(dragItem))
+
+ # fetch data (dragItem)
+ checked = self.IsItemChecked(dragItem)
+ image = self.GetItemImage(dragItem, 0)
+ text = self.GetItemText(dragItem)
+ if self.GetPyData(dragItem)[0]['ctrl']:
+ # recreate data layer
+ btnbmp = Icons["layeropts"].GetBitmap((16,16))
+ newctrl = buttons.GenBitmapButton(self, id=wx.ID_ANY, bitmap=btnbmp, size=(24, 24))
+ newctrl.SetToolTipString(_("Click to edit layer settings"))
+ self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, newctrl)
+ data = self.GetPyData(dragItem)
+
+ elif self.GetPyData(dragItem)[0]['type'] == 'command':
+ # recreate command layer
+ oldctrl = None
+ newctrl = wx.TextCtrl(self, id=wx.ID_ANY, value='',
+ pos=wx.DefaultPosition, size=(250,25),
+ style=wx.TE_MULTILINE|wx.TE_WORDWRAP)
+ try:
+ newctrl.SetValue(self.GetPyData(dragItem)[0]['maplayer'].GetCmd(string=True))
+ except:
+ pass
+ newctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged)
+ newctrl.Bind(wx.EVT_TEXT, self.OnCmdChanged)
+ data = self.GetPyData(dragItem)
+
+ elif self.GetPyData(dragItem)[0]['type'] == 'group':
+ # recreate group
+ newctrl = None
+ data = None
+
+ # decide where to put recreated item
+ if dropTarget != None and dropTarget != self.GetRootItem():
+ if parent:
+ # new item is a group
+ afteritem = parent
+ else:
+ # new item is a single layer
+ afteritem = dropTarget
+
+ # dragItem dropped on group
+ if self.GetPyData(afteritem)[0]['type'] == 'group':
+ newItem = self.PrependItem(afteritem, text=text, \
+ ct_type=1, wnd=newctrl, image=image, \
+ data=data)
+ self.Expand(afteritem)
+ else:
+ #dragItem dropped on single layer
+ newparent = self.GetItemParent(afteritem)
+ newItem = self.InsertItem(newparent, self.GetPrevSibling(afteritem), \
+ text=text, ct_type=1, wnd=newctrl, \
+ image=image, data=data)
+ else:
+ # if dragItem not dropped on a layer or group, append or prepend it to the layer tree
+ if self.flag & wx.TREE_HITTEST_ABOVE:
+ newItem = self.PrependItem(self.root, text=text, \
+ ct_type=1, wnd=newctrl, image=image, \
+ data=data)
+ elif (self.flag & wx.TREE_HITTEST_BELOW) or (self.flag & wx.TREE_HITTEST_NOWHERE) \
+ or (self.flag & wx.TREE_HITTEST_TOLEFT) or (self.flag & wx.TREE_HITTEST_TORIGHT):
+ newItem = self.AppendItem(self.root, text=text, \
+ ct_type=1, wnd=newctrl, image=image, \
+ data=data)
+
+ #update new layer
+ self.SetPyData(newItem, self.GetPyData(dragItem))
+ if newctrl:
+ self.GetPyData(newItem)[0]['ctrl'] = newctrl.GetId()
+ else:
+ self.GetPyData(newItem)[0]['ctrl'] = None
+
+ self.CheckItem(newItem, checked=checked) # causes a new render
+
+ # newItem.SetHeight(TREE_ITEM_HEIGHT)
+
+ return newItem
+
+ def GetOptData(self, dcmd, layer, params, propwin):
+ """!Process layer data"""
+ # set layer text to map name
+ if dcmd:
+ mapLayer = self.GetPyData(layer)[0]['maplayer']
+ opacity = int(mapLayer.GetOpacity(float=True) * 100)
+ mapname = utils.GetLayerNameFromCmd(dcmd, layerType=mapLayer.type,
+ fullyQualified=True)
+ if not mapname:
+ wx.MessageBox(parent=self,
+ message=_("Map <%s> not found.") % utils.GetLayerNameFromCmd(dcmd),
+ caption=_("Error"),
+ style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+
+ return
+
+ self.SetItemText(layer, mapname + ' (opacity: ' + str(opacity) + '%)')
+
+ # update layer data
+ if params:
+ self.SetPyData(layer, (self.GetPyData(layer)[0], params))
+ if dcmd:
+ self.GetPyData(layer)[0]['cmd'] = dcmd
+ self.GetPyData(layer)[0]['propwin'] = propwin
+
+ # change parameters for item in layers list in render.Map
+ self.ChangeLayer(layer)
+
+ # set region if auto-zooming is enabled
+ if dcmd and UserSettings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'):
+ mapLayer = self.GetPyData(layer)[0]['maplayer']
+ if mapLayer.GetType() in ('raster', 'vector'):
+ render = UserSettings.Get(group = 'display', key = 'autoRendering', subkey = 'enabled')
+ self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
+ render = render)
+
+ if self.mapdisplay.toolbars['nviz'] and dcmd:
+ # update nviz session
+ mapLayer = self.GetPyData(layer)[0]['maplayer']
+ mapWin = self.mapdisplay.MapWindow
+ if len(mapLayer.GetCmd()) > 0:
+ id = -1
+ if mapLayer.type == 'raster':
+ if mapWin.IsLoaded(layer):
+ mapWin.UnloadRaster(layer)
+
+ mapWin.LoadRaster(layer)
+
+ elif mapLayer.type == '3d-raster':
+ if mapWin.IsLoaded(layer):
+ mapWin.UnloadRaster3d(layer)
+
+ mapWin.LoadRaster3d(layer)
+
+ elif mapLayer.type == 'vector':
+ if mapWin.IsLoaded(layer):
+ mapWin.UnloadVector(layer)
+
+ mapWin.LoadVector(layer)
+
+ # reset view when first layer loaded
+ nlayers = len(mapWin.Map.GetListOfLayers(l_type=('raster', 'vector'),
+ l_active=True))
+ if nlayers < 2:
+ mapWin.ResetView()
+
+ def ReorderLayers(self):
+ """!Add commands from data associated with
+ any valid layers (checked or not) to layer list in order to
+ match layers in layer tree."""
+
+ # make a list of visible layers
+ treelayers = []
+
+ vislayer = self.GetFirstVisibleItem()
+
+ if not vislayer or self.GetPyData(vislayer) is None:
+ return
+
+ itemList = ""
+
+ for item in range(self.GetCount()):
+ itemList += self.GetItemText(vislayer) + ','
+ if self.GetPyData(vislayer)[0]['type'] != 'group':
+ treelayers.append(self.GetPyData(vislayer)[0]['maplayer'])
+
+ if not self.GetNextVisible(vislayer):
+ break
+ else:
+ vislayer = self.GetNextVisible(vislayer)
+
+ Debug.msg (4, "LayerTree.ReorderLayers(): items=%s" % \
+ (itemList))
+
+ # reorder map layers
+ treelayers.reverse()
+ self.Map.ReorderLayers(treelayers)
+ self.reorder = False
+
+ def ChangeLayer(self, item):
+ """!Change layer"""
+ type = self.GetPyData(item)[0]['type']
+ layerName = None
+
+ if type == 'command':
+ win = self.FindWindowById(self.GetPyData(item)[0]['ctrl'])
+ if win.GetValue() != None:
+ cmd = win.GetValue().split(';')
+ cmdlist = []
+ for c in cmd:
+ cmdlist.append(c.split(' '))
+ opac = 1.0
+ chk = self.IsItemChecked(item)
+ hidden = not self.IsVisible(item)
+ elif type != 'group':
+ if self.GetPyData(item)[0] is not None:
+ cmdlist = self.GetPyData(item)[0]['cmd']
+ opac = self.GetPyData(item)[0]['maplayer'].GetOpacity(float=True)
+ chk = self.IsItemChecked(item)
+ hidden = not self.IsVisible(item)
+ # determine layer name
+ layerName = utils.GetLayerNameFromCmd(cmdlist, fullyQualified=True)
+ if not layerName:
+ layerName = self.GetItemText(item)
+
+ maplayer = self.Map.ChangeLayer(layer=self.GetPyData(item)[0]['maplayer'], type=type,
+ command=cmdlist, name=layerName,
+ l_active=chk, l_hidden=hidden, l_opacity=opac, l_render=False)
+
+ self.GetPyData(item)[0]['maplayer'] = maplayer
+
+ # if digitization tool enabled -> update list of available vector map layers
+ if self.mapdisplay.toolbars['vdigit']:
+ self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool=True)
+
+ # redraw map if auto-rendering is enabled
+ self.rerender = True
+ self.reorder = True
+ #if self.mapdisplay.statusbarWin['render'].GetValue():
+ # print "*** Change OnRender *****"
+ # self.mapdisplay.OnRender(None)
+
+ def OnCloseWindow(self, event):
+ pass
+ # self.Map.Clean()
+
+ def FindItemByData(self, key, value):
+ """!Find item based on key and value (see PyData[0])"""
+ item = self.GetFirstChild(self.root)[0]
+ return self.__FindSubItemByData(item, key, value)
+
+ def EnableItemType(self, type, enable=True):
+ """!Enable/disable items in layer tree"""
+ item = self.GetFirstChild(self.root)[0]
+ while item and item.IsOk():
+ mapLayer = self.GetPyData(item)[0]['maplayer']
+ if mapLayer and type == mapLayer.type:
+ self.EnableItem(item, enable)
+
+ item = self.GetNextSibling(item)
+
+ def __FindSubItemByData(self, item, key, value):
+ """!Support method for FindItemByValue"""
+ while item and item.IsOk():
+ itemValue = self.GetPyData(item)[0][key]
+ if value == itemValue:
+ return item
+ if self.GetPyData(item)[0]['type'] == 'group':
+ subItem = self.GetFirstChild(item)[0]
+ found = self.__FindSubItemByData(subItem, key, value)
+ if found:
+ return found
+ item = self.GetNextSibling(item)
+
+ return None
+
More information about the grass-commit
mailing list