void EditNode(Node node)
        {
            List <Input> inputs = new List <Input>();

            foreach (KeyValuePair <string, Attribute> kvp in node.Instance.Class.AllAttributes)
            {
                Input input = new Input()
                {
                    Name = kvp.Key, Value = node.Instance.GetProperty(kvp.Key)
                };

                switch (kvp.Value.Type)
                {
                case AttributeType.Bool:
                    input.OfferedValues = new List <string>()
                    {
                        "false", "true"
                    };
                    break;

                case AttributeType.Enum:
                    input.OfferedValues = kvp.Value.TargetType.AllAttributes.Keys.ToList();
                    break;

                case AttributeType.Reference:
                    input.OfferedValues = GetNearestTargets(node.X, node.Y, kvp.Value.TargetType);
                    break;
                }

                inputs.Add(input);
            }

            EditWindow w = new EditWindow(inputs);

            w.ShowDialog();
            Dictionary <string, string> fields = w.Result;

            if (fields == null)
            {
                return;
            }

            string mrid    = node.Instance.GetProperty("mRID");
            string newMRID = fields["mRID"];

            if (newMRID != mrid)
            {
                if (string.IsNullOrWhiteSpace(newMRID))
                {
                    return;
                }

                if (nodes.ContainsKey(newMRID))
                {
                    return;
                }

                nodes.Remove(mrid);
                nodes.Add(newMRID, node);

                foreach (string source in node.InReferences)
                {
                    Node sourceNode;

                    if (!nodes.TryGetValue(source, out sourceNode))
                    {
                        continue;
                    }

                    sourceNode.UpdateOutReference(mrid, newMRID);
                }
            }

            foreach (string target in node.OutReferences)
            {
                Node targetNode;

                if (!nodes.TryGetValue(target, out targetNode))
                {
                    continue;
                }

                targetNode.RemoveInReference(mrid);
            }

            foreach (KeyValuePair <string, string> kvp in fields)
            {
                node.Instance.SetProperty(kvp.Key, kvp.Value);
            }

            node.UpdateOutReferences();

            foreach (string target in node.OutReferences)
            {
                Node targetNode;

                if (!nodes.TryGetValue(target, out targetNode))
                {
                    continue;
                }

                targetNode.AddInReference(newMRID);
            }

            Redraw();
        }
        private void Add()
        {
            PickWindow pw = new PickWindow(profile.ConcreteClasses.Select(x => x.Name).ToList());

            pw.ShowDialog();

            if (pw.Result < 0)
            {
                return;
            }

            Class        type   = profile.ConcreteClasses[pw.Result];
            List <Input> inputs = new List <Input>();
            Vector       center = GetCenter();

            foreach (KeyValuePair <string, Attribute> kvp in type.AllAttributes)
            {
                Input input = new Input()
                {
                    Name = kvp.Key
                };

                switch (kvp.Key)
                {
                case "mRID":
                case "name":
                    input.Value = type.Name + "_" + typeCounts[type];
                    break;

                default:
                    input.Value = "";
                    break;
                }

                switch (kvp.Value.Type)
                {
                case AttributeType.Bool:
                    input.OfferedValues = new List <string>()
                    {
                        "false", "true"
                    };
                    break;

                case AttributeType.Enum:
                    input.OfferedValues = kvp.Value.TargetType.AllAttributes.Keys.ToList();
                    break;

                case AttributeType.Reference:
                    input.OfferedValues = GetNearestTargets(center.X, center.Y, kvp.Value.TargetType);
                    break;
                }

                inputs.Add(input);
            }

            EditWindow w = new EditWindow(inputs)
            {
                Title = "Add " + type.Name
            };

            w.ShowDialog();
            Dictionary <string, string> fields = w.Result;

            if (fields == null)
            {
                return;
            }

            Instance instance = new Instance(type);

            foreach (KeyValuePair <string, string> kvp in fields)
            {
                instance.SetProperty(kvp.Key, kvp.Value);
            }

            NodeModel model;

            if (!classToModel.TryGetValue(type.Name, out model))
            {
                return;
            }

            string mrid = instance.GetProperty("mRID");

            if (string.IsNullOrWhiteSpace(mrid))
            {
                return;
            }

            if (nodes.ContainsKey(mrid))
            {
                return;
            }

            Node node = new Node(center.X, center.Y, 0, 1, model, instance);

            nodes.Add(mrid, node);
            ++typeCounts[type];

            foreach (string target in node.OutReferences)
            {
                Node targetNode;

                if (!nodes.TryGetValue(target, out targetNode))
                {
                    continue;
                }

                targetNode.AddInReference(mrid);
            }

            foreach (Node n in selectedNodes)
            {
                n.Selected = false;
            }

            selectedNodes.Clear();

            node.Selected = true;
            selectedNodes.Add(node);

            Redraw();
        }