diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Core/NavigationModel.cs | |
download | xamarin-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.cs | 177 |
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 |