[NUI] View Transition with page switching
authorSeungho Baek <sbsh.baek@samsung.com>
Tue, 2 Mar 2021 15:33:22 +0000 (00:33 +0900)
committerbshsqa <32317749+bshsqa@users.noreply.github.com>
Wed, 14 Apr 2021 11:53:58 +0000 (20:53 +0900)
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
14 files changed:
src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs
src/Tizen.NUI/src/internal/Interop/Interop.TransitionItem.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Interop/Interop.TransitionItemBase.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Interop/Interop.TransitionSet.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Transition/TransitionItem.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Transition/TransitionItemBase.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Transition/TransitionSet.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Transition/TransitionSetSignal.cs [new file with mode: 0755]
src/Tizen.NUI/src/public/Animation/TransitionOptions.cs
src/Tizen.NUI/src/public/BaseComponents/View.cs
src/Tizen.NUI/src/public/Common/TimePeriod.cs [moved from src/Tizen.NUI/src/internal/Common/TimePeriod.cs with 88% similarity]
src/Tizen.NUI/src/public/Transition/Transition.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/Transition/TransitionBase.cs [new file with mode: 0644]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PageTransitionSample.cs [new file with mode: 0755]

index 3d10f28..4df540a 100755 (executable)
@@ -24,18 +24,48 @@ using Tizen.NUI.BaseComponents;
 namespace Tizen.NUI.Components
 {
     /// <summary>
-    /// The Navigator is a class which navigates pages with stack methods such
-    /// as Push and Pop.
+    /// The Navigator is a class which navigates pages with stack methods such as Push and Pop.
+    ///
+    /// With Transition class, Navigator supports smooth transition of View pair between two Pages
+    /// by using PushWithTransition(Page) and PopWithTransition() methods.
+    /// If there is View pair of current top Page and next top Page those have same View.TransitionOptions.TransitionTag,
+    /// Navigator creates smooth transition motion for them.
+    /// Navigator.Transition property can be used to set properties of the Transition such as TimePeriod and AlphaFunction.
+    /// When all transitions are finished, Navigator calls a callback methods those connected on the "TransitionFinished" event.
+    /// 
+    /// <example>
+    /// <code>
+    /// Navigator.Transition = new Transition()
+    /// {
+    ///     TimePeriod = new TimePeriod(0.5),
+    ///     AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseInOutSine)
+    /// }
+    ///
+    /// Navigator.PushWithTransition(newPage);
+    /// </code>
+    /// </example>
     /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
     public class Navigator : Control
     {
+        private static readonly float DefaultTransitionDuration = 0.5f;
+
         //This will be replaced with view transition class instance.
         private Animation curAnimation = null;
 
         //This will be replaced with view transition class instance.
         private Animation newAnimation = null;
 
+        private TransitionSet transitionSet = null;
+
+        private Transition transition = new Transition()
+        {
+            TimePeriod = new TimePeriod(DefaultTransitionDuration),
+            AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Default),
+        };
+
+        private bool transitionFinished = true;
+
         //TODO: Needs to consider how to remove disposed window from dictionary.
         //Two dictionaries are required to remove disposed navigator from dictionary.
         private static Dictionary<Window, Navigator> windowNavigator = new Dictionary<Window, Navigator>();
@@ -49,6 +79,12 @@ namespace Tizen.NUI.Components
         {
             Layout = new AbsoluteLayout();
         }
+        
+        /// <summary>
+        /// An event for the page disappearing signal which can be used to subscribe or unsubscribe the event handler provided by the user.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public event EventHandler<EventArgs> TransitionFinished;
 
         /// <summary>
         /// List of pages of Navigator.
@@ -57,6 +93,113 @@ namespace Tizen.NUI.Components
         public List<Page> NavigationPages { get; } = new List<Page>();
 
         /// <summary>
+        /// Transition properties for the transition of View pair those have same transition tag.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Transition Transition
+        {
+            set
+            {
+                transition = value;
+            }
+            get
+            {
+                return transition;
+            }
+        }
+
+        /// <summary>
+        /// Pushes a page to Navigator.
+        /// If the page is already in Navigator, then it is not pushed.
+        /// </summary>
+        /// <param name="page">The page to push to Navigator.</param>
+        /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void PushWithTransition(Page page)
+        {
+            if (!transitionFinished)
+            {
+                Tizen.Log.Error("NUI", "Transition is still not finished.\n");
+                return;
+            }
+
+            if (page == null)
+            {
+                throw new ArgumentNullException(nameof(page), "page should not be null.");
+            }
+
+            //Duplicate page is not pushed.
+            if (NavigationPages.Contains(page)) return;
+
+            var topPage = Peek();
+
+            if (!topPage)
+            {
+                Insert(0, page);
+                return;
+            }
+
+            NavigationPages.Add(page);
+            Add(page);
+
+            //Invoke Page events
+            page.InvokeAppearing();
+            topPage.InvokeDisappearing();
+
+            transitionSet = CreateTransition(topPage, page, true);
+            transitionSet.Finished += (object sender, EventArgs e) =>
+            {
+                topPage.SetVisible(false);
+            };
+            transitionFinished = false;
+        }
+
+        /// <summary>
+        /// Pops the top page from Navigator.
+        /// </summary>
+        /// <returns>The popped page.</returns>
+        /// <exception cref="InvalidOperationException">Thrown when there is no page in Navigator.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Page PopWithTransition()
+        {
+            if (!transitionFinished)
+            {
+                Tizen.Log.Error("NUI", "Transition is still not finished.\n");
+                return null;
+            }
+
+            if (NavigationPages.Count == 0)
+            {
+                throw new InvalidOperationException("There is no page in Navigator.");
+            }
+
+            var topPage = Peek();
+
+            if (NavigationPages.Count == 1)
+            {
+                Remove(topPage);
+                return topPage;
+            }
+            var newTopPage = NavigationPages[NavigationPages.Count - 2];
+
+//            newTopPage.RaiseAbove(topPage);
+
+            //Invoke Page events
+            newTopPage.InvokeAppearing();
+            topPage.InvokeDisappearing();
+
+            transitionSet = CreateTransition(topPage, newTopPage, false);
+            transitionSet.Finished += (object sender, EventArgs e) =>
+            {
+                Remove(topPage);
+                topPage.SetVisible(true);
+            };
+            transitionFinished = false;
+
+            return topPage;
+        }
+
+        /// <summary>
         /// Pushes a page to Navigator.
         /// If the page is already in Navigator, then it is not pushed.
         /// </summary>
@@ -65,6 +208,12 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Push(Page page)
         {
+            if (!transitionFinished)
+            {
+                Tizen.Log.Error("NUI", "Transition is still not finished.\n");
+                return;
+            }
+
             if (page == null)
             {
                 throw new ArgumentNullException(nameof(page), "page should not be null.");
@@ -138,6 +287,12 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         public Page Pop()
         {
+            if (!transitionFinished)
+            {
+                Tizen.Log.Error("NUI", "Transition is still not finished.\n");
+                return null;
+            }
+
             if (NavigationPages.Count == 0)
             {
                 throw new InvalidOperationException("There is no page in Navigator.");
@@ -441,6 +596,78 @@ namespace Tizen.NUI.Components
             defaultNavigator.Push(dialogPage);
         }
 
+        /// <summary>
+        /// Create Transition between currentTopPage and newTopPage
+        /// </summary>
+        /// <param name="currentTopPage">The top page of Navigator.</param>
+        /// <param name="newTopPage">The new top page after transition.</param>
+        /// <param name="pushTransition">True if this transition is for push new page</param>
+        private TransitionSet CreateTransition(Page currentTopPage, Page newTopPage, bool pushTransition)
+        {
+            currentTopPage.SetVisible(true);
+            newTopPage.SetVisible(true);
+
+            List<View> taggedViewsInNewTopPage = new List<View>();
+            RetrieveTaggedViews(taggedViewsInNewTopPage, newTopPage.Content);
+            List<View> taggedViewsInCurrentTopPage = new List<View>();
+            RetrieveTaggedViews(taggedViewsInCurrentTopPage, currentTopPage.Content);
+
+            List<KeyValuePair<View, View>> sameTaggedViewPair = new List<KeyValuePair<View, View>>();
+            foreach(View currentTopPageView in taggedViewsInCurrentTopPage)
+            {
+                bool findPair = false;
+                foreach(View newTopPageView in taggedViewsInNewTopPage)
+                {
+                    if((currentTopPageView.TransitionOptions != null) && (newTopPageView.TransitionOptions != null) &&
+                        currentTopPageView.TransitionOptions?.TransitionTag == newTopPageView.TransitionOptions?.TransitionTag)
+                    {
+                        sameTaggedViewPair.Add(new KeyValuePair<View, View>(currentTopPageView, newTopPageView));
+                        findPair = true;
+                        break;
+                    }
+                }
+                if(findPair)
+                {
+                    taggedViewsInNewTopPage.Remove(sameTaggedViewPair[sameTaggedViewPair.Count - 1].Value);
+                }
+            }
+            foreach(KeyValuePair<View, View> pair in sameTaggedViewPair)
+            {
+                taggedViewsInCurrentTopPage.Remove(pair.Key);
+            }
+
+            TransitionSet newTransitionSet = new TransitionSet();
+            foreach(KeyValuePair<View, View> pair in sameTaggedViewPair)
+            {
+                TransitionItem pairTransition = transition.CreateTransition(pair.Key, pair.Value);
+                if(pair.Value.TransitionOptions?.TransitionWithChild ?? false)
+                {
+                    pairTransition.TransitionWithChild = true;
+                }
+                newTransitionSet.AddTransition(pairTransition);
+            }
+            newTransitionSet.Play();
+
+            newTransitionSet.Finished += (object sender, EventArgs e) =>
+            {
+                transitionFinished = true;
+                InvokeTransitionFinished();
+                transitionSet.Dispose();
+                currentTopPage.Opacity = 1.0f;
+            };
+
+            // default entering/exit transition - fast fade (half duration compaired with that of view pair transition)
+            float duration = (transition.TimePeriod.DurationSeconds + transition.TimePeriod.DelaySeconds) * 0.8f;
+            Animation fade = new Animation(duration);
+            fade.AnimateTo(currentTopPage, "Opacity", 0.0f);
+            KeyFrames keyframes = new KeyFrames();
+            keyframes.Add(0.0f, 0.0f);
+            keyframes.Add(1.0f, 1.0f);
+            fade.AnimateBetween(newTopPage, "Opacity", keyframes);
+            fade.Play();
+
+            return newTransitionSet;
+        }
 
         private static void SetDialogScrim(Dialog dialog)
         {
@@ -469,5 +696,39 @@ namespace Tizen.NUI.Components
 
             dialog.Scrim = scrim;
         }
+
+
+        /// <summary>
+        /// Retrieve Tagged Views in the view tree.
+        /// </summary>
+        /// <param name="taggedViews">Returned tagged view list..</param>
+        /// <param name="view">Root View to get tagged child View.</param>
+        private void RetrieveTaggedViews(List<View> taggedViews, View view)
+        {
+            if (!string.IsNullOrEmpty(view.TransitionOptions?.TransitionTag))
+            {
+                taggedViews.Add((view as View));
+            }
+
+            if (view.ChildCount == 0)
+            {
+                return;
+            }
+
+            if (view.TransitionOptions?.TransitionWithChild ?? false)
+            {
+                return;
+            }
+
+            foreach (View child in view.Children)
+            {
+                RetrieveTaggedViews(taggedViews, child);
+            }
+        }
+
+        internal void InvokeTransitionFinished()
+        {
+            TransitionFinished?.Invoke(this, new EventArgs());
+        }
     }
 } //namespace Tizen.NUI
diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItem.cs b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItem.cs
new file mode 100755 (executable)
index 0000000..76ccc1c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using global::System;
+    using global::System.Runtime.InteropServices;
+
+    internal static partial class Interop
+    {
+        internal static partial class TransitionItem
+        {
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_Transition")]
+            public static extern IntPtr NewEmpty();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Transition_New")]
+            public static extern IntPtr New(HandleRef source, HandleRef destination, HandleRef timePeriod);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_Transition")]
+            public static extern void Delete(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_Transition_Set")]
+            public static extern IntPtr NewTransitionItem(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Transition_Assign")]
+            public static extern IntPtr Assign(HandleRef destination, HandleRef source);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Transition_ShowSourceAfterFinished")]
+            public static extern void ShowSourceAfterFinished(HandleRef transition, bool showSourceAfterFinished);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItemBase.cs b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItemBase.cs
new file mode 100755 (executable)
index 0000000..3c80bed
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using global::System;
+    using global::System.Runtime.InteropServices;
+
+    internal static partial class Interop
+    {
+        internal static partial class TransitionItemBase
+        {
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_TransitionBase")]
+            public static extern IntPtr NewEmpty();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_New")]
+            public static extern IntPtr New();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_TransitionBase")]
+            public static extern void Delete(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_TransitionBase_Set")]
+            public static extern IntPtr NewTransitionItemBase(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_Assign")]
+            public static extern IntPtr Assign(HandleRef destination, HandleRef source);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_SetDuration")]
+            public static extern void SetDuration(HandleRef transition, float seconds);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_GetDuration")]
+            public static extern float GetDuration(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_SetDelay")]
+            public static extern void SetDelay(HandleRef transition, float seconds);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_GetDelay")]
+            public static extern float GetDelay(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_SetTimePeriod")]
+            public static extern void SetTimePeriod(HandleRef transition, HandleRef seconds);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_SetAlphaFunction")]
+            public static extern void SetAlphaFunction(HandleRef transition, HandleRef seconds);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_GetAlphaFunction")]
+            public static extern IntPtr GetAlphaFunction(HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionBase_TransitionWithChild")]
+            public static extern void TransitionWithChild(HandleRef transition, bool transitionWithChild);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.TransitionSet.cs b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionSet.cs
new file mode 100755 (executable)
index 0000000..32b495a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using global::System;
+    using global::System.Runtime.InteropServices;
+    internal static partial class Interop
+    {
+        internal static partial class TransitionSet
+        {
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_TransitionSet")]
+            public static extern IntPtr NewEmpty();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_New")]
+            public static extern IntPtr New();
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_TransitionSet")]
+            public static extern void Delete(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_TransitionSet_Set")]
+            public static extern IntPtr NewTransitionSet(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Assign")]
+            public static extern IntPtr Assign(HandleRef destination, HandleRef source);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_AddTransition")]
+            public static extern void AddTransition(HandleRef transitionSet, HandleRef transition);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_GetTransitionAt")]
+            public static extern IntPtr GetTransitionAt(HandleRef transitionSet, uint index);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_GetTransitionCount")]
+            public static extern uint GetTransitionCount(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Play")]
+            public static extern void Play(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_FinishedSignal")]
+            public static extern IntPtr FinishedSignal(HandleRef nuiTransitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Signal_Empty")]
+            public static extern bool TransitionSetFinishedSignalEmpty(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Signal_GetConnectionCount")]
+            public static extern uint TransitionSetFinishedSignalGetConnectionCount(HandleRef transitionSet);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Signal_Connect")]
+            public static extern void TransitionSetFinishedSignalConnect(HandleRef transitionSet, HandleRef func);
+
+            [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TransitionSet_Signal_Disconnect")]
+            public static extern void TransitionSetFinishedSignalDisconnect(HandleRef transitionSet, HandleRef func);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Transition/TransitionItem.cs b/src/Tizen.NUI/src/internal/Transition/TransitionItem.cs
new file mode 100755 (executable)
index 0000000..76c6b3a
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using System;
+    using System.ComponentModel;
+
+    using Tizen.NUI.BaseComponents;
+
+    /// <summary>
+    /// TransitionItem is an object to set Transition of View pair those have same TransitionTag.
+    /// TransitionItem object is required for each View pair and this is added to the TransitionSet to play.
+    /// </summary>
+    internal class TransitionItem : TransitionItemBase
+    {
+        /// <summary>
+        /// Creates an initialized transition.<br />
+        /// </summary>
+        /// <remarks>DurationmSeconds must be greater than zero.</remarks>
+        public TransitionItem(View source, View destination, TimePeriod timePeriod, AlphaFunction alphaFunction) : this(Interop.TransitionItem.New(source.SwigCPtr, destination.SwigCPtr, timePeriod.SwigCPtr), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            AlphaFunction = alphaFunction;
+        }
+
+        internal TransitionItem(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+        {
+        }
+
+        /// <summary>
+        /// Sets the source View will be shown after transition finished.
+        /// </summary>
+        public bool ShowSourceAfterFinished
+        {
+            set
+            {
+                Interop.TransitionItem.ShowSourceAfterFinished(SwigCPtr, value);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        internal static global::System.Runtime.InteropServices.HandleRef getCPtr(TransitionItem obj)
+        {
+            return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.SwigCPtr;
+        }
+
+        internal TransitionItem(TransitionItem handle) : this(Interop.TransitionItem.NewTransitionItem(TransitionItem.getCPtr(handle)), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        internal TransitionItem Assign(TransitionItem rhs)
+        {
+            TransitionItem ret = new TransitionItem(Interop.TransitionItem.Assign(SwigCPtr, TransitionItem.getCPtr(rhs)), false);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        /// <summary>
+        /// To make transition instance be disposed.
+        /// </summary>
+        protected override void Dispose(DisposeTypes type)
+        {
+            if (disposed)
+            {
+                return;
+            }
+            base.Dispose(type);
+        }
+
+        /// This will not be public opened.
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+        {
+            if (swigCPtr.Handle == IntPtr.Zero || this.HasBody() == false)
+            {
+                Tizen.Log.Fatal("NUI", $"[ERROR] TransitionItem ReleaseSwigCPtr()! IntPtr=0x{swigCPtr.Handle:X} HasBody={this.HasBody()}");
+                return;
+            }
+            Interop.TransitionItem.Delete(swigCPtr);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Transition/TransitionItemBase.cs b/src/Tizen.NUI/src/internal/Transition/TransitionItemBase.cs
new file mode 100755 (executable)
index 0000000..2819f67
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using System;
+    using System.ComponentModel;
+    using Tizen.NUI.BaseComponents;
+
+    internal class TransitionItemBase : BaseHandle
+    {
+        /// <summary>
+        /// Creates an initialized TransitionItemBase.<br />
+        /// </summary>
+        public TransitionItemBase(View target, bool isEntering, TimePeriod timePeriod, AlphaFunction alphaFunction) : this(Interop.TransitionItemBase.New(/*target.SwigCPtr, isEntering, timePeriod.SwigCPtr*/), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            AlphaFunction = alphaFunction;
+        }
+
+        internal TransitionItemBase(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the duration in milliseconds of the transition.
+        /// </summary>
+        public int Duration
+        {
+            set
+            {
+                Interop.TransitionItemBase.SetDuration(SwigCPtr, MilliSecondsToSeconds(value));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+            get
+            {
+                float ret = Interop.TransitionItemBase.GetDuration(SwigCPtr);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                return SecondsToMilliSeconds(ret);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the delay in milliseconds of the transition.
+        /// </summary>
+        public int Delay
+        {
+            set
+            {
+                Interop.TransitionItemBase.SetDelay(SwigCPtr, MilliSecondsToSeconds(value));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+            get
+            {
+                float ret = Interop.TransitionItemBase.GetDelay(SwigCPtr);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                return SecondsToMilliSeconds(ret);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the TimePeriod
+        /// </summary>
+        public TimePeriod TimePeriod
+        {
+            set
+            {
+                Interop.TransitionItemBase.SetTimePeriod(SwigCPtr, value.SwigCPtr);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the AlphaFunction
+        /// </summary>
+        public AlphaFunction AlphaFunction
+        {
+            set
+            {
+                Interop.TransitionItemBase.SetAlphaFunction(SwigCPtr, value.SwigCPtr);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+            get
+            {
+                AlphaFunction ret = new AlphaFunction(Interop.TransitionItemBase.GetAlphaFunction(SwigCPtr), true);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                return ret;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether the View moves with child or not.
+        /// </summary>
+        public bool TransitionWithChild
+        {
+            set
+            {
+                Interop.TransitionItemBase.TransitionWithChild(SwigCPtr, value);
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        /// <summary>
+        /// Downcasts a handle to TransitionItemBase handle.<br />
+        /// If handle points to an TransitionItemBase object, the downcast produces a valid handle.<br />
+        /// If not, the returned handle is left uninitialized.<br />
+        /// </summary>
+        /// <param name="handle">Handle to an object.</param>
+        /// <returns>Handle to an TransitionItemBase object or an uninitialized handle.</returns>
+        /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
+        public static TransitionItemBase DownCast(BaseHandle handle)
+        {
+            if (handle == null)
+            {
+                throw new ArgumentNullException(nameof(handle));
+            }
+            TransitionItemBase ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as TransitionItemBase;
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        internal static global::System.Runtime.InteropServices.HandleRef getCPtr(TransitionItemBase obj)
+        {
+            return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.SwigCPtr;
+        }
+
+        internal TransitionItemBase(TransitionItemBase handle) : this(Interop.TransitionItemBase.NewTransitionItemBase(TransitionItemBase.getCPtr(handle)), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        internal TransitionItemBase Assign(TransitionItemBase rhs)
+        {
+            TransitionItemBase ret = new TransitionItemBase(Interop.TransitionItemBase.Assign(SwigCPtr, TransitionItemBase.getCPtr(rhs)), false);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        /// <summary>
+        /// To make TransitionItemBase instance be disposed.
+        /// </summary>
+        protected override void Dispose(DisposeTypes type)
+        {
+            if (disposed)
+            {
+                return;
+            }
+            base.Dispose(type);
+        }
+
+        /// This will not be public opened.
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+        {
+            if (swigCPtr.Handle == IntPtr.Zero || this.HasBody() == false)
+            {
+                Tizen.Log.Fatal("NUI", $"[ERROR] TransitionItemBase ReleaseSwigCPtr()! IntPtr=0x{swigCPtr.Handle:X} HasBody={this.HasBody()}");
+                return;
+            }
+            Interop.TransitionItemBase.Delete(swigCPtr);
+        }
+
+        private float MilliSecondsToSeconds(int millisec)
+        {
+            return (float)millisec / 1000.0f;
+        }
+
+        private int SecondsToMilliSeconds(float sec)
+        {
+            return (int)(sec * 1000);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Transition/TransitionSet.cs b/src/Tizen.NUI/src/internal/Transition/TransitionSet.cs
new file mode 100755 (executable)
index 0000000..547b91a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using System;
+    using System.ComponentModel;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// TransitionSet is used to control lifetime of multiple Transitions.
+    /// For the one page transition, may multiple transitions are played coincidently.
+    /// Every transitions added on a TransitionSet have same play lifetime. And emit a single Finished signal.
+    /// </summary>
+    internal class TransitionSet : BaseHandle
+    {
+        private TransitionSetFinishedEventCallbackType transitionSetFinishedEventCallback;
+        private System.IntPtr finishedCallbackOfNative;
+
+        /// <summary>
+        /// Creates an initialized transitionSet.<br />
+        /// </summary>
+        /// <remarks>DurationmSeconds must be greater than zero.</remarks>
+        public TransitionSet() : this(Interop.TransitionSet.New(), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        internal TransitionSet(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+        {
+            transitionSetFinishedEventCallback = OnFinished;
+            finishedCallbackOfNative = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(transitionSetFinishedEventCallback);
+        }
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        private delegate void TransitionSetFinishedEventCallbackType(IntPtr data);
+
+        private event EventHandler transitionSetFinishedEventHandler;
+
+        /**
+        * @brief Event for the finished signal which can be used to subscribe or unsubscribe the event handler.
+        * The finished signal is emitted when an transitionSet's transitionSets have finished.
+        */
+        public event EventHandler Finished
+        {
+            add
+            {
+                if (transitionSetFinishedEventHandler == null && disposed == false)
+                {
+                    TransitionSetFinishedSignal finishedSignal = FinishedSignal();
+                    finishedSignal.Connect(finishedCallbackOfNative);
+                    finishedSignal.Dispose();
+                }
+                transitionSetFinishedEventHandler += value;
+            }
+            remove
+            {
+                transitionSetFinishedEventHandler -= value;
+
+                TransitionSetFinishedSignal finishedSignal = FinishedSignal();
+                if (transitionSetFinishedEventHandler == null && finishedSignal.Empty() == false)
+                {
+                    finishedSignal.Disconnect(finishedCallbackOfNative);
+                }
+                finishedSignal.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Downcasts a handle to transitionSet handle.<br />
+        /// If handle points to an transitionSet object, the downcast produces a valid handle.<br />
+        /// If not, the returned handle is left uninitialized.<br />
+        /// </summary>
+        /// <param name="handle">Handle to an object.</param>
+        /// <returns>Handle to an transitionSet object or an uninitialized handle.</returns>
+        /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
+        internal static TransitionSet DownCast(BaseHandle handle)
+        {
+            if (handle == null)
+            {
+                throw new ArgumentNullException(nameof(handle));
+            }
+            TransitionSet ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as TransitionSet;
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public void AddTransition(TransitionItemBase transition)
+        {
+            Interop.TransitionSet.AddTransition(SwigCPtr, transition.SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        public TransitionItemBase GetTransitionAt(uint index)
+        {
+            //to fix memory leak issue, match the handle count with native side.
+            IntPtr cPtr = Interop.TransitionSet.GetTransitionAt(SwigCPtr, index);
+            HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
+            TransitionItemBase ret = Registry.GetManagedBaseHandleFromNativePtr(CPtr.Handle) as TransitionItemBase;
+            if (cPtr != null && ret == null)
+            {
+                ret = new TransitionItemBase(cPtr, false);
+                if (NDalicPINVOKE.SWIGPendingException.Pending)
+                    throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+                return ret;
+            }
+            Interop.BaseHandle.DeleteBaseHandle(CPtr);
+            CPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
+
+            if (NDalicPINVOKE.SWIGPendingException.Pending)
+                throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public uint GetTransitionCount()
+        {
+            uint ret = Interop.TransitionSet.GetTransitionCount(SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        /// <summary>
+        /// Plays the transitionSet.
+        /// </summary>
+        public void Play()
+        {
+            Interop.TransitionSet.Play(SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        internal static global::System.Runtime.InteropServices.HandleRef getCPtr(TransitionSet obj)
+        {
+            return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.SwigCPtr;
+        }
+
+        internal TransitionSet(TransitionSet handle) : this(Interop.TransitionSet.NewTransitionSet(TransitionSet.getCPtr(handle)), true)
+        {
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        internal TransitionSet Assign(TransitionSet rhs)
+        {
+            TransitionSet ret = new TransitionSet(Interop.TransitionSet.Assign(SwigCPtr, TransitionSet.getCPtr(rhs)), false);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        internal TransitionSetFinishedSignal FinishedSignal()
+        {
+            TransitionSetFinishedSignal ret = new TransitionSetFinishedSignal(Interop.TransitionSet.FinishedSignal(SwigCPtr), false);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        /// <summary>
+        /// To make transitionSet instance be disposed.
+        /// </summary>
+        protected override void Dispose(DisposeTypes type)
+        {
+            if (disposed)
+            {
+                return;
+            }
+
+            if (transitionSetFinishedEventHandler != null)
+            {
+                TransitionSetFinishedSignal finishedSignal = FinishedSignal();
+                finishedSignal?.Disconnect(finishedCallbackOfNative);
+                finishedSignal?.Dispose();
+                transitionSetFinishedEventHandler = null;
+            }
+
+            base.Dispose(type);
+        }
+
+        /// This will not be public opened.
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+        {
+            if (swigCPtr.Handle == IntPtr.Zero || this.HasBody() == false)
+            {
+                Tizen.Log.Fatal("NUI", $"[ERROR] TransitionSet ReleaseSwigCPtr()! IntPtr=0x{swigCPtr.Handle:X} HasBody={this.HasBody()}");
+                return;
+            }
+            Interop.TransitionSet.Delete(swigCPtr);
+        }
+
+        private void OnFinished(IntPtr data)
+        {
+            if (transitionSetFinishedEventHandler != null)
+            {
+                //here we send all data to user event handlers
+                transitionSetFinishedEventHandler(this, null);
+            }
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/internal/Transition/TransitionSetSignal.cs b/src/Tizen.NUI/src/internal/Transition/TransitionSetSignal.cs
new file mode 100755 (executable)
index 0000000..a3bef6f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    internal class TransitionSetFinishedSignal : Disposable
+    {
+        internal TransitionSetFinishedSignal(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+        {
+        }
+
+        public bool Empty()
+        {
+            bool ret = Interop.TransitionSet.TransitionSetFinishedSignalEmpty(SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public uint GetConnectionCount()
+        {
+            uint ret = Interop.TransitionSet.TransitionSetFinishedSignalGetConnectionCount(SwigCPtr);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        public void Connect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
+            {
+                Interop.TransitionSet.TransitionSetFinishedSignalConnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        public void Connect(System.IntPtr callback)
+        {
+            Interop.TransitionSet.TransitionSetFinishedSignalConnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, callback));
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        public void Disconnect(System.Delegate func)
+        {
+            System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate<System.Delegate>(func);
+            {
+                Interop.TransitionSet.TransitionSetFinishedSignalDisconnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, ip));
+                if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            }
+        }
+
+        public void Disconnect(System.IntPtr callback)
+        {
+            Interop.TransitionSet.TransitionSetFinishedSignalDisconnect(SwigCPtr, new System.Runtime.InteropServices.HandleRef(this, callback));
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+    }
+}
index a30aff0..1d2cdd3 100755 (executable)
@@ -22,8 +22,10 @@ using Tizen.NUI.BaseComponents;
 namespace Tizen.NUI
 {
     /// <summary>
-    /// Setting screen transition options.
-    /// This is used to describe the transition of NUIApplication.
+    /// This TransitionOptions class is a class to control Transition motion.
+    /// This class includes multiple options for the Transition.
+    /// NUI supports a kind of Transitions such as App transition, Page transition, and so on.
+    /// Some of options could be used only for the App transition or Page transition, but others could be used for multiple purpose.
     /// </summary>
     /// <seealso cref="NUIApplication.TransitionOptions" />
     [EditorBrowsable(EditorBrowsableState.Never)]
@@ -32,11 +34,9 @@ namespace Tizen.NUI
         private bool disposed = false;
         private FrameProvider frameProvider;
         private DefaultFrameBroker frameBroker;
-
         private bool enableTransition = false;
         private Window mainWindow;
         private View animatedTarget;
-        private string sharedId;
 
         /// <summary>
         /// Initializes the TransitionOptions class.
@@ -49,6 +49,14 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Initializes the TransitionOptions class.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TransitionOptions()
+        {
+        }
+
+        /// <summary>
         /// Set animated view of seamless animation.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
@@ -97,20 +105,19 @@ namespace Tizen.NUI
         }
 
         /// <summary>
-        /// Gets or sets the Shared object Id
+        /// During the Page transition, if two Views each of on the old top Page
+        /// and new top Page have same TransitionTag, the View on the old top Page
+        /// will be transition to the one of new top Page.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public String SharedId
-        {
-            set
-            {
-                sharedId = value;
-            }
-            get
-            {
-                return sharedId;
-            }
-        }
+        public string TransitionTag { set; get; } = null;
+
+        /// <summary>
+        /// A View could be transition with its child Views or without them.
+        /// Default value is false
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool TransitionWithChild { set; get; } = false;
 
         /// <summary>
         /// Gets or sets the forward animation of launching
index 12f4ffb..5885b5d 100755 (executable)
@@ -46,6 +46,7 @@ namespace Tizen.NUI.BaseComponents
         private bool excludeLayouting = false;
         private LayoutTransition layoutTransition;
         private ControlState controlStates = ControlState.Normal;
+        private TransitionOptions transitionOptions = null;
 
         static View() { }
 
@@ -2776,5 +2777,23 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
+        /// <summary>
+        /// Set or Get TransitionOptions for the page transition.
+        /// </summary>
+        /// <remarks>
+        /// Hidden-API (Inhouse-API).
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TransitionOptions TransitionOptions
+        {
+            set
+            {
+                transitionOptions = value;
+            }
+            get
+            {
+                return transitionOptions;
+            }
+        }
     }
 }
similarity index 88%
rename from src/Tizen.NUI/src/internal/Common/TimePeriod.cs
rename to src/Tizen.NUI/src/public/Common/TimePeriod.cs
index 8204ce1..336ce2b 100755 (executable)
  *
  */
 
+using global::System;
+using global::System.ComponentModel;
+
 namespace Tizen.NUI
 {
-    internal class TimePeriod : Disposable
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class TimePeriod : Disposable
     {
         internal TimePeriod(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
@@ -33,16 +37,19 @@ namespace Tizen.NUI
             Interop.TimePeriod.DeleteTimePeriod(swigCPtr);
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public TimePeriod(float durationSeconds) : this(Interop.TimePeriod.NewTimePeriod(durationSeconds), true)
         {
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public TimePeriod(float delaySeconds, float durationSeconds) : this(Interop.TimePeriod.NewTimePeriod(delaySeconds, durationSeconds), true)
         {
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public float DelaySeconds
         {
             set
@@ -58,6 +65,7 @@ namespace Tizen.NUI
             }
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public float DurationSeconds
         {
             set
diff --git a/src/Tizen.NUI/src/public/Transition/Transition.cs b/src/Tizen.NUI/src/public/Transition/Transition.cs
new file mode 100644 (file)
index 0000000..eca93cd
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using System;
+    using System.ComponentModel;
+    using Tizen.NUI.BaseComponents;
+
+    /// <summary>
+    /// Transition class is a cluster of properties for the transition of View Pair.
+    /// Transition class will be used as a property of Navigator.Transition.
+    /// During page Transition each of View pair those have same TransitionTag will be move with same Navigator.Transition property.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class Transition : TransitionBase
+    {
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Transition()
+        {
+        }
+
+        internal TransitionItem CreateTransition(View source, View destination)
+        {
+            TransitionItem transition= new TransitionItem(source, destination, TimePeriod, AlphaFunction);
+            return transition;
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/public/Transition/TransitionBase.cs b/src/Tizen.NUI/src/public/Transition/TransitionBase.cs
new file mode 100644 (file)
index 0000000..04aaf60
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    using System;
+    using System.ComponentModel;
+    using Tizen.NUI.BaseComponents;
+
+    /// <summary>
+    /// TransitionBase class is a base class for each Transitions.
+    /// Each Transition child classes inherits this base class.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class TransitionBase : Disposable
+    {
+        private static readonly float DefaultDuration = 0.5f;
+        protected internal AlphaFunction alphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Default);
+        protected internal TimePeriod timePeriod = new TimePeriod(DefaultDuration);
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TransitionBase()
+        {
+        }
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public AlphaFunction AlphaFunction
+        {
+            set
+            {
+                alphaFunction = value;
+            }
+            get
+            {
+                return alphaFunction;
+            }
+        }
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TimePeriod TimePeriod
+        {
+            set
+            {
+                timePeriod = value;
+            }
+            get
+            {
+                return timePeriod;
+            }
+        }
+
+        internal TransitionItemBase CreateTransition(View target, bool isEntering)
+        {
+            return new TransitionItemBase(target, isEntering, timePeriod, alphaFunction);
+        }
+
+        protected override void Dispose(DisposeTypes type)
+        {
+            alphaFunction.Dispose();
+            timePeriod.Dispose();
+            base.Dispose(type);
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PageTransitionSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PageTransitionSample.cs
new file mode 100755 (executable)
index 0000000..726abfe
--- /dev/null
@@ -0,0 +1,309 @@
+using System;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+
+namespace Tizen.NUI.Samples
+{
+    public class PageTransitionSample : IExample
+    {
+        private readonly string[,] Keywords = new string[3, 2]
+        {
+            {"red", "redGrey"},
+            {"green", "greenGrey"},
+            {"blue", "blueGrey"}
+        };
+        private readonly string totalGreyTag = "totalGrey";
+
+        private Navigator navigator;
+        private Page mainPage;
+        private Page redPage, greenPage, bluePage, totalPage;
+
+        private readonly Vector4 ColorGrey = new Vector4(0.82f, 0.80f, 0.78f, 1.0f);
+        private readonly Vector4 ColorBackground = new Vector4(0.99f, 0.94f, 0.83f, 1.0f);
+
+        private readonly Vector4[] TileColor = { new Color("#F5625D"), new Color("#7DFF83"), new Color("#7E72DF") };
+
+        private readonly Vector2 baseSize = new Vector2(480.0f, 800.0f);
+        private Vector2 contentSize;
+
+        private float magnification;
+
+        private float convertSize(float size)
+        {
+            return size * magnification;
+        }
+
+
+        public void Activate()
+        {
+            Window window = NUIApplication.GetDefaultWindow();
+            Vector2 windowSize = new Vector2((float)(window.Size.Width), (float)(window.Size.Height));
+            magnification = Math.Min(windowSize.X / baseSize.X, windowSize.Y / baseSize.Y);
+            contentSize = baseSize * magnification;
+
+            navigator = new Navigator()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+                Transition = new Transition()
+                {
+                    TimePeriod = new TimePeriod(0.4f),
+                    AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseInOutSine),
+                },
+            };
+            window.Add(navigator);
+
+            View mainRoot = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent
+            };
+
+            View layoutView = new View()
+            {
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.BottomCenter,
+                ParentOrigin = ParentOrigin.BottomCenter,
+                Layout = new LinearLayout()
+                {
+                    LinearAlignment = LinearLayout.Alignment.Center,
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                    CellPadding = new Size(convertSize(60), convertSize(60)),
+                },
+                Position = new Position(0, -convertSize(30))
+            };
+            mainRoot.Add(layoutView);
+
+            View redButton = CreateButton(TileColor[0], Keywords[0, 0], Keywords[0, 1], redPage);
+            View greenButton = CreateButton(TileColor[1], Keywords[1, 0], Keywords[1, 1], greenPage);
+            View blueButton = CreateButton(TileColor[2], Keywords[2, 0], Keywords[2, 1], bluePage);
+
+            layoutView.Add(redButton);
+            layoutView.Add(greenButton);
+            layoutView.Add(blueButton);
+
+            mainPage = new Page(mainRoot);
+            navigator.Push(mainPage);
+
+            View totalGreyView = new View()
+            {
+                Size = new Size(convertSize(50), convertSize(50)),
+                CornerRadius = convertSize(25),
+                BackgroundColor = ColorGrey,
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = totalGreyTag,
+                }
+            };
+
+            totalGreyView.TouchEvent += (object sender, View.TouchEventArgs e) =>
+            {
+                if (e.Touch.GetState(0) == PointStateType.Down)
+                {
+                    navigator.PushWithTransition(totalPage);
+                }
+                return true;
+            };
+            layoutView.Add(totalGreyView);
+
+
+            // ------------------------------------------------------
+
+
+            View totalPageRoot = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                SizeHeight = contentSize.Height,
+            };
+
+            View totalLayoutView = new View()
+            {
+                Layout = new GridLayout()
+                {
+                    Rows = 2,
+                    GridOrientation = GridLayout.Orientation.Vertical,
+                },
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.Center,
+                ParentOrigin = ParentOrigin.Center,
+            };
+            totalPageRoot.Add(totalLayoutView);
+
+            for (int i = 0; i < 3; ++i)
+            {
+                View sizeView = new View()
+                {
+                    Size = new Size(contentSize.Width / 2.0f, contentSize.Height / 2.0f),
+                };
+                View smallView = CreatePageScene(TileColor[i], Keywords[i, 0], Keywords[i, 1]);
+                smallView.Scale = new Vector3(0.45f, 0.45f, 1.0f);
+                smallView.PositionUsesPivotPoint = true;
+                smallView.PivotPoint = PivotPoint.Center;
+                smallView.ParentOrigin = ParentOrigin.Center;
+                sizeView.Add(smallView);
+                totalLayoutView.Add(sizeView);
+            }
+
+            View sizeGreyView = new View()
+            {
+                Size = new Size(contentSize.Width / 2.0f, contentSize.Height / 2.0f),
+            };
+
+            View totalGreyReturnView = new View()
+            {
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.Center,
+                ParentOrigin = ParentOrigin.Center,
+                Size = new Size(convertSize(70), convertSize(70)),
+                CornerRadius = convertSize(20),
+                BackgroundColor = ColorGrey,
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = totalGreyTag,
+                }
+            };
+            sizeGreyView.Add(totalGreyReturnView);
+            totalLayoutView.Add(sizeGreyView);
+
+            totalGreyReturnView.TouchEvent += (object sender, View.TouchEventArgs e) =>
+            {
+                if (e.Touch.GetState(0) == PointStateType.Down)
+                {
+                    navigator.PopWithTransition();
+                }
+                return true;
+            };
+
+            totalPage = new Page(totalPageRoot);
+        }
+
+        private View CreateButton(Color color, string colorTag, string greyTag, Page secondPage)
+        {
+            View colorView = new View()
+            {
+                Size = new Size(convertSize(50), convertSize(50)),
+                CornerRadius = 0.45f,
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                BackgroundColor = color,
+                Orientation = new Rotation(new Radian((float)Math.PI / 2.0f), Vector3.ZAxis),
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = colorTag,
+                },
+            };
+
+            View greyView = new View()
+            {
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.Center,
+                ParentOrigin = ParentOrigin.Center,
+                Size = new Size(convertSize(40), convertSize(40)),
+                CornerRadius = 0.45f,
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                BackgroundColor = ColorGrey,
+                Orientation = new Rotation(new Radian(-(float)Math.PI / 2.0f), Vector3.ZAxis),
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = greyTag,
+                }
+            };
+
+            secondPage = CreatePage(color, colorTag, greyTag);
+
+            greyView.TouchEvent += (object sender, View.TouchEventArgs e) =>
+            {
+                if (e.Touch.GetState(0) == PointStateType.Down)
+                {
+                    navigator.PushWithTransition(secondPage);
+                }
+                return true;
+            };
+            colorView.Add(greyView);
+            return colorView;
+        }
+
+        private View CreatePageScene(Color color, string colorTag, string greyTag)
+        {
+            View pageBackground = new View()
+            {
+                SizeWidth = contentSize.Width,
+                SizeHeight = contentSize.Height,
+            };
+
+            View colorView = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+                CornerRadius = 0.05f,
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                BackgroundColor = color,
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = colorTag
+                }
+            };
+
+            View greyView = new View()
+            {
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.TopCenter,
+                ParentOrigin = ParentOrigin.TopCenter,
+                Position = new Position(0, convertSize(80)),
+                SizeWidth = contentSize.Width * 0.7f,
+                SizeHeight = contentSize.Height * 0.06f,
+                CornerRadius = 0.1f,
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                BackgroundColor = ColorGrey,
+                TransitionOptions = new TransitionOptions()
+                {
+                    TransitionTag = greyTag
+                }
+            };
+
+            View whiteView = new View()
+            {
+                PositionUsesPivotPoint = true,
+                PivotPoint = PivotPoint.BottomCenter,
+                ParentOrigin = ParentOrigin.BottomCenter,
+                Position = new Position(0, -convertSize(60)),
+                SizeWidth = contentSize.Width * 0.75f,
+                SizeHeight = contentSize.Height * 0.7f,
+                CornerRadius = 0.1f,
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                BackgroundColor = Color.AntiqueWhite,
+            };
+            pageBackground.Add(colorView);
+            pageBackground.Add(whiteView);
+            pageBackground.Add(greyView);
+
+            return pageBackground;
+        }
+
+        private Page CreatePage(Color color, string colorTag, string greyTag)
+        {
+            View pageRoot = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent
+            };
+
+            View pageBackground = CreatePageScene(color, colorTag, greyTag);
+            pageBackground.TouchEvent += (object sender, View.TouchEventArgs e) =>
+            {
+                if (e.Touch.GetState(0) == PointStateType.Down)
+                {
+                    navigator.PopWithTransition();
+                }
+                return true;
+            };
+            pageRoot.Add(pageBackground);
+
+            Page page = new Page(pageRoot);
+            return page;
+        }
+
+        public void Deactivate()
+        {
+        }
+    }
+}