summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs390
1 files changed, 390 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs
new file mode 100644
index 00000000..0d2ee2ed
--- /dev/null
+++ b/Xamarin.Forms.Platform.Tizen/Renderers/NavigationPageRenderer.cs
@@ -0,0 +1,390 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Xamarin.Forms.Internals;
+using ElmSharp;
+using EButton = ElmSharp.Button;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class NavigationPageRenderer : VisualElementRenderer<NavigationPage>, IDisposable, IVisualElementRenderer
+ {
+ Naviframe _naviFrame = null;
+ Page _previousPage = null;
+ TaskCompletionSource<bool> _currentTaskSource = null;
+ const string _partBackButton = "elm.swallow.prev_btn";
+ const string _leftToolbar = "title_left_btn";
+ const string _rightToolbar = "title_right_btn";
+ const string _defaultToolbarIcon = "naviframe/drawers";
+ const string _partTitle = "default";
+ const string _styleBackButton = "naviframe/back_btn/default";
+ readonly List<Widget> _naviItemContentPartList = new List<Widget>();
+ ToolbarTracker _toolbarTracker = null;
+
+ public NavigationPageRenderer()
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _naviFrame.AnimationFinished -= AnimationFinishedHandler;
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ if (_naviFrame == null)
+ {
+ _naviFrame = new Naviframe(Forms.Context.MainWindow);
+ _naviFrame.PreserveContentOnPop = true;
+ _naviFrame.DefaultBackButtonEnabled = true;
+ _naviFrame.AnimationFinished += AnimationFinishedHandler;
+
+ SetNativeControl(_naviFrame);
+ }
+
+ if (_toolbarTracker == null)
+ {
+ _toolbarTracker = new ToolbarTracker();
+ _toolbarTracker.CollectionChanged += ToolbarTrackerOnCollectionChanged;
+ }
+
+ if (e.OldElement != null)
+ {
+ var navigation = e.OldElement as INavigationPageController;
+ navigation.PopRequested -= PopRequestedHandler;
+ navigation.PopToRootRequested -= PopToRootRequestedHandler;
+ navigation.PushRequested -= PushRequestedHandler;
+ navigation.RemovePageRequested -= RemovePageRequestedHandler;
+ navigation.InsertPageBeforeRequested -= InsertPageBeforeRequestedHandler;
+
+ var pageController = e.OldElement as IPageController;
+ pageController.InternalChildren.CollectionChanged -= PageCollectionChangedHandler;
+ }
+
+ if (e.NewElement != null)
+ {
+ var navigation = e.NewElement as INavigationPageController;
+ navigation.PopRequested += PopRequestedHandler;
+ navigation.PopToRootRequested += PopToRootRequestedHandler;
+ navigation.PushRequested += PushRequestedHandler;
+ navigation.RemovePageRequested += RemovePageRequestedHandler;
+ navigation.InsertPageBeforeRequested += InsertPageBeforeRequestedHandler;
+
+ var pageController = e.NewElement as IPageController;
+ pageController.InternalChildren.CollectionChanged += PageCollectionChangedHandler;
+
+ foreach (Page page in pageController.InternalChildren)
+ {
+ _naviFrame.Push(Platform.GetOrCreateRenderer(page).NativeView, SpanTitle(page.Title));
+ page.PropertyChanged += NavigationBarPropertyChangedHandler;
+
+ UpdateHasNavigationBar(page);
+ }
+
+ _toolbarTracker.Target = e.NewElement;
+ _previousPage = e.NewElement.CurrentPage;
+ }
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
+ {
+ (_previousPage as IPageController)?.SendDisappearing();
+ _previousPage = Element.CurrentPage;
+ (_previousPage as IPageController)?.SendAppearing();
+ }
+ }
+
+ void PageCollectionChangedHandler(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ if (e.OldItems != null)
+ foreach (Page page in e.OldItems)
+ page.PropertyChanged -= NavigationBarPropertyChangedHandler;
+ if (e.NewItems != null)
+ foreach (Page page in e.NewItems)
+ page.PropertyChanged += NavigationBarPropertyChangedHandler;
+ }
+
+ void ToolbarTrackerOnCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ UpdateToolbarItem(Element.CurrentPage);
+ }
+
+ void NavigationBarPropertyChangedHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ // this handler is invoked only for child pages (contained on a navigation stack)
+ if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ UpdateHasNavigationBar(sender as Page);
+ else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName ||
+ e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
+ UpdateHasBackButton(sender as Page);
+ else if (e.PropertyName == Page.TitleProperty.PropertyName ||
+ e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName ||
+ e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName ||
+ e.PropertyName == NavigationPage.TintProperty.PropertyName)
+ UpdateTitle(sender as Page);
+ }
+
+ void UpdateHasNavigationBar(Page page)
+ {
+ NaviItem item = GetNaviItemForPage(page);
+ item.TitleBarVisible = (bool)page.GetValue(NavigationPage.HasNavigationBarProperty);
+ UpdateToolbarItem(page, item);
+ }
+
+ void UpdateToolbarItem(Page page, NaviItem item = null)
+ {
+ if (item == null)
+ item = GetNaviItemForPage(page);
+
+ if (_naviFrame.NavigationStack.Count == 0 || item == null || item != _naviFrame.NavigationStack.Last())
+ return;
+
+ item.SetPartContent(_leftToolbar, null, false);
+ item.SetPartContent(_rightToolbar, null, false);
+
+ Native.Button rightButton = GetToolbarButtonIfExists(ToolbarItemOrder.Primary);
+ item.SetPartContent(_rightToolbar, rightButton);
+
+ Native.Button leftButton = GetToolbarButtonIfExists(ToolbarItemOrder.Secondary);
+ if (leftButton == null)
+ UpdateHasBackButton(page, item);
+ else
+ item.SetPartContent(_leftToolbar, leftButton);
+ }
+
+ void UpdateHasBackButton(Page page, NaviItem item = null)
+ {
+ if (item == null)
+ item = GetNaviItemForPage(page);
+
+ EButton button = null;
+
+ if ((bool)page.GetValue(NavigationPage.HasBackButtonProperty))
+ button = CreateNavigationButton((string)page.GetValue(NavigationPage.BackButtonTitleProperty));
+ item.SetPartContent(_partBackButton, button);
+ }
+
+ void UpdateTitle(Page page)
+ {
+ NaviItem item = GetNaviItemForPage(page);
+ item.SetPartText(_partTitle, SpanTitle(page.Title));
+ }
+
+ string SpanTitle(string Title)
+ {
+ Native.Span span = new Native.Span { Text = Title };
+ if (Element.BarTextColor != Color.Default)
+ {
+ span.ForegroundColor = Element.BarTextColor.ToNative();
+ }
+ //TODO: changes only background of title not all bar
+ if (Element.BarBackgroundColor != Color.Default)
+ {
+ span.BackgroundColor = Element.BarBackgroundColor.ToNative();
+ }
+ else if (Element.Tint != Color.Default)
+ {
+ //TODO: This is only for backward compatibility
+ //- remove when Tint is no longer in Xamarin API
+ span.BackgroundColor = Element.Tint.ToNative();
+ }
+ return span.GetMarkupText();
+ }
+
+ EButton CreateNavigationButton(string text)
+ {
+ EButton button = new EButton(Forms.Context.MainWindow);
+ button.Clicked += (sender, e) =>
+ {
+ if (!Element.SendBackButtonPressed())
+ Forms.Context.Exit();
+ };
+
+ button.Style = _styleBackButton;
+ button.Text = text;
+
+ _naviItemContentPartList.Add(button);
+ button.Deleted += NaviItemPartContentDeletedHandler;
+
+ return button;
+ }
+
+ void NaviItemPartContentDeletedHandler(object sender, EventArgs e)
+ {
+ _naviItemContentPartList.Remove(sender as Widget);
+ }
+
+ NaviItem GetNaviItemForPage(Page page)
+ {
+ NaviItem item = null;
+
+ if (page != null)
+ {
+ IVisualElementRenderer renderer = Platform.GetRenderer(page);
+ if (renderer != null)
+ {
+ EvasObject content = renderer.NativeView;
+
+ for (int i = _naviFrame.NavigationStack.Count - 1; i >= 0; --i)
+ if (_naviFrame.NavigationStack[i].Content == content)
+ {
+ item = _naviFrame.NavigationStack[i];
+ break;
+ }
+ }
+ }
+ return item;
+ }
+
+ Native.Button GetToolbarButtonIfExists(ToolbarItemOrder order)
+ {
+ ToolbarItem item = _toolbarTracker.ToolbarItems.Where(
+ (i => i.Order == order ||
+ (order == ToolbarItemOrder.Primary && i.Order == ToolbarItemOrder.Default)))
+ .OrderBy(i => i.Priority)
+ .FirstOrDefault();
+
+ if (item != default(ToolbarItem))
+ {
+ return GetToolbarButton(item);
+ }
+ return null;
+ }
+
+ Native.Button GetToolbarButton(ToolbarItem item)
+ {
+ Native.Button button = new Native.Button(Forms.Context.MainWindow);
+ button.Clicked += (s, e) =>
+ {
+ IMenuItemController control = item;
+ control.Activate();
+ };
+ button.Text = item.Text;
+ button.BackgroundColor = Xamarin.Forms.Color.Transparent.ToNative();
+
+ if (String.IsNullOrEmpty(item.Icon) && String.IsNullOrEmpty(item.Text))
+ {
+ button.Style = _defaultToolbarIcon;
+ }
+ else
+ {
+ Native.Image iconImage = new Native.Image(Forms.Context.MainWindow);
+ iconImage.LoadFromImageSourceAsync(item.Icon);
+ button.Image = iconImage;
+ }
+
+ return button;
+ }
+
+ void PopRequestedHandler(object sender, NavigationRequestedEventArgs nre)
+ {
+ if ((Element as IPageController).InternalChildren.Count == _naviFrame.NavigationStack.Count)
+ {
+ if (nre.Animated)
+ {
+ _naviFrame.Pop();
+
+ _currentTaskSource = new TaskCompletionSource<bool>();
+ nre.Task = _currentTaskSource.Task;
+
+ // There is no TransitionFinished (AnimationFinished) event after Pop the last page
+ if (_naviFrame.NavigationStack.Count == 0)
+ CompleteCurrentNavigationTask();
+ }
+ else
+ _naviFrame.NavigationStack.Last().Delete();
+ }
+ }
+
+ void PopToRootRequestedHandler(object sender, NavigationRequestedEventArgs nre)
+ {
+ List<NaviItem> copyOfStack = new List<NaviItem>(_naviFrame.NavigationStack);
+ copyOfStack.Reverse();
+ NaviItem topItem = copyOfStack.FirstOrDefault();
+ NaviItem rootItem = copyOfStack.LastOrDefault();
+
+ foreach (NaviItem naviItem in copyOfStack)
+ if (naviItem != rootItem && naviItem != topItem)
+ naviItem.Delete();
+
+ if (topItem != rootItem)
+ {
+ if (nre.Animated)
+ {
+ _naviFrame.Pop();
+
+ _currentTaskSource = new TaskCompletionSource<bool>();
+ nre.Task = _currentTaskSource.Task;
+ }
+ else
+ topItem.Delete();
+ }
+ }
+
+ void PushRequestedHandler(object sender, NavigationRequestedEventArgs nre)
+ {
+ if (nre.Animated || _naviFrame.NavigationStack.Count == 0)
+ {
+ _naviFrame.Push(Platform.GetOrCreateRenderer(nre.Page).NativeView, SpanTitle(nre.Page.Title));
+ _currentTaskSource = new TaskCompletionSource<bool>();
+ nre.Task = _currentTaskSource.Task;
+
+ // There is no TransitionFinished (AnimationFinished) event after the first Push
+ if (_naviFrame.NavigationStack.Count == 1)
+ CompleteCurrentNavigationTask();
+ }
+ else
+ _naviFrame.InsertAfter(_naviFrame.NavigationStack.Last(), Platform.GetOrCreateRenderer(nre.Page).NativeView, SpanTitle(nre.Page.Title));
+
+ UpdateHasNavigationBar(nre.Page);
+ }
+
+ void RemovePageRequestedHandler(object sender, NavigationRequestedEventArgs nre)
+ {
+ GetNaviItemForPage(nre.Page).Delete();
+ }
+
+ async void InsertPageBeforeRequestedHandler(object sender, NavigationRequestedEventArgs nre)
+ {
+ TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
+ if (Element.CurrentNavigationTask != null && !Element.CurrentNavigationTask.IsCompleted)
+ {
+ await Element.CurrentNavigationTask;
+ }
+ Element.CurrentNavigationTask = tcs.Task;
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(0), () =>
+ {
+ EvasObject page = Platform.GetOrCreateRenderer(nre.Page).NativeView;
+ _naviFrame.InsertBefore(GetNaviItemForPage(nre.BeforePage), page, SpanTitle(nre.Page.Title));
+ tcs.SetResult(true);
+
+ UpdateHasNavigationBar(nre.Page);
+
+ return false;
+ });
+ }
+
+ void AnimationFinishedHandler(object sender, EventArgs e)
+ {
+ CompleteCurrentNavigationTask();
+ }
+
+ void CompleteCurrentNavigationTask()
+ {
+ if (_currentTaskSource != null)
+ {
+ var tmp = _currentTaskSource;
+ _currentTaskSource = null;
+ tmp.SetResult(true);
+ }
+ }
+ }
+}