[NUI] Add EnableBackNavigation to Page
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Navigation / Page.cs
index 298087e..f26a3a4 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 using System;
-using System.Collections.Generic;
 using System.ComponentModel;
-using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Binding;
-using System.Windows.Input;
 
 namespace Tizen.NUI.Components
 {
     /// <summary>
-    /// PageAppearingEventArgs is a class to record page appearing event arguments which will be sent to user.
+    /// PageAppearingEventArgs is a class to record <see cref="Page.Appearing"/> event arguments which will be sent to user.
     /// </summary>
-    [EditorBrowsable(EditorBrowsableState.Never)]
+    /// <since_tizen> 9 </since_tizen>
     public class PageAppearingEventArgs : EventArgs
     {
     }
 
     /// <summary>
-    /// PageDisappearingEventArgs is a class to record page disappearing event arguments which will be sent to user.
+    /// PageDisappearingEventArgs is a class to record <see cref="Page.Disappearing"/> event arguments which will be sent to user.
     /// </summary>
-    [EditorBrowsable(EditorBrowsableState.Never)]
+    /// <since_tizen> 9 </since_tizen>
     public class PageDisappearingEventArgs : EventArgs
     {
     }
 
     /// <summary>
-    /// The Page class is a class which is an element of navigation.
+    /// PageAppearedEventArgs is a class to record <see cref="Page.Appeared"/> event arguments which will be sent to user.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public class PageAppearedEventArgs : EventArgs
+    {
+    }
+
+    /// <summary>
+    /// PageDisappearedEventArgs is a class to record <see cref="Page.Disappeared"/> event arguments which will be sent to user.
     /// </summary>
-    [EditorBrowsable(EditorBrowsableState.Never)]
-    public class Page : Control
+    /// <since_tizen> 9 </since_tizen>
+    public class PageDisappearedEventArgs : EventArgs
     {
-        private AppBar _appBar = null;
-        private View _content = null;
+    }
 
+    /// <summary>
+    /// The Page class is a class which is an element of navigation.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public abstract class Page : Control
+    {
         /// <summary>
-        /// Creates a new instance of a Page.
+        /// AppearingTransitionProperty
         /// </summary>
-        /// <param name="content">The content to set to Content of Page.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Page(View content = null) : this(null, content)
+        public static readonly BindableProperty AppearingTransitionProperty = BindableProperty.Create(nameof(AppearingTransition), typeof(TransitionBase), typeof(Page), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
-        }
+            var instance = (Page)bindable;
+            if (newValue != null)
+            {
+                instance.InternalAppearingTransition = newValue as TransitionBase;
+            }
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var instance = (Page)bindable;
+            return instance.InternalAppearingTransition;
+        });
 
         /// <summary>
-        /// Creates a new instance of a Page.
+        /// DisappearingTransitionProperty
         /// </summary>
-        /// <param name="appBar">The content to set to AppBar of Page.</param>
-        /// <param name="content">The content to set to Content of Page.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Page(AppBar appBar, View content = null) : base()
+        public static readonly BindableProperty DisappearingTransitionProperty = BindableProperty.Create(nameof(DisappearingTransition), typeof(TransitionBase), typeof(Page), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
-            //AppBar and Content are located verically.
-            var linearLayout = new LinearLayout();
-            linearLayout.LinearOrientation = LinearLayout.Orientation.Vertical;
-            Layout = linearLayout;
-
-            //Page fills to parent by default.
-            WidthResizePolicy = ResizePolicyType.FillToParent;
-            HeightResizePolicy = ResizePolicyType.FillToParent;
-
-            if (appBar)
+            var instance = (Page)bindable;
+            if (newValue != null)
             {
-                AppBar = appBar;
+                instance.InternalDisappearingTransition = newValue as TransitionBase;
             }
-
-            if (content)
-            {
-                Content = content;
-            }
-        }
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var instance = (Page)bindable;
+            return instance.InternalDisappearingTransition;
+        });
 
         /// <summary>
-        /// Dispose Page and all children on it.
+        /// EnableBackNavigationProperty
         /// </summary>
