1f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy/*
2f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Copyright (C) 2009 The Android Open Source Project
3f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy *
4f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * you may not use this file except in compliance with the License.
6f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * You may obtain a copy of the License at
7f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy *
8f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy *
10f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * Unless required by applicable law or agreed to in writing, software
11f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * See the License for the specific language governing permissions and
14f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * limitations under the License.
15f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy */
16f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
17f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guypackage android.graphics.drawable;
18f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
19f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.Canvas;
20f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.Rect;
21f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.graphics.ColorFilter;
22f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.content.res.Resources;
23f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.content.res.TypedArray;
24f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.AttributeSet;
25f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.TypedValue;
26f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.util.Log;
27f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport android.os.SystemClock;
28f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport org.xmlpull.v1.XmlPullParser;
29f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport org.xmlpull.v1.XmlPullParserException;
30f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
31f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport java.io.IOException;
32f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
33f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guyimport com.android.internal.R;
34f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
35f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy/**
36f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy * @hide
37f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy */
38b5537c452271634b6ff3981b0624fa65384abd5bRomain Guypublic class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
39b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        Animatable {
40b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy
41f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private AnimatedRotateState mState;
42f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private boolean mMutated;
43f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private float mCurrentDegrees;
44f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private float mIncrement;
45b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    private boolean mRunning;
46f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
47f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public AnimatedRotateDrawable() {
48c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(null, null);
49f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
50f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
51c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private AnimatedRotateDrawable(AnimatedRotateState rotateState, Resources res) {
52c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mState = new AnimatedRotateState(rotateState, this, res);
53f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        init();
54f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
55f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
56f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private void init() {
57f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final AnimatedRotateState state = mState;
580d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        mIncrement = 360.0f / state.mFramesCount;
59f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final Drawable drawable = state.mDrawable;
60f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (drawable != null) {
61f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            drawable.setFilterBitmap(true);
62f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if (drawable instanceof BitmapDrawable) {
63f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                ((BitmapDrawable) drawable).setAntiAlias(true);
64f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
65f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
66f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
67f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
680d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    @Override
69f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void draw(Canvas canvas) {
70f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int saveCount = canvas.save();
71f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
72f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final AnimatedRotateState st = mState;
73f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final Drawable drawable = st.mDrawable;
74f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final Rect bounds = drawable.getBounds();
75f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
76f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int w = bounds.right - bounds.left;
77f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int h = bounds.bottom - bounds.top;
78f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
79f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX;
80f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY;
81f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
82e5cdb6c8394e321266fb8940fdd0c97b2f87b2f3Chet Haase        canvas.rotate(mCurrentDegrees, px + bounds.left, py + bounds.top);
83f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
84f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        drawable.draw(canvas);
85f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
86f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        canvas.restoreToCount(saveCount);
87f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
88b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy
89b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    public void start() {
90b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        if (!mRunning) {
91b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy            mRunning = true;
92b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy            nextFrame();
93b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        }
94b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    }
95b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy
96b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    public void stop() {
97b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        mRunning = false;
98b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        unscheduleSelf(this);
99b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    }
100b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy
101b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    public boolean isRunning() {
102b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        return mRunning;
103b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy    }
104b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy
105f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    private void nextFrame() {
106f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        unscheduleSelf(this);
107f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        scheduleSelf(this, SystemClock.uptimeMillis() + mState.mFrameDuration);
108f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
109f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
110f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void run() {
111f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        // TODO: This should be computed in draw(Canvas), based on the amount
112f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        // of time since the last frame drawn
113f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        mCurrentDegrees += mIncrement;
114f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (mCurrentDegrees > (360.0f - mIncrement)) {
115f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            mCurrentDegrees = 0.0f;
116f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
117f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        invalidateSelf();
118b5537c452271634b6ff3981b0624fa65384abd5bRomain Guy        nextFrame();
119f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
120f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
121f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
122f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public boolean setVisible(boolean visible, boolean restart) {
123f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        mState.mDrawable.setVisible(visible, restart);
124f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        boolean changed = super.setVisible(visible, restart);
125f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (visible) {
126f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if (changed || restart) {
127f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mCurrentDegrees = 0.0f;
128f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                nextFrame();
129f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
130f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        } else {
131f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            unscheduleSelf(this);
132f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
133f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return changed;
134f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
135f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
136f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    /**
137f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy     * Returns the drawable rotated by this RotateDrawable.
138f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy     */
139f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public Drawable getDrawable() {
140f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable;
141f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
142f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
143f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
144f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public int getChangingConfigurations() {
145f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return super.getChangingConfigurations()
146f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                | mState.mChangingConfigurations
147f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                | mState.mDrawable.getChangingConfigurations();
148f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
149f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
1500d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    @Override
151f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void setAlpha(int alpha) {
152f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        mState.mDrawable.setAlpha(alpha);
153f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
154f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
1550d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    @Override
156f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void setColorFilter(ColorFilter cf) {
157f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        mState.mDrawable.setColorFilter(cf);
158f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
159f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
1600d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    @Override
161f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public int getOpacity() {
162f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable.getOpacity();
163f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
164f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
165f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void invalidateDrawable(Drawable who) {
166f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        final Callback callback = getCallback();
167f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (callback != null) {
168f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            callback.invalidateDrawable(this);
169f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
170f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
171f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
172f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void scheduleDrawable(Drawable who, Runnable what, long when) {
173f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        final Callback callback = getCallback();
174f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (callback != null) {
175f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            callback.scheduleDrawable(this, what, when);
176f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
177f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
178f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
179f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void unscheduleDrawable(Drawable who, Runnable what) {
180f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        final Callback callback = getCallback();
181f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (callback != null) {
182f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            callback.unscheduleDrawable(this, what);
183f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
184f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
185f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
186f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
187f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public boolean getPadding(Rect padding) {
188f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable.getPadding(padding);
189f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
190f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
191f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
192f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public boolean isStateful() {
193f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable.isStateful();
194f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
195f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
196f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
197f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    protected void onBoundsChange(Rect bounds) {
198f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        mState.mDrawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
199f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
200f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
201f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
202f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public int getIntrinsicWidth() {
203f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable.getIntrinsicWidth();
204f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
205f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
206f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
207f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public int getIntrinsicHeight() {
208f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return mState.mDrawable.getIntrinsicHeight();
209f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
210f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
211f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
212f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public ConstantState getConstantState() {
213f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (mState.canConstantState()) {
2146efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais            mState.mChangingConfigurations = getChangingConfigurations();
215f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            return mState;
216f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
217f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return null;
218f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
219f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
220f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
221f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
222f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            throws XmlPullParserException, IOException {
223f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
224f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedRotateDrawable);
225f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
226f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
227f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
228f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
229f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
230f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
231f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
232f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
233f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
234f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
2350d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey
2360d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
2370d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
2380d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey
239f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
240f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        Drawable drawable = null;
241f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (res > 0) {
242f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            drawable = r.getDrawable(res);
243f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
244f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
245f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        a.recycle();
246f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
247f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int outerDepth = parser.getDepth();
248f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int type;
249f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
250f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy               (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
251f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
252f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if (type != XmlPullParser.START_TAG) {
253f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                continue;
254f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
255f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
256f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs)) == null) {
257f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                Log.w("drawable", "Bad element under <animated-rotate>: "
258f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                        + parser .getName());
259f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
260f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
261f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
262f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (drawable == null) {
263f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            Log.w("drawable", "No drawable specified for <animated-rotate>");
264f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
265f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
266f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        final AnimatedRotateState rotateState = mState;
267f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        rotateState.mDrawable = drawable;
268f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        rotateState.mPivotXRel = pivotXRel;
269f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        rotateState.mPivotX = pivotX;
270f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        rotateState.mPivotYRel = pivotYRel;
271f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        rotateState.mPivotY = pivotY;
272f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
273f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        init();
274f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
275f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (drawable != null) {
276f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            drawable.setCallback(this);
277f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
278f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
279f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
2800d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    public void setFramesCount(int framesCount) {
2810d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        mState.mFramesCount = framesCount;
2820d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        mIncrement = 360.0f / mState.mFramesCount;
2830d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    }
2840d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey
2850d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    public void setFramesDuration(int framesDuration) {
2860d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey        mState.mFrameDuration = framesDuration;
2870d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey    }
2880d32b317c2d1cacfa5acd34253cc626d6a776ec0Jeff Sharkey
289f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    @Override
290f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    public Drawable mutate() {
291f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        if (!mMutated && super.mutate() == this) {
292f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            mState.mDrawable.mutate();
293f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            mMutated = true;
294f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
295f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        return this;
296f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
297f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
298f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    final static class AnimatedRotateState extends Drawable.ConstantState {
299f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        Drawable mDrawable;
300f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
301f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int mChangingConfigurations;
302f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
303f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        boolean mPivotXRel;
304f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        float mPivotX;
305f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        boolean mPivotYRel;
306f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        float mPivotY;
307f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int mFrameDuration;
308f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        int mFramesCount;
309f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
310f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        private boolean mCanConstantState;
311f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        private boolean mCheckedConstantState;
312f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
313c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner,
314c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                Resources res) {
315f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if (source != null) {
316c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                if (res != null) {
317c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                    mDrawable = source.mDrawable.getConstantState().newDrawable(res);
318c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                } else {
319c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                    mDrawable = source.mDrawable.getConstantState().newDrawable();
320c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                }
321f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mDrawable.setCallback(owner);
322f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mPivotXRel = source.mPivotXRel;
323f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mPivotX = source.mPivotX;
324f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mPivotYRel = source.mPivotYRel;
325f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mPivotY = source.mPivotY;
326f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mFramesCount = source.mFramesCount;
327f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mFrameDuration = source.mFrameDuration;
328f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mCanConstantState = mCheckedConstantState = true;
329f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
330f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
331f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
332f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        @Override
333f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        public Drawable newDrawable() {
334c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimatedRotateDrawable(this, null);
335c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
336c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
337c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
338c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
339c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new AnimatedRotateDrawable(this, res);
340f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
341f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
342f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        @Override
343f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        public int getChangingConfigurations() {
344f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            return mChangingConfigurations;
345f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
346f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
347f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        public boolean canConstantState() {
348f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            if (!mCheckedConstantState) {
349f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mCanConstantState = mDrawable.getConstantState() != null;
350f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy                mCheckedConstantState = true;
351f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            }
352f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy
353f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy            return mCanConstantState;
354f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy        }
355f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy    }
356f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy}
357