예제 #1
0
        private TreeNode CreateThemeRuleNode(LayerNodeMetadata layer, ThemeCategory themeCat, double viewScale, string labelText, int geomType, int categoryIndex)
        {
            var lyr = layer.Layer;
            TreeNode node = new TreeNode();
            node.Text = labelText;

            Image icon = _map.GetLegendImage(lyr.LayerDefinitionID,
                                             viewScale,
                                             16,
                                             16,
                                             "PNG",
                                             geomType,
                                             categoryIndex);
            legendCallCount++;

            var tag = new LayerThemeNodeMetadata(false, icon, labelText);
            layer.AddThemeNode(themeCat, tag);
            node.Tag = tag;

            return node;
        }
예제 #2
0
        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.Groups;
            var layers = _map.Layers;

            legendCallCount = 0;

            //Process groups first
            List<RuntimeMapGroup> remainingNodes = new List<RuntimeMapGroup>();
            for (int i = 0; i < groups.Count; i++)
            {
                var group = groups[i];
                if (!_legend.ShowAllLayersAndGroups && !group.ShowInLegend)
                    continue;

                //Add ones without parents first. Queue up child groups
                if (!string.IsNullOrEmpty(group.Group))
                {
                    remainingNodes.Add(group);
                }
                else
                {
                    var node = CreateGroupNode(group);
                    topLevelNodes.Add(node);
                    nodesById.Add(group.ObjectId, node);
                    groupsById.Add(group.ObjectId, node);
                }
            }

            //Process child groups
            while (remainingNodes.Count > 0)
            {
                List<RuntimeMapGroup> toRemove = new List<RuntimeMapGroup>();
                //Establish parent-child relationships for any child groups here
                for (int j = 0; j < remainingNodes.Count; j++)
                {
                    var grpName = remainingNodes[j].Group;
                    var parentGroup = _map.Groups[grpName];
                    if (parentGroup != null && nodesById.ContainsKey(parentGroup.ObjectId))
                    {
                        var node = CreateGroupNode(remainingNodes[j]);
                        nodesById[parentGroup.ObjectId].Nodes.Add(node);
                        var grpId = remainingNodes[j].ObjectId;
                        //Got to add this group node too, otherwise we could infinite
                        //loop looking for a parent that's not registered
                        nodesById.Add(grpId, node);
                        groupsById.Add(grpId, node);

                        toRemove.Add(remainingNodes[j]);
                    }
                }
                //Whittle down this list
                if (toRemove.Count > 0)
                {
                    foreach (var g in toRemove)
                    {
                        remainingNodes.Remove(g);
                    }
                }
            }

            //Collect all resource contents in a batch
            var layerIds = new List<string>();
            //Also collect the layer metadata nodes to create or update
            var layerMetaNodesToUpdate = new Dictionary<string, RuntimeMapLayer>();
            //Now process layers. Layers without metadata nodes or without layer definition content
            //are added to the list
            for (int i = 0; i < layers.Count; i++)
            {
                var lyr = layers[i];
                bool display = lyr.ShowInLegend;
                bool visible = lyr.IsVisibleAtScale(_map.ViewScale);
                if (!_legend.ShowAllLayersAndGroups && !display)
                    continue;

                if (!_legend.ShowAllLayersAndGroups && !visible)
                    continue;

                if (_layers.ContainsKey(lyr.ObjectId))
                {
                    if (string.IsNullOrEmpty(_layers[lyr.ObjectId].LayerDefinitionContent))
                    {
                        var ldfId = lyr.LayerDefinitionID;
                        layerIds.Add(ldfId.ToString());
                        layerMetaNodesToUpdate[ldfId.ToString()] = lyr;
                    }
                }
                else
                {
                    var ldfId = lyr.LayerDefinitionID;
                    layerIds.Add(ldfId.ToString());
                    layerMetaNodesToUpdate[ldfId.ToString()] = lyr;
                }
            }

            if (layerIds.Count > 0)
            {
                int added = 0;
                int updated = 0;
                //Fetch the contents and create/update the required layer metadata nodes
                //TODO: Surely we can optimize this better
                foreach (var lid in layerIds)
                {
                    using (var sr = new StreamReader(_resSvc.GetResourceXmlData(lid)))
                    {
                        string content = sr.ReadToEnd();

                        var lyr = layerMetaNodesToUpdate[lid];
                        var objId = lyr.ObjectId;
                        LayerNodeMetadata meta = null;
                        if (_layers.ContainsKey(objId))
                        {
                            meta = _layers[objId];
                            updated++;
                        }
                        else
                        {
                            RuntimeMapGroup group = null;
                            if (!string.IsNullOrEmpty(lyr.Group))
                                group = _map.Groups[lyr.Group];
                            meta = new LayerNodeMetadata(lyr, lyr.Selectable);
                            _layers[objId] = meta;
                            added++;
                        }
                        meta.LayerDefinitionContent = content;
                    }
                }
                Trace.TraceInformation("CreateNodes: {0} layer contents added, {1} layer contents updated", added, updated);
            }

            //Now create our layer nodes
            List<RuntimeMapLayer> remainingLayers = new List<RuntimeMapLayer>();
            //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 = layers.Count - 1; i >= 0; i--)
            {
                var layer = layers[i];

                bool display = layer.ShowInLegend;
                bool visible = layer.IsVisibleAtScale(_map.ViewScale);
                if (!_legend.ShowAllLayersAndGroups && !display)
                    continue;

                if (!_legend.ShowAllLayersAndGroups && !visible)
                    continue;

                //Add ones without parents first. Queue up parented layers
                if (!string.IsNullOrEmpty(layer.Group))
                {
                    remainingLayers.Add(layer);
                }
                else
                {
                    var node = CreateLayerNode(layer);
                    if (node != null)
                    {
                        topLevelNodes.Insert(0, node);
                        nodesById.Add(layer.ObjectId, node);
                        if (layer.ExpandInLegend)
                            node.Expand();
                    }
                }
            }

            //Process parented layers
            while (remainingLayers.Count > 0)
            {
                List<RuntimeMapLayer> toRemove = new List<RuntimeMapLayer>();
                for (int j = remainingLayers.Count - 1; j >= 0; j--)
                {
                    var grpName = remainingLayers[j].Group;
                    var parentGroup = _map.Groups[grpName];
                    if (parentGroup != null)
                    {
                        if (nodesById.ContainsKey(parentGroup.ObjectId))
                        {
                            var node = CreateLayerNode(remainingLayers[j]);
                            if (node != null)
                            {
                                nodesById[parentGroup.ObjectId].Nodes.Add(node); //.Insert(0, node);
                                if (remainingLayers[j].ExpandInLegend)
                                    node.Expand();
                            }
                            toRemove.Add(remainingLayers[j]);
                        }
                        else //Group may not even be set to show in legend. Check for this
                        {
                            if (!parentGroup.ShowInLegend)
                                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.Count; i++)
            {
                var group = groups[i];
                if (group.ExpandInLegend)
                {
                    var groupId = group.ObjectId;
                    if (nodesById.ContainsKey(groupId))
                    {
                        nodesById[groupId].Expand();
                    }
                }
            }
            Trace.TraceInformation("{0} calls made to GenerateLegendImage", legendCallCount);
            return topLevelNodes.ToArray();
        }
예제 #3
0
 private TreeNode CreateCompressedThemeNode(LayerNodeMetadata layer, ThemeCategory cat, int count)
 {
     TreeNode node = new TreeNode();
     node.Text = (count + " other styles");
     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;
 }
예제 #4
0
        private TreeNode CreateLayerNode(RuntimeMapLayer layer)
        {
            var node = new TreeNode();
            node.Name = layer.ObjectId;
            node.Text = layer.LegendLabel;
            node.Checked = layer.Visible;
            //node.ContextMenuStrip = _legend.LayerContextMenu;
            var lt = layer.Type;
            var fsId = layer.FeatureSourceID;

            LayerNodeMetadata layerMeta = null;
            if (fsId.EndsWith("DrawingSource"))
            {
                node.SelectedImageKey = node.ImageKey = IMG_DWF;
                bool bInitiallySelectable = layer.Selectable;
                if (_layers.ContainsKey(layer.ObjectId))
                {
                    layerMeta = _layers[layer.ObjectId];
                    bInitiallySelectable = layerMeta.WasInitiallySelectable;
                }
                else //If not in the dictionary, assume it is a dynamically added layer
                {
                    RuntimeMapGroup group = null;
                    if (!string.IsNullOrEmpty(layer.Group))
                        group = _map.Groups[layer.Group];
                    layerMeta = new LayerNodeMetadata(layer, bInitiallySelectable);
                    _layers[layer.ObjectId] = layerMeta;
                }
                node.Tag = layerMeta;
                node.ToolTipText = string.Format(Properties.Resources.DrawingLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID);
            }
            else //Vector or Grid layer
            {
                var ldfId = layer.LayerDefinitionID;
                if (_layers.ContainsKey(layer.ObjectId))
                {
                    layerMeta = _layers[layer.ObjectId];
                }
                else
                {
                    RuntimeMapGroup group = null;
                    if (!string.IsNullOrEmpty(layer.Group))
                        group = _map.Groups[layer.Group];
                    layerMeta = new LayerNodeMetadata(layer, layer.Selectable);
                    _layers[layer.ObjectId] = 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");
                if (scaleRanges.Count == 0)
                {
                    scaleRanges = doc.GetElementsByTagName("GridScaleRange");
                    if (scaleRanges.Count == 0)
                    {
                        scaleRanges = doc.GetElementsByTagName("DrawingLayerDefinition");
                        if (scaleRanges.Count == 0)
                            return null;
                        type = LAYER_DWF;
                    }
                    else
                        type = LAYER_RASTER;
                }

                String[] typeStyles = new String[] { "PointTypeStyle", "LineTypeStyle", "AreaTypeStyle", "CompositeTypeStyle" };
                String[] ruleNames = new String[] { "PointRule", "LineRule", "AreaRule", "CompositeRule" };

                node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName);
                //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");
                        XmlNodeList maxElt = scaleRange.GetElementsByTagName("MaxScale");
                        String minScale, maxScale;
                        minScale = "0";
                        maxScale = "1000000000000.0";   // 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;

                        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(Properties.Resources.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName, 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
                                    {
                                        var img = _map.GetLegendImage(layer.LayerDefinitionID,
                                                                                _map.ViewScale,
                                                                                16,
                                                                                16,
                                                                                "PNG",
                                                                                (theRule.GeomType + 1),
                                                                                -1);
                                        legendCallCount++;
                                        layerMeta.SetDefaultIcon(themeCat, img);
                                        node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName);
                                    }
                                    catch
                                    {
                                        //layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_broken);
                                    }
                                }
                            }
                        }

                        //for (int geomType = 0; geomType < typeStyles.Length; geomType++)
                        //{
                        //    ThemeCategory themeCat = new ThemeCategory()
                        //    {
                        //        MinScale = minScale,
                        //        MaxScale = maxScale,
                        //        GeometryType = geomType
                        //    };

                        //    if (layerMeta.CategoryExists(themeCat))
                        //        continue;

                        //    int catIndex = 0;
                        //    XmlNodeList typeStyle = scaleRange.GetElementsByTagName(typeStyles[geomType]);
                        //    for (int st = 0; st < typeStyle.Count; st++)
                        //    {
                        //        // We will check if this typestyle is going to be shown in the legend
                        //        XmlNodeList showInLegend = ((XmlElement)typeStyle[st]).GetElementsByTagName("ShowInLegend");
                        //        if (showInLegend.Count > 0)
                        //            if (!bool.Parse(showInLegend[0].ChildNodes[0].Value))
                        //                continue;   // This typestyle does not need to be shown in the legend

                        //        XmlNodeList rules = ((XmlElement)typeStyle[st]).GetElementsByTagName(ruleNames[geomType]);
                        //        if (rules.Count > 1)
                        //        {
                        //            layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_theme);
                        //            node.ToolTipText = string.Format(Properties.Resources.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName, rules.Count);

                        //            if (_legend.ThemeCompressionLimit > 0 && rules.Count > _legend.ThemeCompressionLimit)
                        //            {
                        //                AddThemeRuleNode(layerMeta, themeCat, node, geomType, 0, rules, 0);
                        //                node.Nodes.Add(CreateCompressedThemeNode(layerMeta, themeCat, rules.Count - 2));
                        //                AddThemeRuleNode(layerMeta, themeCat, node, geomType, rules.Count - 1, rules, rules.Count - 1);
                        //            }
                        //            else
                        //            {
                        //                for (int r = 0; r < rules.Count; r++)
                        //                {
                        //                    AddThemeRuleNode(layerMeta, themeCat, node, geomType, catIndex++, rules, r);
                        //                }
                        //            }
                        //        }
                        //        else
                        //        {
                        //            if (LayerNodeMetadata.ScaleIsApplicable(_map.ViewScale, themeCat))
                        //            {
                        //                if (!layerMeta.HasDefaultIconsAt(_map.ViewScale))
                        //                {
                        //                    try
                        //                    {
                        //                        var img = _map.GetLegendImage(layer.LayerDefinitionID,
                        //                                                                _map.ViewScale,
                        //                                                                16,
                        //                                                                16,
                        //                                                                "PNG",
                        //                                                                -1,
                        //                                                                -1);
                        //                        legendCallCount++;
                        //                        layerMeta.SetDefaultIcon(themeCat, img);
                        //                        node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName);
                        //                    }
                        //                    catch
                        //                    {
                        //                        //layerMeta.SetDefaultIcon(themeCat, Properties.Resources.lc_broken);
                        //                    }
                        //                }
                        //            }
                        //        }
                        //    }
                        //}
                    }
                }
                else //Already cached
                {
                    Trace.TraceInformation("Icons already cached for: " + layer.Name);
                    node.Nodes.AddRange(layerMeta.CreateThemeNodesFromCachedMetadata(_map.ViewScale));
                }
            }

            return node;
        }
예제 #5
0
        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");
            XmlNodeList filter = rule.GetElementsByTagName("Filter");

            String labelText = "";
            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;

            if (LayerNodeMetadata.ScaleIsApplicable(_map.ViewScale, themeCat))
            {
                var child = CreateThemeRuleNode(layerMeta, themeCat, _map.ViewScale, labelText, (geomType + 1), catIndex);
                node.Nodes.Add(child);
            }
            else
            {

            }
        }