Beispiel #1
0
        public void AddMatch(string shellSegment, string userSegment, object node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            switch (node)
            {
            case ShellUriHandler.GlobalRouteItem globalRoute:
                if (globalRoute.IsFinished)
                {
                    _globalRouteMatches.Add(globalRoute.SourceRoute);
                }
                break;

            case Shell shell:
                Shell = shell;
                break;

            case ShellItem item:
                Item = item;
                break;

            case ShellSection section:
                Section = section;

                if (Item == null)
                {
                    Item = Section.Parent as ShellItem;
                    _fullSegments.Add(Item.Route);
                }

                break;

            case ShellContent content:
                Content = content;
                if (Section == null)
                {
                    Section = Content.Parent as ShellSection;
                    _fullSegments.Add(Section.Route);
                }

                if (Item == null)
                {
                    Item = Section.Parent as ShellItem;
                    _fullSegments.Insert(0, Item.Route);
                }

                break;
            }

            // if shellSegment == userSegment it means the implicit route is part of the request
            if (!Routing.IsImplicit(shellSegment) || shellSegment == userSegment)
            {
                _matchedSegments.Add(shellSegment);
            }

            _fullSegments.Add(shellSegment);
        }
			public Uri GetUri()
			{
				List<string> paths = new List<string>();
				paths.Add(Shell.RouteHost);
				paths.Add(Shell.Route);
				if (Item != null && !Routing.IsImplicit(Item))
					paths.Add(Item.Route);
				if (Section != null && !Routing.IsImplicit(Section))
					paths.Add(Section.Route);
				if (Content != null && !Routing.IsImplicit(Content))
					paths.Add(Content.Route);

				string uri = String.Join(_pathSeparator, paths);
				return new Uri($"{Shell.RouteScheme}://{uri}");
			}
Beispiel #3
0
        internal static List <string> CollapsePath(
            string[] myRoute,
            IEnumerable <string> currentRouteStack,
            bool removeUserDefinedRoute)
        {
            var localRouteStack = currentRouteStack.ToList();

            for (var i = localRouteStack.Count - 1; i >= 0; i--)
            {
                var route = localRouteStack[i];
                if (Routing.IsImplicit(route) ||
                    (Routing.IsDefault(route) && removeUserDefinedRoute))
                {
                    localRouteStack.RemoveAt(i);
                }
            }

            var paths = myRoute.ToList();

            // collapse similar leaves
            int walkBackCurrentStackIndex = -1;

            if (paths.Count > 0)
            {
                walkBackCurrentStackIndex = localRouteStack.IndexOf(paths[0]);
            }

            while (paths.Count > 1 && walkBackCurrentStackIndex >= 0)
            {
                if (localRouteStack.Count <= walkBackCurrentStackIndex)
                {
                    break;
                }

                if (paths[0] == localRouteStack[walkBackCurrentStackIndex])
                {
                    paths.RemoveAt(0);
                }
                else
                {
                    break;
                }

                walkBackCurrentStackIndex++;
            }

            return(paths);
        }
Beispiel #4
0
        public override void Add(ShellItem item)
        {
            /*
             * This is purely for the case where a user is only specifying Tabs at the highest level
             * <shell>
             * <tab></tab>
             * <tab></tab>
             * </shell>
             * */
            if (Routing.IsImplicit(item) &&
                item is TabBar
                )
            {
                int i = Count - 1;
                if (i >= 0 && this[i] is TabBar && Routing.IsImplicit(this[i]))
                {
                    (this[i] as ShellItem).Items.Add(item.Items[0]);
                    return;
                }
            }

            Inner.Add(item);
        }
