1/*
2 * Copyright (C) 2006 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
17package android.view.animation;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.util.AttributeSet;
22
23/**
24 * An animation that controls the rotation of an object. This rotation takes
25 * place in the X-Y plane. You can specify the point to use for the center of
26 * the rotation, where (0,0) is the top left point. If not specified, (0,0) is
27 * the default rotation point.
28 *
29 */
30public class RotateAnimation extends Animation {
31    private float mFromDegrees;
32    private float mToDegrees;
33
34    private int mPivotXType = ABSOLUTE;
35    private int mPivotYType = ABSOLUTE;
36    private float mPivotXValue = 0.0f;
37    private float mPivotYValue = 0.0f;
38
39    private float mPivotX;
40    private float mPivotY;
41
42    /**
43     * Constructor used when a RotateAnimation is loaded from a resource.
44     *
45     * @param context Application context to use
46     * @param attrs Attribute set from which to read values
47     */
48    public RotateAnimation(Context context, AttributeSet attrs) {
49        super(context, attrs);
50
51        TypedArray a = context.obtainStyledAttributes(attrs,
52                com.android.internal.R.styleable.RotateAnimation);
53
54        mFromDegrees = a.getFloat(
55                com.android.internal.R.styleable.RotateAnimation_fromDegrees, 0.0f);
56        mToDegrees = a.getFloat(com.android.internal.R.styleable.RotateAnimation_toDegrees, 0.0f);
57
58        Description d = Description.parseValue(a.peekValue(
59            com.android.internal.R.styleable.RotateAnimation_pivotX));
60        mPivotXType = d.type;
61        mPivotXValue = d.value;
62
63        d = Description.parseValue(a.peekValue(
64            com.android.internal.R.styleable.RotateAnimation_pivotY));
65        mPivotYType = d.type;
66        mPivotYValue = d.value;
67
68        a.recycle();
69
70        initializePivotPoint();
71    }
72
73    /**
74     * Constructor to use when building a RotateAnimation from code.
75     * Default pivotX/pivotY point is (0,0).
76     *
77     * @param fromDegrees Rotation offset to apply at the start of the
78     *        animation.
79     *
80     * @param toDegrees Rotation offset to apply at the end of the animation.
81     */
82    public RotateAnimation(float fromDegrees, float toDegrees) {
83        mFromDegrees = fromDegrees;
84        mToDegrees = toDegrees;
85        mPivotX = 0.0f;
86        mPivotY = 0.0f;
87    }
88
89    /**
90     * Constructor to use when building a RotateAnimation from code
91     *
92     * @param fromDegrees Rotation offset to apply at the start of the
93     *        animation.
94     *
95     * @param toDegrees Rotation offset to apply at the end of the animation.
96     *
97     * @param pivotX The X coordinate of the point about which the object is
98     *        being rotated, specified as an absolute number where 0 is the left
99     *        edge.
100     * @param pivotY The Y coordinate of the point about which the object is
101     *        being rotated, specified as an absolute number where 0 is the top
102     *        edge.
103     */
104    public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
105        mFromDegrees = fromDegrees;
106        mToDegrees = toDegrees;
107
108        mPivotXType = ABSOLUTE;
109        mPivotYType = ABSOLUTE;
110        mPivotXValue = pivotX;
111        mPivotYValue = pivotY;
112        initializePivotPoint();
113    }
114
115    /**
116     * Constructor to use when building a RotateAnimation from code
117     *
118     * @param fromDegrees Rotation offset to apply at the start of the
119     *        animation.
120     *
121     * @param toDegrees Rotation offset to apply at the end of the animation.
122     *
123     * @param pivotXType Specifies how pivotXValue should be interpreted. One of
124     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
125     *        Animation.RELATIVE_TO_PARENT.
126     * @param pivotXValue The X coordinate of the point about which the object
127     *        is being rotated, specified as an absolute number where 0 is the
128     *        left edge. This value can either be an absolute number if
129     *        pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
130     *        otherwise.
131     * @param pivotYType Specifies how pivotYValue should be interpreted. One of
132     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
133     *        Animation.RELATIVE_TO_PARENT.
134     * @param pivotYValue The Y coordinate of the point about which the object
135     *        is being rotated, specified as an absolute number where 0 is the
136     *        top edge. This value can either be an absolute number if
137     *        pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
138     *        otherwise.
139     */
140    public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
141            int pivotYType, float pivotYValue) {
142        mFromDegrees = fromDegrees;
143        mToDegrees = toDegrees;
144
145        mPivotXValue = pivotXValue;
146        mPivotXType = pivotXType;
147        mPivotYValue = pivotYValue;
148        mPivotYType = pivotYType;
149        initializePivotPoint();
150    }
151
152    /**
153     * Called at the end of constructor methods to initialize, if possible, values for
154     * the pivot point. This is only possible for ABSOLUTE pivot values.
155     */
156    private void initializePivotPoint() {
157        if (mPivotXType == ABSOLUTE) {
158            mPivotX = mPivotXValue;
159        }
160        if (mPivotYType == ABSOLUTE) {
161            mPivotY = mPivotYValue;
162        }
163    }
164
165    @Override
166    protected void applyTransformation(float interpolatedTime, Transformation t) {
167        float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
168        float scale = getScaleFactor();
169
170        if (mPivotX == 0.0f && mPivotY == 0.0f) {
171            t.getMatrix().setRotate(degrees);
172        } else {
173            t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);
174        }
175    }
176
177    @Override
178    public void initialize(int width, int height, int parentWidth, int parentHeight) {
179        super.initialize(width, height, parentWidth, parentHeight);
180        mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
181        mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
182    }
183}
184