summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/NavigationModel.cs
diff options
context:
space:
mode:
authorJason Smith <jason.smith@xamarin.com>2016-03-22 13:02:25 -0700
committerJason Smith <jason.smith@xamarin.com>2016-03-22 16:13:41 -0700
commit17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch)
treeb5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Core/NavigationModel.cs
downloadxamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz
xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2
xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip
Initial import
Diffstat (limited to 'Xamarin.Forms.Core/NavigationModel.cs')
-rw-r--r--Xamarin.Forms.Core/NavigationModel.cs177
1 files changed, 177 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/NavigationModel.cs b/Xamarin.Forms.Core/NavigationModel.cs
new file mode 100644
index 00000000..4591d4a4
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationModel.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class NavigationModel
+ {
+ readonly List<Page> _modalStack = new List<Page>();
+ readonly List<List<Page>> _navTree = new List<List<Page>>();
+
+ public Page CurrentPage
+ {
+ get
+ {
+ if (_navTree.Any())
+ return _navTree.Last().Last();
+ return null;
+ }
+ }
+
+ public IEnumerable<Page> Modals
+ {
+ get { return _modalStack; }
+ }
+
+ public IEnumerable<Page> Roots
+ {
+ get
+ {
+ foreach (List<Page> list in _navTree)
+ {
+ yield return list[0];
+ }
+ }
+ }
+
+ public IReadOnlyList<IReadOnlyList<Page>> Tree
+ {
+ get { return _navTree; }
+ }
+
+ public void Clear()
+ {
+ _navTree.Clear();
+ }
+
+ public void InsertPageBefore(Page page, Page before)
+ {
+ List<Page> currentStack = _navTree.Last();
+ int index = currentStack.IndexOf(before);
+
+ if (index == -1)
+ throw new ArgumentException("before must be in the current navigation context");
+
+ currentStack.Insert(index, page);
+ }
+
+ public Page Pop(Page ancestralNav)
+ {
+ ancestralNav = AncestorToRoot(ancestralNav);
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ if (stack.Count <= 1)
+ throw new InvalidNavigationException("Can not pop final item in stack");
+ Page result = stack.Last();
+ stack.Remove(result);
+ return result;
+ }
+ }
+
+ throw new InvalidNavigationException("Popped from unpushed item?");
+ }
+
+ public Page PopModal()
+ {
+ if (_navTree.Count <= 1)
+ throw new InvalidNavigationException("Can't pop modal without any modals pushed");
+ Page modal = _navTree.Last().First();
+ _modalStack.Remove(modal);
+ _navTree.Remove(_navTree.Last());
+ return modal;
+ }
+
+ public Page PopTopPage()
+ {
+ Page itemToRemove;
+ if (_navTree.Count == 1)
+ {
+ if (_navTree[0].Count > 1)
+ {
+ itemToRemove = _navTree[0].Last();
+ _navTree[0].Remove(itemToRemove);
+ return itemToRemove;
+ }
+ return null;
+ }
+ itemToRemove = _navTree.Last().Last();
+ _navTree.Last().Remove(itemToRemove);
+ if (!_navTree.Last().Any())
+ {
+ _navTree.RemoveAt(_navTree.Count - 1);
+ }
+ return itemToRemove;
+ }
+
+ public void PopToRoot(Page ancestralNav)
+ {
+ ancestralNav = AncestorToRoot(ancestralNav);
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ if (stack.Count <= 1)
+ throw new InvalidNavigationException("Can not pop final item in stack");
+ stack.RemoveRange(1, stack.Count - 1);
+ return;
+ }
+ }
+
+ throw new InvalidNavigationException("Popped from unpushed item?");
+ }
+
+ public void Push(Page page, Page ancestralNav)
+ {
+ if (ancestralNav == null)
+ {
+ if (_navTree.Any())
+ throw new InvalidNavigationException("Ancestor must be provided for all pushes except first");
+ _navTree.Add(new List<Page> { page });
+ return;
+ }
+
+ ancestralNav = AncestorToRoot(ancestralNav);
+
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ stack.Add(page);
+ return;
+ }
+ }
+
+ throw new InvalidNavigationException("Invalid ancestor passed");
+ }
+
+ public void PushModal(Page page)
+ {
+ _navTree.Add(new List<Page> { page });
+ _modalStack.Add(page);
+ }
+
+ public bool RemovePage(Page page)
+ {
+ bool found;
+ List<Page> currentStack = _navTree.Last();
+ var i = 0;
+ while (!(found = currentStack.Remove(page)) && i < _navTree.Count - 1)
+ {
+ currentStack = _navTree[i++];
+ }
+
+ return found;
+ }
+
+ Page AncestorToRoot(Page ancestor)
+ {
+ Page result = ancestor;
+ while (!Application.IsApplicationOrNull(result.RealParent))
+ result = (Page)result.RealParent;
+ return result;
+ }
+ }
+} \ No newline at end of file