Beispiel #5
0
        static void SearchPath(
            object node,
            RouteRequestBuilder currentMatchedPath,
            string[] segments,
            List <RouteRequestBuilder> possibleRoutePaths,
            int depthToStart,
            int myDepth = -1,
            NodeLocation currentLocation = null,
            bool ignoreGlobalRoutes      = true)
        {
            if (node is GlobalRouteItem && ignoreGlobalRoutes)
            {
                return;
            }

            ++myDepth;
            currentLocation = currentLocation ?? new NodeLocation();
            currentLocation.SetNode(node);

            IEnumerable items = null;

            if (depthToStart > myDepth)
            {
                items = GetItems(node);
                if (items == null)
                {
                    return;
                }

                foreach (var nextNode in items)
                {
                    SearchPath(nextNode, null, segments, possibleRoutePaths, depthToStart, myDepth, currentLocation, ignoreGlobalRoutes);
                }
                return;
            }

            string shellSegment = GetRoute(node);
            string userSegment  = null;

            if (currentMatchedPath == null)
            {
                userSegment = segments[0];
            }
            else
            {
                userSegment = currentMatchedPath.NextSegment;
            }

            if (userSegment == null)
            {
                return;
            }

            RouteRequestBuilder builder = null;

            if (shellSegment == userSegment || Routing.IsImplicit(shellSegment))
            {
                if (currentMatchedPath == null)
                {
                    builder = new RouteRequestBuilder(shellSegment, userSegment, node, segments);
                }
                else
                {
                    builder = new RouteRequestBuilder(currentMatchedPath);
                    builder.AddMatch(shellSegment, userSegment, node);
                }

                if (!Routing.IsImplicit(shellSegment) || shellSegment == userSegment)
                {
                    possibleRoutePaths.Add(builder);
                }
            }

            items = GetItems(node);
            if (items == null)
            {
                return;
            }

            foreach (var nextNode in items)
            {
                SearchPath(nextNode, builder, segments, possibleRoutePaths, depthToStart, myDepth, currentLocation, ignoreGlobalRoutes);
            }
        }
Beispiel #6
0
        public static void ApplyQueryAttributes(Element element, IDictionary <string, string> query, bool isLastItem, bool isPopping)
        {
            string prefix = "";

            if (!isLastItem)
            {
                var route = Routing.GetRoute(element);
                if (string.IsNullOrEmpty(route) || Routing.IsImplicit(route))
                {
                    return;
                }
                prefix = route + ".";
            }

            //if the lastItem is implicitly wrapped, get the actual ShellContent
            if (isLastItem)
            {
                if (element is IShellItemController shellitem && shellitem.GetItems().FirstOrDefault() is ShellSection section)
                {
                    element = section;
                }
                if (element is IShellSectionController shellsection && shellsection.GetItems().FirstOrDefault() is ShellContent content)
                {
                    element = content;
                }
                if (element is ShellContent shellcontent && shellcontent.Content is Element e)
                {
                    element = e;
                }
            }

            if (!(element is BaseShellItem baseShellItem))
            {
                baseShellItem = element?.Parent as BaseShellItem;
            }

            //filter the query to only apply the keys with matching prefix
            var filteredQuery = new Dictionary <string, string>(query.Count);

            foreach (var q in query)
            {
                if (!q.Key.StartsWith(prefix, StringComparison.Ordinal))
                {
                    continue;
                }
                var key = q.Key.Substring(prefix.Length);
                if (key.Contains("."))
                {
                    continue;
                }
                filteredQuery.Add(key, q.Value);
            }


            if (baseShellItem is ShellContent)
            {
                baseShellItem.ApplyQueryAttributes(MergeData(element, filteredQuery, isPopping));
            }
            else if (isLastItem)
            {
                element.SetValue(ShellContent.QueryAttributesProperty, MergeData(element, query, isPopping));
            }

            IDictionary <string, string> MergeData(Element shellElement, IDictionary <string, string> data, bool isPopping)
            {
                if (!isPopping)
                {
                    return(data);
                }

                var returnValue = new Dictionary <string, string>(data);

                var existing = (IDictionary <string, string>)shellElement.GetValue(ShellContent.QueryAttributesProperty);

                if (existing == null)
                {
                    return(data);
                }

                foreach (var datum in existing)
                {
                    if (!returnValue.ContainsKey(datum.Key))
                    {
                        returnValue[datum.Key] = datum.Value;
                    }
                }

                return(returnValue);
            }
        }
