2 @package lmgr.layertree
4 @brief Utility classes for map layer management.
9 (C) 2007-2013 by the GRASS Development Team
11 This program is free software under the GNU General Public License
12 (>=v2). Read the file COPYING that comes with GRASS for details.
14 @author Michael Barton (Arizona State University)
15 @author Jachym Cepicky (Mendel University of Agriculture)
16 @author Martin Landa <landa.martin gmail.com>
22 import wx.lib.agw.customtreectrl
as CT
24 import wx.lib.customtreectrl
as CT
25 import wx.lib.buttons
as buttons
29 from wx.lib.mixins
import treemixin
34 from core
import globalvar
36 from gui_core.forms
import GUI
46 from icons.icon
import MetaIcon
51 'rastImport' : MetaIcon(img =
'layer-import',
52 label = _(
'Import raster data')),
53 'rastLink' : MetaIcon(img =
'layer-import',
54 label = _(
'Link external raster data')),
55 'rastOut' : MetaIcon(img =
'layer-export',
56 label = _(
'Set raster output format')),
57 'vectImport' : MetaIcon(img =
'layer-import',
58 label = _(
'Import vector data')),
59 'vectLink' : MetaIcon(img =
'layer-import',
60 label = _(
'Link external vector data')),
61 'vectOut' : MetaIcon(img =
'layer-export',
62 label = _(
'Set vector output format')),
63 'addCmd' : MetaIcon(img =
'layer-command-add',
64 label = _(
'Add command layer')),
65 'quit' : MetaIcon(img =
'quit',
67 'addRgb' : MetaIcon(img =
'layer-rgb-add',
68 label = _(
'Add RGB map layer')),
69 'addHis' : MetaIcon(img =
'layer-his-add',
70 label = _(
'Add HIS map layer')),
71 'addShaded' : MetaIcon(img =
'layer-shaded-relief-add',
72 label = _(
'Add shaded relief map layer')),
73 'addRArrow' : MetaIcon(img =
'layer-aspect-arrow-add',
74 label = _(
'Add raster flow arrows')),
75 'addRNum' : MetaIcon(img =
'layer-cell-cats-add',
76 label = _(
'Add raster cell numbers')),
77 'addThematic': MetaIcon(img =
'layer-vector-thematic-add',
78 label = _(
'Add thematic area (choropleth) map layer')),
79 'addChart' : MetaIcon(img =
'layer-vector-chart-add',
80 label = _(
'Add thematic chart layer')),
81 'addGrid' : MetaIcon(img =
'layer-grid-add',
82 label = _(
'Add grid layer')),
83 'addGeodesic': MetaIcon(img =
'shortest-distance',
84 label = _(
'Add geodesic line layer')),
85 'addRhumb' : MetaIcon(img =
'shortest-distance',
86 label = _(
'Add rhumbline layer')),
87 'addLabels' : MetaIcon(img =
'layer-label-add',
88 label = _(
'Add labels')),
89 'addRast3d' : MetaIcon(img =
'layer-raster3d-add',
90 label = _(
'Add 3D raster map layer'),
91 desc = _(
'Note that 3D raster data are rendered only in 3D view mode')),
92 'layerOptions' : MetaIcon(img =
'options',
93 label = _(
'Set options')),
96 class LayerTree(treemixin.DragAndDrop, CT.CustomTreeCtrl):
97 """!Creates layer tree structure
100 id = wx.ID_ANY, style = wx.SUNKEN_BORDER,
101 ctstyle = CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT |
102 CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT |
103 CT.TR_MULTIPLE, **kwargs):
105 if 'style' in kwargs:
106 ctstyle |= kwargs[
'style']
113 del kwargs[
'notebook']
116 showMapDisplay = kwargs[
'showMapDisplay']
117 del kwargs[
'showMapDisplay']
133 ctstyle |= CT.TR_ALIGN_WINDOWS
134 except AttributeError:
138 super(LayerTree, self).
__init__(parent, id, agwStyle = ctstyle, **kwargs)
140 super(LayerTree, self).
__init__(parent, id, style = ctstyle, **kwargs)
141 self.SetName(
"LayerTree")
146 self.SetGradientStyle(1)
147 self.EnableSelectionGradient(
True)
153 id = wx.ID_ANY, pos = pos,
154 size = globalvar.MAP_WINDOW_SIZE,
155 style = wx.DEFAULT_FRAME_STYLE,
156 tree = self, notebook = self.
notebook,
161 self.mapdisplay.SetTitle(_(
"GRASS GIS %(version)s Map Display: %(id)d - Location: %(loc)s") % \
162 {
'version' : grass.version()[
'version'],
164 'loc' : grass.gisenv()[
"LOCATION_NAME"] })
167 if showMapDisplay
is True:
168 self.mapdisplay.Show()
169 self.mapdisplay.Refresh()
170 self.mapdisplay.Update()
172 self.
root = self.AddRoot(_(
"Map Layers"))
173 self.SetPyData(self.
root, (
None,
None))
176 il = wx.ImageList(16, 16, mask =
False)
178 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16))
180 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
184 trgif = BaseIcons[
"addRast"].GetBitmap(bmpsize)
187 trgif = LMIcons[
"addRast3d"].GetBitmap(bmpsize)
190 trgif = LMIcons[
"addRgb"].GetBitmap(bmpsize)
193 trgif = LMIcons[
"addHis"].GetBitmap(bmpsize)
196 trgif = LMIcons[
"addShaded"].GetBitmap(bmpsize)
199 trgif = LMIcons[
"addRArrow"].GetBitmap(bmpsize)
202 trgif = LMIcons[
"addRNum"].GetBitmap(bmpsize)
205 trgif = BaseIcons[
"addVect"].GetBitmap(bmpsize)
208 trgif = LMIcons[
"addThematic"].GetBitmap(bmpsize)
211 trgif = LMIcons[
"addChart"].GetBitmap(bmpsize)
214 trgif = LMIcons[
"addGrid"].GetBitmap(bmpsize)
217 trgif = LMIcons[
"addGeodesic"].GetBitmap(bmpsize)
220 trgif = LMIcons[
"addRhumb"].GetBitmap(bmpsize)
223 trgif = LMIcons[
"addLabels"].GetBitmap(bmpsize)
226 trgif = LMIcons[
"addCmd"].GetBitmap(bmpsize)
229 self.AssignImageList(il)
231 self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.
OnExpandNode)
234 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.
OnChangeSel)
240 self.Bind(wx.EVT_TREE_END_DRAG, self.
OnEndDrag)
241 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.
OnRenamed)
242 self.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
243 self.Bind(wx.EVT_IDLE, self.
OnIdle)
244 self.Bind(wx.EVT_MOTION, self.
OnMotion)
246 def _setGradient(self, iType = None):
247 """!Set gradient for items
249 @param iType bgmap, vdigit or None
252 self.SetFirstGradientColour(wx.Colour(0, 100, 0))
253 self.SetSecondGradientColour(wx.Colour(0, 150, 0))
254 elif iType ==
'vdigit':
255 self.SetFirstGradientColour(wx.Colour(100, 0, 0))
256 self.SetSecondGradientColour(wx.Colour(150, 0, 0))
258 self.SetFirstGradientColour(wx.Colour(100, 100, 100))
259 self.SetSecondGradientColour(wx.Colour(150, 150, 150))
262 """Returns a list of selected items.
264 This method is copied from customtreecontrol and overriden because
265 with some version wx (?) multiple selection doesn't work.
266 Probably it is caused by another GetSelections method in treemixin.DragAndDrop?
269 idRoot = self.GetRootItem()
271 array = self.FillArray(idRoot, array)
278 """!Get map instace"""
282 """!Get associated MapFrame"""
286 """!Only re-order and re-render a composite map image from GRASS during
287 idle time instead of multiple times during layer changing.
290 if self.mapdisplay.GetToolbar(
'vdigit'):
294 if self.mapdisplay.IsAutoRendered():
295 self.mapdisplay.MapWindow2D.UpdateMap(render =
True, renderVector = vector)
296 if self.lmgr.IsPaneShown(
'toolbarNviz'):
297 self.mapdisplay.MapWindow3D.UpdateMap(render =
True)
305 key = event.GetKeyCode()
307 if key == wx.WXK_DELETE
and self.
lmgr and \
308 not self.GetEditControl():
309 self.lmgr.OnDeleteLayer(
None)
314 """!Contextual menu for item/layer"""
322 Debug.msg (4,
"LayerTree.OnContextMenu: layertype=%s" % \
325 if not hasattr (self,
"popupID"):
327 for key
in (
'remove',
'rename',
'opacity',
'nviz',
'zoom',
328 'region',
'export',
'attr',
'edit0',
'edit1',
329 'bgmap',
'topo',
'meta',
'null',
'zoom1',
'region1',
330 'color',
'hist',
'univar',
'prof',
'properties'):
337 self.popupMenu.Append(self.
popupID[
'remove'], text = _(
"Remove"))
338 self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id = self.
popupID[
'remove'])
340 if ltype !=
"command":
341 self.popupMenu.Append(self.
popupID[
'rename'], text = _(
"Rename"))
344 self.popupMenu.Enable(self.
popupID[
'rename'],
False)
347 if ltype
not in (
"group",
"command"):
348 self.popupMenu.AppendSeparator()
349 self.popupMenu.Append(self.
popupID[
'opacity'], text = _(
"Change opacity level"))
351 self.popupMenu.Append(self.
popupID[
'properties'], text = _(
"Properties"))
355 self.popupMenu.Enable(self.
popupID[
'opacity'],
False)
356 self.popupMenu.Enable(self.
popupID[
'properties'],
False)
358 if ltype
in (
'raster',
'vector',
'3d-raster')
and self.lmgr.IsPaneShown(
'toolbarNviz'):
359 self.popupMenu.Append(self.
popupID[
'nviz'], _(
"3D view properties"))
362 if ltype
in (
'raster',
'vector',
'rgb'):
363 self.popupMenu.Append(self.
popupID[
'zoom'], text = _(
"Zoom to selected map(s)"))
364 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id = self.
popupID[
'zoom'])
365 self.popupMenu.Append(self.
popupID[
'region'], text = _(
"Set computational region from selected map(s)"))
375 if mltype
and mltype ==
"vector":
376 self.popupMenu.AppendSeparator()
377 self.popupMenu.Append(self.
popupID[
'export'], text = _(
"Export"))
378 self.Bind(wx.EVT_MENU,
lambda x: self.lmgr.OnMenuCmd(cmd = [
'v.out.ogr',
379 'input=%s' % mapLayer.GetName()]),
382 self.popupMenu.AppendSeparator()
384 self.popupMenu.Append(self.
popupID[
'color'], _(
"Set color table"))
387 self.popupMenu.Append(self.
popupID[
'attr'], text = _(
"Show attribute data"))
388 self.Bind(wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id = self.
popupID[
'attr'])
390 self.popupMenu.Append(self.
popupID[
'edit0'], text = _(
"Start editing"))
391 self.popupMenu.Append(self.
popupID[
'edit1'], text = _(
"Stop editing"))
392 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
398 digitToolbar = self.mapdisplay.GetToolbar(
'vdigit')
401 self.popupMenu.Append(self.
popupID[
'bgmap'],
402 text = _(
"Use as background vector map for digitizer"),
403 kind = wx.ITEM_CHECK)
405 if UserSettings.Get(group =
'vdigit', key =
'bgmap', subkey =
'value',
406 internal =
True) == layer.GetName():
407 self.popupMenu.Check(self.
popupID[
'bgmap'],
True)
409 self.popupMenu.Append(self.
popupID[
'topo'], text = _(
"Rebuild topology"))
412 if layer.GetMapset() != grass.gisenv()[
'MAPSET']:
414 self.popupMenu.Enable (self.
popupID[
'edit0'],
False)
415 self.popupMenu.Enable (self.
popupID[
'edit1'],
False)
416 self.popupMenu.Enable (self.
popupID[
'topo'],
False)
417 elif digitToolbar
and digitToolbar.GetLayer():
419 vdigitLayer = digitToolbar.GetLayer()
420 if vdigitLayer
is layer:
421 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
422 self.popupMenu.Enable(self.
popupID[
'edit1'],
True)
423 self.popupMenu.Enable(self.
popupID[
'remove'],
False)
424 self.popupMenu.Enable(self.
popupID[
'bgmap'],
False)
425 self.popupMenu.Enable(self.
popupID[
'topo'],
False)
427 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
428 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
429 self.popupMenu.Enable(self.
popupID[
'bgmap'],
True)
431 self.popupMenu.Append(self.
popupID[
'meta'], _(
"Metadata"))
434 self.popupMenu.Enable(self.
popupID[
'attr'],
False)
435 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
436 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
437 self.popupMenu.Enable(self.
popupID[
'meta'],
False)
438 self.popupMenu.Enable(self.
popupID[
'bgmap'],
False)
439 self.popupMenu.Enable(self.
popupID[
'topo'],
False)
440 self.popupMenu.Enable(self.
popupID[
'export'],
False)
443 elif mltype
and mltype ==
"raster":
444 self.popupMenu.Append(self.
popupID[
'zoom1'], text = _(
"Zoom to selected map(s) (ignore NULLs)"))
445 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id = self.
popupID[
'zoom1'])
446 self.popupMenu.Append(self.
popupID[
'region1'], text = _(
"Set computational region from selected map(s) (ignore NULLs)"))
449 self.popupMenu.AppendSeparator()
450 self.popupMenu.Append(self.
popupID[
'export'], text = _(
"Export"))
451 self.Bind(wx.EVT_MENU,
lambda x: self.lmgr.OnMenuCmd(cmd = [
'r.out.gdal',
452 'input=%s' % mapLayer.GetName()]),
455 self.popupMenu.AppendSeparator()
456 self.popupMenu.Append(self.
popupID[
'color'], _(
"Set color table"))
458 self.popupMenu.Append(self.
popupID[
'hist'], _(
"Histogram"))
460 self.popupMenu.Append(self.
popupID[
'univar'], _(
"Univariate raster statistics"))
462 self.popupMenu.Append(self.
popupID[
'prof'], _(
"Profile"))
464 self.popupMenu.Append(self.
popupID[
'meta'], _(
"Metadata"))
468 self.popupMenu.Enable(self.
popupID[
'zoom1'],
False)
469 self.popupMenu.Enable(self.
popupID[
'region1'],
False)
470 self.popupMenu.Enable(self.
popupID[
'color'],
False)
471 self.popupMenu.Enable(self.
popupID[
'hist'],
False)
472 self.popupMenu.Enable(self.
popupID[
'univar'],
False)
473 self.popupMenu.Enable(self.
popupID[
'prof'],
False)
474 self.popupMenu.Enable(self.
popupID[
'meta'],
False)
475 self.popupMenu.Enable(self.
popupID[
'export'],
False)
476 if self.lmgr.IsPaneShown(
'toolbarNviz'):
477 self.popupMenu.Enable(self.
popupID[
'nviz'],
False)
480 self.popupMenu.Destroy()
483 """!Rebuild topology of selected vector map"""
486 'map=%s' % mapLayer.GetName()]
487 self.lmgr.goutput.RunCmd(cmd, switchPage =
True)
490 """!Print metadata of raster/vector map layer
491 TODO: Dialog to modify metadata
496 if mltype ==
'raster':
498 elif mltype ==
'vector':
500 cmd.append(
'map=%s' % mapLayer.GetName())
503 self.lmgr.goutput.RunCmd(cmd, switchPage =
True)
506 """!Set computational region from selected raster map (ignore NULLs)"""
511 'zoom=%s' % mapLayer.GetName()]
514 self.lmgr.goutput.RunCmd(cmd)
517 """!Set computational region from selected raster/vector map
523 mapLayer = self.GetPyData(layer)[0][
'maplayer']
524 mltype = self.GetPyData(layer)[0][
'type']
526 if mltype ==
'raster':
527 rast.append(mapLayer.GetName())
528 elif mltype ==
'vector':
529 vect.append(mapLayer.GetName())
530 elif mltype ==
'3d-raster':
531 rast3d.append(mapLayer.GetName())
532 elif mltype ==
'rgb':
533 for rname
in mapLayer.GetName().splitlines():
538 cmd.append(
'rast=%s' %
','.join(rast))
540 cmd.append(
'vect=%s' %
','.join(vect))
542 cmd.append(
'rast3d=%s' %
','.join(rast3d))
547 self.lmgr.goutput.RunCmd(cmd, compReg =
False)
550 """!Plot profile of given raster map layer"""
552 if not mapLayer.GetName():
553 wx.MessageBox(parent = self,
554 message = _(
"Unable to create profile of "
556 caption = _(
"Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
559 if not hasattr (self,
"profileFrame"):
562 if hasattr (self.
mapdisplay,
"profile")
and self.mapdisplay.profile:
567 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300),
568 style = wx.DEFAULT_FRAME_STYLE, rasterList = [mapLayer.GetName()])
570 self.profileFrame.Show()
573 """!Set color table for raster map"""
574 name = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
575 GUI(parent = self).ParseCommand([
'r.colors',
579 """!Set color table for vector map"""
580 name = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
581 GUI(parent = self, centreOnParent =
False).ParseCommand([
'v.colors',
585 """!Plot histogram for given raster map layer
588 if not mapLayer.GetName():
589 GError(parent = self,
590 message = _(
"Unable to display histogram of "
591 "raster map. No map name defined."))
594 win = HistogramFrame(parent = self)
598 win.SetHistLayer(mapLayer.GetName())
599 win.HistWindow.UpdateHist()
604 """!Univariate raster statistics"""
605 name = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
606 self.lmgr.goutput.RunCmd([
'r.univar',
'map=%s' % name], switchPage =
True)
609 """!Start editing vector map layer requested by the user
617 if not self.mapdisplay.GetToolbar(
'vdigit'):
618 self.mapdisplay.AddToolbar(
'vdigit')
620 if not self.mapdisplay.toolbars[
'vdigit']:
623 self.mapdisplay.toolbars[
'vdigit'].StartEditing(maplayer)
629 """!Stop editing the current vector map layer
633 self.mapdisplay.toolbars[
'vdigit'].OnExit()
635 self.lmgr.toolbars[
'tools'].Enable(
'vdigit', enable =
True)
641 """!Set background vector map for editing sesstion"""
642 digit = self.mapdisplay.GetWindow().digit
643 if event.IsChecked():
644 mapName = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
645 UserSettings.Set(group =
'vdigit', key =
'bgmap', subkey =
'value',
646 value = str(mapName), internal =
True)
647 digit.OpenBackgroundMap(mapName)
650 UserSettings.Set(group =
'vdigit', key =
'bgmap', subkey =
'value',
651 value =
'', internal =
True)
652 digit.CloseBackgroundMap()
658 """!Popup properties dialog"""
662 """!Popup opacity level indicator"""
667 current_opacity = maplayer.GetOpacity()
669 dlg = SetOpacityDialog(self, opacity = current_opacity,
670 title = _(
"Set opacity of <%s>") % maplayer.GetName())
674 if dlg.ShowModal() == wx.ID_OK:
679 """!Handles EVT_APPLY_OPACITY event."""
683 """!Change opacity value of layer
684 @param layer layer for which to change (item in layertree)
685 @param value opacity value (float between 0 and 1)
687 maplayer = self.GetPyData(layer)[0][
'maplayer']
688 self.Map.ChangeOpacity(maplayer, value)
689 maplayer.SetOpacity(value)
690 self.SetItemText(layer,
695 self.
GetMapDisplay().GetToolbar(
'vdigit').GetLayer() == maplayer:
696 alpha = int(value * 255)
703 self.
GetMapDisplay().GetWindow().UpdateMap(render =
False, renderVector = renderVector)
706 """!Nviz-related properties (raster/vector/volume)
710 self.lmgr.notebook.SetSelectionByName(
'nviz')
712 if ltype ==
'raster':
713 self.lmgr.nviz.SetPage(
'surface')
714 elif ltype ==
'vector':
715 self.lmgr.nviz.SetPage(
'vector')
716 elif ltype ==
'3d-raster':
717 self.lmgr.nviz.SetPage(
'volume')
722 self.GetEditControl().SetSelection(-1, -1)
727 self.GetPyData(item)[0][
'label'] = event.GetLabel()
732 def AddLayer(self, ltype, lname = None, lchecked = None,
733 lopacity = 1.0, lcmd =
None, lgroup =
None, lvdigit =
None, lnviz =
None, multiple =
True):
734 """!Add new item to the layer tree, create corresponding MapLayer instance.
735 Launch property dialog if needed (raster, vector, etc.)
737 @param ltype layer type (raster, vector, 3d-raster, ...)
738 @param lname layer name
739 @param lchecked if True layer is checked
740 @param lopacity layer opacity level
741 @param lcmd command (given as a list)
742 @param lgroup index of group item (-1 for root) or None
743 @param lvdigit vector digitizer settings (eg. geometry attributes)
744 @param lnviz layer Nviz properties
745 @param multiple True to allow multiple map layers in layer tree
747 if lname
and not multiple:
749 item = self.GetFirstVisibleItem()
750 while item
and item.IsOk():
751 if self.GetPyData(item)[0][
'type'] ==
'vector':
752 name = self.GetPyData(item)[0][
'maplayer'].GetName()
755 item = self.GetNextVisible(item)
764 Debug.msg (3,
"LayerTree().AddLayer(): ltype=%s" % (ltype))
766 if ltype ==
'command':
771 elif ltype ==
'group':
774 grouptext = _(
'Layer group:') + str(self.
groupnode)
777 btnbmp = LMIcons[
"layerOptions"].GetBitmap((16,16))
778 ctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24,24))
779 ctrl.SetToolTipString(_(
"Click to edit layer settings"))
787 text =
'', ct_type = 1, wnd = ctrl)
792 layer = self.AppendItem(parentId = self.
root,
793 text =
'', ct_type = 1, wnd = ctrl)
799 layer = self.AppendItem(parentId = parent,
800 text =
'', ct_type = 1, wnd = ctrl)
804 layer = self.InsertItem(parentId = parent,
806 text =
'', ct_type = 1, wnd = ctrl)
808 layer = self.PrependItem(parent = self.
root, text =
'', ct_type = 1, wnd = ctrl)
812 if lchecked
is not None:
818 self.CheckItem(layer, checked = checked)
821 label = _(
'(double click to set properties)') +
' ' * 15
822 if ltype ==
'raster':
824 self.SetItemText(layer,
'%s %s' % (_(
'raster'), label))
825 elif ltype ==
'3d-raster':
827 self.SetItemText(layer,
'%s %s' % (_(
'3D raster'), label))
829 self.SetItemImage(layer, self.
rgb_icon)
830 self.SetItemText(layer,
'%s %s' % (_(
'RGB'), label))
832 self.SetItemImage(layer, self.
his_icon)
833 self.SetItemText(layer,
'%s %s' % (_(
'HIS'), label))
834 elif ltype ==
'shaded':
836 self.SetItemText(layer,
'%s %s' % (_(
'shaded relief'), label))
837 elif ltype ==
'rastnum':
839 self.SetItemText(layer,
'%s %s' % (_(
'raster cell numbers'), label))
840 elif ltype ==
'rastarrow':
842 self.SetItemText(layer,
'%s %s' % (_(
'raster flow arrows'), label))
843 elif ltype ==
'vector':
845 self.SetItemText(layer,
'%s %s' % (_(
'vector'), label))
846 elif ltype ==
'thememap':
848 self.SetItemText(layer,
'%s %s' % (_(
'thematic map'), label))
849 elif ltype ==
'themechart':
851 self.SetItemText(layer,
'%s %s' % (_(
'thematic charts'), label))
852 elif ltype ==
'grid':
854 self.SetItemText(layer,
'%s %s' % (_(
'grid'), label))
855 elif ltype ==
'geodesic':
857 self.SetItemText(layer,
'%s %s' % (_(
'geodesic line'), label))
858 elif ltype ==
'rhumb':
860 self.SetItemText(layer,
'%s %s' % (_(
'rhumbline'), label))
861 elif ltype ==
'labels':
863 self.SetItemText(layer,
'%s %s' % (_(
'vector labels'), label))
864 elif ltype ==
'command':
865 self.SetItemImage(layer, self.
cmd_icon)
866 elif ltype ==
'group':
867 self.SetItemImage(layer, self.
folder)
868 self.SetItemText(layer, grouptext)
873 if lcmd
and len(lcmd) > 1:
879 if ltype ==
'command' and lname:
880 for c
in lname.split(
';'):
881 cmd.append(c.split(
' '))
887 ctrlId = ctrl.GetId()
892 self.SetPyData(layer, ({
'cmd' : cmd,
903 prevItem = self.GetFirstChild(self.
root)[0]
906 while prevItem
and prevItem.IsOk()
and prevItem != layer:
907 if self.GetPyData(prevItem)[0][
'maplayer']:
908 prevMapLayer = self.GetPyData(prevItem)[0][
'maplayer']
910 prevItem = self.GetNextSibling(prevItem)
913 pos = self.Map.GetLayerIndex(prevMapLayer)
917 maplayer = self.Map.AddLayer(pos = pos,
918 type = ltype, command = self.GetPyData(layer)[0][
'cmd'], name = name,
919 l_active = checked, l_hidden =
False,
920 l_opacity = lopacity, l_render = render)
921 self.GetPyData(layer)[0][
'maplayer'] = maplayer
928 self.SetPyData(layer, ({
'cmd' :
None,
937 self.SelectItem(layer, select =
True)
943 self.SetItemText(layer, lname)
944 elif ltype ==
'command':
951 self.mapdisplay.GetProgressBar().
SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
956 """!Launch the properties dialog"""
957 if 'propwin' in self.GetPyData(layer)[0]
and \
958 self.GetPyData(layer)[0][
'propwin']
is not None:
960 win = self.GetPyData(layer)[0][
'propwin']
969 params = self.GetPyData(layer)[1]
970 ltype = self.GetPyData(layer)[0][
'type']
972 Debug.msg (3,
"LayerTree.PropertiesDialog(): ltype=%s" % \
976 if self.GetPyData(layer)[0][
'cmd']:
977 module = GUI(parent = self, show = show, centreOnParent =
False)
978 module.ParseCommand(self.GetPyData(layer)[0][
'cmd'],
981 self.GetPyData(layer)[0][
'cmd'] = module.GetCmd()
982 elif ltype ==
'raster':
984 if UserSettings.Get(group=
'cmd', key=
'rasterOverlay', subkey=
'enabled'):
987 elif ltype ==
'3d-raster':
988 cmd = [
'd.rast3d.py']
992 if UserSettings.Get(group=
'cmd', key=
'rasterOverlay', subkey=
'enabled'):
998 elif ltype ==
'shaded':
999 cmd = [
'd.shadedmap']
1001 elif ltype ==
'rastarrow':
1002 cmd = [
'd.rast.arrow']
1004 elif ltype ==
'rastnum':
1005 cmd = [
'd.rast.num']
1007 elif ltype ==
'vector':
1009 for ftype
in [
'point',
'line',
'boundary',
'centroid',
'area',
'face']:
1010 if UserSettings.Get(group =
'cmd', key =
'showType', subkey = [ftype,
'enabled']):
1013 cmd = [
'd.vect',
'type=%s' %
','.join(types)]
1015 elif ltype ==
'thememap':
1018 cmd = [
'd.vect.thematic',
'-s']
1020 elif ltype ==
'themechart':
1021 cmd = [
'd.vect.chart']
1023 elif ltype ==
'grid':
1026 elif ltype ==
'geodesic':
1027 cmd = [
'd.geodesic']
1029 elif ltype ==
'rhumb':
1030 cmd = [
'd.rhumbline']
1032 elif ltype ==
'labels':
1036 GUI(parent = self, centreOnParent =
False).ParseCommand(cmd,
1040 """!Double click on the layer item.
1041 Launch property dialog, or expand/collapse group of items, etc.
1043 self.lmgr.WorkspaceChanged()
1044 layer = event.GetItem()
1049 if self.GetPyData(layer)[0][
'type'] ==
'group':
1050 if self.IsExpanded(layer):
1051 self.Collapse(layer)
1056 """!Remove selected layer item from the layer tree"""
1057 self.lmgr.WorkspaceChanged()
1058 item = event.GetItem()
1061 item.properties.Close(
True)
1065 if item != self.
root:
1066 Debug.msg (3,
"LayerTree.OnDeleteLayer(): name=%s" % \
1067 (self.GetItemText(item)))
1076 if self.GetPyData(item)[0][
'type'] !=
'group':
1077 self.Map.DeleteLayer( self.GetPyData(item)[0][
'maplayer'])
1085 if self.mapdisplay.GetToolbar(
'vdigit'):
1086 self.mapdisplay.toolbars[
'vdigit'].UpdateListOfLayers (updateTool =
True)
1089 self.mapdisplay.GetProgressBar().
SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
1094 if self.lmgr.IsPaneShown(
'toolbarNviz')
and \
1095 self.GetPyData(item)
is not None:
1097 mapLayer = self.GetPyData(item)[0][
'maplayer']
1098 self.mapdisplay.SetStatusText(_(
"Please wait, updating data..."), 0)
1099 if mapLayer.type ==
'raster':
1100 self.mapdisplay.MapWindow.UnloadRaster(item)
1101 elif mapLayer.type ==
'3d-raster':
1102 self.mapdisplay.MapWindow.UnloadRaster3d(item)
1103 elif mapLayer.type ==
'vector':
1104 self.mapdisplay.MapWindow.UnloadVector(item)
1105 self.mapdisplay.SetStatusText(
"", 0)
1110 """!Layer checkbox is being checked.
1112 Continue only if mouse is above checkbox or layer was checked programatically.
1121 """!Enable/disable data layer"""
1122 self.lmgr.WorkspaceChanged()
1124 item = event.GetItem()
1125 checked = item.IsChecked()
1127 digitToolbar = self.mapdisplay.GetToolbar(
'vdigit')
1130 if self.GetPyData(item)[0][
'type'] ==
'group':
1131 child, cookie = self.GetFirstChild(item)
1134 self.CheckItem(child, checked)
1135 mapLayer = self.GetPyData(child)[0][
'maplayer']
1136 if not digitToolbar
or \
1137 (digitToolbar
and digitToolbar.GetLayer() != mapLayer):
1139 self.Map.ChangeLayerActive(mapLayer, checked)
1140 child = self.GetNextSibling(child)
1142 mapLayer = self.GetPyData(item)[0][
'maplayer']
1143 if not digitToolbar
or \
1144 (digitToolbar
and digitToolbar.GetLayer() != mapLayer):
1146 self.Map.ChangeLayerActive(mapLayer, checked)
1149 self.mapdisplay.GetProgressBar().
SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
1152 if self.lmgr.IsPaneShown(
'toolbarNviz')
and \
1153 self.GetPyData(item)
is not None:
1155 mapLayer = self.GetPyData(item)[0][
'maplayer']
1157 self.mapdisplay.SetStatusText(_(
"Please wait, updating data..."), 0)
1160 if mapLayer.type ==
'raster':
1161 self.mapdisplay.MapWindow.LoadRaster(item)
1162 elif mapLayer.type ==
'3d-raster':
1163 self.mapdisplay.MapWindow.LoadRaster3d(item)
1164 elif mapLayer.type ==
'vector':
1165 vInfo = gvector.vector_info_topo(mapLayer.GetName())
1166 if (vInfo[
'points'] + vInfo[
'centroids']) > 0:
1167 self.mapdisplay.MapWindow.LoadVector(item, points =
True)
1168 if (vInfo[
'lines'] + vInfo[
'boundaries']) > 0:
1169 self.mapdisplay.MapWindow.LoadVector(item, points =
False)
1172 if mapLayer.type ==
'raster':
1173 self.mapdisplay.MapWindow.UnloadRaster(item)
1174 elif mapLayer.type ==
'3d-raster':
1175 self.mapdisplay.MapWindow.UnloadRaster3d(item)
1176 elif mapLayer.type ==
'vector':
1177 self.mapdisplay.MapWindow.UnloadVector(item)
1179 self.mapdisplay.SetStatusText(
"", 0)
1186 """!Change command string"""
1187 ctrl = event.GetEventObject().GetId()
1188 cmd = event.GetString()
1191 layer = self.GetFirstVisibleItem()
1192 while layer
and layer.IsOk():
1193 if self.GetPyData(layer)[0][
'ctrl'] == ctrl:
1195 layer = self.GetNextVisible(layer)
1203 """!Mouse is moving.
1205 Detects if mouse points at checkbox.
1207 thisItem, flags = self.HitTest(event.GetPosition())
1211 if (flags & CT.TREE_HITTEST_ONITEMCHECKICON)
and not (flags & CT.TREE_HITTEST_ONITEMLABEL):
1218 """!Selection is changing.
1220 If the user is clicking on checkbox, selection change is vetoed.
1226 """!Selection changed"""
1227 layer = event.GetItem()
1228 digitToolbar = self.mapdisplay.GetToolbar(
'vdigit')
1230 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1231 bgmap = UserSettings.Get(group =
'vdigit', key =
'bgmap', subkey =
'value',
1234 if digitToolbar.GetLayer() == mapLayer:
1236 elif bgmap == mapLayer.GetName():
1246 if self.IsSelected(oldlayer):
1247 self.SetItemWindowEnabled(oldlayer,
True)
1249 self.SetItemWindowEnabled(oldlayer,
False)
1251 if self.IsSelected(layer):
1252 self.SetItemWindowEnabled(layer,
True)
1254 self.SetItemWindowEnabled(layer,
False)
1259 self.RefreshLine(oldlayer)
1260 self.RefreshLine(layer)
1265 if self.GetPyData(layer)
and self.GetPyData(layer)[0][
'maplayer']:
1266 cmd = self.GetPyData(layer)[0][
'maplayer'].GetCmd(string =
True)
1268 self.lmgr.SetStatusText(cmd)
1271 if self.GetPyData(layer)
and self.GetPyData(layer)[0][
'cmd']
and \
1272 UserSettings.Get(group =
'display', key =
'autoZooming', subkey =
'enabled'):
1273 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1274 if mapLayer.GetType()
in (
'raster',
'vector'):
1275 render = self.mapdisplay.IsAutoRendered()
1276 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
1280 if self.lmgr.IsPaneShown(
'toolbarNviz')
and \
1282 if self.layer_selected.IsChecked():
1286 if type ==
'raster':
1287 self.lmgr.nviz.UpdatePage(
'surface')
1288 self.lmgr.nviz.SetPage(
'surface')
1289 elif type ==
'vector':
1290 self.lmgr.nviz.UpdatePage(
'vector')
1291 self.lmgr.nviz.SetPage(
'vector')
1292 elif type ==
'3d-raster':
1293 self.lmgr.nviz.UpdatePage(
'volume')
1294 self.lmgr.nviz.SetPage(
'volume')
1311 dropTarget = event.GetItem()
1312 self.
flag = self.HitTest(event.GetPoint())[1]
1313 if self.IsValidDropTarget(dropTarget):
1315 if dropTarget !=
None:
1316 self.SelectItem(dropTarget)
1317 self.
OnDrop(dropTarget, self._dragItem)
1318 elif dropTarget ==
None:
1319 self.
OnDrop(dropTarget, self._dragItem)
1328 Debug.msg (4,
"LayerTree.OnDrop(): layer=%s" % \
1329 (self.GetItemText(dragItem)))
1335 if self.GetPyData(newItem)[0][
'type'] ==
'group':
1336 (child, cookie) = self.GetFirstChild(dragItem)
1341 child = self.GetNextChild(old, cookie)[0]
1346 except AttributeError:
1354 self.SelectItem(newItem)
1357 """!Recreate item (needed for OnEndDrag())
1359 Debug.msg (4,
"LayerTree.RecreateItem(): layer=%s" % \
1360 self.GetItemText(dragItem))
1363 checked = self.IsItemChecked(dragItem)
1364 image = self.GetItemImage(dragItem, 0)
1365 text = self.GetItemText(dragItem)
1367 if self.GetPyData(dragItem)[0][
'type'] ==
'command':
1371 newctrl.SetValue(self.GetPyData(dragItem)[0][
'maplayer'].GetCmd(string =
True))
1375 data = self.GetPyData(dragItem)
1377 elif self.GetPyData(dragItem)[0][
'ctrl']:
1379 btnbmp = LMIcons[
"layerOptions"].GetBitmap((16,16))
1380 newctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24, 24))
1381 newctrl.SetToolTipString(_(
"Click to edit layer settings"))
1383 data = self.GetPyData(dragItem)
1385 elif self.GetPyData(dragItem)[0][
'type'] ==
'group':
1391 if dropTarget !=
None and dropTarget != self.GetRootItem():
1397 afteritem = dropTarget
1400 if self.GetPyData(afteritem)[0][
'type'] ==
'group':
1401 newItem = self.PrependItem(afteritem, text = text, \
1402 ct_type = 1, wnd = newctrl, image = image, \
1404 self.Expand(afteritem)
1407 newparent = self.GetItemParent(afteritem)
1408 newItem = self.InsertItem(newparent, self.GetPrevSibling(afteritem), \
1409 text = text, ct_type = 1, wnd = newctrl, \
1410 image = image, data = data)
1413 if self.
flag & wx.TREE_HITTEST_ABOVE:
1414 newItem = self.PrependItem(self.
root, text = text, \
1415 ct_type = 1, wnd = newctrl, image = image, \
1417 elif (self.
flag & wx.TREE_HITTEST_BELOW)
or (self.
flag & wx.TREE_HITTEST_NOWHERE) \
1418 or (self.
flag & wx.TREE_HITTEST_TOLEFT)
or (self.
flag & wx.TREE_HITTEST_TORIGHT):
1419 newItem = self.AppendItem(self.
root, text = text, \
1420 ct_type = 1, wnd = newctrl, image = image, \
1424 self.SetPyData(newItem, self.GetPyData(dragItem))
1426 self.GetPyData(newItem)[0][
'ctrl'] = newctrl.GetId()
1428 self.GetPyData(newItem)[0][
'ctrl'] =
None
1431 self.CheckItem(newItem, checked = checked)
1435 def _getLayerName(self, item, lname = ''):
1436 """!Get layer name string
1438 @param lname optional layer name
1440 mapLayer = self.GetPyData(item)[0][
'maplayer']
1442 lname = self.GetPyData(item)[0][
'label']
1443 opacity = int(mapLayer.GetOpacity(float =
True) * 100)
1445 dcmd = self.GetPyData(item)[0][
'cmd']
1447 fullyQualified =
True)
1452 return lname +
' (%s %d' % (_(
'opacity:'), opacity) +
'%)'
1457 """!Process layer data (when changes in propertiesdialog are applied)"""
1460 self.GetPyData(layer)[0][
'cmd'] = dcmd
1463 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1464 self.SetItemText(layer, mapName)
1466 if not mapText
or not found:
1468 GWarning(parent = self,
1469 message = _(
"Map <%s> not found.") % mapName)
1474 self.SetPyData(layer, (self.GetPyData(layer)[0], params))
1475 self.GetPyData(layer)[0][
'propwin'] = propwin
1481 if dcmd
and UserSettings.Get(group =
'display', key =
'autoZooming', subkey =
'enabled'):
1482 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1483 if mapLayer.GetType()
in (
'raster',
'vector'):
1484 render = UserSettings.Get(group =
'display', key =
'autoRendering', subkey =
'enabled')
1485 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
1489 if self.lmgr.IsPaneShown(
'toolbarNviz')
and dcmd:
1490 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1491 mapWin = self.mapdisplay.MapWindow
1492 if len(mapLayer.GetCmd()) > 0:
1494 if mapLayer.type ==
'raster':
1495 if mapWin.IsLoaded(layer):
1496 mapWin.UnloadRaster(layer)
1498 mapWin.LoadRaster(layer)
1500 elif mapLayer.type ==
'3d-raster':
1501 if mapWin.IsLoaded(layer):
1502 mapWin.UnloadRaster3d(layer)
1504 mapWin.LoadRaster3d(layer)
1506 elif mapLayer.type ==
'vector':
1507 if mapWin.IsLoaded(layer):
1508 mapWin.UnloadVector(layer)
1510 mapWin.LoadVector(layer)
1513 nlayers = len(mapWin.Map.GetListOfLayers(l_type = (
'raster',
'3d-raster',
'vector'),
1519 """!Add commands from data associated with any valid layers
1520 (checked or not) to layer list in order to match layers in
1526 vislayer = self.GetFirstVisibleItem()
1528 if not vislayer
or self.GetPyData(vislayer)
is None:
1533 for item
in range(self.GetCount()):
1534 itemList += self.GetItemText(vislayer) +
','
1535 if self.GetPyData(vislayer)[0][
'type'] !=
'group':
1536 treelayers.append(self.GetPyData(vislayer)[0][
'maplayer'])
1538 if not self.GetNextVisible(vislayer):
1541 vislayer = self.GetNextVisible(vislayer)
1543 Debug.msg (4,
"LayerTree.ReorderLayers(): items=%s" % \
1547 treelayers.reverse()
1548 self.Map.ReorderLayers(treelayers)
1553 type = self.GetPyData(item)[0][
'type']
1556 if type ==
'command':
1557 win = self.FindWindowById(self.GetPyData(item)[0][
'ctrl'])
1558 if win.GetValue() !=
None:
1559 cmd = win.GetValue().
split(
';')
1562 cmdlist.append(c.split(
' '))
1564 chk = self.IsItemChecked(item)
1565 hidden =
not self.IsVisible(item)
1566 elif type !=
'group':
1567 if self.GetPyData(item)[0]
is not None:
1568 cmdlist = self.GetPyData(item)[0][
'cmd']
1569 opac = self.GetPyData(item)[0][
'maplayer'].GetOpacity(float =
True)
1570 chk = self.IsItemChecked(item)
1571 hidden =
not self.IsVisible(item)
1575 layerName = self.GetItemText(item)
1577 maplayer = self.Map.ChangeLayer(layer = self.GetPyData(item)[0][
'maplayer'], type = type,
1578 command = cmdlist, name = layerName,
1579 l_active = chk, l_hidden = hidden, l_opacity = opac, l_render =
False)
1581 self.GetPyData(item)[0][
'maplayer'] = maplayer
1584 if self.mapdisplay.GetToolbar(
'vdigit'):
1585 self.mapdisplay.GetToolbar(
'vdigit').UpdateListOfLayers(updateTool =
True)
1595 """!Find item based on key and value (see PyData[0])
1597 @return item instance
1598 @return None not found
1600 item = self.GetFirstChild(self.root)[0]
1601 return self.__FindSubItemByData(item, key, value)
1604 """!Find item by index (starting at 0)
1606 @return item instance
1607 @return None not found
1609 item = self.GetFirstChild(self.
root)[0]
1611 while item
and item.IsOk():
1615 item = self.GetNextVisible(item)
1621 """!Enable/disable items in layer tree"""
1622 item = self.GetFirstChild(self.
root)[0]
1623 while item
and item.IsOk():
1624 mapLayer = self.GetPyData(item)[0][
'maplayer']
1625 if mapLayer
and type == mapLayer.type:
1626 self.EnableItem(item, enable)
1628 item = self.GetNextSibling(item)
1630 def __FindSubItemByData(self, item, key, value):
1631 """!Support method for FindItemByValue"""
1632 while item
and item.IsOk():
1634 itemValue = self.GetPyData(item)[0][key]
1638 if value == itemValue:
1640 if self.GetPyData(item)[0][
'type'] ==
'group':
1641 subItem = self.GetFirstChild(item)[0]
1645 item = self.GetNextSibling(item)
1649 def _createCommandCtrl(self):
1650 """!Creates text control for command layer"""
1652 if sys.platform
in (
'win32',
'darwin'):
1654 ctrl = wx.TextCtrl(self, id = wx.ID_ANY, value =
'',
1655 size = (self.GetSize()[0]-100, height),
1656 style = wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
def OnRenamed
Layer renamed.
def FindItemByIndex
Find item by index (starting at 0)
def OnChangingSel
Selection is changing.
def _setGradient
Set gradient for items.
def OnSetCompRegFromRaster
Set computational region from selected raster map (ignore NULLs)
def OnMetadata
Print metadata of raster/vector map layer TODO: Dialog to modify metadata.
def OnActivateLayer
Double click on the layer item.
def OnIdle
Only re-order and re-render a composite map image from GRASS during idle time instead of multiple tim...
def OnLayerChecking
Layer checkbox is being checked.
def GetMapDisplay
Get associated MapFrame.
def __FindSubItemByData
Support method for FindItemByValue.
def FindItemByData
Find item based on key and value (see PyData[0])
Creates layer tree structure.
Map display with toolbar for various display management functions, and additional toolbars (vector di...
mapdisplay
SetAutoLayout() causes that no vertical scrollbar is displayed when some layers are not visible in la...
def OnMotion
Mouse is moving.
def RecreateItem
Recreate item (needed for OnEndDrag())
def GetOptData
Process layer data (when changes in propertiesdialog are applied)
def _createCommandCtrl
Creates text control for command layer.
def ChangeLayerOpacity
Change opacity value of layer.
Various dialogs used in wxGUI.
Rendering map layers and overlays into map composition image.
def split
Platform spefic shlex.split.
def OnCollapseNode
Collapse node.
def OnRasterColorTable
Set color table for raster map.
def OnCmdChanged
Change command string.
def OnNvizProperties
Nviz-related properties (raster/vector/volume)
def OnPopupOpacityLevel
Popup opacity level indicator.
def ChangeLayer
Change layer.
def GetLayerNameFromCmd
Get map name from GRASS command.
Plotting histogram based on d.histogram.
def ReorderLayers
Add commands from data associated with any valid layers (checked or not) to layer list in order to ma...
def OnChangeSel
Selection changed.
def OnProfile
Plot profile of given raster map layer.
def OnExpandNode
Expand node.
def OnSetCompRegFromMap
Set computational region from selected raster/vector map.
def OnStartEditing
Start editing vector map layer requested by the user.
def OnApplyLayerOpacity
Handles EVT_APPLY_OPACITY event.
def AddLayer
Add new item to the layer tree, create corresponding MapLayer instance.
Misc utilities for wxGUI.
def OnLayerChecked
Enable/disable data layer.
def OnRenameLayer
Rename layer.
def OnDeleteLayer
Remove selected layer item from the layer tree.
def OnSetBgMap
Set background vector map for editing sesstion.
def GetMap
Get map instace.
def PropertiesDialog
Launch the properties dialog.
def OnLayerContextMenu
Contextual menu for item/layer.
def OnPopupProperties
Popup properties dialog.
def _getLayerName
Get layer name string.
def OnVectorColorTable
Set color table for vector map.
def OnTopology
Rebuild topology of selected vector map.
def OnStopEditing
Stop editing the current vector map layer.
def EnableItemType
Enable/disable items in layer tree.
def OnUnivariateStats
Univariate raster statistics.
def OnHistogram
Plot histogram for given raster map layer.