private void RestoreExpandedNodes(string searchText, NavigationPane.NavigationMode searchMode)
        {
            if ((searchText != _lastSearchText && searchText.Length > 0) || (searchMode == NavigationPane.NavigationMode.SavedSearch && _lastSearchMode != NavigationPane.NavigationMode.SavedSearch))
            {
                // expand all nodes if there's a search and the search has changed.
                _treeView.ExpandAll();
            }

            if (searchText.Length == 0 && searchMode != NavigationPane.NavigationMode.SavedSearch)
            {
                // if there isn't a search persist the user's expanded nodes.
                var list = AssignList(searchMode);

                var allNodes = new List<VirtualTreeNode>(_treeView.AllNodes);

                foreach (VirtualTreeNode.PersistenceInfo info in list)
                {
                    VirtualTreeNode match;

                    // First, look for the object in the same position
                    if (_treeView.TryExactMatch(info.Path, out match) >= info.Path.Count)
                    {
                        if (!match.IsExpanded)
                            match.Expand();

                        allNodes.Remove(match);
                        continue;
                    }

                    // Second, find the object in the maximal sub tree where it appeared only once
                    if (_treeView.TryExactMatch(info.PathToMaximalSubTree, out match) >= info.PathToMaximalSubTree.Count)
                    {
                        match = _treeView.FindNodeIn(match, info.Tag);
                        if (match != null)
                        {
                            if (!match.IsExpanded)
                                match.Expand();

                            allNodes.Remove(match);
                        }
                    }
                }

                // collapse everything else
                foreach (VirtualTreeNode n in allNodes)
                {
                    if (n.Tag != null && n.Parent != null && n.IsExpanded)
                        n.Collapse();
                }

                // special case for root node
                if (_rootExpanded)
                    _treeView.Nodes[0].Expand();
            }
        }
        /// <summary>
        /// Updates the <see cref="TreeView"/> with the specified new root node. This is done by merging the specified
        /// root node with the existing root node to minimize updates to the treeview to reduce flicker.
        /// </summary>
        /// <param name="newRootNode">The new root node.</param>
        /// <param name="searchText">The search text for the currently active search.</param>
        public void RefreshTreeView(VirtualTreeNode newRootNode, string searchText, NavigationPane.NavigationMode searchMode)
        {
            Util.ThrowIfParameterNull(newRootNode, "newRootNode");
            Util.ThrowIfParameterNull(searchText, "searchText");

            Program.AssertOnEventThread();

            _treeView.BeginUpdate();

            PersistExpandedNodes(searchText);

            _treeView.UpdateRootNodes(new[] { newRootNode });

            RestoreExpandedNodes(searchText, searchMode);

            bool searchTextCleared = (searchText.Length == 0 && searchText != _lastSearchText);

            _lastSearchText = searchText;
            _lastSearchMode = searchMode;
            _treeView.EndUpdate();

            // ensure that the selected nodes are visible when search text is cleared (CA-102127)
            if (searchTextCleared)
            {
                ExpandSelection();
            }
        }
 private List<VirtualTreeNode.PersistenceInfo> AssignList(NavigationPane.NavigationMode mode)
 {
     switch (mode)
     {
         case NavigationPane.NavigationMode.Objects:
             return _objectViewExpanded;
         case NavigationPane.NavigationMode.Tags:
             return _tagsViewExpanded;
         case NavigationPane.NavigationMode.Folders:
             return _foldersViewExpanded;
         case NavigationPane.NavigationMode.CustomFields:
             return _fieldsViewExpanded;
         case NavigationPane.NavigationMode.vApps:
             return _vappsViewExpanded;
         default:
             return _infraViewExpanded;
     }
 }
        public VirtualTreeNode CreateNewRootNode(Search search, NavigationPane.NavigationMode mode)
        {
            IAcceptGroups groupAcceptor;
            VirtualTreeNode newRootNode;

            switch (mode)
            {
                case NavigationPane.NavigationMode.Objects:
                    newRootNode = viewObjects.RootNode;
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    viewObjects.Populate(search, groupAcceptor);
                    break;
                case NavigationPane.NavigationMode.Tags:
                    newRootNode = viewTags.RootNode;
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    viewTags.Populate(search, groupAcceptor);
                    break;
                case NavigationPane.NavigationMode.Folders:
                    newRootNode = viewFolders.RootNode;
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    viewFolders.Populate(search, groupAcceptor);
                    break;
                case NavigationPane.NavigationMode.CustomFields:
                    newRootNode = viewFields.RootNode;
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    viewFields.Populate(search, groupAcceptor);
                    break;
                case NavigationPane.NavigationMode.vApps:
                    newRootNode = viewVapps.RootNode;
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    viewVapps.Populate(search, groupAcceptor);
                    break;
                case NavigationPane.NavigationMode.SavedSearch:
                    Util.ThrowIfParameterNull(search, "search");
                    newRootNode = new VirtualTreeNode(search.Name)
                        {
                            Tag = search,
                            ImageIndex = search.DefaultSearch
                                             ? (int)Icons.DefaultSearch
                                             : (int)Icons.Search
                        };
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    search.PopulateAdapters(groupAcceptor);
                    break;
                default://includes Infrastructure and Notifications
                    Util.ThrowIfParameterNull(search, "search");
                    newRootNode = new VirtualTreeNode("XenCenter") { ImageIndex = (int)Icons.Home };
                    groupAcceptor = CreateGroupAcceptor(_highlightedDragTarget, newRootNode);
                    search.PopulateAdapters(groupAcceptor);
                    break;
            }

            return newRootNode;
        }