Beispiel #7
0
        public static ShellNavigationState GetNavigationState(ShellItem shellItem, ShellSection shellSection, ShellContent shellContent, IReadOnlyList <Page> sectionStack, IReadOnlyList <Page> modalStack)
        {
            List <string> routeStack = new List <string>();

            bool stackAtRoot         = sectionStack == null || sectionStack.Count <= 1;
            bool hasUserDefinedRoute =
                (Routing.IsUserDefined(shellItem)) ||
                (Routing.IsUserDefined(shellSection)) ||
                (Routing.IsUserDefined(shellContent));

            if (shellItem != null)
            {
                var shellItemRoute = shellItem.Route;
                routeStack.Add(shellItemRoute);

                if (shellSection != null)
                {
                    var shellSectionRoute = shellSection.Route;
                    routeStack.Add(shellSectionRoute);

                    if (shellContent != null)
                    {
                        var shellContentRoute = shellContent.Route;
                        routeStack.Add(shellContentRoute);
                    }

                    if (!stackAtRoot)
                    {
                        for (int i = 1; i < sectionStack.Count; i++)
                        {
                            var page = sectionStack[i];
                            routeStack.AddRange(CollapsePath(Routing.GetRoute(page), routeStack, hasUserDefinedRoute));
                        }
                    }

                    if (modalStack != null && modalStack.Count > 0)
                    {
                        for (int i = 0; i < modalStack.Count; i++)
                        {
                            var topPage = modalStack[i];

                            routeStack.AddRange(CollapsePath(Routing.GetRoute(topPage), routeStack, hasUserDefinedRoute));

                            for (int j = 1; j < topPage.Navigation.NavigationStack.Count; j++)
                            {
                                routeStack.AddRange(CollapsePath(Routing.GetRoute(topPage.Navigation.NavigationStack[j]), routeStack, hasUserDefinedRoute));
                            }
                        }
                    }
                }
            }

            if (routeStack.Count > 0)
            {
                routeStack.Insert(0, "/");
            }

            return(new ShellNavigationState(String.Join("/", routeStack), true));


            List <string> CollapsePath(
                string myRoute,
                IEnumerable <string> currentRouteStack,
                bool userDefinedRoute)
            {
                var localRouteStack = currentRouteStack.ToList();

                for (var i = localRouteStack.Count - 1; i >= 0; i--)
                {
                    var route = localRouteStack[i];
                    if (Routing.IsImplicit(route) ||
                        (Routing.IsDefault(route) && userDefinedRoute))
                    {
                        localRouteStack.RemoveAt(i);
                    }
                }

                var paths = myRoute.Split('/').ToList();

                // collapse similar leaves
                int walkBackCurrentStackIndex = localRouteStack.Count - (paths.Count - 1);

                while (paths.Count > 1 && walkBackCurrentStackIndex >= 0)
                {
                    if (paths[0] == localRouteStack[walkBackCurrentStackIndex])
                    {
                        paths.RemoveAt(0);
                    }
                    else
                    {
                        break;
                    }

                    walkBackCurrentStackIndex++;
                }

                return(paths);
            }
        }
