Ejemplo n.º 1
0
        void AddExpandedChildrenRecursively(TreeViewItem item, ExpandedMarkerIdHierarchy expandedHierarchy)
        {
            if (item.children == null)
            {
                return;
            }

            for (var i = 0; i < item.children.Count; ++i)
            {
                var childItem = item.children[i];
                // Inlining !IsChildListForACollapsedParent without childList.Count == 1 check, as we only create list if we have children
                if (childItem.children != null && childItem.children[0] != null)
                {
                    var subHierarchy = new ExpandedMarkerIdHierarchy();
                    if (expandedHierarchy.expandedMarkers == null)
                    {
                        expandedHierarchy.expandedMarkers = new Dictionary <int, ExpandedMarkerIdHierarchy>();
                    }
                    try
                    {
                        expandedHierarchy.expandedMarkers.Add(m_FrameDataView.GetItemMarkerID(childItem.id), subHierarchy);
                    }
                    catch (ArgumentException)
                    {
                    }

                    AddExpandedChildrenRecursively(childItem, subHierarchy);
                }
            }
        }
Ejemplo n.º 2
0
        void StoreExpandedState()
        {
            if (m_ExpandedMarkersHierarchy != null)
            {
                return;
            }
            if (m_FrameDataView == null || !m_FrameDataView.IsValid())
            {
                return;
            }

            m_ExpandedMarkersHierarchy = new ExpandedMarkerIdHierarchy();
            AddExpandedChildrenRecursively(rootItem, m_ExpandedMarkersHierarchy);
        }
Ejemplo n.º 3
0
 protected override void ExpandedStateChanged()
 {
     // Invalidate saved expanded state if user altered current state.
     m_ExpandedMarkersHierarchy = null;
 }
Ejemplo n.º 4
0
        void AddAllChildren(FrameDataTreeViewItem parent, ExpandedMarkerIdHierarchy parentExpandedHierararchy, IList <TreeViewItem> newRows, List <int> newExpandedIds)
        {
            m_ReusableVisitList.AddFirst(AcquireTreeTraversalStateNode(parent, parentExpandedHierararchy));

            // Depth-first traversal.
            // Think of it as an unrolled recursion where stack state is defined by TreeTraversalState.
            while (m_ReusableVisitList.First != null)
            {
                var currentItem = m_ReusableVisitList.First.Value;
                m_TreeTraversalStatePool.Push(m_ReusableVisitList.First);
                m_ReusableVisitList.RemoveFirst();

                if (currentItem.item.depth != -1)
                {
                    newRows.Add(currentItem.item);
                }

                m_FrameDataView.GetItemChildren(currentItem.item.id, m_ReusableChildrenIds);
                var childrenCount = m_ReusableChildrenIds.Count;
                if (childrenCount == 0)
                {
                    continue;
                }

                if (currentItem.item.depth != -1)
                {
                    // Check expansion state from a previous frame view state (marker id path) or current tree view state (frame-specific id).
                    bool needsExpansion;
                    if (m_ExpandedMarkersHierarchy == null)
                    {
                        // When we alter expansion state of the currently selected frame,
                        // we rely on TreeView's IsExpanded functionality.
                        needsExpansion = IsExpanded(currentItem.item.id);
                    }
                    else
                    {
                        // When we switch to another frame, we rebuild expanded state based on stored m_ExpandedMarkersHierarchy
                        // which represents tree of expanded nodes.
                        needsExpansion = currentItem.expandedHierarchy != null;
                    }

                    if (!needsExpansion)
                    {
                        if (currentItem.item.children == null)
                        {
                            currentItem.item.children = CreateChildListForCollapsedParent();
                        }
                        continue;
                    }

                    if (newExpandedIds != null)
                    {
                        newExpandedIds.Add(currentItem.item.id);
                    }
                }

                // Generate children based on the view data.
                if (currentItem.item.children == null)
                {
                    // Reuse existing list.
                    if (m_ChildrenPool.Count > 0)
                    {
                        currentItem.item.children = m_ChildrenPool.Pop();
                    }
                    else
                    {
                        currentItem.item.children = new List <TreeViewItem>();
                    }
                }
                currentItem.item.children.Clear();
                currentItem.item.children.Capacity = childrenCount;

                for (var i = 0; i < childrenCount; ++i)
                {
                    var child = AcquireFrameDataTreeViewItem(m_FrameDataView, m_ReusableChildrenIds[i], currentItem.item.depth + 1, currentItem.item);
                    currentItem.item.children.Add(child);
                }

                // Add children to the traversal list.
                // We add all of them in front, so it is depth search, but with preserved siblings order.
                LinkedListNode <TreeTraversalState> prev = null;
                foreach (var child in currentItem.item.children)
                {
                    var childMarkerId = m_FrameDataView.GetItemMarkerID(child.id);
                    ExpandedMarkerIdHierarchy childExpandedHierarchy = null;
                    if (currentItem.expandedHierarchy != null && currentItem.expandedHierarchy.expandedMarkers != null)
                    {
                        currentItem.expandedHierarchy.expandedMarkers.TryGetValue(childMarkerId, out childExpandedHierarchy);
                    }

                    var traversalState = AcquireTreeTraversalStateNode((FrameDataTreeViewItem)child, childExpandedHierarchy);
                    if (prev == null)
                    {
                        m_ReusableVisitList.AddFirst(traversalState);
                    }
                    else
                    {
                        m_ReusableVisitList.AddAfter(prev, traversalState);
                    }
                    prev = traversalState;
                }
            }

            if (newExpandedIds != null)
            {
                newExpandedIds.Sort();
            }
        }