-        /// <param name="type">Dispose type.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected override void Dispose(DisposeTypes type)
+        public static readonly BindableProperty EnableBackNavigationProperty = BindableProperty.Create(nameof(EnableBackNavigation), typeof(bool), typeof(Page), default(bool), propertyChanged: (bindable, oldValue, newValue) =>
         {
-            if (disposed)
+            var instance = (Page)bindable;
+            if (newValue != null)
             {
-                return;
+                instance.InternalEnableBackNavigation = (bool)newValue;
             }
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var instance = (Page)bindable;
+            return instance.InternalEnableBackNavigation;
+        });
 
-            if (type == DisposeTypes.Explicit)
-            {
-                if (_appBar != null)
-                {
-                    Utility.Dispose(_appBar);
-                }
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected internal BaseComponents.View LastFocusedView = null;
 
-                if (_content != null)
-                {
-                    Utility.Dispose(_content);
-                }
-            }
+        private Navigator navigator = null;
+
+        // Default transition is Fade.
+        private TransitionBase appearingTransition = null;
+
+        private TransitionBase disappearingTransition = null;
 
-            base.Dispose(type);
+        private bool enableBackNavigation = true;
+
+        /// <summary>
+        /// Creates a new instance of a Page.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public Page() : base()
+        {
         }
 
         /// <summary>
-        /// AppBar of Page. AppBar is added to Children automatically.
+        /// Creates a new instance of a Page with style.
         /// </summary>
+        /// <param name="style">A style applied to the newly created Page.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public AppBar AppBar
+        public Page(ControlStyle style) : base(style)
+        {
+        }
+
+        /// <summary>
+        /// Navigator which has pushed the Page into its stack.
+        /// If this Page has not been pushed into any Navigator, then Navigator is null.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public Navigator Navigator
         {
             get
             {
-                return _appBar;
+                return navigator;
             }
-            set
+            internal set
             {
-                if (_appBar == value)
+                if (navigator == value)
                 {
                     return;
                 }
 
-                if (_appBar != null)
-                {
-                    Remove(_appBar);
-                }
-
-                _appBar = value;
-                if (_appBar == null)
-                {
-                    return;
-                }
-
-                _appBar.Weight = 0.0f;
-
-                ResetContent();
+                navigator = value;
             }
         }
 
         /// <summary>
-        /// Content of Page. Content is added to Children automatically.
+        /// Transition properties for the transition of Views in this page during this page is pushed to Navigator.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public View Content
+        public TransitionBase AppearingTransition
         {
             get
             {
-                return _content;
+                return GetValue(AppearingTransitionProperty) as TransitionBase;
             }
             set
             {
-                if (_content == value)
-                {
-                    return;
-                }
-
-                if (_content != null)
-                {
-                    Remove(_content);
-                }
-
-                _content = value;
-                if (_content == null)
-                {
-                    return;
-                }
-
-                _content.Weight = 1.0f;
-
-                ResetContent();
+                SetValue(AppearingTransitionProperty, value);
+                NotifyPropertyChanged();
             }
         }
-
-        private void ResetContent()
+        private TransitionBase InternalAppearingTransition
         {
-            //To keep the order of AppBar and Content, the existing contents are
-            //removed and added again.
-            if ((_appBar != null) && Children.Contains(_appBar))
+            set
             {
-                Remove(_appBar);
+                appearingTransition = value;
             }
-
-            if ((_content != null) && Children.Contains(_content))
+            get
             {
-                Remove(_content);
+                return appearingTransition;
             }
+        }
 
