Moving animation configuration and definition out of state definition

This removes cross dependency between StateManager and State object so
that it can be easily generalized

Change-Id: I62851fc4b653655cb40f37023db9651055ec7c9c
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1d9c0c3..873b066 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -92,6 +92,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.LauncherStateManager.AtomicAnimationFactory;
 import com.android.launcher3.LauncherStateManager.StateHandler;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.allapps.AllAppsContainerView;
@@ -2724,6 +2725,13 @@
         return new StateHandler[] { getAllAppsController(), getWorkspace() };
     }
 
+    /**
+     * Creates a factory for atomic state animations
+     */
+    public AtomicAnimationFactory createAtomicAnimationFactory() {
+        return new AtomicAnimationFactory(0);
+    }
+
     public TouchController[] createTouchControllers() {
         return new TouchController[] {getDragController(), new AllAppsSwipeController(this)};
     }
diff --git a/src/com/android/launcher3/LauncherAppTransitionManager.java b/src/com/android/launcher3/LauncherAppTransitionManager.java
index 9148c2f..24e0d14 100644
--- a/src/com/android/launcher3/LauncherAppTransitionManager.java
+++ b/src/com/android/launcher3/LauncherAppTransitionManager.java
@@ -13,11 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.android.launcher3;
 
-
-import android.animation.Animator;
 import android.app.ActivityOptions;
 import android.content.Context;
 import android.graphics.Rect;
@@ -58,17 +55,6 @@
     }
 
     /**
-     * Number of animations which run on state properties.
-     */
-    public int getStateElementAnimationsCount() {
-        return 0;
-    }
-
-    public Animator createStateElementAnimation(int index, float... values) {
-        throw new RuntimeException("Unknown gesture animation " + index);
-    }
-
-    /**
      * Registers remote animations for certain system transitions.
      */
     public void registerRemoteAnimations() {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 686a241..e133d31 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -15,19 +15,7 @@
  */
 package com.android.launcher3;
 
-import static android.view.View.VISIBLE;
-
-import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
 import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
 import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
 import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
@@ -39,20 +27,16 @@
 import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
 
 import android.content.Context;
-import android.view.View;
 import android.view.animation.Interpolator;
 
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.states.HintState;
 import com.android.launcher3.states.SpringLoadedState;
-import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.uioverrides.states.AllAppsState;
 import com.android.launcher3.uioverrides.states.OverviewState;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 
 import java.util.Arrays;
 
-
 /**
  * Base state for various states used for the Launcher
  */
@@ -293,55 +277,6 @@
         }
     }
 