Ejemplo n.º 5
0
        LinkedListNode <TreeTraversalState> AcquireTreeTraversalStateNode(FrameDataTreeViewItem item, ExpandedMarkerIdHierarchy expandedHierarchy)
        {
            if (m_TreeTraversalStatePool.Count == 0)
            {
                return(new LinkedListNode <TreeTraversalState>(new TreeTraversalState()
                {
                    item = item, expandedHierarchy = expandedHierarchy
                }));
            }

            var node = m_TreeTraversalStatePool.Pop();

            node.Value = new TreeTraversalState()
            {
                item = item, expandedHierarchy = expandedHierarchy
            };
            return(node);
        }
        void AddAllChildren(FrameDataTreeViewItem parent, ExpandedMarkerIdHierarchy parentExpandedHierararchy, IList <TreeViewItem> newRows, List <int> newExpandedIds)
        {
            m_ReusableVisitList.AddFirst(AcquireTreeTraversalStateNode(parent, parentExpandedHierararchy));

            // Depth-first traversal.
            // Think of it as an unrolled recursion where stack state is defined by TreeTraversalState.
            while (m_ReusableVisitList.First != null)
            {
                var currentItem = m_ReusableVisitList.First.Value.item;
                var currentExpandedHierarchy = m_ReusableVisitList.First.Value.expandedHierarchy;
                {
                    // scope firstItem to avoid reusing it accidentally
                    var firstItem = m_ReusableVisitList.First;
                    firstItem.Value = default;
                    m_TreeTraversalStatePool.Push(firstItem);
                    m_ReusableVisitList.RemoveFirst();
                }

                // This loop can be a bit of a hot path so, micro optimizations like property caching and inlinig have some effect:
                // So... cache depth
                var currentItemDepth = currentItem.depth;
                // and cache children, remember to also set currentItem.children if a new list is assigned
                var currentItemChildren = currentItem.children;

                if (currentItemDepth != ProfilerFrameDataHierarchyView.invalidTreeViewDepth)
                {
                    newRows.Add(currentItem);
                }

                m_FrameDataView.GetItemChildren(currentItem.id, m_ReusableChildrenIds);
                var childrenCount = m_ReusableChildrenIds.Count;
                if (childrenCount == 0)
                {
                    continue;
                }

                if (currentItemDepth != ProfilerFrameDataHierarchyView.invalidTreeViewDepth)
                {
                    // Check expansion state from a previous frame view state (marker id path) or current tree view state (frame-specific id).
                    bool needsExpansion;
                    if (m_ExpandedMarkersHierarchy == null)
                    {
                        // When we alter expansion state of the currently selected frame,
                        // we rely on TreeView's IsExpanded functionality.
                        needsExpansion = IsExpanded(currentItem.id);
                    }
                    else
                    {
                        // When we switch to another frame, we rebuild expanded state based on stored m_ExpandedMarkersHierarchy
                        // which represents tree of expanded nodes.
                        needsExpansion = currentExpandedHierarchy != null;
                    }

                    if (!needsExpansion)
                    {
                        if (currentItemChildren == null)
                        {
                            // Lets create a fake laze child list.
                            // Not using CreateChildListForCollapsedParent as that list returns a static list and will cause funkyness later on.
                            // We have a pool, so we're gonna use that.
                            if (m_ChildrenPool.Count > 0)
                            {
                                currentItem.children = currentItemChildren = m_ChildrenPool.Pop();
                                currentItemChildren.Clear();
                            }
                            else
                            {
                                currentItem.children = currentItemChildren = new List <TreeViewItem>();
                            }
                            currentItemChildren.Add(null);
                        }
                        continue;
                    }

                    if (newExpandedIds != null)
                    {
                        newExpandedIds.Add(currentItem.id);
                    }
                }

                // Generate children based on the view data.
                if (currentItemChildren == null)
                {
                    // Reuse existing list.
                    if (m_ChildrenPool.Count > 0)
                    {
                        currentItem.children = currentItemChildren = m_ChildrenPool.Pop();
                    }
                    else
                    {
                        currentItem.children = currentItemChildren = new List <TreeViewItem>();
                    }
                }
                currentItemChildren.Clear();
                const int k_MaxSuperflousCapacity = 32 - 1;
                // only reset capacity if needed or if too much space would be wasted. Otherwise, what's the point of pooling them?
                if (currentItemChildren.Capacity < childrenCount || currentItemChildren.Capacity > childrenCount + k_MaxSuperflousCapacity)
                {
                    currentItemChildren.Capacity = childrenCount;
                }

                for (var i = 0; i < childrenCount; ++i)
                {
                    var child = AcquireFrameDataTreeViewItem(m_FrameDataView, m_ReusableChildrenIds[i], currentItemDepth + 1, currentItem);
                    currentItemChildren.Add(child);
                }

                // Add children to the traversal list.
                // We add all of them in front, so it is depth search, but with preserved siblings order.
                LinkedListNode <TreeTraversalState> prev = null;
                foreach (var child in currentItemChildren)
                {
                    var childMarkerId = m_FrameDataView.GetItemMarkerID(child.id);
                    ExpandedMarkerIdHierarchy childExpandedHierarchy = null;
                    if (currentExpandedHierarchy != null && currentExpandedHierarchy.expandedMarkers != null)
                    {
                        currentExpandedHierarchy.expandedMarkers.TryGetValue(childMarkerId, out childExpandedHierarchy);
                    }

                    var traversalState = AcquireTreeTraversalStateNode((FrameDataTreeViewItem)child, childExpandedHierarchy);
                    if (prev == null)
                    {
                        m_ReusableVisitList.AddFirst(traversalState);
                    }
                    else
                    {
                        m_ReusableVisitList.AddAfter(prev, traversalState);
                    }
                    prev = traversalState;
                }
            }

            if (newExpandedIds != null)
            {
                newExpandedIds.Sort();
            }
        }