[go: nahoru, domu]

Expose animation label attribute through ComposeAnimation

The animation label will be used to represent the animation as text in
Android Studio when applicable. The first direct example is naming the tabs
representing the animations in the animation inspector.

For transition animations (the only supported type so far), we first try to
use the label set explicitly in TransitionAnimation, but we also fall back
to the class name of the transition states as an alternative.

Test: PreviewAnimationClockTest#animationLabelIsSetExplicitlyOrImplicitly
Bug: 161709804
Relnote: N/A
Change-Id: I17fb74bd189bc1e2cb54dda52879d726050fd013
diff --git a/ui/ui-animation-tooling-internal/api/0.1.0-dev16.txt b/ui/ui-animation-tooling-internal/api/0.1.0-dev16.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/0.1.0-dev16.txt
+++ b/ui/ui-animation-tooling-internal/api/0.1.0-dev16.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/api/current.txt b/ui/ui-animation-tooling-internal/api/current.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/current.txt
+++ b/ui/ui-animation-tooling-internal/api/current.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/api/public_plus_experimental_0.1.0-dev16.txt b/ui/ui-animation-tooling-internal/api/public_plus_experimental_0.1.0-dev16.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/public_plus_experimental_0.1.0-dev16.txt
+++ b/ui/ui-animation-tooling-internal/api/public_plus_experimental_0.1.0-dev16.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/api/public_plus_experimental_current.txt b/ui/ui-animation-tooling-internal/api/public_plus_experimental_current.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-tooling-internal/api/public_plus_experimental_current.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/api/restricted_0.1.0-dev16.txt b/ui/ui-animation-tooling-internal/api/restricted_0.1.0-dev16.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/restricted_0.1.0-dev16.txt
+++ b/ui/ui-animation-tooling-internal/api/restricted_0.1.0-dev16.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/api/restricted_current.txt b/ui/ui-animation-tooling-internal/api/restricted_current.txt
index d718a78..a3e6340 100644
--- a/ui/ui-animation-tooling-internal/api/restricted_current.txt
+++ b/ui/ui-animation-tooling-internal/api/restricted_current.txt
@@ -3,6 +3,7 @@
 
   public interface ComposeAnimation {
     method public Object getAnimation();
+    method public String? getLabel();
     method public default java.util.Set<java.lang.Object> getStates();
     method public androidx.compose.animation.tooling.ComposeAnimationType getType();
   }
diff --git a/ui/ui-animation-tooling-internal/src/main/java/androidx/compose/animation/tooling/ComposeAnimation.kt b/ui/ui-animation-tooling-internal/src/main/java/androidx/compose/animation/tooling/ComposeAnimation.kt
index c725ac3..6854f93 100644
--- a/ui/ui-animation-tooling-internal/src/main/java/androidx/compose/animation/tooling/ComposeAnimation.kt
+++ b/ui/ui-animation-tooling-internal/src/main/java/androidx/compose/animation/tooling/ComposeAnimation.kt
@@ -51,4 +51,10 @@
     fun getStates(): Set<Any> {
         throw UnsupportedOperationException("Only available when getType() is TRANSITION_ANIMATION")
     }
+
+    /**
+     * Returns the animation label, which can be used to represent it as text in Android Studio.
+     * Null if the label is not set or if it can't be inferred from the animation states.
+     */
+    fun getLabel(): String?
 }
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
index 39a50d0..0790967 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
@@ -198,6 +198,20 @@
         assertEquals(1000, testClock.getMaxDuration())
     }
 
+    @Test
+    fun animationLabelIsSetExplicitlyOrImplicitly() {
+        TransitionAnimation(rotationColorDef, testClock, label = "MyRot").toState(RotationColor.RC2)
+        val rotationAnimation = testClock.observersToAnimations.values.single {
+            it.getStates().contains(RotationColor.RC1)
+        }
+        // Label explicitly set
+        assertEquals("MyRot", rotationAnimation.getLabel())
+
+        val offsetAnimation = setUpOffsetScenario()
+        // Label is not explicitly set, but inferred from the state type
+        assertEquals("Offset", offsetAnimation.getLabel())
+    }
+
     // Sets up a transition animation scenario, going from RotationColor.RC1 to RotationColor.RC3.
     private fun setUpRotationColorScenario(): ComposeAnimation {
         TransitionAnimation(rotationColorDef, testClock).toState(RotationColor.RC2)
diff --git a/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/animation/ComposeAnimationParser.kt b/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/animation/ComposeAnimationParser.kt
index e106d82..ed6ea0c 100644
--- a/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/animation/ComposeAnimationParser.kt
+++ b/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/animation/ComposeAnimationParser.kt
@@ -32,11 +32,15 @@
 internal fun TransitionAnimation<*>.TransitionAnimationClockObserver.parse(): ComposeAnimation {
     Log.d("ComposeAnimationParser", "TransitionAnimation subscribed")
     animation.monotonic = false
+    val states = animation.getStates().filterNotNull().toSet()
     return object : ComposeAnimation {
         override fun getType() = ComposeAnimationType.TRANSITION_ANIMATION
 
         override fun getAnimation() = animation
 
-        override fun getStates() = animation.getStates().filterNotNull().toSet()
+        override fun getStates() = states
+
+        override fun getLabel() =
+            animation.label ?: states.firstOrNull()?.let { it::class.simpleName }
     }
 }
\ No newline at end of file