1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.ui.tooling.animation
18 
19 import androidx.compose.animation.core.Animatable
20 import androidx.compose.animation.core.AnimationSpec
21 import androidx.compose.animation.core.AnimationVector
22 import androidx.compose.animation.tooling.ComposeAnimation
23 import androidx.compose.animation.tooling.ComposeAnimationType
24 import org.jetbrains.annotations.TestOnly
25 
26 /** [ComposeAnimation] of type [ComposeAnimationType.ANIMATE_X_AS_STATE]. */
27 internal class AnimateXAsStateComposeAnimation<T, V : AnimationVector>
28 private constructor(
29     val toolingState: ToolingState<T>,
30     val animationSpec: AnimationSpec<T>,
31     override val animationObject: Animatable<T, V>,
32 ) : ComposeAnimation {
33     override val type = ComposeAnimationType.ANIMATE_X_AS_STATE
34 
35     override val states: Set<Any> =
<lambda>null36         (animationObject.value as Any).let { it.javaClass.enumConstants?.toSet() ?: setOf(it) }
37 
38     override val label: String = animationObject.label
39 
40     @Suppress("UNCHECKED_CAST")
setStatenull41     fun setState(value: Any) {
42         toolingState.value = value as T
43     }
44 
45     companion object {
46 
47         /**
48          * [ComposeAnimationType] from ANIMATABLE to UNSUPPORTED are not available in previous
49          * versions of the library. To avoid creating non-existing enum,
50          * [AnimateXAsStateComposeAnimation] should only be instantiated if [ComposeAnimationType]
51          * API for ANIMATE_X_AS_STATE enum is available.
52          */
53         var apiAvailable =
<lambda>null54             enumValues<ComposeAnimationType>().any { it.name == "ANIMATE_X_AS_STATE" }
55             private set
56 
57         internal fun <T, V : AnimationVector> AnimationSearch.AnimateXAsStateSearchInfo<T, V>
parsenull58             .parse(): AnimateXAsStateComposeAnimation<*, *>? {
59             if (!apiAvailable) return null
60             // Tooling can't control nullable Animatable with value set to null.
61             if (animatable.value == null) return null
62             return AnimateXAsStateComposeAnimation(toolingState, animationSpec, animatable)
63         }
64 
65         /** This method is for testing only. */
66         @TestOnly
testOverrideAvailabilitynull67         fun testOverrideAvailability(override: Boolean) {
68             apiAvailable = override
69         }
70     }
71 }
72