Beispiel #8
0
        bool UpdateFlyoutGroupings()
        {
            // The idea here is to create grouping such that the Flyout would
            // render correctly if it renderered each item in the groups in order
            // but put a line between the groups. This is needed because our grouping can
            // actually go 3 layers deep.

            // Ideally this lets us control where lines are drawn in the core code
            // just by changing how we generate these groupings

            var result = new List <List <Element> >();

            var currentGroup = new List <Element>();

            foreach (var shellItem in ShellController.GetItems())
            {
                if (!ShowInFlyoutMenu(shellItem))
                {
                    continue;
                }

                if (Routing.IsImplicit(shellItem) || shellItem.FlyoutDisplayOptions == FlyoutDisplayOptions.AsMultipleItems)
                {
                    if (shellItem.FlyoutDisplayOptions == FlyoutDisplayOptions.AsMultipleItems)
                    {
                        IncrementGroup();
                    }

                    foreach (var shellSection in (shellItem as IShellItemController).GetItems())
                    {
                        if (!ShowInFlyoutMenu(shellSection))
                        {
                            continue;
                        }

                        var shellContents = ((IShellSectionController)shellSection).GetItems();
                        if (Routing.IsImplicit(shellSection) || shellSection.FlyoutDisplayOptions == FlyoutDisplayOptions.AsMultipleItems)
                        {
                            foreach (var shellContent in shellContents)
                            {
                                if (!ShowInFlyoutMenu(shellContent))
                                {
                                    continue;
                                }

                                currentGroup.Add(shellContent);
                                if (shellContent == shellSection.CurrentItem)
                                {
                                    AddMenuItems(shellContent.MenuItems);
                                }
                            }

                            if (shellSection.FlyoutDisplayOptions == FlyoutDisplayOptions.AsMultipleItems)
                            {
                                IncrementGroup();
                            }
                        }
                        else
                        {
                            if (!(shellSection.Parent is TabBar))
                            {
                                if (Routing.IsImplicit(shellSection) && shellContents.Count == 1)
                                {
                                    if (!ShowInFlyoutMenu(shellContents[0]))
                                    {
                                        continue;
                                    }

                                    currentGroup.Add(shellContents[0]);
                                }
                                else
                                {
                                    currentGroup.Add(shellSection);
                                }
                            }

                            // If we have only a single child we will also show the items menu items
                            if (shellContents.Count == 1 && shellSection == shellItem.CurrentItem && shellSection.CurrentItem.MenuItems.Count > 0)
                            {
                                AddMenuItems(shellSection.CurrentItem.MenuItems);
                            }
                        }
                    }

                    if (shellItem.FlyoutDisplayOptions == FlyoutDisplayOptions.AsMultipleItems)
                    {
                        IncrementGroup();
                    }
                }
                else
                {
                    if (!(shellItem is TabBar))
                    {
                        currentGroup.Add(shellItem);
                    }
                }
            }

            IncrementGroup();

            // If the flyout groupings haven't changed just return
            // the same instance so the caller knows it hasn't changed
            // at a later point this will all get converted to an observable collection
            if (_lastGeneratedFlyoutItems?.Count == result.Count)
            {
                bool hasChanged = false;
                for (var i = 0; i < result.Count && !hasChanged; i++)
                {
                    var topLevelNew      = result[i];
                    var topLevelPrevious = _lastGeneratedFlyoutItems[i];

                    if (topLevelNew.Count != topLevelPrevious.Count)
                    {
                        hasChanged = true;
                        break;
                    }

                    for (var j = 0; j > topLevelNew.Count; j++)
                    {
                        if (topLevelNew[j] != topLevelPrevious[j])
                        {
                            hasChanged = true;
                            break;
                        }
                    }
                }

                if (!hasChanged)
                {
                    return(false);
                }
            }

            _lastGeneratedFlyoutItems = result;
            return(true);

            bool ShowInFlyoutMenu(BindableObject bo)
            {
                if (bo is MenuShellItem msi)
                {
                    return(Shell.GetFlyoutItemIsVisible(msi.MenuItem));
                }

                return(Shell.GetFlyoutItemIsVisible(bo));
            }

            void AddMenuItems(MenuItemCollection menuItems)
            {
                foreach (var item in menuItems)
                {
                    if (ShowInFlyoutMenu(item))
                    {
                        currentGroup.Add(item);
                    }
                }
            }

            void IncrementGroup()
            {
                if (currentGroup.Count > 0)
                {
                    result.Add(currentGroup);
                    currentGroup = new List <Element>();
                }
            }
        }