1 /*
2  * Copyright (C) 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.constraintlayout.compose
18 
19 import android.annotation.SuppressLint
20 import android.util.Log
21 import androidx.compose.runtime.Immutable
22 import androidx.constraintlayout.core.parser.CLObject
23 import androidx.constraintlayout.core.parser.CLParser
24 import androidx.constraintlayout.core.parser.CLParsingException
25 import androidx.constraintlayout.core.state.TransitionParser
26 import org.intellij.lang.annotations.Language
27 
28 /** Defines interpolation parameters between two [ConstraintSet]s. */
29 @ExperimentalMotionApi
30 @Immutable
31 interface Transition {
getStartConstraintSetIdnull32     fun getStartConstraintSetId(): String
33 
34     fun getEndConstraintSetId(): String
35 }
36 
37 /**
38  * Parses the given JSON5 into a [Transition].
39  *
40  * See the official
41  * [GitHub Wiki](https://github.com/androidx/constraintlayout/wiki/Compose-MotionLayout-JSON-Syntax#transitions)
42  * to learn the syntax.
43  */
44 @SuppressLint("ComposableNaming")
45 @ExperimentalMotionApi
46 fun Transition(@Language("json5") content: String): Transition {
47     val parsed =
48         try {
49             CLParser.parse(content)
50         } catch (e: CLParsingException) {
51             Log.e("CML", "Error parsing JSON $e")
52             null
53         }
54     return parsed?.let { TransitionImpl(parsed) } ?: TransitionImpl.EMPTY
55 }
56 
57 /**
58  * Subclass of [Transition] for internal use.
59  *
60  * Used to reduced the exposed API from [Transition].
61  */
62 @ExperimentalMotionApi
63 internal class TransitionImpl(private val parsedTransition: CLObject) : Transition {
64 
65     /** Applies all Transition properties to [transition]. */
applyAllTonull66     fun applyAllTo(transition: androidx.constraintlayout.core.state.Transition) {
67         try {
68             TransitionParser.parse(parsedTransition, transition)
69         } catch (e: CLParsingException) {
70             Log.e("CML", "Error parsing JSON $e")
71         }
72     }
73 
74     /**
75      * Applies only the KeyFrame related properties (KeyCycles, KeyAttributes, KeyPositions) to
76      * [transition], which effectively sets the respective parameters for each WidgetState.
77      */
applyKeyFramesTonull78     fun applyKeyFramesTo(transition: androidx.constraintlayout.core.state.Transition) {
79         try {
80             TransitionParser.parseKeyFrames(parsedTransition, transition)
81         } catch (e: CLParsingException) {
82             Log.e("CML", "Error parsing JSON $e")
83         }
84     }
85 
getStartConstraintSetIdnull86     override fun getStartConstraintSetId(): String {
87         return parsedTransition.getStringOrNull("from") ?: "start"
88     }
89 
getEndConstraintSetIdnull90     override fun getEndConstraintSetId(): String {
91         return parsedTransition.getStringOrNull("to") ?: "end"
92     }
93 
equalsnull94     override fun equals(other: Any?): Boolean {
95         if (this === other) return true
96         if (javaClass != other?.javaClass) return false
97 
98         other as TransitionImpl
99 
100         if (parsedTransition != other.parsedTransition) return false
101 
102         return true
103     }
104 
hashCodenull105     override fun hashCode(): Int {
106         return parsedTransition.hashCode()
107     }
108 
109     internal companion object {
110         internal val EMPTY = TransitionImpl(CLObject(charArrayOf()))
111     }
112 }
113