private TreeNode CreateLayerNode(MgLayerBase layer) { var node = new TreeNode(); node.Name = layer.GetObjectId(); node.Text = layer.GetLegendLabel(); node.Checked = layer.GetVisible(); //node.ContextMenuStrip = _legend.LayerContextMenu; var lt = layer.GetLayerType(); var fsId = layer.GetFeatureSourceId(); LayerNodeMetadata layerMeta = null; if (fsId.EndsWith("DrawingSource")) //NOXLATE { node.SelectedImageKey = node.ImageKey = IMG_DWF; bool bInitiallySelectable = layer.Selectable; if (_layers.ContainsKey(layer.GetObjectId())) { layerMeta = _layers[layer.GetObjectId()]; bInitiallySelectable = layerMeta.WasInitiallySelectable; } else //If not in the dictionary, assume it is a dynamically added layer { layerMeta = new LayerNodeMetadata(layer, bInitiallySelectable); _layers[layer.GetObjectId()] = layerMeta; } node.Tag = layerMeta; node.ToolTipText = string.Format(Strings.DrawingLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId); } else //Vector or Grid layer { var ldfId = layer.LayerDefinition; if (_layers.ContainsKey(layer.GetObjectId())) { layerMeta = _layers[layer.GetObjectId()]; } else { layerMeta = new LayerNodeMetadata(layer, layer.Selectable); _layers[layer.GetObjectId()] = layerMeta; } if (string.IsNullOrEmpty(layerMeta.LayerDefinitionContent)) return null; node.Tag = layerMeta; const int LAYER_VECTOR = 0; const int LAYER_RASTER = 1; const int LAYER_DWF = 2; XmlDocument doc = new XmlDocument(); doc.LoadXml(layerMeta.LayerDefinitionContent); int type = LAYER_VECTOR; XmlNodeList scaleRanges = doc.GetElementsByTagName("VectorScaleRange"); //NOXLATE if (scaleRanges.Count == 0) { scaleRanges = doc.GetElementsByTagName("GridScaleRange"); //NOXLATE if (scaleRanges.Count == 0) { scaleRanges = doc.GetElementsByTagName("DrawingLayerDefinition"); //NOXLATE if (scaleRanges.Count == 0) return null; type = LAYER_DWF; } else type = LAYER_RASTER; } String[] typeStyles = new String[] { "PointTypeStyle", "LineTypeStyle", "AreaTypeStyle", "CompositeTypeStyle" }; //NOXLATE String[] ruleNames = new String[] { "PointRule", "LineRule", "AreaRule", "CompositeRule" }; //NOXLATE node.ToolTipText = string.Format(Strings.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName); //Do this if not cached already from a previous run if (!layerMeta.HasTheme() || !layerMeta.HasDefaultIcons()) { for (int sc = 0; sc < scaleRanges.Count; sc++) { XmlElement scaleRange = (XmlElement)scaleRanges[sc]; XmlNodeList minElt = scaleRange.GetElementsByTagName("MinScale"); //NOXLATE XmlNodeList maxElt = scaleRange.GetElementsByTagName("MaxScale"); //NOXLATE String minScale, maxScale; minScale = "0"; //NOXLATE maxScale = "1000000000000.0"; //NOXLATE // as MDF's VectorScaleRange::MAX_MAP_SCALE if (minElt.Count > 0) minScale = minElt[0].ChildNodes[0].Value; if (maxElt.Count > 0) maxScale = maxElt[0].ChildNodes[0].Value; if (type != LAYER_VECTOR) break; if (!LayerNodeMetadata.ScaleIsApplicable(_map.ViewScale, minScale, maxScale)) continue; bool bComposite = false; //Check TS count. Give precedence to composite type styles List<XmlNode> typeStyleCol = new List<XmlNode>(); XmlNodeList styleNodes = scaleRange.GetElementsByTagName(typeStyles[3]); List<RuleData> rules = new List<RuleData>(); if (styleNodes.Count > 0) { foreach (XmlNode n in styleNodes) { // We will check if this typestyle is going to be shown in the legend XmlNodeList showInLegend = ((XmlElement)n).GetElementsByTagName("ShowInLegend"); //NOXLATE if (showInLegend.Count > 0) if (!bool.Parse(showInLegend[0].ChildNodes[0].Value)) continue; // This typestyle does not need to be shown in the legend typeStyleCol.Add(n); var ruleData = new RuleData(); ruleData.GeomType = 3; ruleData.RuleNodes = ((XmlElement)n).GetElementsByTagName(ruleNames[3]); if (ruleData.RuleNodes.Count > 0) rules.Add(ruleData); } bComposite = true; } else { for (int t = 0; t < 3; t++) { styleNodes = scaleRange.GetElementsByTagName(typeStyles[t]); foreach (XmlNode n in styleNodes) { // We will check if this typestyle is going to be shown in the legend XmlNodeList showInLegend = ((XmlElement)n).GetElementsByTagName("ShowInLegend"); //NOXLATE if (showInLegend.Count > 0) if (!bool.Parse(showInLegend[0].ChildNodes[0].Value)) continue; // This typestyle does not need to be shown in the legend typeStyleCol.Add(n); var ruleData = new RuleData(); ruleData.GeomType = t; ruleData.RuleNodes = ((XmlElement)n).GetElementsByTagName(ruleNames[t]); if (ruleData.RuleNodes.Count > 0) rules.Add(ruleData); } } } //No type styles. Skip if (typeStyleCol.Count == 0) continue; //Determine if this is themed or not int nTotalRules = 0; foreach(RuleData r in rules) { nTotalRules += r.RuleNodes.Count; } bool bThemed = nTotalRules > 1; if (bThemed) { int catIndex = 0; for (int i = 0; i < rules.Count; i++) { RuleData theRule = rules[i]; ThemeCategory themeCat = new ThemeCategory() { MinScale = minScale, MaxScale = maxScale, GeometryType = theRule.GeomType }; //Non-composite styles must be processed once if (layerMeta.CategoryExists(themeCat) && theRule.GeomType != 3) continue; layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_theme); node.ToolTipText = string.Format(Strings.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName, nTotalRules); if (_legend.ThemeCompressionLimit > 0 && theRule.RuleNodes.Count > _legend.ThemeCompressionLimit) { AddThemeRuleNode(layerMeta, themeCat, node, theRule.GeomType, catIndex, theRule.RuleNodes, 0); node.Nodes.Add(CreateCompressedThemeNode(layerMeta, themeCat, theRule.RuleNodes.Count - 2)); AddThemeRuleNode(layerMeta, themeCat, node, theRule.GeomType, (catIndex + (theRule.RuleNodes.Count - 1)), theRule.RuleNodes, theRule.RuleNodes.Count - 1); } else { for (int r = 0; r < theRule.RuleNodes.Count; r++) { AddThemeRuleNode(layerMeta, themeCat, node, theRule.GeomType, (catIndex + r), theRule.RuleNodes, r); } } //Only bump catIndex if composite, as category indexes for composite styles are handled differently if (bComposite) catIndex += theRule.RuleNodes.Count; } } else { Trace.Assert(rules.Count == 1); Trace.Assert(rules[0].RuleNodes.Count == 1); RuleData theRule = rules[0]; ThemeCategory themeCat = new ThemeCategory() { MinScale = minScale, MaxScale = maxScale, GeometryType = theRule.GeomType }; if (layerMeta.CategoryExists(themeCat)) continue; if (LayerNodeMetadata.ScaleIsApplicable(_map.ViewScale, themeCat)) { if (!layerMeta.HasDefaultIconsAt(_map.ViewScale)) { try { MgByteReader layerIcon = _provider.GenerateLegendImage(layer.LayerDefinition, _map.ViewScale, 16, 16, "PNG", //NOXLATE (theRule.GeomType+1), -1); legendCallCount++; if (layerIcon != null) { try { byte[] b = new byte[layerIcon.GetLength()]; layerIcon.Read(b, b.Length); using (var ms = new MemoryStream(b)) { layerMeta.SetDefaultIcon(themeCat, Image.FromStream(ms)); node.ToolTipText = string.Format(Strings.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceId, layer.FeatureClassName); } } finally { layerIcon.Dispose(); } } else { layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_broken); } } catch { layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_broken); } } } } } } else //Already cached { Trace.TraceInformation("Icons already cached for: " + layer.Name); //NOXLATE node.Nodes.AddRange(layerMeta.CreateThemeNodesFromCachedMetadata(_map.ViewScale)); } } return node; }
public TreeNode[] CreateNodes() { List<TreeNode> topLevelNodes = new List<TreeNode>(); var scale = _map.ViewScale; if (scale < 10.0) return topLevelNodes.ToArray(); var nodesById = new Dictionary<string, TreeNode>(); var groupsById = new Dictionary<string, TreeNode>(); var groups = _map.GetLayerGroups(); var layers = _map.GetLayers(); legendCallCount = 0; //Process groups first List<MgLayerGroup> remainingNodes = new List<MgLayerGroup>(); for (int i = 0; i < groups.GetCount(); i++) { var group = groups.GetItem(i); if (!group.GetDisplayInLegend()) continue; //Add ones without parents first. Queue up child groups if (group.Group != null) { remainingNodes.Add(group); } else { var node = CreateGroupNode(group); topLevelNodes.Add(node); nodesById.Add(group.GetObjectId(), node); groupsById.Add(group.GetObjectId(), node); } } //Process child groups while (remainingNodes.Count > 0) { List<MgLayerGroup> toRemove = new List<MgLayerGroup>(); //Establish parent-child relationship for any child groups here for (int j = 0; j < remainingNodes.Count; j++) { var parentId = remainingNodes[j].Group.GetObjectId(); if (nodesById.ContainsKey(parentId)) { MgLayerGroup grp = remainingNodes[j]; var node = CreateGroupNode(grp); nodesById[parentId].Nodes.Add(node); //Got to add this group node too, otherwise we could infinite //loop looking for a parent that's not registered nodesById.Add(grp.GetObjectId(), node); groupsById.Add(grp.GetObjectId(), node); toRemove.Add(grp); } } //Whittle down this list if (toRemove.Count > 0) { foreach (var g in toRemove) { remainingNodes.Remove(g); } } } //Collect all resource contents in a batch MgStringCollection layerIds = new MgStringCollection(); //Also collect the layer metadata nodes to create or update var layerMetaNodesToUpdate = new Dictionary<string, MgLayerBase>(); //Now process layers. Layers without metadata nodes or without layer definition content //are added to the list int layerCount = layers.GetCount(); for (int i = 0; i < layerCount; i++) { var lyr = layers.GetItem(i); bool display = lyr.DisplayInLegend; bool visible = _provider.IsLayerPotentiallyVisibleAtScale(lyr, false); if (!display) continue; if (!visible) continue; var lyrObjId = lyr.GetObjectId(); if (_layers.ContainsKey(lyrObjId)) { if (string.IsNullOrEmpty(_layers[lyrObjId].LayerDefinitionContent)) { var ldfId = lyr.LayerDefinition; var ldfIdStr = ldfId.ToString(); layerIds.Add(ldfIdStr); layerMetaNodesToUpdate[ldfIdStr] = lyr; } } else { var ldfId = lyr.LayerDefinition; var ldfIdStr = ldfId.ToString(); layerIds.Add(ldfIdStr); layerMetaNodesToUpdate[ldfIdStr] = lyr; } } int layerIdCount = layerIds.GetCount(); if (layerIdCount > 0) { int added = 0; int updated = 0; //Fetch the contents and create/update the required layer metadata nodes MgStringCollection layerContents = _resSvc.GetResourceContents(layerIds, null); for (int i = 0; i < layerIdCount; i++) { string lid = layerIds.GetItem(i); var lyr = layerMetaNodesToUpdate[lid]; var objId = lyr.GetObjectId(); LayerNodeMetadata meta = null; if (_layers.ContainsKey(objId)) { meta = _layers[objId]; updated++; } else { meta = new LayerNodeMetadata(lyr, lyr.Selectable); _layers[objId] = meta; added++; } meta.LayerDefinitionContent = layerContents.GetItem(i); } Trace.TraceInformation("CreateNodes: {0} layer contents added, {1} layer contents updated", added, updated); //NOXLATE } //Now create our layer nodes List<MgLayerBase> remainingLayers = new List<MgLayerBase>(); //NOTE: We're taking a page out of the Fusion playbook of reverse iterating the layer //collection and prepending the nodes, as this control suffered the same problem as the //Legend widget in Fusion. Doing it this way eliminates the need for doing an extra pass to fix //the layer/group ordering, which may make an impact on really chunky maps. for (int i = layerCount - 1; i >= 0; i--) { var layer = layers.GetItem(i); bool display = layer.DisplayInLegend; bool visible = _provider.IsLayerPotentiallyVisibleAtScale(layer, false); if (!display) continue; if (!visible) continue; //Add ones without parents first. if (layer.Group != null) { remainingLayers.Add(layer); } else { var node = CreateLayerNode(layer); if (node != null) { topLevelNodes.Insert(0, node); nodesById.Add(layer.GetObjectId(), node); if (layer.ExpandInLegend) node.Expand(); } } } while (remainingLayers.Count > 0) { List<MgLayerBase> toRemove = new List<MgLayerBase>(); for (int j = remainingLayers.Count - 1; j >= 0; j--) { var parentGroup = remainingLayers[j].Group; var parentId = parentGroup.GetObjectId(); if (nodesById.ContainsKey(parentId)) { var node = CreateLayerNode(remainingLayers[j]); if (node != null) { nodesById[parentId].Nodes.Insert(0, node); if (remainingLayers[j].ExpandInLegend) node.Expand(); } toRemove.Add(remainingLayers[j]); } else { if (!parentGroup.GetDisplayInLegend()) toRemove.Add(remainingLayers[j]); } } //Whittle down this list if (toRemove.Count > 0) { foreach (var g in toRemove) { remainingLayers.Remove(g); } } } //Now expand any relevant groups for (int i = 0; i < groups.GetCount(); i++) { var group = groups.GetItem(i); if (group.ExpandInLegend) { var groupId = group.GetObjectId(); if (nodesById.ContainsKey(groupId)) { nodesById[groupId].Expand(); } } } Trace.TraceInformation("{0} calls made to GenerateLegendImage", legendCallCount); //NOXLATE return topLevelNodes.ToArray(); }
private TreeNode CreateCompressedThemeNode(LayerNodeMetadata layer, ThemeCategory cat, int count) { TreeNode node = new TreeNode(); node.Text = string.Format(Strings.CountOtherStyles, count); node.ImageKey = node.SelectedImageKey = IMG_OTHER; var meta = new LayerThemeNodeMetadata(true, Properties.Resources.icon_etc, node.Text); node.Tag = meta; layer.AddThemeNode(cat, meta); return node; }
private TreeNode CreateThemeRuleNode(LayerNodeMetadata layer, ThemeCategory themeCat, double viewScale, string labelText, int geomType, int categoryIndex) { MgLayerBase lyr = layer.Layer; MgByteReader icon = _provider.GenerateLegendImage(lyr.LayerDefinition, viewScale, 16, 16, "PNG", //NOXLATE geomType, categoryIndex); legendCallCount++; TreeNode node = new TreeNode(); node.Text = labelText; if (icon != null) { try { byte[] b = new byte[icon.GetLength()]; icon.Read(b, b.Length); using (var ms = new MemoryStream(b)) { var tag = new LayerThemeNodeMetadata(false, Image.FromStream(ms), labelText); layer.AddThemeNode(themeCat, tag); node.Tag = tag; } } finally { icon.Dispose(); } } return node; }
private void AddThemeRuleNode(LayerNodeMetadata layerMeta, ThemeCategory themeCat, TreeNode node, int geomType, int catIndex, XmlNodeList rules, int ruleOffset) { XmlElement rule = (XmlElement)rules[ruleOffset]; XmlNodeList label = rule.GetElementsByTagName("LegendLabel"); //NOXLATE XmlNodeList filter = rule.GetElementsByTagName("Filter"); //NOXLATE String labelText = string.Empty; if (label != null && label.Count > 0 && label[0].ChildNodes.Count > 0) labelText = label[0].ChildNodes[0].Value; //String filterText = ""; //if (filter != null && filter.Count > 0 && filter[0].ChildNodes.Count > 0) // filterText = filter[0].ChildNodes[0].Value; var child = CreateThemeRuleNode(layerMeta, themeCat, _map.ViewScale, labelText, (geomType + 1), catIndex); node.Nodes.Add(child); }