[NUI] Fix Navigator to enable multiple Pop()
authorJaehyun Cho <jae_hyun.cho@samsung.com>
Mon, 5 Dec 2022 08:16:09 +0000 (17:16 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 6 Dec 2022 08:08:09 +0000 (17:08 +0900)
A popped page is removed in the Pop() animation's Finished callback.

Previously, Navigator could not support multiple Pop().
Because Pop() simply stopped the previous Pop() animation without
calling the animation's Finished callback.

Now, Pop() stops the previous Pop() animation with calling the
animation's Finished callback by emitting FinishedSignal().
Consequently, Navigator can support multiple Pop() now.

src/Tizen.NUI.Components/Controls/Navigation/Navigator.cs

index 99b225d..d012093 100755 (executable)
@@ -393,6 +393,9 @@ namespace Tizen.NUI.Components
             //Duplicate page is not pushed.
             if (navigationPages.Contains(page)) return;
 
+            //TODO: The following transition codes will be replaced with view transition.
+            InitializeAnimation();
+
             var curTop = Peek();
 
             if (!curTop)
@@ -411,9 +414,6 @@ namespace Tizen.NUI.Components
 
             curTop.SaveKeyFocus();
 
-            //TODO: The following transition codes will be replaced with view transition.
-            InitializeAnimation();
-
             if (page is DialogPage == false)
             {
                 curAnimation = new Animation(DefaultTransitionDuration);
@@ -475,6 +475,9 @@ namespace Tizen.NUI.Components
                 throw new InvalidOperationException("There is no page in Navigator.");
             }
 
+            //TODO: The following transition codes will be replaced with view transition.
+            InitializeAnimation();
+
             var curTop = Peek();
 
             if (navigationPages.Count == 1)
@@ -494,9 +497,6 @@ namespace Tizen.NUI.Components
             curTop.InvokeDisappearing();
             curTop.SaveKeyFocus();
 
-            //TODO: The following transition codes will be replaced with view transition.
-            InitializeAnimation();
-
             if (curTop is DialogPage == false)
             {
                 curAnimation = new Animation(DefaultTransitionDuration);
@@ -1071,17 +1071,50 @@ namespace Tizen.NUI.Components
         //TODO: The following transition codes will be replaced with view transition.
         private void InitializeAnimation()
         {
+            bool isCurAnimPlaying = false;
+            bool isNewAnimPlaying = false;
+
             if (curAnimation != null)
             {
-                curAnimation.Stop();
+                if (curAnimation.State == Animation.States.Playing)
+                {
+                    isCurAnimPlaying = true;
+                    curAnimation.Stop();
+                }
+            }
+
+            if (newAnimation != null)
+            {
+                if (newAnimation.State == Animation.States.Playing)
+                {
+                    isNewAnimPlaying = true;
+                    newAnimation.Stop();
+                }
+            }
+
+            if (isCurAnimPlaying)
+            {
+                // To enable multiple Pop(), animation's Finished callback is required.
+                // To call animation's Finished callback, FinishedSignal is emitted.
+                curAnimation.FinishedSignal().Emit(curAnimation);
                 curAnimation.Clear();
+
+                // InitializeAnimation() can be called by FinishedSignal().Emit().
+                // Not to cause null pointer dereference by calling InitializeAnimation() in InitializeAnimation(),
+                // animation handle is assigned to be null only if the animation is playing.
                 curAnimation = null;
             }
 
-            if (newAnimation != null)
+            if (isNewAnimPlaying)
             {
-                newAnimation.Stop();
+                // To enable multiple Pop(), animation's Finished callback is required.
+                // To call animation's Finished callback, FinishedSignal is emitted.
+                newAnimation.FinishedSignal().Emit(newAnimation);
                 newAnimation.Clear();
+
+                // InitializeAnimation() can be called by FinishedSignal().Emit().
+                // Not to cause null pointer dereference by calling InitializeAnimation() in InitializeAnimation(),
+                // animation handle is assigned to be null only if the animation is playing.
                 newAnimation = null;
             }
         }