4 @brief Utility classes for map layer management.
11 (C) 2007-2011 by the GRASS Development Team
12 This program is free software under the GNU General Public
13 License (>=v2). Read the file COPYING that comes with GRASS
16 @author Michael Barton (Arizona State University)
17 @author Jachym Cepicky (Mendel University of Agriculture)
18 @author Martin Landa <landa.martin gmail.com>
27 import wx.lib.agw.customtreectrl
as CT
29 import wx.lib.customtreectrl
as CT
31 import wx.lib.newevent
32 import wx.lib.buttons
as buttons
36 from wx.lib.mixins
import treemixin
50 from debug
import Debug
as Debug
51 from icon
import Icons
as Icons
52 from preferences
import globalSettings
as UserSettings
53 from vdigit
import haveVDigit
54 from gcmd
import GWarning
58 class LayerTree(treemixin.DragAndDrop, CT.CustomTreeCtrl):
59 """!Creates layer tree structure
62 id = wx.ID_ANY, style = wx.SUNKEN_BORDER,
63 ctstyle = CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT |
64 CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT |
65 CT.TR_MULTIPLE, **kwargs):
68 ctstyle |= kwargs[
'style']
75 del kwargs[
'notebook']
78 showMapDisplay = kwargs[
'showMapDisplay']
79 del kwargs[
'showMapDisplay']
93 ctstyle |= CT.TR_ALIGN_WINDOWS
94 except AttributeError:
98 super(LayerTree, self).
__init__(parent, id, agwStyle = ctstyle, **kwargs)
100 super(LayerTree, self).
__init__(parent, id, style = ctstyle, **kwargs)
101 self.SetName(
"LayerTree")
106 self.SetGradientStyle(1)
107 self.EnableSelectionGradient(
True)
113 id = wx.ID_ANY, pos = pos,
114 size = globalvar.MAP_WINDOW_SIZE,
115 style = wx.DEFAULT_FRAME_STYLE,
116 tree = self, notebook = self.
notebook,
121 self.mapdisplay.SetTitle(_(
"GRASS GIS Map Display: %(id)d - Location: %(loc)s") % \
123 'loc' : grass.gisenv()[
"LOCATION_NAME"] })
126 if showMapDisplay
is True:
127 self.mapdisplay.Show()
128 self.mapdisplay.Refresh()
129 self.mapdisplay.Update()
131 self.
root = self.AddRoot(_(
"Map Layers"))
132 self.SetPyData(self.
root, (
None,
None))
135 il = wx.ImageList(16, 16, mask =
False)
137 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16))
139 trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
143 icons = Icons[
'layerManager']
144 trgif = icons[
"addRast"].GetBitmap(bmpsize)
147 trgif = icons[
"addRast3d"].GetBitmap(bmpsize)
150 trgif = icons[
"addRgb"].GetBitmap(bmpsize)
153 trgif = icons[
"addHis"].GetBitmap(bmpsize)
156 trgif = icons[
"addShaded"].GetBitmap(bmpsize)
159 trgif = icons[
"addRArrow"].GetBitmap(bmpsize)
162 trgif = icons[
"addRNum"].GetBitmap(bmpsize)
165 trgif = icons[
"addVect"].GetBitmap(bmpsize)
168 trgif = icons[
"addThematic"].GetBitmap(bmpsize)
171 trgif = icons[
"addChart"].GetBitmap(bmpsize)
174 trgif = icons[
"addGrid"].GetBitmap(bmpsize)
177 trgif = icons[
"addGeodesic"].GetBitmap(bmpsize)
180 trgif = icons[
"addRhumb"].GetBitmap(bmpsize)
183 trgif = icons[
"addLabels"].GetBitmap(bmpsize)
186 trgif = icons[
"addCmd"].GetBitmap(bmpsize)
189 self.AssignImageList(il)
191 self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.
OnExpandNode)
194 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.
OnChangeSel)
198 self.Bind(wx.EVT_TREE_END_DRAG, self.
OnEndDrag)
199 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.
OnRenamed)
200 self.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
201 self.Bind(wx.EVT_IDLE, self.
OnIdle)
203 def _setGradient(self, iType = None):
204 """!Set gradient for items
206 @param iType bgmap, vdigit or None
209 self.SetFirstGradientColour(wx.Colour(0, 100, 0))
210 self.SetSecondGradientColour(wx.Colour(0, 150, 0))
211 elif iType ==
'vdigit':
212 self.SetFirstGradientColour(wx.Colour(100, 0, 0))
213 self.SetSecondGradientColour(wx.Colour(150, 0, 0))
215 self.SetFirstGradientColour(wx.Colour(100, 100, 100))
216 self.SetSecondGradientColour(wx.Colour(150, 150, 150))
219 """!Get map instace"""
223 """!Get associated MapFrame"""
227 """!Only re-order and re-render a composite map image from GRASS during
228 idle time instead of multiple times during layer changing.
231 if self.mapdisplay.toolbars[
'vdigit']:
235 if self.mapdisplay.statusbarWin[
'render'].GetValue():
236 self.mapdisplay.MapWindow.UpdateMap(render =
True, renderVector = vector)
244 key = event.GetKeyCode()
246 if key == wx.WXK_DELETE
and self.
lmgr and \
247 not self.GetEditControl():
248 self.lmgr.OnDeleteLayer(
None)
253 """!Contextual menu for item/layer"""
261 Debug.msg (4,
"LayerTree.OnContextMenu: layertype=%s" % \
264 if not hasattr (self,
"popupID"):
266 for key
in (
'remove',
'rename',
'opacity',
'nviz',
'zoom',
267 'region',
'export',
'attr',
'edit0',
'edit1',
268 'bgmap',
'topo',
'meta',
'null',
'zoom1',
'region1',
269 'color',
'hist',
'univar',
'prof',
'properties'):
274 numSelected = len(self.GetSelections())
276 self.popupMenu.Append(self.
popupID[
'remove'], text = _(
"Remove"))
277 self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id = self.
popupID[
'remove'])
279 if ltype !=
"command":
280 self.popupMenu.Append(self.
popupID[
'rename'], text = _(
"Rename"))
283 self.popupMenu.Enable(self.
popupID[
'rename'],
False)
286 if ltype
not in (
"group",
"command"):
287 self.popupMenu.AppendSeparator()
288 self.popupMenu.Append(self.
popupID[
'opacity'], text = _(
"Change opacity level"))
290 self.popupMenu.Append(self.
popupID[
'properties'], text = _(
"Properties"))
294 self.popupMenu.Enable(self.
popupID[
'opacity'],
False)
295 self.popupMenu.Enable(self.
popupID[
'properties'],
False)
297 if ltype
in (
'raster',
'vector',
'3d-raster')
and self.mapdisplay.toolbars[
'nviz']:
298 self.popupMenu.Append(self.
popupID[
'nviz'], _(
"3D view properties"))
301 if ltype
in (
'raster',
'vector',
'rgb'):
302 self.popupMenu.Append(self.
popupID[
'zoom'], text = _(
"Zoom to selected map(s)"))
303 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id = self.
popupID[
'zoom'])
304 self.popupMenu.Append(self.
popupID[
'region'], text = _(
"Set computational region from selected map(s)"))
314 if mltype
and mltype ==
"vector":
315 self.popupMenu.AppendSeparator()
316 self.popupMenu.Append(self.
popupID[
'export'], text = _(
"Export"))
317 self.Bind(wx.EVT_MENU,
lambda x: self.lmgr.OnMenuCmd(cmd = [
'v.out.ogr',
318 'input=%s' % mapLayer.GetName()]),
321 self.popupMenu.AppendSeparator()
322 self.popupMenu.Append(self.
popupID[
'attr'], text = _(
"Show attribute data"))
323 self.Bind(wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id = self.
popupID[
'attr'])
325 self.popupMenu.Append(self.
popupID[
'edit0'], text = _(
"Start editing"))
326 self.popupMenu.Append(self.
popupID[
'edit1'], text = _(
"Stop editing"))
327 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
333 digitToolbar = self.mapdisplay.toolbars[
'vdigit']
336 self.popupMenu.Append(self.
popupID[
'bgmap'],
337 text = _(
"Use as background vector map for digitizer"),
338 kind = wx.ITEM_CHECK)
340 if UserSettings.Get(group =
'vdigit', key =
'bgmap', subkey =
'value',
341 internal =
True) == layer.GetName():
342 self.popupMenu.Check(self.
popupID[
'bgmap'],
True)
344 self.popupMenu.Append(self.
popupID[
'topo'], text = _(
"Rebuild topology"))
347 if layer.GetMapset() != grass.gisenv()[
'MAPSET']:
349 self.popupMenu.Enable (self.
popupID[
'edit0'],
False)
350 self.popupMenu.Enable (self.
popupID[
'edit1'],
False)
351 self.popupMenu.Enable (self.
popupID[
'topo'],
False)
352 elif digitToolbar
and digitToolbar.GetLayer():
354 vdigitLayer = digitToolbar.GetLayer()
355 if vdigitLayer
is layer:
356 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
357 self.popupMenu.Enable(self.
popupID[
'edit1'],
True)
358 self.popupMenu.Enable(self.
popupID[
'remove'],
False)
359 self.popupMenu.Enable(self.
popupID[
'bgmap'],
False)
360 self.popupMenu.Enable(self.
popupID[
'topo'],
False)
362 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
363 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
364 self.popupMenu.Enable(self.
popupID[
'bgmap'],
True)
366 self.popupMenu.Append(self.
popupID[
'meta'], _(
"Metadata"))
369 self.popupMenu.Enable(self.
popupID[
'attr'],
False)
370 self.popupMenu.Enable(self.
popupID[
'edit0'],
False)
371 self.popupMenu.Enable(self.
popupID[
'edit1'],
False)
372 self.popupMenu.Enable(self.
popupID[
'meta'],
False)
373 self.popupMenu.Enable(self.
popupID[
'bgmap'],
False)
374 self.popupMenu.Enable(self.
popupID[
'topo'],
False)
375 self.popupMenu.Enable(self.
popupID[
'export'],
False)
378 elif mltype
and mltype ==
"raster":
379 self.popupMenu.Append(self.
popupID[
'zoom1'], text = _(
"Zoom to selected map(s) (ignore NULLs)"))
380 self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id = self.
popupID[
'zoom1'])
381 self.popupMenu.Append(self.
popupID[
'region1'], text = _(
"Set computational region from selected map(s) (ignore NULLs)"))
384 self.popupMenu.AppendSeparator()
385 self.popupMenu.Append(self.
popupID[
'export'], text = _(
"Export"))
386 self.Bind(wx.EVT_MENU,
lambda x: self.lmgr.OnMenuCmd(cmd = [
'r.out.gdal',
387 'input=%s' % mapLayer.GetName()]),
390 self.popupMenu.AppendSeparator()
391 self.popupMenu.Append(self.
popupID[
'color'], _(
"Set color table"))
393 self.popupMenu.Append(self.
popupID[
'hist'], _(
"Histogram"))
395 self.popupMenu.Append(self.
popupID[
'univar'], _(
"Univariate raster statistics"))
397 self.popupMenu.Append(self.
popupID[
'prof'], _(
"Profile"))
399 self.popupMenu.Append(self.
popupID[
'meta'], _(
"Metadata"))
403 self.popupMenu.Enable(self.
popupID[
'zoom1'],
False)
404 self.popupMenu.Enable(self.
popupID[
'region1'],
False)
405 self.popupMenu.Enable(self.
popupID[
'color'],
False)
406 self.popupMenu.Enable(self.
popupID[
'hist'],
False)
407 self.popupMenu.Enable(self.
popupID[
'univar'],
False)
408 self.popupMenu.Enable(self.
popupID[
'prof'],
False)
409 self.popupMenu.Enable(self.
popupID[
'meta'],
False)
410 self.popupMenu.Enable(self.
popupID[
'nviz'],
False)
411 self.popupMenu.Enable(self.
popupID[
'export'],
False)
414 self.popupMenu.Destroy()
417 """!Rebuild topology of selected vector map"""
420 'map=%s' % mapLayer.GetName()]
421 self.lmgr.goutput.RunCmd(cmd, switchPage =
True)
424 """!Print metadata of raster/vector map layer
425 TODO: Dialog to modify metadata
430 if mltype ==
'raster':
432 elif mltype ==
'vector':
434 cmd.append(
'map=%s' % mapLayer.GetName())
437 self.lmgr.goutput.RunCmd(cmd, switchPage =
True)
440 """!Set computational region from selected raster map (ignore NULLs)"""
445 'zoom=%s' % mapLayer.GetName()]
448 self.lmgr.goutput.RunCmd(cmd)
451 """!Set computational region from selected raster/vector map
456 for layer
in self.GetSelections():
457 mapLayer = self.GetPyData(layer)[0][
'maplayer']
458 mltype = self.GetPyData(layer)[0][
'type']
460 if mltype ==
'raster':
461 rast.append(mapLayer.GetName())
462 elif mltype ==
'vector':
463 vect.append(mapLayer.GetName())
464 elif mltype ==
'3d-raster':
465 rast3d.append(mapLayer.GetName())
466 elif mltype ==
'rgb':
467 for rname
in mapLayer.GetName().splitlines():
472 cmd.append(
'rast=%s' %
','.join(rast))
474 cmd.append(
'vect=%s' %
','.join(vect))
476 cmd.append(
'rast3d=%s' %
','.join(rast3d))
481 self.lmgr.goutput.RunCmd(cmd)
484 """!Plot profile of given raster map layer"""
486 if not mapLayer.GetName():
487 wx.MessageBox(parent = self,
488 message = _(
"Unable to create profile of "
490 caption = _(
"Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
493 if not hasattr (self,
"profileFrame"):
496 if hasattr (self.
mapdisplay,
"profile")
and self.mapdisplay.profile:
501 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300),
502 style = wx.DEFAULT_FRAME_STYLE, rasterList = [mapLayer.GetName()])
504 self.profileFrame.Show()
507 """!Set color table for raster map"""
508 name = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
514 Plot histogram for given raster map layer
517 if not mapLayer.GetName():
518 wx.MessageBox(parent = self,
519 message = _(
"Unable to display histogram of "
521 caption = _(
"Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
524 if not hasattr (self,
"histogramFrame"):
527 if hasattr (self.
mapdisplay,
"histogram")
and self.mapdisplay.histogram:
533 pos = wx.DefaultPosition, size = globalvar.HIST_WINDOW_SIZE,
534 style = wx.DEFAULT_FRAME_STYLE)
536 self.histogramFrame.Show()
538 self.histogramFrame.SetHistLayer(mapLayer.GetName())
539 self.histogramFrame.HistWindow.UpdateHist()
540 self.histogramFrame.Refresh()
541 self.histogramFrame.Update()
546 """!Univariate raster statistics"""
547 name = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
552 """!Start editing vector map layer requested by the user
560 if not self.mapdisplay.toolbars[
'vdigit']:
561 self.mapdisplay.AddToolbar(
'vdigit')
563 if not self.mapdisplay.toolbars[
'vdigit']:
566 self.mapdisplay.toolbars[
'vdigit'].StartEditing(maplayer)
572 """!Stop editing the current vector map layer
576 self.mapdisplay.toolbars[
'vdigit'].OnExit()
578 self.lmgr.toolbars[
'tools'].Enable(
'vdigit', enable =
True)
584 """!Set background vector map for editing sesstion"""
585 digit = self.mapdisplay.GetWindow().digit
586 if event.IsChecked():
587 mapName = self.GetPyData(self.
layer_selected)[0][
'maplayer'].GetName()
588 UserSettings.Set(group =
'vdigit', key =
'bgmap', subkey =
'value',
589 value = str(mapName), internal =
True)
590 digit.OpenBackgroundMap(mapName)
593 UserSettings.Set(group =
'vdigit', key =
'bgmap', subkey =
'value',
594 value =
'', internal =
True)
595 digit.CloseBackgroundMap()
601 """!Popup properties dialog"""
605 """!Popup opacity level indicator"""
610 current_opacity = maplayer.GetOpacity()
613 title = _(
"Set opacity <%s>") % maplayer.GetName())
616 if dlg.ShowModal() == wx.ID_OK:
617 new_opacity = dlg.GetOpacity()
618 self.Map.ChangeOpacity(maplayer, new_opacity)
619 maplayer.SetOpacity(new_opacity)
624 if self.mapdisplay.toolbars[
'vdigit']
and \
625 self.mapdisplay.toolbars[
'vdigit'].GetLayer() == maplayer:
626 alpha = int(new_opacity * 255)
627 self.mapdisplay.GetWindow().digit.GetDisplay().UpdateSettings(alpha = alpha)
634 """!Nviz-related properties (raster/vector/volume)
638 self.lmgr.notebook.SetSelectionByName(
'nviz')
640 if ltype ==
'raster':
641 self.lmgr.nviz.SetPage(
'surface')
642 elif ltype ==
'vector':
643 self.lmgr.nviz.SetPage(
'vector')
644 elif ltype ==
'3d-raster':
645 self.lmgr.nviz.SetPage(
'volume')
650 self.GetEditControl().SetSelection(-1, -1)
655 self.GetPyData(item)[0][
'label'] = event.GetLabel()
660 def AddLayer(self, ltype, lname = None, lchecked = None,
661 lopacity = 1.0, lcmd =
None, lgroup =
None, lvdigit =
None, lnviz =
None, multiple =
True):
662 """!Add new item to the layer tree, create corresponding MapLayer instance.
663 Launch property dialog if needed (raster, vector, etc.)
665 @param ltype layer type (raster, vector, 3d-raster, ...)
666 @param lname layer name
667 @param lchecked if True layer is checked
668 @param lopacity layer opacity level
669 @param lcmd command (given as a list)
670 @param lgroup index of group item (-1 for root) or None
671 @param lvdigit vector digitizer settings (eg. geometry attributes)
672 @param lnviz layer Nviz properties
673 @param multiple True to allow multiple map layers in layer tree
675 if lname
and not multiple:
677 item = self.GetFirstVisibleItem()
678 while item
and item.IsOk():
679 if self.GetPyData(item)[0][
'type'] ==
'vector':
680 name = self.GetPyData(item)[0][
'maplayer'].GetName()
683 item = self.GetNextVisible(item)
692 Debug.msg (3,
"LayerTree().AddLayer(): ltype=%s" % (ltype))
694 if ltype ==
'command':
696 ctrl = wx.TextCtrl(self, id = wx.ID_ANY, value =
'',
697 pos = wx.DefaultPosition, size = (self.GetSize()[0]-100,25),
699 style = wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
702 elif ltype ==
'group':
705 grouptext = _(
'Layer group:') + str(self.
groupnode)
708 btnbmp = Icons[
'layerManager'][
"layerOptions"].GetBitmap((16,16))
709 ctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24,24))
710 ctrl.SetToolTipString(_(
"Click to edit layer settings"))
718 text =
'', ct_type = 1, wnd = ctrl)
723 layer = self.AppendItem(parentId = self.
root,
724 text =
'', ct_type = 1, wnd = ctrl)
730 layer = self.AppendItem(parentId = parent,
731 text =
'', ct_type = 1, wnd = ctrl)
735 layer = self.InsertItem(parentId = parent,
737 text =
'', ct_type = 1, wnd = ctrl)
739 layer = self.PrependItem(parent = self.
root, text =
'', ct_type = 1, wnd = ctrl)
743 if lchecked
is not None:
748 self.CheckItem(layer, checked = checked)
751 label = _(
'(double click to set properties)') +
' ' * 15
752 if ltype ==
'raster':
754 self.SetItemText(layer,
'%s %s' % (_(
'raster'), label))
755 elif ltype ==
'3d-raster':
757 self.SetItemText(layer,
'%s %s' % (_(
'3d raster'), label))
759 self.SetItemImage(layer, self.
rgb_icon)
760 self.SetItemText(layer,
'%s %s' % (_(
'RGB'), label))
762 self.SetItemImage(layer, self.
his_icon)
763 self.SetItemText(layer,
'%s %s' % (_(
'HIS'), label))
764 elif ltype ==
'shaded':
766 self.SetItemText(layer,
'%s %s' % (_(
'Shaded relief'), label))
767 elif ltype ==
'rastnum':
769 self.SetItemText(layer,
'%s %s' % (_(
'raster cell numbers'), label))
770 elif ltype ==
'rastarrow':
772 self.SetItemText(layer,
'%s %s' % (_(
'raster flow arrows'), label))
773 elif ltype ==
'vector':
775 self.SetItemText(layer,
'%s %s' % (_(
'vector'), label))
776 elif ltype ==
'thememap':
778 self.SetItemText(layer,
'%s %s' % (_(
'thematic map'), label))
779 elif ltype ==
'themechart':
781 self.SetItemText(layer,
'%s %s' % (_(
'thematic charts'), label))
782 elif ltype ==
'grid':
784 self.SetItemText(layer,
'%s %s' % (_(
'grid'), label))
785 elif ltype ==
'geodesic':
787 self.SetItemText(layer,
'%s %s' % (_(
'geodesic line'), label))
788 elif ltype ==
'rhumb':
790 self.SetItemText(layer,
'%s %s' % (_(
'rhumbline'), label))
791 elif ltype ==
'labels':
793 self.SetItemText(layer,
'%s %s' % (_(
'vector labels'), label))
794 elif ltype ==
'command':
795 self.SetItemImage(layer, self.
cmd_icon)
796 elif ltype ==
'group':
797 self.SetItemImage(layer, self.
folder)
798 self.SetItemText(layer, grouptext)
803 if lcmd
and len(lcmd) > 1:
806 name, found = utils.GetLayerNameFromCmd(lcmd)
809 if ltype ==
'command' and lname:
810 for c
in lname.split(
';'):
811 cmd.append(c.split(
' '))
817 ctrlId = ctrl.GetId()
822 self.SetPyData(layer, ({
'cmd' : cmd,
833 prevItem = self.GetFirstChild(self.
root)[0]
836 while prevItem
and prevItem.IsOk()
and prevItem != layer:
837 if self.GetPyData(prevItem)[0][
'maplayer']:
838 prevMapLayer = self.GetPyData(prevItem)[0][
'maplayer']
840 prevItem = self.GetNextSibling(prevItem)
843 pos = self.Map.GetLayerIndex(prevMapLayer)
847 maplayer = self.Map.AddLayer(pos = pos,
848 type = ltype, command = self.GetPyData(layer)[0][
'cmd'], name = name,
849 l_active = checked, l_hidden =
False,
850 l_opacity = lopacity, l_render = render)
851 self.GetPyData(layer)[0][
'maplayer'] = maplayer
858 self.SetPyData(layer, ({
'cmd' :
None,
867 self.SelectItem(layer, select =
True)
873 self.SetItemText(layer, lname)
874 elif ltype ==
'command':
881 self.mapdisplay.statusbarWin[
'progress'].SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
886 """!Launch the properties dialog"""
887 if 'propwin' in self.GetPyData(layer)[0]
and \
888 self.GetPyData(layer)[0][
'propwin']
is not None:
890 win = self.GetPyData(layer)[0][
'propwin']
892 win.notebookpanel.OnUpdateSelection(
None)
901 params = self.GetPyData(layer)[1]
902 ltype = self.GetPyData(layer)[0][
'type']
904 Debug.msg (3,
"LayerTree.PropertiesDialog(): ltype=%s" % \
907 if self.GetPyData(layer)[0][
'cmd']:
908 module =
menuform.GUI(parent = self, show = show, centreOnParent =
False)
909 module.ParseCommand(self.GetPyData(layer)[0][
'cmd'],
912 self.GetPyData(layer)[0][
'cmd'] = module.GetCmd()
913 elif ltype ==
'raster':
916 if UserSettings.Get(group=
'cmd', key=
'rasterOverlay', subkey=
'enabled'):
919 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand(cmd,
922 elif ltype ==
'3d-raster':
924 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand(cmd,
928 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.rgb'],
932 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.his'],
935 elif ltype ==
'shaded':
936 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.shadedmap'],
939 elif ltype ==
'rastarrow':
940 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.rast.arrow'],
943 elif ltype ==
'rastnum':
944 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.rast.num'],
947 elif ltype ==
'vector':
949 for ftype
in [
'point',
'line',
'boundary',
'centroid',
'area',
'face']:
950 if UserSettings.Get(group =
'cmd', key =
'showType', subkey = [ftype,
'enabled']):
953 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.vect',
'type=%s' %
','.join(types)],
956 elif ltype ==
'thememap':
959 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.vect.thematic',
'-s'],
962 elif ltype ==
'themechart':
963 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.vect.chart'],
966 elif ltype ==
'grid':
967 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.grid'],
970 elif ltype ==
'geodesic':
971 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.geodesic'],
974 elif ltype ==
'rhumb':
975 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.rhumbline'],
978 elif ltype ==
'labels':
979 menuform.GUI(parent = self, centreOnParent =
False).ParseCommand([
'd.labels'],
982 elif ltype ==
'cmdlayer':
984 elif ltype ==
'group':
988 """!Double click on the layer item.
989 Launch property dialog, or expand/collapse group of items, etc.
991 self.lmgr.WorkspaceChanged()
992 layer = event.GetItem()
997 if self.GetPyData(layer)[0][
'type'] ==
'group':
998 if self.IsExpanded(layer):
1004 """!Remove selected layer item from the layer tree"""
1005 self.lmgr.WorkspaceChanged()
1006 item = event.GetItem()
1009 item.properties.Close(
True)
1013 if item != self.
root:
1014 Debug.msg (3,
"LayerTree.OnDeleteLayer(): name=%s" % \
1015 (self.GetItemText(item)))
1024 if self.GetPyData(item)[0][
'type'] !=
'group':
1025 self.Map.DeleteLayer( self.GetPyData(item)[0][
'maplayer'])
1033 if self.mapdisplay.toolbars[
'vdigit']:
1034 self.mapdisplay.toolbars[
'vdigit'].UpdateListOfLayers (updateTool =
True)
1037 self.mapdisplay.statusbarWin[
'progress'].SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
1042 """!Enable/disable data layer"""
1043 self.lmgr.WorkspaceChanged()
1045 item = event.GetItem()
1046 checked = item.IsChecked()
1048 digitToolbar = self.mapdisplay.toolbars[
'vdigit']
1049 if self.
first ==
False:
1051 if self.GetPyData(item)[0][
'type'] ==
'group':
1052 child, cookie = self.GetFirstChild(item)
1054 self.CheckItem(child, checked)
1055 mapLayer = self.GetPyData(child)[0][
'maplayer']
1056 if not digitToolbar
or \
1057 (digitToolbar
and digitToolbar.GetLayer() != mapLayer):
1059 self.Map.ChangeLayerActive(mapLayer, checked)
1060 child = self.GetNextSibling(child)
1062 mapLayer = self.GetPyData(item)[0][
'maplayer']
1063 if not digitToolbar
or \
1064 (digitToolbar
and digitToolbar.GetLayer() != mapLayer):
1066 self.Map.ChangeLayerActive(mapLayer, checked)
1071 self.mapdisplay.statusbarWin[
'progress'].SetRange(len(self.Map.GetListOfLayers(l_active =
True)))
1076 if self.mapdisplay.toolbars[
'nviz']
and \
1077 self.GetPyData(item)
is not None:
1079 mapLayer = self.GetPyData(item)[0][
'maplayer']
1081 self.mapdisplay.SetStatusText(_(
"Please wait, updating data..."), 0)
1084 if mapLayer.type ==
'raster':
1085 self.mapdisplay.MapWindow.LoadRaster(item)
1086 elif mapLayer.type ==
'3d-raster':
1087 self.mapdisplay.MapWindow.LoadRaster3d(item)
1088 elif mapLayer.type ==
'vector':
1089 npoints, nlines, nfeatures, mapIs3D = self.lmgr.nviz.VectorInfo(mapLayer)
1091 self.mapdisplay.MapWindow.LoadVector(item, points =
True)
1093 self.mapdisplay.MapWindow.LoadVector(item, points =
False)
1096 if mapLayer.type ==
'raster':
1097 self.mapdisplay.MapWindow.UnloadRaster(item)
1098 elif mapLayer.type ==
'3d-raster':
1099 self.mapdisplay.MapWindow.UnloadRaster3d(item)
1100 elif mapLayer.type ==
'vector':
1101 self.mapdisplay.MapWindow.UnloadVector(item)
1103 self.mapdisplay.SetStatusText(
"", 0)
1110 """!Change command string"""
1111 ctrl = event.GetEventObject().GetId()
1112 cmd = event.GetString()
1114 layer = self.GetFirstVisibleItem()
1116 while layer
and layer.IsOk():
1117 if self.GetPyData(layer)[0][
'ctrl'] == ctrl:
1120 layer = self.GetNextVisible(layer)
1128 """!Selection changed"""
1129 oldlayer = event.GetOldItem()
1130 layer = event.GetItem()
1131 if layer == oldlayer:
1135 digitToolbar = self.mapdisplay.toolbars[
'vdigit']
1137 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1138 bgmap = UserSettings.Get(group =
'vdigit', key =
'bgmap', subkey =
'value',
1141 if digitToolbar.GetLayer() == mapLayer:
1143 elif bgmap == mapLayer.GetName():
1153 if self.IsSelected(oldlayer):
1154 self.SetItemWindowEnabled(oldlayer,
True)
1156 self.SetItemWindowEnabled(oldlayer,
False)
1158 if self.IsSelected(layer):
1159 self.SetItemWindowEnabled(layer,
True)
1161 self.SetItemWindowEnabled(layer,
False)
1166 self.RefreshLine(oldlayer)
1167 self.RefreshLine(layer)
1172 if self.GetPyData(layer)
and self.GetPyData(layer)[0][
'maplayer']:
1173 cmd = self.GetPyData(layer)[0][
'maplayer'].GetCmd(string =
True)
1175 self.lmgr.SetStatusText(cmd)
1178 if self.GetPyData(layer)
and self.GetPyData(layer)[0][
'cmd']
and \
1179 UserSettings.Get(group =
'display', key =
'autoZooming', subkey =
'enabled'):
1180 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1181 if mapLayer.GetType()
in (
'raster',
'vector'):
1182 render = self.mapdisplay.statusbarWin[
'render'].IsChecked()
1183 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
1187 if self.mapdisplay.toolbars[
'nviz']
and \
1189 if self.layer_selected.IsChecked():
1193 if type ==
'raster':
1194 self.lmgr.nviz.UpdatePage(
'surface')
1195 self.lmgr.nviz.SetPage(
'surface')
1196 elif type ==
'vector':
1197 self.lmgr.nviz.UpdatePage(
'vector')
1198 self.lmgr.nviz.SetPage(
'vector')
1199 elif type ==
'3d-raster':
1200 self.lmgr.nviz.UpdatePage(
'volume')
1201 self.lmgr.nviz.SetPage(
'volume')
1218 dropTarget = event.GetItem()
1219 self.
flag = self.HitTest(event.GetPoint())[1]
1220 if self.IsValidDropTarget(dropTarget):
1222 if dropTarget !=
None:
1223 self.SelectItem(dropTarget)
1224 self.
OnDrop(dropTarget, self._dragItem)
1225 elif dropTarget ==
None:
1226 self.
OnDrop(dropTarget, self._dragItem)
1235 Debug.msg (4,
"LayerTree.OnDrop(): layer=%s" % \
1236 (self.GetItemText(dragItem)))
1242 if self.GetPyData(newItem)[0][
'type'] ==
'group':
1243 (child, cookie) = self.GetFirstChild(dragItem)
1248 child = self.GetNextChild(old, cookie)[0]
1253 except AttributeError:
1261 self.SelectItem(newItem)
1264 """!Recreate item (needed for OnEndDrag())
1266 Debug.msg (4,
"LayerTree.RecreateItem(): layer=%s" % \
1267 self.GetItemText(dragItem))
1270 checked = self.IsItemChecked(dragItem)
1271 image = self.GetItemImage(dragItem, 0)
1272 text = self.GetItemText(dragItem)
1273 if self.GetPyData(dragItem)[0][
'ctrl']:
1275 btnbmp = Icons[
'layerManager'][
"layerOptions"].GetBitmap((16,16))
1276 newctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24, 24))
1277 newctrl.SetToolTipString(_(
"Click to edit layer settings"))
1279 data = self.GetPyData(dragItem)
1281 elif self.GetPyData(dragItem)[0][
'type'] ==
'command':
1284 newctrl = wx.TextCtrl(self, id = wx.ID_ANY, value =
'',
1285 pos = wx.DefaultPosition, size = (250,25),
1286 style = wx.TE_MULTILINE|wx.TE_WORDWRAP)
1288 newctrl.SetValue(self.GetPyData(dragItem)[0][
'maplayer'].GetCmd(string =
True))
1293 data = self.GetPyData(dragItem)
1295 elif self.GetPyData(dragItem)[0][
'type'] ==
'group':
1301 if dropTarget !=
None and dropTarget != self.GetRootItem():
1307 afteritem = dropTarget
1310 if self.GetPyData(afteritem)[0][
'type'] ==
'group':
1311 newItem = self.PrependItem(afteritem, text = text, \
1312 ct_type = 1, wnd = newctrl, image = image, \
1314 self.Expand(afteritem)
1317 newparent = self.GetItemParent(afteritem)
1318 newItem = self.InsertItem(newparent, self.GetPrevSibling(afteritem), \
1319 text = text, ct_type = 1, wnd = newctrl, \
1320 image = image, data = data)
1323 if self.
flag & wx.TREE_HITTEST_ABOVE:
1324 newItem = self.PrependItem(self.
root, text = text, \
1325 ct_type = 1, wnd = newctrl, image = image, \
1327 elif (self.
flag & wx.TREE_HITTEST_BELOW)
or (self.
flag & wx.TREE_HITTEST_NOWHERE) \
1328 or (self.
flag & wx.TREE_HITTEST_TOLEFT)
or (self.
flag & wx.TREE_HITTEST_TORIGHT):
1329 newItem = self.AppendItem(self.
root, text = text, \
1330 ct_type = 1, wnd = newctrl, image = image, \
1334 self.SetPyData(newItem, self.GetPyData(dragItem))
1336 self.GetPyData(newItem)[0][
'ctrl'] = newctrl.GetId()
1338 self.GetPyData(newItem)[0][
'ctrl'] =
None
1340 self.CheckItem(newItem, checked = checked)
1344 def _getLayerName(self, item, lname = ''):
1345 """!Get layer name string
1347 @param lname optional layer name
1349 mapLayer = self.GetPyData(item)[0][
'maplayer']
1351 lname = self.GetPyData(item)[0][
'label']
1352 opacity = int(mapLayer.GetOpacity(float =
True) * 100)
1354 dcmd = self.GetPyData(item)[0][
'cmd']
1355 lname, found = utils.GetLayerNameFromCmd(dcmd, layerType = mapLayer.GetType(),
1356 fullyQualified =
True)
1361 return lname +
' (%s %d' % (_(
'opacity:'), opacity) +
'%)'
1366 """!Process layer data (when changes in propertiesdialog are applied)"""
1369 self.GetPyData(layer)[0][
'cmd'] = dcmd
1371 mapName, found = utils.GetLayerNameFromCmd(dcmd)
1372 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1373 self.SetItemText(layer, mapName)
1375 if not mapText
or not found:
1377 GWarning(parent = self,
1378 message = _(
"Map <%s> not found.") % mapName)
1383 self.SetPyData(layer, (self.GetPyData(layer)[0], params))
1384 self.GetPyData(layer)[0][
'propwin'] = propwin
1390 if dcmd
and UserSettings.Get(group =
'display', key =
'autoZooming', subkey =
'enabled'):
1391 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1392 if mapLayer.GetType()
in (
'raster',
'vector'):
1393 render = UserSettings.Get(group =
'display', key =
'autoRendering', subkey =
'enabled')
1394 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
1398 if self.mapdisplay.toolbars[
'nviz']
and dcmd:
1399 mapLayer = self.GetPyData(layer)[0][
'maplayer']
1400 mapWin = self.mapdisplay.MapWindow
1401 if len(mapLayer.GetCmd()) > 0:
1403 if mapLayer.type ==
'raster':
1404 if mapWin.IsLoaded(layer):
1405 mapWin.UnloadRaster(layer)
1407 mapWin.LoadRaster(layer)
1409 elif mapLayer.type ==
'3d-raster':
1410 if mapWin.IsLoaded(layer):
1411 mapWin.UnloadRaster3d(layer)
1413 mapWin.LoadRaster3d(layer)
1415 elif mapLayer.type ==
'vector':
1416 if mapWin.IsLoaded(layer):
1417 mapWin.UnloadVector(layer)
1419 mapWin.LoadVector(layer)
1422 nlayers = len(mapWin.Map.GetListOfLayers(l_type = (
'raster',
'vector'),
1428 """!Add commands from data associated with any valid layers
1429 (checked or not) to layer list in order to match layers in
1435 vislayer = self.GetFirstVisibleItem()
1437 if not vislayer
or self.GetPyData(vislayer)
is None:
1442 for item
in range(self.GetCount()):
1443 itemList += self.GetItemText(vislayer) +
','
1444 if self.GetPyData(vislayer)[0][
'type'] !=
'group':
1445 treelayers.append(self.GetPyData(vislayer)[0][
'maplayer'])
1447 if not self.GetNextVisible(vislayer):
1450 vislayer = self.GetNextVisible(vislayer)
1452 Debug.msg (4,
"LayerTree.ReorderLayers(): items=%s" % \
1456 treelayers.reverse()
1457 self.Map.ReorderLayers(treelayers)
1462 type = self.GetPyData(item)[0][
'type']
1465 if type ==
'command':
1466 win = self.FindWindowById(self.GetPyData(item)[0][
'ctrl'])
1467 if win.GetValue() !=
None:
1468 cmd = win.GetValue().
split(
';')
1471 cmdlist.append(c.split(
' '))
1473 chk = self.IsItemChecked(item)
1474 hidden =
not self.IsVisible(item)
1475 elif type !=
'group':
1476 if self.GetPyData(item)[0]
is not None:
1477 cmdlist = self.GetPyData(item)[0][
'cmd']
1478 opac = self.GetPyData(item)[0][
'maplayer'].GetOpacity(float =
True)
1479 chk = self.IsItemChecked(item)
1480 hidden =
not self.IsVisible(item)
1482 layerName, found = utils.GetLayerNameFromCmd(cmdlist, fullyQualified =
True)
1484 layerName = self.GetItemText(item)
1486 maplayer = self.Map.ChangeLayer(layer = self.GetPyData(item)[0][
'maplayer'], type = type,
1487 command = cmdlist, name = layerName,
1488 l_active = chk, l_hidden = hidden, l_opacity = opac, l_render =
False)
1490 self.GetPyData(item)[0][
'maplayer'] = maplayer
1493 if self.mapdisplay.toolbars[
'vdigit']:
1494 self.mapdisplay.toolbars[
'vdigit'].UpdateListOfLayers(updateTool =
True)
1505 """!Find item based on key and value (see PyData[0])
1507 @return item instance
1508 @return None not found
1510 item = self.GetFirstChild(self.root)[0]
1511 return self.__FindSubItemByData(item, key, value)
1514 """!Find item by index (starting at 0)
1516 @return item instance
1517 @return None not found
1519 item = self.GetFirstChild(self.
root)[0]
1521 while item
and item.IsOk():
1525 item = self.GetNextVisible(item)
1531 """!Enable/disable items in layer tree"""
1532 item = self.GetFirstChild(self.
root)[0]
1533 while item
and item.IsOk():
1534 mapLayer = self.GetPyData(item)[0][
'maplayer']
1535 if mapLayer
and type == mapLayer.type:
1536 self.EnableItem(item, enable)
1538 item = self.GetNextSibling(item)
1540 def __FindSubItemByData(self, item, key, value):
1541 """!Support method for FindItemByValue"""
1542 while item
and item.IsOk():
1544 itemValue = self.GetPyData(item)[0][key]
1548 if value == itemValue:
1550 if self.GetPyData(item)[0][
'type'] ==
'group':
1551 subItem = self.GetFirstChild(item)[0]
1555 item = self.GetNextSibling(item)