summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs236
1 files changed, 236 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
new file mode 100644
index 00000000..33923a49
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media.Animation;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class TabbedPageRenderer
+ : IVisualElementRenderer
+ {
+ Canvas _canvas;
+
+ bool _disposed;
+ TabsControl _tabs;
+ VisualElementTracker<Page, Canvas> _tracker;
+
+ public TabbedPage Page
+ {
+ get { return (TabbedPage)Element; }
+ }
+
+ protected VisualElementTracker<Page, Canvas> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _tracker = value;
+ }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public FrameworkElement ContainerElement
+ {
+ get { return _canvas; }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public void SetElement(VisualElement element)
+ {
+ if (element != null && !(element is TabbedPage))
+ throw new ArgumentException("Element must be a TabbedPage", "element");
+
+ var oldElement = Page;
+ Element = element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ ((INotifyCollectionChanged)oldElement.Children).CollectionChanged -= OnPagesChanged;
+ }
+
+ if (element != null)
+ {
+ if (_tracker == null)
+ {
+ _tabs = new TabsControl();
+
+ _canvas = new Canvas();
+
+ _canvas.ChildrenTransitions = new TransitionCollection
+ {
+ new EntranceThemeTransition()
+ };
+
+ Tracker = new BackgroundTracker<Canvas>(Panel.BackgroundProperty)
+ {
+ Element = (Page)element,
+ Control = _canvas,
+ Container = _canvas
+ };
+
+ _canvas.Loaded += OnLoaded;
+ _canvas.Unloaded += OnUnloaded;
+ }
+
+ _tabs.DataContext = element;
+
+ OnPagesChanged(Page.Children, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ UpdateCurrentPage();
+
+ ((INotifyCollectionChanged)Page.Children).CollectionChanged += OnPagesChanged;
+ element.PropertyChanged += OnElementPropertyChanged;
+ }
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (_canvas.Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+ var child = (FrameworkElement)_canvas.Children[0];
+
+ var oldWidth = child.Width;
+ var oldHeight = child.Height;
+
+ child.Height = double.NaN;
+ child.Width = double.NaN;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ child.Width = oldWidth;
+ child.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+ SetElement(null);
+ Tracker = null;
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply(Page.Children, _tabs.Items);
+ }
+
+ internal void OnTabSelected(Page tab)
+ {
+ CloseTabs();
+ Page.CurrentPage = tab;
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ UpdateCurrentPage();
+ }
+
+ void UpdateCurrentPage()
+ {
+ var renderer = Page.CurrentPage.GetOrCreateRenderer();
+ _canvas.Children.Clear();
+
+ if (renderer != null)
+ _canvas.Children.Add(renderer.ContainerElement);
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ if (Page == null)
+ return;
+
+ ShowTabs();
+ Page.SendAppearing();
+ }
+
+ Windows.UI.Xaml.Controls.Page GetTopPage()
+ {
+ var frame = Window.Current.Content as Windows.UI.Xaml.Controls.Frame;
+ if (frame == null)
+ return null;
+
+ return frame.Content as Windows.UI.Xaml.Controls.Page;
+ }
+
+ AppBar GetOrCreateAppBar()
+ {
+ var npage = GetTopPage();
+ if (npage == null)
+ return null;
+
+ if (npage.TopAppBar == null)
+ npage.TopAppBar = new AppBar();
+
+ return npage.TopAppBar;
+ }
+
+ void ShowTabs()
+ {
+ var bar = GetOrCreateAppBar();
+ if (bar != null)
+ bar.Content = _tabs;
+ }
+
+ void CloseTabs()
+ {
+ var page = GetTopPage();
+ if (page == null)
+ return;
+
+ if (page.TopAppBar != null)
+ page.TopAppBar.IsOpen = false;
+ }
+
+ void RemoveTabs()
+ {
+ var page = GetTopPage();
+ if (page == null)
+ return;
+
+ // Explicitly unparent this.tabs so we can reuse
+ if (page.TopAppBar != null)
+ page.TopAppBar.Content = null;
+
+ page.TopAppBar = null;
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ RemoveTabs();
+ if (Page != null)
+ Page.SendDisappearing();
+ }
+ }
+} \ No newline at end of file