-    /**
-     * Prepares for a non-user controlled animation from fromState to this state. Preparations
-     * include:
-     * - Setting interpolators for various animations included in the state transition.
-     * - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
-     */
-    public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
-            StateAnimationConfig config) {
-        if (this == NORMAL && fromState == OVERVIEW) {
-            config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
-            config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
-            config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
-            config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
-            config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
-            Workspace workspace = launcher.getWorkspace();
-
-            // Start from a higher workspace scale, but only if we're invisible so we don't jump.
-            boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
-            if (isWorkspaceVisible) {
-                CellLayout currentChild = (CellLayout) workspace.getChildAt(
-                        workspace.getCurrentPage());
-                isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
-                        && currentChild.getShortcutsAndWidgets().getAlpha() > 0;
-            }
-            if (!isWorkspaceVisible) {
-                workspace.setScaleX(0.92f);
-                workspace.setScaleY(0.92f);
-            }
-            Hotseat hotseat = launcher.getHotseat();
-            boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
-            if (!isHotseatVisible) {
-                hotseat.setScaleX(0.92f);
-                hotseat.setScaleY(0.92f);
-                if (ENABLE_OVERVIEW_ACTIONS.get()) {
-                    AllAppsContainerView qsbContainer = launcher.getAppsView();
-                    View qsb = qsbContainer.getSearchView();
-                    boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
-                    if (!qsbVisible) {
-                        qsbContainer.setScaleX(0.92f);
-                        qsbContainer.setScaleY(0.92f);
-                    }
-                }
-            }
-        } else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
-            // Keep fully visible until the very end (when overview is offscreen) to make invisible.
-            config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
-        }
-    }
-
     public static abstract class PageAlphaProvider {
 
         public final Interpolator interpolator;
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index ea41fc4..1aae201 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -86,7 +86,7 @@
     private final ArrayList<StateListener> mListeners = new ArrayList<>();
 
     // Animators which are run on properties also controlled by state animations.
-    private Animator[] mStateElementAnimators;
+    private final AtomicAnimationFactory mAtomicAnimationFactory;
 
     private StateHandler[] mStateHandlers;
     private LauncherState mState = NORMAL;
@@ -99,6 +99,8 @@
     public LauncherStateManager(Launcher l) {
         mUiHandler = new Handler(Looper.getMainLooper());
         mLauncher = l;
+
+        mAtomicAnimationFactory = l.createAtomicAnimationFactory();
     }
 
     public LauncherState getState() {
@@ -195,7 +197,7 @@
     public void reapplyState(boolean cancelCurrentAnimation) {
         boolean wasInAnimation = mConfig.currentAnimation != null;
         if (cancelCurrentAnimation) {
-            cancelAllStateElementAnimation();
+            mAtomicAnimationFactory.cancelAllStateElementAnimation();
             cancelAnimation();
         }
         if (mConfig.currentAnimation == null) {
@@ -233,7 +235,7 @@
         mConfig.reset();
 
         if (!animated) {
-            cancelAllStateElementAnimation();
+            mAtomicAnimationFactory.cancelAllStateElementAnimation();
             onStateTransitionStart(state);
             for (StateHandler handler : getStateHandlers()) {
                 handler.setState(state);
@@ -284,7 +286,7 @@
      */
     public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
             StateAnimationConfig config) {
-        toState.prepareForAtomicAnimation(mLauncher, fromState, config);
+        mAtomicAnimationFactory.prepareForAtomicAnimation(fromState, toState, config);
     }
 
     /**
@@ -447,42 +449,23 @@
         mConfig.setAnimation(anim, null);
     }
 
-    private void cancelAllStateElementAnimation() {
-        if (mStateElementAnimators == null) {
-            return;
-        }
-
-        for (Animator animator : mStateElementAnimators) {
-            if (animator != null) {
-                animator.cancel();
-            }
-        }
-    }
-
     /**
      * Cancels a currently running gesture animation
      */
     public void cancelStateElementAnimation(int index) {
-        if (mStateElementAnimators == null) {
-            return;
-        }
-        if (mStateElementAnimators[index] != null) {
-            mStateElementAnimators[index].cancel();
+        if (mAtomicAnimationFactory.mStateElementAnimators[index] != null) {
+            mAtomicAnimationFactory.mStateElementAnimators[index].cancel();
         }
     }
 
     public Animator createStateElementAnimation(int index, float... values) {
         cancelStateElementAnimation(index);
-        LauncherAppTransitionManager latm = mLauncher.getAppTransitionManager();
-        if (mStateElementAnimators == null) {
-            mStateElementAnimators = new Animator[latm.getStateElementAnimationsCount()];
-        }
-        Animator anim = latm.createStateElementAnimation(index, values);
-        mStateElementAnimators[index] = anim;
+        Animator anim = mAtomicAnimationFactory.createStateElementAnimation(index, values);
+        mAtomicAnimationFactory.mStateElementAnimators[index] = anim;
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                mStateElementAnimators[index] = null;
+                mAtomicAnimationFactory.mStateElementAnimators[index] = null;
             }
         });
         return anim;
@@ -590,4 +573,46 @@
 
         default void onStateTransitionComplete(LauncherState finalState) { }
     }
+
+    /**
+     * Factory class to configure and create atomic animations.
+     */
+    public static class AtomicAnimationFactory {
+
+        private final Animator[] mStateElementAnimators;
+
+        /**
+         *
+         * @param sharedElementAnimCount number of animations which run on state properties
+         */
+        public AtomicAnimationFactory(int sharedElementAnimCount) {
+            mStateElementAnimators = new Animator[sharedElementAnimCount];
+        }
+
+        void cancelAllStateElementAnimation() {
+            for (Animator animator : mStateElementAnimators) {
+                if (animator != null) {
+                    animator.cancel();
+                }
+            }
+        }
+
+        /**
+         * Creates animations for elements which can be also be part of state transitions. The
+         * actual definition of the animation is up to the app to define.
+         *
+         */
+        public Animator createStateElementAnimation(int index, float... values) {
+            throw new RuntimeException("Unknown gesture animation " + index);
+        }
+
+        /**
+         * Prepares for a non-user controlled animation from fromState to this state. Preparations
+         * include:
+         * - Setting interpolators for various animations included in the state transition.
+         * - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
+         */
+        public void prepareForAtomicAnimation(
+                LauncherState fromState, LauncherState toState, StateAnimationConfig config) { }
+    }
 }