public static TreeNode FindNode(TreeView CallGraphTreeView, string InText, bool bTextIsRegex, bool bInMatchCase)
        {
            var SearchParams = new FNodeSearchParams(InText, bTextIsRegex, bInMatchCase);

            TreeNode SelectedTreeNode = CallGraphTreeView.SelectedNode;

            FCallGraphNode FoundNode = FindRecursiveChildNode((FCallGraphNode)SelectedTreeNode.Tag, SearchParams);

            while (SelectedTreeNode != null && FoundNode == null)
            {
                var Siblings = SelectedTreeNode.Parent != null ? ((FCallGraphNode)SelectedTreeNode.Parent.Tag).Children : ((FCallGraphTreeViewTag)CallGraphTreeView.Tag).RootNodes;
                FoundNode        = FindRecursiveSiblingNode(Siblings, (FCallGraphNode)SelectedTreeNode.Tag, SearchParams);
                SelectedTreeNode = SelectedTreeNode.Parent;
            }

            if (FoundNode != null)
            {
                CallGraphTreeView.BeginUpdate();
                EnsureTreeNode(FoundNode);
                CallGraphTreeView.EndUpdate();

                return(FoundNode.TreeNode);
            }

            return(null);
        }
        public static int HighlightAllNodes(TreeView CallGraphTreeView, string InText, bool bTextIsRegex, bool bInMatchCase, out TreeNode FirstResult, out long AllocationSize, out int AllocationCount)
        {
            var SearchParams = new FNodeSearchParams(InText, bTextIsRegex, bInMatchCase);

            var MatchingNodes   = new List <FCallGraphNode>();
            var NodeSearchState = new FNodeSearchState();

            foreach (FCallGraphNode RootNode in ((FCallGraphTreeViewTag)CallGraphTreeView.Tag).RootNodes)
            {
                GetAllMatchingNodes(RootNode, MatchingNodes, NodeSearchState, SearchParams);
            }

            CallGraphTreeView.BeginUpdate();
            foreach (FCallGraphNode MatchingNode in MatchingNodes)
            {
                EnsureTreeNode(MatchingNode);

                MatchingNode.TreeNode.BackColor = Color.CornflowerBlue;
                MatchingNode.TreeNode.EnsureVisible();
            }
            CallGraphTreeView.EndUpdate();

            FirstResult = null;
            if (MatchingNodes.Count > 0)
            {
                FirstResult = MatchingNodes[0].TreeNode;
            }

            AllocationSize  = NodeSearchState.AllocationSize;
            AllocationCount = NodeSearchState.AllocationCount;

            return(MatchingNodes.Count);
        }
        private static void GetAllMatchingNodes(FCallGraphNode ParentNode, List <FCallGraphNode> MatchingNodes, FNodeSearchState SearchState, FNodeSearchParams SearchParams)
        {
            foreach (FCallGraphNode ChildNode in ParentNode.Children)
            {
                if (SearchParams.DoesNodeMatchSearch(ChildNode))
                {
                    MatchingNodes.Add(ChildNode);

                    if (!SearchState.CallStacks.Contains(ChildNode.CallStacks[0]))
                    {
                        // If one callstack from this node is new, then all must be, due to the way the graph is arranged and the order in which it is searched
                        foreach (FCallStack CallStack in ChildNode.CallStacks)
                        {
                            SearchState.CallStacks.Add(CallStack);
                        }
                        SearchState.AllocationSize  += ChildNode.AllocationSize;
                        SearchState.AllocationCount += ChildNode.AllocationCount;
                    }
                }

                GetAllMatchingNodes(ChildNode, MatchingNodes, SearchState, SearchParams);
            }
        }
        private static FCallGraphNode FindRecursiveChildNode(FCallGraphNode SelectedNode, FNodeSearchParams SearchParams)
        {
            foreach (FCallGraphNode ChildNode in SelectedNode.Children)
            {
                if (SearchParams.DoesNodeMatchSearch(ChildNode))
                {
                    return(ChildNode);
                }

                FCallGraphNode FoundNode = FindRecursiveChildNode(ChildNode, SearchParams);
                if (FoundNode != null)
                {
                    return(FoundNode);
                }
            }

            return(null);
        }
        private static FCallGraphNode FindRecursiveSiblingNode(List <FCallGraphNode> Siblings, FCallGraphNode SelectedNode, FNodeSearchParams SearchParams)
        {
            for (int SiblingIndex = Siblings.IndexOf(SelectedNode) + 1; SiblingIndex < Siblings.Count; ++SiblingIndex)
            {
                FCallGraphNode SiblingNode = Siblings[SiblingIndex];

                if (SearchParams.DoesNodeMatchSearch(SiblingNode))
                {
                    return(SiblingNode);
                }

                FCallGraphNode FoundNode = FindRecursiveChildNode(SiblingNode, SearchParams);
                if (FoundNode != null)
                {
                    return(FoundNode);
                }
            }

            return(null);
        }
		private static void GetAllMatchingNodes(FCallGraphNode ParentNode, List<FCallGraphNode> MatchingNodes, FNodeSearchState SearchState, FNodeSearchParams SearchParams)
		{
			foreach (FCallGraphNode ChildNode in ParentNode.Children)
			{
				if (SearchParams.DoesNodeMatchSearch(ChildNode))
				{
					MatchingNodes.Add(ChildNode);

					if (!SearchState.CallStacks.Contains(ChildNode.CallStacks[0]))
					{
						// If one callstack from this node is new, then all must be, due to the way the graph is arranged and the order in which it is searched
						foreach (FCallStack CallStack in ChildNode.CallStacks)
						{
							SearchState.CallStacks.Add(CallStack);
						}
						SearchState.AllocationSize += ChildNode.AllocationSize;
						SearchState.AllocationCount += ChildNode.AllocationCount;
					}
				}

				GetAllMatchingNodes(ChildNode, MatchingNodes, SearchState, SearchParams);
			}
		}
		public static int HighlightAllNodes( TreeView CallGraphTreeView, string InText, bool bTextIsRegex, bool bInMatchCase, out TreeNode FirstResult, out long AllocationSize, out int AllocationCount )
		{
			var SearchParams = new FNodeSearchParams(InText, bTextIsRegex, bInMatchCase);

			var MatchingNodes = new List<FCallGraphNode>();
			var NodeSearchState = new FNodeSearchState();
			foreach (FCallGraphNode RootNode in ((FCallGraphTreeViewTag)CallGraphTreeView.Tag).RootNodes)
			{
				GetAllMatchingNodes(RootNode, MatchingNodes, NodeSearchState, SearchParams);
			}

			CallGraphTreeView.BeginUpdate();
			foreach (FCallGraphNode MatchingNode in MatchingNodes)
			{
				EnsureTreeNode(MatchingNode);

				MatchingNode.TreeNode.BackColor = Color.CornflowerBlue;
				MatchingNode.TreeNode.EnsureVisible();
			}
			CallGraphTreeView.EndUpdate();

			FirstResult = null;
			if (MatchingNodes.Count > 0)
			{
				FirstResult = MatchingNodes[0].TreeNode;
			}

			AllocationSize = NodeSearchState.AllocationSize;
			AllocationCount = NodeSearchState.AllocationCount;

			return MatchingNodes.Count;
		}
		private static FCallGraphNode FindRecursiveChildNode(FCallGraphNode SelectedNode, FNodeSearchParams SearchParams)
		{
			foreach (FCallGraphNode ChildNode in SelectedNode.Children)
			{
				if (SearchParams.DoesNodeMatchSearch(ChildNode))
				{
					return ChildNode;
				}

				FCallGraphNode FoundNode = FindRecursiveChildNode(ChildNode, SearchParams);
				if (FoundNode != null)
				{
					return FoundNode;
				}
			}

			return null;
		}
		private static FCallGraphNode FindRecursiveSiblingNode(List<FCallGraphNode> Siblings, FCallGraphNode SelectedNode, FNodeSearchParams SearchParams)
		{
			for (int SiblingIndex = Siblings.IndexOf(SelectedNode) + 1; SiblingIndex < Siblings.Count; ++SiblingIndex)
			{
				FCallGraphNode SiblingNode = Siblings[SiblingIndex];

				if (SearchParams.DoesNodeMatchSearch(SiblingNode))
				{
					return SiblingNode;
				}

				FCallGraphNode FoundNode = FindRecursiveChildNode(SiblingNode, SearchParams);
				if (FoundNode != null)
				{
					return FoundNode;
				}
			}

			return null;
		}
		public static TreeNode FindNode( TreeView CallGraphTreeView, string InText, bool bTextIsRegex, bool bInMatchCase )
		{
			var SearchParams = new FNodeSearchParams(InText, bTextIsRegex, bInMatchCase);

			TreeNode SelectedTreeNode = CallGraphTreeView.SelectedNode;

			FCallGraphNode FoundNode = FindRecursiveChildNode((FCallGraphNode)SelectedTreeNode.Tag, SearchParams);
			while (SelectedTreeNode != null && FoundNode == null)
			{
				var Siblings = SelectedTreeNode.Parent != null ? ((FCallGraphNode)SelectedTreeNode.Parent.Tag).Children : ((FCallGraphTreeViewTag)CallGraphTreeView.Tag).RootNodes;
				FoundNode = FindRecursiveSiblingNode(Siblings, (FCallGraphNode)SelectedTreeNode.Tag, SearchParams);
				SelectedTreeNode = SelectedTreeNode.Parent;
			}

			if (FoundNode != null)
			{
				CallGraphTreeView.BeginUpdate();
				EnsureTreeNode(FoundNode);
				CallGraphTreeView.EndUpdate();

				return FoundNode.TreeNode;
			}

			return null;
		}