public static List <FCallStack> GetHighlightedCallStacks(TreeView CallGraphTreeView)
        {
            List <FCallStack> Results = new List <FCallStack>();

            Worklist.Clear();
            foreach (TreeNode node in CallGraphTreeView.Nodes)
            {
                Worklist.Add(node);
            }

            while (Worklist.Count > 0)
            {
                TreeNode node = Worklist[Worklist.Count - 1];
                Worklist.RemoveAt(Worklist.Count - 1);

                if (node.BackColor != Color.Transparent)
                {
                    FNodePayload payload = ( FNodePayload )node.Tag;
                    Results.AddRange(payload.CallStacks);
                }
                else
                {
                    // Only search children if this node isn't highlighted.
                    // This makes the search go faster, and means that we don't
                    // have to worry about duplicate callstacks in the list.
                    foreach (TreeNode childNode in node.Nodes)
                    {
                        Worklist.Add(childNode);
                    }
                }
            }

            return(Results);
        }
        private static void UpdateNodeText(TreeNode RootNode)
        {
            // Compile a list of all nodes in the graph without recursion.
            List <TreeNode> TreeNodes = new List <TreeNode>();

            TreeNodes.Add(RootNode);
            int NodeIndex = 0;

            while (NodeIndex < TreeNodes.Count)
            {
                foreach (TreeNode Node in TreeNodes[NodeIndex].Nodes)
                {
                    TreeNodes.Add(Node);
                }
                NodeIndex++;
            }

            // Iterate over all nodes and prepend size in KByte.
            foreach (TreeNode Node in TreeNodes)
            {
                // Some nodes like root node won't have a tag.
                if (Node.Tag != null)
                {
                    FNodePayload Payload = Node.Tag as FNodePayload;
                    string       size    = MainWindow.FormatSizeString(Payload.AllocationSize);

                    Node.Text = size + "  " + Payload.AllocationCount + " Allocations  " + Node.Text;
                }
                // Count down work remaining.
                NodeIndex--;
            }
        }
        private static TreeNode UpdateNodeAndPayload(TreeNode ParentNode, int AddressIndex, FCallStackAllocationInfo AllocationInfo)
        {
            FCallStack CallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];

            // Iterate over existing nodes to see whether there is a match.
            foreach (TreeNode Node in ParentNode.Nodes)
            {
                FNodePayload Payload = (FNodePayload)Node.Tag;
                // If there is a match, update the allocation size and return the current node.
                if (FStreamInfo.GlobalInstance.CallStackAddressArray[Payload.AddressIndex].FunctionIndex == FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex].FunctionIndex)
                {
                    Payload.AllocationSize  += AllocationInfo.Size;
                    Payload.AllocationCount += AllocationInfo.Count;
                    Payload.CallStacks.Add(CallStack);
                    // Return current node as parent for next iteration.
                    return(Node);
                }
            }

            // If we made it here it means that we need to add a new node.
            string   NodeName = FStreamInfo.GlobalInstance.NameArray[FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex].FunctionIndex];
            TreeNode NewNode  = new TreeNode(NodeName);

            // Create payload for the node and associate it.
            FNodePayload NewPayload = new FNodePayload(AddressIndex, AllocationInfo.Size, AllocationInfo.Count, CallStack);

            NewNode.Tag = NewPayload;

            // Add to parent node and return new node as subsequent parent.
            ParentNode.Nodes.Add(NewNode);
            return(NewNode);
        }
        private static int HighlightAllNodesAux(TreeView CallGraphTreeView, TreeNodeCollection TreeNodes, FNodeSearchState SearchState, ref TreeNode FirstResult)
        {
            int ResultCount = 0;

            for (int NodeIndex = 0; NodeIndex < TreeNodes.Count; NodeIndex++)
            {
                TreeNode N          = TreeNodes[NodeIndex];
                bool     bNodeMatch = false;
                if (SearchRegex != null)
                {
                    bNodeMatch = SearchRegex.Match(N.Text).Success;
                }
                else
                {
                    if (bMatchCase)
                    {
                        bNodeMatch = N.Text.IndexOf(SearchText, StringComparison.InvariantCulture) != -1;
                    }
                    else
                    {
                        bNodeMatch = N.Text.IndexOf(SearchText, StringComparison.InvariantCultureIgnoreCase) != -1;
                    }
                }

                if (bNodeMatch)
                {
                    if (FirstResult == null)
                    {
                        FirstResult = N;
                    }

                    N.BackColor = Color.CornflowerBlue;
                    N.EnsureVisible();
                    ResultCount++;

                    FNodePayload payload = ( FNodePayload )N.Tag;
                    if (!SearchState.CallStacks.Contains(payload.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

                        SearchState.CallStacks.AddRange(payload.CallStacks);
                        SearchState.AllocationCount += payload.AllocationCount;
                        SearchState.AllocationSize  += payload.AllocationSize;
                    }
                }

                ResultCount += HighlightAllNodesAux(CallGraphTreeView, N.Nodes, SearchState, ref FirstResult);
            }

            return(ResultCount);
        }
        public int Compare(object ObjectA, object ObjectB)
        {
            // We sort by size, which requires payload.
            TreeNode     NodeA    = ObjectA as TreeNode;
            TreeNode     NodeB    = ObjectB as TreeNode;
            FNodePayload PayloadA = NodeA.Tag as FNodePayload;
            FNodePayload PayloadB = NodeB.Tag as FNodePayload;

            // Can only sort if there is payload.
            if (PayloadA != null && PayloadB != null)
            {
                // Sort by size, descending.
                return(Math.Sign(PayloadB.AllocationCount - PayloadA.AllocationCount));
            }
            // Treat missing payload as unsorted
            else
            {
                return(0);
            }
        }
        public static List <string> GetHighlightedNodesAsStrings(TreeView CallGraphTreeView)
        {
            List <string> Results = new List <string>();

            Worklist.Clear();
            foreach (TreeNode node in CallGraphTreeView.Nodes)
            {
                Worklist.Add(node);
            }

            while (Worklist.Count > 0)
            {
                TreeNode Node = Worklist[Worklist.Count - 1];
                Worklist.RemoveAt(Worklist.Count - 1);

                if (Node.BackColor != Color.Transparent)
                {
                    FNodePayload Payload = ( FNodePayload )Node.Tag;
                    if (Payload != null)
                    {
                        string FunctionName    = FStreamInfo.GlobalInstance.NameArray[FStreamInfo.GlobalInstance.CallStackAddressArray[Payload.AddressIndex].FunctionIndex];
                        int    AllocationCount = Payload.AllocationCount;
                        long   AllocationSize  = Payload.AllocationSize;
                        Results.Add(FunctionName + "," + AllocationCount + "," + AllocationSize);
                    }
                }
                else
                {
                    // Only search children if this node isn't highlighted.
                    // This makes the search go faster, and means that we don't
                    // have to worry about duplicate callstacks in the list.
                    foreach (TreeNode childNode in Node.Nodes)
                    {
                        Worklist.Add(childNode);
                    }
                }
            }

            return(Results);
        }
        private static TreeNode UpdateNodeAndPayload( TreeNode ParentNode, int AddressIndex, FCallStackAllocationInfo AllocationInfo )
        {
            FCallStack CallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];

            // Iterate over existing nodes to see whether there is a match.
            foreach( TreeNode Node in ParentNode.Nodes )
            {
                FNodePayload Payload = (FNodePayload) Node.Tag;
                // If there is a match, update the allocation size and return the current node.
                if( FStreamInfo.GlobalInstance.CallStackAddressArray[Payload.AddressIndex].FunctionIndex == FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex].FunctionIndex )
                {
                    Payload.AllocationSize += AllocationInfo.Size;
                    Payload.AllocationCount += AllocationInfo.Count;
                    Payload.CallStacks.Add(CallStack);
                    // Return current node as parent for next iteration.
                    return Node;
                }
            }

            // If we made it here it means that we need to add a new node.
            string NodeName = FStreamInfo.GlobalInstance.NameArray[FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex].FunctionIndex];
            TreeNode NewNode = new TreeNode( NodeName );

            // Create payload for the node and associate it.
            FNodePayload NewPayload = new FNodePayload(AddressIndex, AllocationInfo.Size, AllocationInfo.Count, CallStack);
            NewNode.Tag = NewPayload;

            // Add to parent node and return new node as subsequent parent.
            ParentNode.Nodes.Add( NewNode );
            return NewNode;
        }