private MultiSourceTreeNode UpdateNode(NodeInfo info)
        {
            if (InvokeRequired)
            {
                return((MultiSourceTreeNode)(Invoke((NodeMethodDelegate) delegate { return UpdateNode(info); })));
            }

            //Output.Write(OutputTypes.Debug, "Updating Node (" + info.NodeType.GetType() + "): " + info.Identifier);

            string treePath = info.NodeType.GetTreePath(info);

            if (treePath == "")
            {
                return(null);
            }
            MultiSourceTreeNode node = (MultiSourceTreeNode)GetNodeFromPath(treePath);

            if (node != null)
            {
                //Output.Write(OutputTypes.Debug, "Found node in the tree.");
                // Add Node Info to node.
                //Output.Write(OutputTypes.Debug, "Adding info entry.");
                if (!node.ContainsEntry(info))
                {
                    node.AddInfoEntry(info);
                }
                //else
                //Output.Write(OutputTypes.Debug, " - (Already contained)");
                info.ParentSource.UpdateNode(node);

                // Recursively update the parent nodes.
                NodeInfo parentInfo = info.NodeType.GetParentNodeInfo(info);
                if (parentInfo != null)
                {
                    if (parentInfo.Identifier != "")
                    {
                        //Output.Write(OutputTypes.Debug, "Updating parent node.");
                        UpdateNode(parentInfo);
                    }
                }

                return(node);
            }
            else
            {
                //Output.Write(OutputTypes.Debug, "The node does not exist in the tree.");
                NodeInfo            parentInfo = info.NodeType.GetParentNodeInfo(info);
                MultiSourceTreeNode parentNode;
                if (parentInfo.Identifier != "")
                {
                    //Output.Write(OutputTypes.Debug, "Updating parent node.");
                    parentNode = UpdateNode(parentInfo);
                }
                else
                {
                    // We've reached the root node, and the item does not exist.
                    string parentTreePath = parentInfo.NodeType.GetTreePath(parentInfo);
                    parentNode = (MultiSourceTreeNode)GetNodeFromPath(parentTreePath);
                }

                if (parentNode != null)
                {
                    if (parentNode.ChildrenAdded)
                    {
                        //Output.Write(OutputTypes.Debug, "Parent node exists and its children have been added.");
                        // Create the node.
                        string nodeName = info.NodeType.GetNodeName(info.Identifier);
                        node = info.ParentSource.CreateNode(nodeName, info, info.NodeType.HasChildren);
                        //Output.Write(OutputTypes.Debug, "Manually add the new node (" + node.Text + ") to " + parentNode.Text + ".");
                        AddChildNodes(parentNode, new MultiSourceTreeNode[] { node });
                        return(node);
                    }
                }
                return(parentNode);
            }
        }
 void source_ItemAdded(NodeInfo info)
 {
     UpdateNode(info);
 }
        private void RemoveNodeInfo(NodeInfo info)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(delegate { RemoveNodeInfo(info); }));
                return;
            }

            // Retreive the node from the tree (if it exists).
            //Output.Write(OutputTypes.Debug, "Removing Node (" + info.NodeType.GetType() + "): " + info.Identifier);
            string treePath          = info.NodeType.GetTreePath(info);
            MultiSourceTreeNode node = (MultiSourceTreeNode)GetNodeFromPath(treePath);

            if (node != null)
            {
                // Store our parent, since this will change once we remove the node from it.
                TreeNode parentNode = node.Parent;

                //Output.Write(OutputTypes.Debug, "Node exists in the tree.");

                // Remove the entry if it exists.
                NodeInfo entry = node.FindInfoEntry(info.NodeType);
                if (entry != null)
                {
                    node.RemoveInfoEntry(entry);
                    //Output.Write(OutputTypes.Debug, "Removed matching InfoEntry from the node.");
                }
                //else
                //Output.Write(OutputTypes.Debug, "Matching InfoEntry was not found!");


                // Update the node if we still have entries.
                // DESIGN ISSUE:
                // -------------
                // When an entry is removed, child nodes will also need updating.
                // The problem is, there is no way to do this without recreating the child nodes.
                if (node.EntryCount > 0)
                {
                    info.ParentSource.UpdateNode(node);
                    //Output.Write(OutputTypes.Debug, "Node still contains entries - updating.");
                }
                else
                // Remove the node (if there is a parent to remove it from)
                if (parentNode != null)
                {
                    //Output.Write(OutputTypes.Debug, "Node contains no more entries - removing node.");
                    parentNode.Nodes.Remove(node);
                    if (parentNode.Nodes.Count == 0)
                    {
                        parentNode.Collapse();
                    }
                }

                // Verify the parent node.
                if (parentNode != null)
                {
                    if (parentNode is MultiSourceTreeNode)
                    {
                        //Output.Write(OutputTypes.Debug, "Verifying parent node: " + parentNode.Text);
                        VerifyNode(parentNode as MultiSourceTreeNode);
                    }
                }
            }
            else
            {
                //Output.Write(OutputTypes.Debug, "Node does not exist in the tree.");
                // The node doesn't exist in the tree, so we don't need to remove it.
                // We do, however, still need to update the node's parent to ensure that
                // it still contains child objects of this type.

                // Direct parent may not exist (which was causing issues previously)
                // Because of that, we will need to go all the way up the tree until we
                // either find a node, or hit the root node.
                MultiSourceTreeNode parentNode = GetFirstExistingParentNode(info);
                if (parentNode != null)
                {
                    //Output.Write(OutputTypes.Debug, "Located a parent node: " + parentNode.Text + " - Updating.");
                    VerifyNode(parentNode);
                }
                //else
                //Output.Write(OutputTypes.Debug, "No parent node was found - no updates required.");
            }
        }
 void source_ItemRemoved(NodeInfo info)
 {
     RemoveNodeInfo(info);
 }