-            if (_appBar != null)
+        /// <summary>
+        /// Transition properties for the transition of Views in this page during this page is popped from Navigator.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TransitionBase DisappearingTransition
+        {
+            get
             {
-                Add(_appBar);
+                return GetValue(DisappearingTransitionProperty) as TransitionBase;
             }
-
-            if (_content != null)
+            set
+            {
+                SetValue(DisappearingTransitionProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+        private TransitionBase InternalDisappearingTransition
+        {
+            set
+            {
+                disappearingTransition = value;
+            }
+            get
             {
-                Add(_content);
+                return disappearingTransition;
             }
         }
 
         /// <summary>
-        /// An event for the page appearing signal which can be used to subscribe or unsubscribe the event handler provided by the user.
+        /// Appearing event is invoked right before the page appears.
         /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
+        /// <since_tizen> 9 </since_tizen>
         public event EventHandler<PageAppearingEventArgs> Appearing;
 
         /// <summary>
-        /// An event for the page disappearing signal which can be used to subscribe or unsubscribe the event handler provided by the user.
+        /// Disappearing event is invoked right before the page disappears.
         /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
+        /// <since_tizen> 9 </since_tizen>
         public event EventHandler<PageDisappearingEventArgs> Disappearing;
 
+        /// <summary>
+        /// Appeared event is invoked right after the page appears.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public event EventHandler<PageAppearedEventArgs> Appeared;
+
+        /// <summary>
+        /// Disappeared event is invoked right after the page disappears.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public event EventHandler<PageDisappearedEventArgs> Disappeared;
+
+        /// <summary>
+        /// Gets or sets if this page is popped when back button or back key is pressed and released.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool EnableBackNavigation
+        {
+            get
+            {
+                return (bool)GetValue(EnableBackNavigationProperty);
+            }
+            set
+            {
+                SetValue(EnableBackNavigationProperty, value);
+                NotifyPropertyChanged();
+            }
+        }
+
+        private bool InternalEnableBackNavigation
+        {
+            set
+            {
+                enableBackNavigation = value;
+            }
+            get
+            {
+                return enableBackNavigation;
+            }
+        }
+
         internal void InvokeAppearing()
         {
             Appearing?.Invoke(this, new PageAppearingEventArgs());
@@ -227,5 +282,88 @@ namespace Tizen.NUI.Components
         {
             Disappearing?.Invoke(this, new PageDisappearingEventArgs());
         }
+
+        internal void InvokeAppeared()
+        {
+            Appeared?.Invoke(this, new PageAppearedEventArgs());
+        }
+
+        internal void InvokeDisappeared()
+        {
+            Disappeared?.Invoke(this, new PageDisappearedEventArgs());
+        }
+
+        /// <summary>
+        /// works only when DefaultAlgorithm is enabled.
+        /// to save the currently focused View when disappeared.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected internal virtual void SaveKeyFocus()
+        {
+            if (FocusManager.Instance.IsDefaultAlgorithmEnabled())
+            {
+                if (this is DialogPage)
+                {
+                    FocusManager.Instance.ResetFocusFinderRootView();
+                }
+
+                var currentFocusedView = FocusManager.Instance.GetCurrentFocusView();
+                if (currentFocusedView)
+                {
+                    var findChild = FindDescendantByID(currentFocusedView.ID);
+                    if (findChild)
+                    {
+                        LastFocusedView = findChild;
+                        return;
+                    }
+                }
+                LastFocusedView = null;
+            }
+        }
+
+        /// <summary>
+        /// works only when DefaultAlgorithm is enabled.
+        /// to set key focused View when showing.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected internal virtual void RestoreKeyFocus()
+        {
+            if (FocusManager.Instance.IsDefaultAlgorithmEnabled())
+            {
+                if (LastFocusedView)
+                {
+                    FocusManager.Instance.SetCurrentFocusView(LastFocusedView);
+                }
+                else
+                {
+                    var temp = new Tizen.NUI.BaseComponents.View()
+                    {
+                        Size = new Size(0.1f, 0.1f, 0.0f),
+                        Position = new Position(0, 0, 0),
+                        Focusable = true,
+                    };
+                    this.Add(temp);
+                    temp.LowerToBottom();
+                    FocusManager.Instance.SetCurrentFocusView(temp);
+                    var focused = FocusManager.Instance.GetNearestFocusableActor(this, temp, Tizen.NUI.BaseComponents.View.FocusDirection.Down);
+                    if (focused)
+                    {
+                        FocusManager.Instance.SetCurrentFocusView(focused);
+                    }
+                    else
+                    {
+                        FocusManager.Instance.ClearFocus();
+                    }
+                    temp.Unparent();
+                    temp.Dispose();
+                }
+
+                if (this is DialogPage)
+                {
+                    FocusManager.Instance.SetFocusFinderRootView(this);
+                }
+            }
+        }
+
     }
 }