19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viveretteimport com.android.internal.R; 2017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 27b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode; 28b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 3152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 38a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * <p> 39a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * A Drawable that can rotate another Drawable based on the current level value. 40a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * The start and end angles of rotation can be controlled to map any circular 41a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * arc to the level values range. 42a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * <p> 43a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * It can be defined in an XML file with the <code><rotate></code> element. 44a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * For more information, see the guide to 45a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * <a href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_visible 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_fromDegrees 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_toDegrees 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_pivotX 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_pivotY 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RotateDrawable_drawable 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RotateDrawable extends Drawable implements Drawable.Callback { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final float MAX_LEVEL = 10000.0f; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 57a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette private final RotateState mState; 58a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMutated; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 62a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Create a new rotating drawable with an empty state. 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public RotateDrawable() { 659db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru this(null, null); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 69a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Create a new rotating drawable with the specified state. A copy of 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this state is used as the internal state for the newly created 71a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * drawable. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rotateState the state for this drawable 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru private RotateDrawable(RotateState rotateState, Resources res) { 769db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru mState = new RotateState(rotateState, this, res); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas canvas) { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RotateState st = mState; 82a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final Drawable d = st.mDrawable; 83a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final Rect bounds = d.getBounds(); 84a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final int w = bounds.right - bounds.left; 85a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final int h = bounds.bottom - bounds.top; 86a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX; 87a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY; 88a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 89a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final int saveCount = canvas.save(); 90a1b92c5e8b750d8f5b2dc5ca7e8b4edc97de5575Adam Powell canvas.rotate(st.mCurrentDegrees, px + bounds.left, py + bounds.top); 91a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette d.draw(canvas); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restoreToCount(saveCount); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 96a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets the drawable rotated by this RotateDrawable. 97a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 98a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param drawable The drawable to rotate 99a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 100a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setDrawable(Drawable drawable) { 101a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final Drawable oldDrawable = mState.mDrawable; 102a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette if (oldDrawable != drawable) { 103a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette if (oldDrawable != null) { 104a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette oldDrawable.setCallback(null); 105a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 106a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mDrawable = drawable; 107a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette if (drawable != null) { 108a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette drawable.setCallback(this); 109a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 110a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 111a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 112a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 113a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 114a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return The drawable rotated by this RotateDrawable 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable getDrawable() { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getChangingConfigurations() 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | mState.mChangingConfigurations 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | mState.mDrawable.getChangingConfigurations(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 126a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 127a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAlpha(int alpha) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.setAlpha(alpha); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 132b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase @Override 133b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase public int getAlpha() { 134b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase return mState.mDrawable.getAlpha(); 135b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase } 136b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase 137a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColorFilter(ColorFilter cf) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.setColorFilter(cf); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 142a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 143a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintList(ColorStateList tint) { 144a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mState.mDrawable.setTintList(tint); 145a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette } 146a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette 147a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette @Override 148a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintMode(Mode tintMode) { 149a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mState.mDrawable.setTintMode(tintMode); 150b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette } 151b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 152b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette @Override 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable.getOpacity(); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 157a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 158a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets the start angle for rotation. 159a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 160a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param fromDegrees Starting angle in degrees 161e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 162e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #getFromDegrees() 163e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_fromDegrees 164a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 165a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setFromDegrees(float fromDegrees) { 166a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette if (mState.mFromDegrees != fromDegrees) { 167a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mFromDegrees = fromDegrees; 168a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 169a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 170a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 171a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 172a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 173a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return The starting angle for rotation in degrees 174e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 175e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #setFromDegrees(float) 176e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_fromDegrees 177a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 178a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public float getFromDegrees() { 179a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mFromDegrees; 180a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 181a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 182a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 183a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets the end angle for rotation. 184a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 185a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param toDegrees Ending angle in degrees 186e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 187e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #getToDegrees() 188e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_toDegrees 189a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 190a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setToDegrees(float toDegrees) { 191a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette if (mState.mToDegrees != toDegrees) { 192a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mToDegrees = toDegrees; 193a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 194a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 195a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 196a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 197a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 198a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return The ending angle for rotation in degrees 199e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 200e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #setToDegrees(float) 201e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_toDegrees 202a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 203a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public float getToDegrees() { 204a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mToDegrees; 205a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 206a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 207a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 208a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets the X position around which the drawable is rotated. 209a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 210a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param pivotX X position around which to rotate. If the X pivot is 211a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * relative, the position represents a fraction of the drawable 212a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * width. Otherwise, the position represents an absolute value in 213a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * pixels. 214e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 215a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @see #setPivotXRelative(boolean) 216e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_pivotX 217a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 218a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setPivotX(float pivotX) { 219735b75ce274ef7a4c78745844a4269d72cb4feaejungheang.lee if (mState.mPivotX != pivotX) { 220a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mPivotX = pivotX; 221a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 222a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 223a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 224a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 225a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 226a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return X position around which to rotate 227e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 228a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @see #setPivotX(float) 229e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_pivotX 230a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 231a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public float getPivotX() { 232a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mPivotX; 233a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 234a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 235a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 236a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets whether the X pivot value represents a fraction of the drawable 237a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * width or an absolute value in pixels. 238a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 239a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param relative True if the X pivot represents a fraction of the drawable 240a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * width, or false if it represents an absolute value in pixels 241e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 242e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #isPivotXRelative() 243a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 244a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setPivotXRelative(boolean relative) { 245735b75ce274ef7a4c78745844a4269d72cb4feaejungheang.lee if (mState.mPivotXRel != relative) { 246a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mPivotXRel = relative; 247a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 248a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 249a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 250a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 251a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 252a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return True if the X pivot represents a fraction of the drawable width, 253a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * or false if it represents an absolute value in pixels 254e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 255a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @see #setPivotXRelative(boolean) 256a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 257a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public boolean isPivotXRelative() { 258a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mPivotXRel; 259a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 260a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 261a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 262a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets the Y position around which the drawable is rotated. 263a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 264a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param pivotY Y position around which to rotate. If the Y pivot is 265a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * relative, the position represents a fraction of the drawable 266a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * height. Otherwise, the position represents an absolute value 267a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * in pixels. 268e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 269e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #getPivotY() 270e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_pivotY 271a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 272a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setPivotY(float pivotY) { 273735b75ce274ef7a4c78745844a4269d72cb4feaejungheang.lee if (mState.mPivotY != pivotY) { 274a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mPivotY = pivotY; 275a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 276a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 277a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 278a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 279a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 280a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return Y position around which to rotate 281e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 282a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @see #setPivotY(float) 283e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @attr ref android.R.styleable#RotateDrawable_pivotY 284a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 285a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public float getPivotY() { 286a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mPivotY; 287a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 288a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 289a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 290a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Sets whether the Y pivot value represents a fraction of the drawable 291a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * height or an absolute value in pixels. 292a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * 293a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @param relative True if the Y pivot represents a fraction of the drawable 294a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * height, or false if it represents an absolute value in pixels 295e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 296e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * @see #isPivotYRelative() 297a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 298a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public void setPivotYRelative(boolean relative) { 299735b75ce274ef7a4c78745844a4269d72cb4feaejungheang.lee if (mState.mPivotYRel != relative) { 300a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette mState.mPivotYRel = relative; 301a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette invalidateSelf(); 302a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 303a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 304a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 305a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette /** 306a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @return True if the Y pivot represents a fraction of the drawable height, 307a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * or false if it represents an absolute value in pixels 308e5b082d6eb0489e7dbe3159338f8c94c0af61deeAlan Viverette * 309a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * @see #setPivotYRelative(boolean) 310a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette */ 311a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette public boolean isPivotYRelative() { 312a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette return mState.mPivotYRel; 313a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette } 314a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 315a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 316d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette public boolean canApplyTheme() { 317d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); 318d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 319d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 320d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette @Override 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void invalidateDrawable(Drawable who) { 322f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 323f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 324f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.invalidateDrawable(this); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 328a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void scheduleDrawable(Drawable who, Runnable what, long when) { 330f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 331f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 332f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.scheduleDrawable(this, what, when); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 336a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette @Override 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unscheduleDrawable(Drawable who, Runnable what) { 338f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy final Callback callback = getCallback(); 339f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy if (callback != null) { 340f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy callback.unscheduleDrawable(this, what); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getPadding(Rect padding) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable.getPadding(padding); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setVisible(boolean visible, boolean restart) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.setVisible(visible, restart); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.setVisible(visible, restart); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStateful() { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable.isStateful(); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 359a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean onStateChange(int[] state) { 362a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette final boolean changed = mState.mDrawable.setState(state); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onBoundsChange(getBounds()); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return changed; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean onLevelChange(int level) { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.setLevel(level); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onBoundsChange(getBounds()); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mCurrentDegrees = mState.mFromDegrees + 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mState.mToDegrees - mState.mFromDegrees) * 374a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette (level / MAX_LEVEL); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateSelf(); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect bounds) { 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.setBounds(bounds.left, bounds.top, 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.right, bounds.bottom); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable.getIntrinsicWidth(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState.mDrawable.getIntrinsicHeight(); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ConstantState getConstantState() { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState.canConstantState()) { 3996efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mState.mChangingConfigurations = getChangingConfigurations(); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 40652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 408d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable); 409d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible); 410a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 411d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette // Reset mDrawable to preserve old multiple-inflate behavior. This is 412d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette // silly, but we have CTS tests that rely on it. 413d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mDrawable = null; 414d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 415d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette updateStateFromTypedArray(a); 416d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette inflateChildElements(r, parser, attrs, theme); 417d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette verifyRequiredAttributes(a); 418d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette a.recycle(); 419d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 420b81b1447d2cfa9dc5bcc02c8a1b7193400a97ab6Cyril Mottier 421d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette @Override 422d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette public void applyTheme(Theme t) { 423d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette super.applyTheme(t); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 425d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final RotateState state = mState; 426d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (state == null) { 427d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4307f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette if (state.mThemeAttrs != null) { 4317f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable); 4327f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette try { 4337f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette updateStateFromTypedArray(a); 4347f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette verifyRequiredAttributes(a); 4357f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette } catch (XmlPullParserException e) { 4367f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette throw new RuntimeException(e); 4377f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette } finally { 4387f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette a.recycle(); 4397f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette } 440d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 441a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 442d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { 443d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mDrawable.applyTheme(t); 444d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 4457f4a63d1ebc13c6499a48331ecb78c4d27446dbcAlan Viverette 446d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 448d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, 449d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette Theme theme) throws XmlPullParserException, IOException { 450d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette Drawable dr = null; 451d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int type; 452d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final int outerDepth = parser.getDepth(); 453d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 454d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type != XmlPullParser.START_TAG) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 458d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette dr = Drawable.createFromXmlInner(r, parser, attrs, theme); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 461d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (dr != null) { 462d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mState.mDrawable = dr; 463d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette dr.setCallback(this); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 465d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 467d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { 468d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette // If we're not waiting on a theme, verify required attributes. 469d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (mState.mDrawable == null && (mState.mThemeAttrs == null 470d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) { 471d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette throw new XmlPullParserException(a.getPositionDescription() 472d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette + ": <rotate> tag requires a 'drawable' attribute or " 473d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette + "child tag defining a drawable"); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 477d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette private void updateStateFromTypedArray(TypedArray a) { 47817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette final RotateState state = mState; 479d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 480d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette // Account for any configuration changes. 481d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 482d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 483d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette // Extract the theme attributes, if any. 484d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 485d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 486d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (a.hasValue(R.styleable.RotateDrawable_pivotX)) { 487d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX); 488d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION; 489d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); 49017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 49117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 492d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (a.hasValue(R.styleable.RotateDrawable_pivotY)) { 493d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY); 494d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION; 495d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); 49617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 49717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 498d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees); 499d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees); 500d03963ce364e9946f1bd603c2fcf07a49088af19Alan Viverette state.mCurrentDegrees = state.mFromDegrees; 501d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 502d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable); 503d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette if (dr != null) { 504d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette state.mDrawable = dr; 505d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette dr.setCallback(this); 506d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 50717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 50817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 50917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette @Override 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable mutate() { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mMutated && super.mutate() == this) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.mDrawable.mutate(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMutated = true; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 519727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette * @hide 520727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette */ 521727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette public void clearMutated() { 522727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette super.clearMutated(); 523727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mState.mDrawable.clearMutated(); 524727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mMutated = false; 525727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette } 526727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette 527727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette /** 528a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * Represents the state of a rotation for a given drawable. The same 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * rotate drawable can be invoked with different states to drive several 530a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette * rotations at the same time. 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final static class RotateState extends Drawable.ConstantState { 533d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette int[] mThemeAttrs; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mChangingConfigurations; 535a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 536d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette Drawable mDrawable; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 538d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette boolean mPivotXRel = true; 539d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette float mPivotX = 0.5f; 540d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette boolean mPivotYRel = true; 541d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette float mPivotY = 0.5f; 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 543d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette float mFromDegrees = 0.0f; 544d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette float mToDegrees = 360.0f; 545d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 546d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette float mCurrentDegrees = 0.0f; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 548a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette private boolean mCheckedConstantState; 549d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette private boolean mCanConstantState; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 551d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette RotateState(RotateState orig, RotateDrawable owner, Resources res) { 552d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette if (orig != null) { 553d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mThemeAttrs = orig.mThemeAttrs; 554d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mChangingConfigurations = orig.mChangingConfigurations; 5559db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru if (res != null) { 556d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mDrawable = orig.mDrawable.getConstantState().newDrawable(res); 5579db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru } else { 558d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mDrawable = orig.mDrawable.getConstantState().newDrawable(); 5599db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawable.setCallback(owner); 561d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection()); 562d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mDrawable.setBounds(orig.mDrawable.getBounds()); 563d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mDrawable.setLevel(orig.mDrawable.getLevel()); 564d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mPivotXRel = orig.mPivotXRel; 565d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mPivotX = orig.mPivotX; 566d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mPivotYRel = orig.mPivotYRel; 567d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mPivotY = orig.mPivotY; 568d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mFromDegrees = orig.mFromDegrees; 569d7853e576301bf68e96148a0b9e52085bfc7cf95Alan Viverette mToDegrees = orig.mToDegrees; 570d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mCurrentDegrees = orig.mCurrentDegrees; 571d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette mCheckedConstantState = mCanConstantState = true; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 576d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette public boolean canApplyTheme() { 577d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) 578d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette || super.canApplyTheme(); 579d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 580d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 581d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette @Override 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable newDrawable() { 5839db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru return new RotateDrawable(this, null); 5849db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru } 585a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 5869db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru @Override 5879db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru public Drawable newDrawable(Resources res) { 5889db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru return new RotateDrawable(this, res); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 590a8b2edec93beeaa76b3cfc93bb9cb3e19fc34addAlan Viverette 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChangingConfigurations; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean canConstantState() { 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mCheckedConstantState) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCanConstantState = mDrawable.getConstantState() != null; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCheckedConstantState = true; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCanConstantState; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 606