public static void Traverse(
            SelectionNode root,
            bool realizeChildren,
            Action <TreeWalkNodeInfo> nodeAction)
        {
            var pendingNodes = new List <TreeWalkNodeInfo>();
            var current      = new IndexPath(null);

            pendingNodes.Add(new TreeWalkNodeInfo(root, current));

            while (pendingNodes.Count > 0)
            {
                var nextNode = pendingNodes.Last();
                pendingNodes.RemoveAt(pendingNodes.Count - 1);
                int count = realizeChildren ? nextNode.Node.DataCount : nextNode.Node.ChildrenNodeCount;
                for (int i = count - 1; i >= 0; i--)
                {
                    var child     = nextNode.Node.GetAt(i, realizeChildren, nextNode.Path);
                    var childPath = nextNode.Path.CloneWithChildIndex(i);
                    if (child != null)
                    {
                        pendingNodes.Add(new TreeWalkNodeInfo(child, childPath, nextNode.Node));
                    }
                }

                // Queue the children first and then perform the action. This way
                // the action can remove the children in the action if necessary
                nodeAction(nextNode);
            }
        }
            public TreeWalkNodeInfo(SelectionNode node, IndexPath indexPath)
            {
                node = node ?? throw new ArgumentNullException(nameof(node));

                Node       = node;
                Path       = indexPath;
                ParentNode = null;
            }
        private ItemsRepeater GetChildRepeaterForIndexPath(IndexPath ip)
        {
            if (GetContainerForIndexPath(ip) is NavigationViewItem nvi)
            {
                return(nvi.GetRepeater);
            }

            return(null);
        }
Esempio n. 4
0
 internal SelectionModelChildrenRequestedEventArgs(
     object source,
     IndexPath sourceIndexPath,
     IndexPath finalIndexPath,
     bool throwOnAccess)
 {
     source = source ?? throw new ArgumentNullException(nameof(source));
     Initialize(source, sourceIndexPath, finalIndexPath, throwOnAccess);
 }
        private static IndexPath StartPath(IndexPath path, int length)
        {
            var subPath = new List <int>();

            for (int i = 0; i < length; i++)
            {
                subPath.Add(path.GetAt(i));
            }

            return(new IndexPath(subPath));
        }
