summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/MasterDetailPage.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/MasterDetailPage.cs')
-rw-r--r--Xamarin.Forms.Core/MasterDetailPage.cs229
1 files changed, 229 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/MasterDetailPage.cs b/Xamarin.Forms.Core/MasterDetailPage.cs
new file mode 100644
index 00000000..a0849aa4
--- /dev/null
+++ b/Xamarin.Forms.Core/MasterDetailPage.cs
@@ -0,0 +1,229 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_MasterDetailPageRenderer))]
+ public class MasterDetailPage : Page
+ {
+ public static readonly BindableProperty IsGestureEnabledProperty = BindableProperty.Create("IsGestureEnabled", typeof(bool), typeof(MasterDetailPage), true);
+
+ public static readonly BindableProperty IsPresentedProperty = BindableProperty.Create("IsPresented", typeof(bool), typeof(MasterDetailPage), default(bool),
+ propertyChanged: OnIsPresentedPropertyChanged, propertyChanging: OnIsPresentedPropertyChanging);
+
+ public static readonly BindableProperty MasterBehaviorProperty = BindableProperty.Create("MasterBehavior", typeof(MasterBehavior), typeof(MasterDetailPage), default(MasterBehavior),
+ propertyChanged: OnMasterBehaviorPropertyChanged);
+
+ Page _detail;
+
+ Rectangle _detailBounds;
+
+ Page _master;
+
+ Rectangle _masterBounds;
+
+ public Page Detail
+ {
+ get { return _detail; }
+ set
+ {
+ if (_detail != null && value == null)
+ throw new ArgumentNullException("value", "Detail cannot be set to null once a value is set.");
+
+ if (_detail == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Detail must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_detail != null)
+ InternalChildren.Remove(_detail);
+ _detail = value;
+ InternalChildren.Add(_detail);
+ OnPropertyChanged();
+ }
+ }
+
+ public bool IsGestureEnabled
+ {
+ get { return (bool)GetValue(IsGestureEnabledProperty); }
+ set { SetValue(IsGestureEnabledProperty, value); }
+ }
+
+ public bool IsPresented
+ {
+ get { return (bool)GetValue(IsPresentedProperty); }
+ set { SetValue(IsPresentedProperty, value); }
+ }
+
+ public Page Master
+ {
+ get { return _master; }
+ set
+ {
+ if (_master != null && value == null)
+ throw new ArgumentNullException("value", "Master cannot be set to null once a value is set");
+
+ if (string.IsNullOrEmpty(value.Title))
+ throw new InvalidOperationException("Title property must be set on Master page");
+
+ if (_master == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Master must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_master != null)
+ InternalChildren.Remove(_master);
+ _master = value;
+ InternalChildren.Add(_master);
+ OnPropertyChanged();
+ }
+ }
+
+ public MasterBehavior MasterBehavior
+ {
+ get { return (MasterBehavior)GetValue(MasterBehaviorProperty); }
+ set { SetValue(MasterBehaviorProperty, value); }
+ }
+
+ internal bool CanChangeIsPresented { get; set; } = true;
+
+ internal Rectangle DetailBounds
+ {
+ get { return _detailBounds; }
+ set
+ {
+ _detailBounds = value;
+ if (_detail == null)
+ throw new InvalidOperationException("Detail must be set before using a MasterDetailPage");
+ _detail.Layout(value);
+ }
+ }
+
+ internal Rectangle MasterBounds
+ {
+ get { return _masterBounds; }
+ set
+ {
+ _masterBounds = value;
+ if (_master == null)
+ throw new InvalidOperationException("Master must be set before using a MasterDetailPage");
+ _master.Layout(value);
+ }
+ }
+
+ internal bool ShouldShowSplitMode
+ {
+ get
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return false;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior == MasterBehavior.Split || isSplitOnLandscape || isSplitOnPortrait;
+ }
+ }
+
+ public event EventHandler IsPresentedChanged;
+
+ public virtual bool ShouldShowToolbarButton()
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return true;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior != MasterBehavior.Split && !isSplitOnLandscape && !isSplitOnPortrait;
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (Master == null || Detail == null)
+ throw new InvalidOperationException("Master and Detail must be set before using a MasterDetailPage");
+ _master.Layout(_masterBounds);
+ _detail.Layout(_detailBounds);
+ }
+
+ protected override void OnAppearing()
+ {
+ CanChangeIsPresented = true;
+ UpdateMasterBehavior(this);
+ base.OnAppearing();
+ }
+
+ protected override bool OnBackButtonPressed()
+ {
+ if (IsPresented)
+ {
+ if (Master.SendBackButtonPressed())
+ return true;
+ }
+
+ EventHandler<BackButtonPressedEventArgs> handler = BackButtonPressed;
+ if (handler != null)
+ {
+ var args = new BackButtonPressedEventArgs();
+ handler(this, args);
+ if (args.Handled)
+ return true;
+ }
+
+ if (Detail.SendBackButtonPressed())
+ {
+ return true;
+ }
+
+ return base.OnBackButtonPressed();
+ }
+
+ protected override void OnParentSet()
+ {
+ if (RealParent != null && (Master == null || Detail == null))
+ throw new InvalidOperationException("Master and Detail must be set before adding MasterDetailPage to a container");
+ base.OnParentSet();
+ }
+
+ internal event EventHandler<BackButtonPressedEventArgs> BackButtonPressed;
+
+ internal static void UpdateMasterBehavior(MasterDetailPage page)
+ {
+ if (page.ShouldShowSplitMode)
+ {
+ page.SetValueCore(IsPresentedProperty, true);
+ if (page.MasterBehavior != MasterBehavior.Default)
+ page.CanChangeIsPresented = false;
+ }
+ }
+
+ static void OnIsPresentedPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ EventHandler handler = page.IsPresentedChanged;
+ if (handler != null)
+ handler(page, EventArgs.Empty);
+ }
+
+ static void OnIsPresentedPropertyChanging(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ if (!page.CanChangeIsPresented)
+ throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", page.MasterBehavior));
+ }
+
+ static void OnMasterBehaviorPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ UpdateMasterBehavior(page);
+ }
+ }
+} \ No newline at end of file