From 17fdde66d94155fc62a034fa6658995bef6fd6e5 Mon Sep 17 00:00:00 2001 From: Jason Smith Date: Tue, 22 Mar 2016 13:02:25 -0700 Subject: Initial import --- Xamarin.Forms.Core/NavigationProxy.cs | 233 ++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 Xamarin.Forms.Core/NavigationProxy.cs (limited to 'Xamarin.Forms.Core/NavigationProxy.cs') diff --git a/Xamarin.Forms.Core/NavigationProxy.cs b/Xamarin.Forms.Core/NavigationProxy.cs new file mode 100644 index 00000000..65e2fee9 --- /dev/null +++ b/Xamarin.Forms.Core/NavigationProxy.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Xamarin.Forms +{ + internal class NavigationProxy : INavigation + { + INavigation _inner; + Lazy> _modalStack = new Lazy>(() => new List()); + + Lazy> _pushStack = new Lazy>(() => new List()); + + public INavigation Inner + { + get { return _inner; } + set + { + if (_inner == value) + return; + _inner = value; + // reverse so that things go into the new stack in the same order + // null out to release memory that will likely never be needed again + + if (ReferenceEquals(_inner, null)) + { + _pushStack = new Lazy>(() => new List()); + _modalStack = new Lazy>(() => new List()); + } + else + { + if (_pushStack != null && _pushStack.IsValueCreated) + { + foreach (Page page in _pushStack.Value) + { + _inner.PushAsync(page); + } + } + + if (_modalStack != null && _modalStack.IsValueCreated) + { + foreach (Page page in _modalStack.Value) + { + _inner.PushModalAsync(page); + } + } + + _pushStack = null; + _modalStack = null; + } + } + } + + public void InsertPageBefore(Page page, Page before) + { + OnInsertPageBefore(page, before); + } + + public IReadOnlyList ModalStack + { + get { return GetModalStack(); } + } + + public IReadOnlyList NavigationStack + { + get { return GetNavigationStack(); } + } + + public Task PopAsync() + { + return OnPopAsync(true); + } + + public Task PopAsync(bool animated) + { + return OnPopAsync(animated); + } + + public Task PopModalAsync() + { + return OnPopModal(true); + } + + public Task PopModalAsync(bool animated) + { + return OnPopModal(animated); + } + + public Task PopToRootAsync() + { + return OnPopToRootAsync(true); + } + + public Task PopToRootAsync(bool animated) + { + return OnPopToRootAsync(animated); + } + + public Task PushAsync(Page root) + { + return PushAsync(root, true); + } + + public Task PushAsync(Page root, bool animated) + { + if (root.RealParent != null) + throw new InvalidOperationException("Page must not already have a parent."); + return OnPushAsync(root, animated); + } + + public Task PushModalAsync(Page modal) + { + return PushModalAsync(modal, true); + } + + public Task PushModalAsync(Page modal, bool animated) + { + if (modal.RealParent != null) + throw new InvalidOperationException("Page must not already have a parent."); + return OnPushModal(modal, animated); + } + + public void RemovePage(Page page) + { + OnRemovePage(page); + } + + protected virtual IReadOnlyList GetModalStack() + { + INavigation currentInner = Inner; + return currentInner == null ? _modalStack.Value : currentInner.ModalStack; + } + + protected virtual IReadOnlyList GetNavigationStack() + { + INavigation currentInner = Inner; + return currentInner == null ? _pushStack.Value : currentInner.NavigationStack; + } + + protected virtual void OnInsertPageBefore(Page page, Page before) + { + INavigation currentInner = Inner; + if (currentInner == null) + { + int index = _pushStack.Value.IndexOf(before); + if (index == -1) + throw new ArgumentException("before must be in the pushed stack of the current context"); + _pushStack.Value.Insert(index, page); + } + else + { + currentInner.InsertPageBefore(page, before); + } + } + + protected virtual Task OnPopAsync(bool animated) + { + INavigation inner = Inner; + return inner == null ? Task.FromResult(Pop()) : inner.PopAsync(animated); + } + + protected virtual Task OnPopModal(bool animated) + { + INavigation innerNav = Inner; + return innerNav == null ? Task.FromResult(PopModal()) : innerNav.PopModalAsync(animated); + } + + protected virtual Task OnPopToRootAsync(bool animated) + { + INavigation currentInner = Inner; + if (currentInner == null) + { + Page root = _pushStack.Value.Last(); + _pushStack.Value.Clear(); + _pushStack.Value.Add(root); + return Task.FromResult(root); + } + return currentInner.PopToRootAsync(animated); + } + + protected virtual Task OnPushAsync(Page page, bool animated) + { + INavigation currentInner = Inner; + if (currentInner == null) + { + _pushStack.Value.Add(page); + return Task.FromResult(page); + } + return currentInner.PushAsync(page, animated); + } + + protected virtual Task OnPushModal(Page modal, bool animated) + { + INavigation currentInner = Inner; + if (currentInner == null) + { + _modalStack.Value.Add(modal); + return Task.FromResult(null); + } + return currentInner.PushModalAsync(modal, animated); + } + + protected virtual void OnRemovePage(Page page) + { + INavigation currentInner = Inner; + if (currentInner == null) + { + _pushStack.Value.Remove(page); + } + else + { + currentInner.RemovePage(page); + } + } + + Page Pop() + { + List list = _pushStack.Value; + Page result = list[list.Count - 1]; + list.RemoveAt(list.Count - 1); + return result; + } + + Page PopModal() + { + List list = _modalStack.Value; + Page result = list[list.Count - 1]; + list.RemoveAt(list.Count - 1); + return result; + } + } +} \ No newline at end of file -- cgit v1.2.3