From 616a0e8bad6a33a40ab0e8113e30df339f78da8d Mon Sep 17 00:00:00 2001 From: Seungho Baek Date: Wed, 3 Mar 2021 00:33:22 +0900 Subject: [PATCH] [NUI] View Transition with page switching Signed-off-by: Seungho Baek --- .../Controls/Navigation/Navigator.cs | 265 +++++++++++++++++- .../src/internal/Interop/Interop.TransitionItem.cs | 46 +++ .../internal/Interop/Interop.TransitionItemBase.cs | 67 +++++ .../src/internal/Interop/Interop.TransitionSet.cs | 69 +++++ .../src/internal/Transition/TransitionItem.cs | 98 +++++++ .../src/internal/Transition/TransitionItemBase.cs | 187 +++++++++++++ .../src/internal/Transition/TransitionSet.cs | 211 ++++++++++++++ .../src/internal/Transition/TransitionSetSignal.cs | 70 +++++ .../src/public/Animation/TransitionOptions.cs | 39 +-- src/Tizen.NUI/src/public/BaseComponents/View.cs | 19 ++ .../src/{internal => public}/Common/TimePeriod.cs | 10 +- src/Tizen.NUI/src/public/Transition/Transition.cs | 43 +++ .../src/public/Transition/TransitionBase.cs | 78 ++++++ .../Samples/PageTransitionSample.cs | 309 +++++++++++++++++++++ 14 files changed, 1492 insertions(+), 19 deletions(-) create mode 100755 src/Tizen.NUI/src/internal/Interop/Interop.TransitionItem.cs create mode 100755 src/Tizen.NUI/src/internal/Interop/Interop.TransitionItemBase.cs create mode 100755 src/Tizen.NUI/src/internal/Interop/Interop.TransitionSet.cs create mode 100755 src/Tizen.NUI/src/internal/Transition/TransitionItem.cs create mode 100755 src/Tizen.NUI/src/internal/Transition/TransitionItemBase.cs create mode 100755 src/Tizen.NUI/src/internal/Transition/TransitionSet.cs create mode 100755 src/Tizen.NUI/src/internal/Transition/TransitionSetSignal.cs rename src/Tizen.NUI/src/{internal => public}/Common/TimePeriod.cs (88%) create mode 100644 src/Tizen.NUI/src/public/Transition/Transition.cs create mode 100644 src/Tizen.NUI/src/public/Transition/TransitionBase.cs create mode 100755 test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PageTransitionSample.cs diff --git a/src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs b/src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs index 3d10f28..4df540a 100755 --- a/src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs +++ b/src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs @@ -24,18 +24,48 @@ using Tizen.NUI.BaseComponents; namespace Tizen.NUI.Components { /// - /// 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. + /// + /// + /// + /// Navigator.Transition = new Transition() + /// { + /// TimePeriod = new TimePeriod(0.5), + /// AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseInOutSine) + /// } + /// + /// Navigator.PushWithTransition(newPage); + /// + /// /// [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 windowNavigator = new Dictionary(); @@ -49,6 +79,12 @@ namespace Tizen.NUI.Components { Layout = new AbsoluteLayout(); } + + /// + /// An event for the page disappearing signal which can be used to subscribe or unsubscribe the event handler provided by the user. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler TransitionFinished; /// /// List of pages of Navigator. @@ -57,6 +93,113 @@ namespace Tizen.NUI.Components public List NavigationPages { get; } = new List(); /// + /// Transition properties for the transition of View pair those have same transition tag. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Transition Transition + { + set + { + transition = value; + } + get + { + return transition; + } + } + + /// + /// Pushes a page to Navigator. + /// If the page is already in Navigator, then it is not pushed. + /// + /// The page to push to Navigator. + /// Thrown when the argument page is null. + [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; + } + + /// + /// Pops the top page from Navigator. + /// + /// The popped page. + /// Thrown when there is no page in Navigator. + [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; + } + + /// /// Pushes a page to Navigator. /// If the page is already in Navigator, then it is not pushed. /// @@ -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); } + /// + /// Create Transition between currentTopPage and newTopPage + /// + /// The top page of Navigator. + /// The new top page after transition. + /// True if this transition is for push new page + private TransitionSet CreateTransition(Page currentTopPage, Page newTopPage, bool pushTransition) + { + currentTopPage.SetVisible(true); + newTopPage.SetVisible(true); + + List taggedViewsInNewTopPage = new List(); + RetrieveTaggedViews(taggedViewsInNewTopPage, newTopPage.Content); + List taggedViewsInCurrentTopPage = new List(); + RetrieveTaggedViews(taggedViewsInCurrentTopPage, currentTopPage.Content); + + List> sameTaggedViewPair = new List>(); + 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(currentTopPageView, newTopPageView)); + findPair = true; + break; + } + } + if(findPair) + { + taggedViewsInNewTopPage.Remove(sameTaggedViewPair[sameTaggedViewPair.Count - 1].Value); + } + } + foreach(KeyValuePair pair in sameTaggedViewPair) + { + taggedViewsInCurrentTopPage.Remove(pair.Key); + } + + TransitionSet newTransitionSet = new TransitionSet(); + foreach(KeyValuePair 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; } + + + /// + /// Retrieve Tagged Views in the view tree. + /// + /// Returned tagged view list.. + /// Root View to get tagged child View. + private void RetrieveTaggedViews(List 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 index 0000000..76ccc1c --- /dev/null +++ b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItem.cs @@ -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 index 0000000..3c80bed --- /dev/null +++ b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionItemBase.cs @@ -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 index 0000000..32b495a --- /dev/null +++ b/src/Tizen.NUI/src/internal/Interop/Interop.TransitionSet.cs @@ -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 index 0000000..76c6b3a --- /dev/null +++ b/src/Tizen.NUI/src/internal/Transition/TransitionItem.cs @@ -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; + + /// + /// 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. + /// + internal class TransitionItem : TransitionItemBase + { + /// + /// Creates an initialized transition.
+ ///
+ /// DurationmSeconds must be greater than zero. + 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) + { + } + + /// + /// Sets the source View will be shown after transition finished. + /// + 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; + } + + /// + /// To make transition instance be disposed. + /// + 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 index 0000000..2819f67 --- /dev/null +++ b/src/Tizen.NUI/src/internal/Transition/TransitionItemBase.cs @@ -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 + { + /// + /// Creates an initialized TransitionItemBase.
+ ///
+ 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) + { + } + + /// + /// Gets or sets the duration in milliseconds of the transition. + /// + 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); + } + } + + /// + /// Gets or sets the delay in milliseconds of the transition. + /// + 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); + } + } + + /// + /// Gets or sets the TimePeriod + /// + public TimePeriod TimePeriod + { + set + { + Interop.TransitionItemBase.SetTimePeriod(SwigCPtr, value.SwigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } + + /// + /// Gets or sets the AlphaFunction + /// + 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; + } + } + + /// + /// Gets or sets whether the View moves with child or not. + /// + public bool TransitionWithChild + { + set + { + Interop.TransitionItemBase.TransitionWithChild(SwigCPtr, value); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } + + /// + /// Downcasts a handle to TransitionItemBase handle.
+ /// If handle points to an TransitionItemBase object, the downcast produces a valid handle.
+ /// If not, the returned handle is left uninitialized.
+ ///
+ /// Handle to an object. + /// Handle to an TransitionItemBase object or an uninitialized handle. + /// Thrown when handle is null. + 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; + } + + /// + /// To make TransitionItemBase instance be disposed. + /// + 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 index 0000000..547b91a --- /dev/null +++ b/src/Tizen.NUI/src/internal/Transition/TransitionSet.cs @@ -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; + + /// + /// 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. + /// + internal class TransitionSet : BaseHandle + { + private TransitionSetFinishedEventCallbackType transitionSetFinishedEventCallback; + private System.IntPtr finishedCallbackOfNative; + + /// + /// Creates an initialized transitionSet.
+ ///
+ /// DurationmSeconds must be greater than zero. + 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(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(); + } + } + + /// + /// Downcasts a handle to transitionSet handle.
+ /// If handle points to an transitionSet object, the downcast produces a valid handle.
+ /// If not, the returned handle is left uninitialized.
+ ///
+ /// Handle to an object. + /// Handle to an transitionSet object or an uninitialized handle. + /// Thrown when handle is null. + 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; + } + + /// + /// Plays the transitionSet. + /// + 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; + } + + /// + /// To make transitionSet instance be disposed. + /// + 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 index 0000000..a3bef6f --- /dev/null +++ b/src/Tizen.NUI/src/internal/Transition/TransitionSetSignal.cs @@ -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(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(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(); + } + } +} diff --git a/src/Tizen.NUI/src/public/Animation/TransitionOptions.cs b/src/Tizen.NUI/src/public/Animation/TransitionOptions.cs index a30aff0..1d2cdd3 100755 --- a/src/Tizen.NUI/src/public/Animation/TransitionOptions.cs +++ b/src/Tizen.NUI/src/public/Animation/TransitionOptions.cs @@ -22,8 +22,10 @@ using Tizen.NUI.BaseComponents; namespace Tizen.NUI { /// - /// 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. /// /// [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; /// /// Initializes the TransitionOptions class. @@ -49,6 +49,14 @@ namespace Tizen.NUI } /// + /// Initializes the TransitionOptions class. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public TransitionOptions() + { + } + + /// /// Set animated view of seamless animation. /// [EditorBrowsable(EditorBrowsableState.Never)] @@ -97,20 +105,19 @@ namespace Tizen.NUI } /// - /// 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. /// [EditorBrowsable(EditorBrowsableState.Never)] - public String SharedId - { - set - { - sharedId = value; - } - get - { - return sharedId; - } - } + public string TransitionTag { set; get; } = null; + + /// + /// A View could be transition with its child Views or without them. + /// Default value is false + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool TransitionWithChild { set; get; } = false; /// /// Gets or sets the forward animation of launching diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index 12f4ffb..5885b5d 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -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 } } + /// + /// Set or Get TransitionOptions for the page transition. + /// + /// + /// Hidden-API (Inhouse-API). + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public TransitionOptions TransitionOptions + { + set + { + transitionOptions = value; + } + get + { + return transitionOptions; + } + } } } diff --git a/src/Tizen.NUI/src/internal/Common/TimePeriod.cs b/src/Tizen.NUI/src/public/Common/TimePeriod.cs 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 --- a/src/Tizen.NUI/src/internal/Common/TimePeriod.cs +++ b/src/Tizen.NUI/src/public/Common/TimePeriod.cs @@ -15,9 +15,13 @@ * */ +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 index 0000000..eca93cd --- /dev/null +++ b/src/Tizen.NUI/src/public/Transition/Transition.cs @@ -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; + + /// + /// 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. + /// + [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 index 0000000..04aaf60 --- /dev/null +++ b/src/Tizen.NUI/src/public/Transition/TransitionBase.cs @@ -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; + + /// + /// TransitionBase class is a base class for each Transitions. + /// Each Transition child classes inherits this base class. + /// + [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 index 0000000..726abfe --- /dev/null +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PageTransitionSample.cs @@ -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() + { + } + } +} -- 2.7.4