Esempio n. 6
0
        internal void Initialize(
            object?source,
            IndexPath sourceIndexPath,
            IndexPath finalIndexPath,
            bool throwOnAccess)
        {
            if (!throwOnAccess && source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            _source          = source;
            _sourceIndexPath = sourceIndexPath;
            _finalIndexPath  = finalIndexPath;
            _throwOnAccess   = throwOnAccess;
        }
        public static void TraverseIndexPath(
            SelectionNode root,
            IndexPath path,
            bool realizeChildren,
            Action <SelectionNode, IndexPath, int, int> nodeAction)
        {
            var node = root;

            for (int depth = 0; depth < path.GetSize(); depth++)
            {
                int childIndex = path.GetAt(depth);
                nodeAction(node, path, depth, childIndex);

                if (depth < path.GetSize() - 1)
                {
                    node = node.GetAt(childIndex, realizeChildren, path) !;
                }
            }
        }
        private static bool IsSubSet(IndexPath path, IndexPath subset)
        {
            var subsetSize = subset.GetSize();

            if (path.GetSize() < subsetSize)
            {
                return(false);
            }

            for (int i = 0; i < subsetSize; i++)
            {
                if (path.GetAt(i) != subset.GetAt(i))
                {
                    return(false);
                }
            }

            return(true);
        }
        private IndexPath GetIndexPathForContainer(NavigationViewItemBase nvib)
        {
            var  path           = new List <int>(4);
            bool isInFooterMenu = false;

            IControl child  = nvib;
            var      parent = nvib.GetVisualParent();

            if (parent == null)
            {
                return(IndexPath.CreateFromIndices(path));
            }

            // Search through VisualTree for a root ItemsRepeater
            while (parent != null && !IsRootItemsRepeater(parent) && !IsRootGridOfFlyout(parent))
            {
                if (parent is ItemsRepeater ir)
                {
                    path.Insert(0, ir.GetElementIndex(child));
                }
                child  = (IControl)parent;
                parent = parent.GetVisualParent();
            }

            // If the item is in a flyout, then we need to final index of its parent
            if (IsRootGridOfFlyout(parent))
            {
                if (_lastItemExpandedIntoFlyout != null)
                {
                    child  = _lastItemExpandedIntoFlyout;
                    parent = IsTopNavigationView ? _topNavRepeater : _leftNavRepeater;
                }
            }

            // If item is in one of the disconnected ItemRepeaters, account for that in IndexPath calculations
            if (parent == _topNavRepeaterOverflowView)
            {
                // Convert index of selected item in overflow to index in datasource
                var contIndex   = _topNavRepeaterOverflowView.GetElementIndex(child);
                var item        = _topDataProvider.GetOverflowItems()[contIndex];
                var indexAtRoot = _topDataProvider.IndexOf(item);
                path.Insert(0, indexAtRoot);
            }
            else if (parent == _topNavRepeater)
            {
                // Convert index of selected item in overflow to index in datasource
                var contIndex   = _topNavRepeater.GetElementIndex(child);
                var item        = _topDataProvider.GetPrimaryItems()[contIndex];
                var indexAtRoot = _topDataProvider.IndexOf(item);
                path.Insert(0, indexAtRoot);
            }
            else if (parent is ItemsRepeater parentIR)
            {
                path.Insert(0, parentIR.GetElementIndex(child));
            }

            isInFooterMenu = parent == _leftNavFooterMenuRepeater || parent == _topNavFooterMenuRepeater;

            path.Insert(0, isInFooterMenu ? _footerMenuBlockIndex : _mainMenuBlockIndex);

            return(IndexPath.CreateFromIndices(path));
        }
        public static void TraverseRangeRealizeChildren(
            SelectionNode root,
            IndexPath start,
            IndexPath end,
            Action <TreeWalkNodeInfo> nodeAction)
        {
            var pendingNodes = new List <TreeWalkNodeInfo>();
            var current      = start;

            // Build up the stack to account for the depth first walk up to the
            // start index path.
            TraverseIndexPath(
                root,
                start,
                true,
                (node, path, depth, childIndex) =>
            {
                var currentPath  = StartPath(path, depth);
                bool isStartPath = IsSubSet(start, currentPath);
                bool isEndPath   = IsSubSet(end, currentPath);

                int startIndex = depth < start.GetSize() && isStartPath ? start.GetAt(depth) : 0;
                int endIndex   = depth < end.GetSize() && isEndPath ? end.GetAt(depth) : node.DataCount - 1;

                for (int i = endIndex; i >= startIndex; i--)
                {
                    var child = node.GetAt(i, true, end);
                    if (child != null)
                    {
                        var childPath = currentPath.CloneWithChildIndex(i);
                        pendingNodes.Add(new TreeWalkNodeInfo(child, childPath, node));
                    }
                }
            });

            // From the start index path, do a depth first walk as long as the
            // current path is less than the end path.
            while (pendingNodes.Count > 0)
            {
                var info = pendingNodes.Last();
                pendingNodes.RemoveAt(pendingNodes.Count - 1);
                int  depth       = info.Path.GetSize();
                bool isStartPath = IsSubSet(start, info.Path);
                bool isEndPath   = IsSubSet(end, info.Path);
                int  startIndex  = depth < start.GetSize() && isStartPath?start.GetAt(depth) : 0;

                int endIndex = depth < end.GetSize() && isEndPath?end.GetAt(depth) : info.Node.DataCount - 1;

                for (int i = endIndex; i >= startIndex; i--)
                {
                    var child = info.Node.GetAt(i, true, end);
                    if (child != null)
                    {
                        var childPath = info.Path.CloneWithChildIndex(i);
                        pendingNodes.Add(new TreeWalkNodeInfo(child, childPath, info.Node));
                    }
                }

                nodeAction(info);

                if (info.Path.CompareTo(end) == 0)
                {
                    // We reached the end index path. stop iterating.
                    break;
                }
            }
        }