DrawableContainer.java revision f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 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
1958945975b256739fdfe78435d7846d1e2fd29da1Chris Craikimport android.annotation.NonNull;
20b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList;
21c2974809373697147cbe5754835cc871fb93aef1Dianne Hackbornimport android.content.res.Resources;
2252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme;
23dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reckimport android.graphics.Bitmap;
2478aaa97b77d56e35e994611406deb398eb9005dbGilles Debunneimport android.graphics.Canvas;
2578aaa97b77d56e35e994611406deb398eb9005dbGilles Debunneimport android.graphics.ColorFilter;
26bbd51f1e360b22eece1d74bd65c7e6a0b59dee59Philip Milneimport android.graphics.Insets;
2758945975b256739fdfe78435d7846d1e2fd29da1Chris Craikimport android.graphics.Outline;
2878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunneimport android.graphics.PixelFormat;
2978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunneimport android.graphics.Rect;
30b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
31079e23575024e103358c982152afb7a720ae1a8aDianne Hackbornimport android.os.SystemClock;
32f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viveretteimport android.util.DisplayMetrics;
33600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglioimport android.util.LayoutDirection;
34f390f770ee570f1f4def41b165cb9492e381be40Alan Viveretteimport android.util.SparseArray;
35dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viveretteimport android.view.View;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reckimport java.util.Collection;
38dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck
3978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne/**
4078aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne * A helper class that contains several {@link Drawable}s and selects which one to use.
4178aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne *
4278aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne * You can subclass it to create your own DrawableContainers or directly use one its child classes.
4378aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne */
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class DrawableContainer extends Drawable implements Drawable.Callback {
45079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private static final boolean DEBUG = false;
46079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private static final String TAG = "DrawableContainer";
47211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed
48211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    /**
49211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * To be proper, we should have a getter for dither (and alpha, etc.)
50211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * so that proxy classes like this can save/restore their delegates'
51211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * values, but we don't have getters. Since we do have setters
52211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * (e.g. setDither), which this proxy forwards on, we have to have some
53211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * default/initial setting.
54211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     *
55211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * The initial setting for dither is now true, since it almost always seems
56211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * to improve the quality at negligible cost.
57211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     */
58211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    private static final boolean DEFAULT_DITHER = true;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private DrawableContainerState mDrawableContainerState;
607068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    private Rect mHotspotBounds;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mCurrDrawable;
62ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette    private Drawable mLastDrawable;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mAlpha = 0xFF;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette    /** Whether setAlpha() has been called at least once. */
66729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette    private boolean mHasAlpha;
67729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mCurIndex = -1;
69ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette    private int mLastIndex = -1;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMutated;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    // Animations.
73079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private Runnable mAnimationRunnable;
74079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private long mEnterAnimationEnd;
75079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private long mExitAnimationEnd;
76079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // overrides from Drawable
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.draw(canvas);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
84079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
85079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.draw(canvas);
86079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChangingConfigurations() {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.getChangingConfigurations()
92e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                | mDrawableContainerState.getChangingConfigurations();
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
94f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
95600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio    private boolean needsMirroring() {
96600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
97600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio    }
98600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPadding(Rect padding) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect r = mDrawableContainerState.getConstantPadding();
102f7a93ef3847258157d144dfefaa5757128cc807dFabrice Di Meglio        boolean result;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r != null) {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            padding.set(r);
105f7a93ef3847258157d144dfefaa5757128cc807dFabrice Di Meglio            result = (r.left | r.top | r.bottom | r.right) != 0;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
107600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            if (mCurrDrawable != null) {
108600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio                result = mCurrDrawable.getPadding(padding);
109600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            } else {
110600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio                result = super.getPadding(padding);
111600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
113600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        if (needsMirroring()) {
114600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            final int left = padding.left;
115600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            final int right = padding.right;
116600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            padding.left = right;
117600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            padding.right = left;
118600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        }
119600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        return result;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1221557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    /**
1231557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * @hide
1241557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     */
1251557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    @Override
1267b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne    public Insets getOpticalInsets() {
1278de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        if (mCurrDrawable != null) {
1288de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette            return mCurrDrawable.getOpticalInsets();
1298de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        }
1308de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        return Insets.NONE;
1311557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    }
1321557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
13431ba192dd201df2cad96a8c503f730130ab0d80fChris Craik    public void getOutline(@NonNull Outline outline) {
13558945975b256739fdfe78435d7846d1e2fd29da1Chris Craik        if (mCurrDrawable != null) {
13631ba192dd201df2cad96a8c503f730130ab0d80fChris Craik            mCurrDrawable.getOutline(outline);
13758945975b256739fdfe78435d7846d1e2fd29da1Chris Craik        }
13858945975b256739fdfe78435d7846d1e2fd29da1Chris Craik    }
13958945975b256739fdfe78435d7846d1e2fd29da1Chris Craik
14058945975b256739fdfe78435d7846d1e2fd29da1Chris Craik    @Override
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
14234bd56b546bce47422a430d9d7806dc3cb4254bfAlan Viverette        if (!mHasAlpha || mAlpha != alpha) {
14334bd56b546bce47422a430d9d7806dc3cb4254bfAlan Viverette            mHasAlpha = true;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAlpha = alpha;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
146079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mEnterAnimationEnd == 0) {
1475f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                    mCurrDrawable.mutate().setAlpha(alpha);
148079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
149079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animate(false);
150079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
156b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
157b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mAlpha;
158b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
159b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
160b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
162a41581ed4033004c73115113f45b9844e9b0210fRomain Guy        if (mDrawableContainerState.mDither != dither) {
163a41581ed4033004c73115113f45b9844e9b0210fRomain Guy            mDrawableContainerState.mDither = dither;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
1655f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                mCurrDrawable.mutate().setDither(mDrawableContainerState.mDither);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
171bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik    public void setColorFilter(ColorFilter colorFilter) {
1726f51440a746ef4925ec329cd3a71a9689be2b10bAlan Viverette        mDrawableContainerState.mHasColorFilter = true;
173729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
174bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        if (mDrawableContainerState.mColorFilter != colorFilter) {
175bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mDrawableContainerState.mColorFilter = colorFilter;
176729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
178bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik                mCurrDrawable.mutate().setColorFilter(colorFilter);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
182f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
183b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
184a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintList(ColorStateList tint) {
185bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        mDrawableContainerState.mHasTintList = true;
186b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
187bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        if (mDrawableContainerState.mTintList != tint) {
188bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette            mDrawableContainerState.mTintList = tint;
189a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
190a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            if (mCurrDrawable != null) {
191a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette                mCurrDrawable.mutate().setTintList(tint);
192a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            }
193a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        }
194a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    }
195a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
196a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    @Override
197a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintMode(Mode tintMode) {
198bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        mDrawableContainerState.mHasTintMode = true;
199a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
200a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (mDrawableContainerState.mTintMode != tintMode) {
201b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mDrawableContainerState.mTintMode = tintMode;
202b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
203b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            if (mCurrDrawable != null) {
204a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette                mCurrDrawable.mutate().setTintMode(tintMode);
205b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            }
206b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
207b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
208b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
209079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    /**
210079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * Change the global fade duration when a new drawable is entering
211079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * the scene.
212079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
213079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
214079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setEnterFadeDuration(int ms) {
215079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mEnterFadeDuration = ms;
216079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
217f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
218079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    /**
219079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * Change the global fade duration when a new drawable is leaving
220079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * the scene.
221079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
222079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
223079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setExitFadeDuration(int ms) {
224079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mExitFadeDuration = ms;
225079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
226f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect bounds) {
229079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
230079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setBounds(bounds);
231079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setBounds(bounds);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
236f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDrawableContainerState.isStateful();
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
241f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2433f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public void setAutoMirrored(boolean mirrored) {
244729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        if (mDrawableContainerState.mAutoMirrored != mirrored) {
245729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            mDrawableContainerState.mAutoMirrored = mirrored;
246729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mCurrDrawable != null) {
247729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette                mCurrDrawable.mutate().setAutoMirrored(mDrawableContainerState.mAutoMirrored);
248729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
2493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
2503f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2513f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2523f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
2533f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public boolean isAutoMirrored() {
2543f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return mDrawableContainerState.mAutoMirrored;
2553f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2573f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
258079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void jumpToCurrentState() {
259079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean changed = false;
260079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
261079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.jumpToCurrentState();
262079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable = null;
263ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mLastIndex = -1;
264079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
265079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
266079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
267079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.jumpToCurrentState();
268729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mHasAlpha) {
269729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette                mCurrDrawable.mutate().setAlpha(mAlpha);
270729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
271079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
272079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mExitAnimationEnd != 0) {
273079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
274079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
275079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
276079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0) {
277079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
278079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
279079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
280079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (changed) {
281079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            invalidateSelf();
282079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
283079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
284079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
285079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    @Override
286c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette    public void setHotspot(float x, float y) {
287307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        if (mCurrDrawable != null) {
288c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette            mCurrDrawable.setHotspot(x, y);
289307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        }
290307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    }
291307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette
292307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    @Override
29353a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    public void setHotspotBounds(int left, int top, int right, int bottom) {
2947068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds == null) {
29527cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds = new Rect(left, top, right, bottom);
2967068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
29727cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds.set(left, top, right, bottom);
2987068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
2997068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
30053a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        if (mCurrDrawable != null) {
30153a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette            mCurrDrawable.setHotspotBounds(left, top, right, bottom);
30253a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        }
30353a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    }
30453a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette
3057068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    @Override
3067068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    public void getHotspotBounds(Rect outRect) {
3077068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds != null) {
3087068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            outRect.set(mHotspotBounds);
3097068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
3107068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            super.getHotspotBounds(outRect);
3117068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
3127068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    }
3137068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
31453a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    @Override
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean onStateChange(int[] state) {
316079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
317079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setState(state);
318079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setState(state);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3260b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
327079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
328079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setLevel(level);
329079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setLevel(level);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
337dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viverette    public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
338a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // Let the container handle setting its own layout direction. Otherwise,
339a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // we're accessing potentially unused states.
340a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        return mDrawableContainerState.setLayoutDirection(layoutDirection, getCurrentIndex());
341a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    }
342a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
343a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    @Override
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantWidth();
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicWidth() : -1;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantHeight();
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicHeight() : -1;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
358f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumWidth() {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumWidth();
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumWidth() : 0;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumHeight() {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumHeight();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumHeight() : 0;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37572146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
376079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void invalidateDrawable(Drawable who) {
377f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
378f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().invalidateDrawable(this);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38272146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
383079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void scheduleDrawable(Drawable who, Runnable what, long when) {
384f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
385f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().scheduleDrawable(this, what, when);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38972146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
390079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void unscheduleDrawable(Drawable who, Runnable what) {
391f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
392f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().unscheduleDrawable(this, what);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setVisible(boolean visible, boolean restart) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changed = super.setVisible(visible, restart);
399079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
400079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setVisible(visible, restart);
401079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setVisible(visible, restart);
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return changed;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
41083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        return mCurrDrawable == null || !mCurrDrawable.isVisible() ? PixelFormat.TRANSPARENT :
41183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                mDrawableContainerState.getOpacity();
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4145e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4155e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public void setCurrentIndex(int index) {
4165e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        selectDrawable(index);
4175e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4185e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
4195e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4205e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public int getCurrentIndex() {
4215e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        return mCurIndex;
4225e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4235e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
424a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    /**
425a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * Sets the currently displayed drawable by index.
426a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * <p>
427a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * If an invalid index is specified, the current drawable will be set to
428a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * {@code null} and the index will be set to {@code -1}.
429a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     *
430a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @param index the index of the drawable to display
431a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @return {@code true} if the drawable changed, {@code false} otherwise
432a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     */
433a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    public boolean selectDrawable(int index) {
434a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index == mCurIndex) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
437079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
438079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
439079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
440a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (DEBUG) android.util.Log.i(TAG, toString() + " from " + mCurIndex + " to " + index
441079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + ": exit=" + mDrawableContainerState.mExitFadeDuration
442079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + " enter=" + mDrawableContainerState.mEnterFadeDuration);
443079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
444079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mDrawableContainerState.mExitFadeDuration > 0) {
445079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mLastDrawable != null) {
446079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable.setVisible(false, false);
447079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
449079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = mCurrDrawable;
450ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = mCurIndex;
451079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = now + mDrawableContainerState.mExitFadeDuration;
452079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
453079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = null;
454ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = -1;
455079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = 0;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
457079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else if (mCurrDrawable != null) {
458079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.setVisible(false, false);
459079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
460079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
461a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index >= 0 && index < mDrawableContainerState.mNumChildren) {
462a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            final Drawable d = mDrawableContainerState.getChild(index);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = d;
464a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            mCurIndex = index;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (d != null) {
466079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mDrawableContainerState.mEnterFadeDuration > 0) {
467079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
4687068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette                }
469419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(d);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = null;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIndex = -1;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
475079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
476079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0 || mExitAnimationEnd != 0) {
477079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mAnimationRunnable == null) {
478079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mAnimationRunnable = new Runnable() {
479079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    @Override public void run() {
480079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        animate(true);
481079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        invalidateSelf();
482079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    }
483079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                };
484079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
485079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                unscheduleSelf(mAnimationRunnable);
486079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
487079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            // Compute first frame and schedule next animation.
488079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            animate(true);
489079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
490079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
492079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
495f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
496419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    /**
497419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * Initializes a drawable for display in this container.
498419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     *
499419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * @param d The drawable to initialize.
500419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     */
501419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    private void initializeDrawableForDisplay(Drawable d) {
502419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.mutate();
503419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
504419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
505419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            d.setAlpha(mAlpha);
506419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        }
507419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
508419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        if (mDrawableContainerState.mHasColorFilter) {
509419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            // Color filter always overrides tint.
510419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            d.setColorFilter(mDrawableContainerState.mColorFilter);
511419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        } else {
512419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            if (mDrawableContainerState.mHasTintList) {
513419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                d.setTintList(mDrawableContainerState.mTintList);
514419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
515419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            if (mDrawableContainerState.mHasTintMode) {
516419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                d.setTintMode(mDrawableContainerState.mTintMode);
517419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
518419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        }
519419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
520419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setVisible(isVisible(), true);
521419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setDither(mDrawableContainerState.mDither);
522419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setState(getState());
5230b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette        d.setLevel(getLevel());
524419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setBounds(getBounds());
525419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setLayoutDirection(getLayoutDirection());
526419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
527419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
528419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        final Rect hotspotBounds = mHotspotBounds;
529419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        if (hotspotBounds != null) {
530419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
531419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                    hotspotBounds.right, hotspotBounds.bottom);
532419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        }
533419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    }
534419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
535079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    void animate(boolean schedule) {
536729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        mHasAlpha = true;
537729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
538079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
539079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean animating = false;
540079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
541079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mEnterAnimationEnd != 0) {
542079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mEnterAnimationEnd <= now) {
5435f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                    mCurrDrawable.mutate().setAlpha(mAlpha);
544079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = 0;
545079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
546079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mEnterAnimationEnd-now)*255)
547079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mEnterFadeDuration;
548079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    if (DEBUG) android.util.Log.i(TAG, toString() + " cur alpha " + animAlpha);
5495f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                    mCurrDrawable.mutate().setAlpha(((255-animAlpha)*mAlpha)/255);
550079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
551079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
552079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
553079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
554079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
555079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
556079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
557079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mExitAnimationEnd != 0) {
558079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mExitAnimationEnd <= now) {
559079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable.setVisible(false, false);
560079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable = null;
561ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                    mLastIndex = -1;
562079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mExitAnimationEnd = 0;
563079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
564079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mExitAnimationEnd-now)*255)
565079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mExitFadeDuration;
566079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    if (DEBUG) android.util.Log.i(TAG, toString() + " last alpha " + animAlpha);
5675f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                    mLastDrawable.mutate().setAlpha((animAlpha*mAlpha)/255);
568079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
569079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
570079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
571079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
572079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
573079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
574079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
575079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (schedule && animating) {
5768dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            scheduleSelf(mAnimationRunnable, now + 1000 / 60);
577079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
578079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
579079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getCurrent() {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
585f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    /**
586f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * Updates the source density based on the resources used to inflate
587f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * density-dependent values. Implementing classes should call this method
588f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * during inflation.
589f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     *
590f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * @param res the resources used to inflate density-dependent values
591f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     */
592f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    final void updateDensity(Resources res) {
593f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        mDrawableContainerState.updateDensity(res);
594f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    }
595f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
59752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void applyTheme(Theme theme) {
59852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        mDrawableContainerState.applyTheme(theme);
59952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
60052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
60152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
60252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
60352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        return mDrawableContainerState.canApplyTheme();
60452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
60552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
60652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.canConstantState()) {
6096efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais            mDrawableContainerState.mChangingConfigurations = getChangingConfigurations();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
6185ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            final DrawableContainerState clone = cloneConstantState();
6195ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            clone.mutate();
6205ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            setConstantState(clone);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62678aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne    /**
6278dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * Returns a shallow copy of the container's constant state to be used as
6288dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * the base state for {@link #mutate()}.
6298dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     *
6308dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * @return a shallow copy of the constant state
6318dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     */
6328dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    DrawableContainerState cloneConstantState() {
6338dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        return mDrawableContainerState;
6348dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    }
6358dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
6368dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    /**
637727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
638727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
639727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
640727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
641727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mDrawableContainerState.clearMutated();
642727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
643727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
644727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
645727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
64678aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * A ConstantState that can contain several {@link Drawable}s.
64778aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     *
64878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * This class was made public to enable testing, and its visibility may change in a future
64978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * release.
65078aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     */
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract static class DrawableContainerState extends ConstantState {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final DrawableContainer mOwner;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
654f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        Resources mSourceRes;
655f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        int mDensity = DisplayMetrics.DENSITY_DEFAULT;
656f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mChangingConfigurations;
657f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mChildrenChangingConfigurations;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        SparseArray<ConstantStateFuture> mDrawableFutures;
660f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Drawable[] mDrawables;
661f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mNumChildren;
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
663d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mVariablePadding = false;
664f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedPadding;
665f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Rect mConstantPadding;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
667d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mConstantSize = false;
668f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedConstantSize;
669f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantWidth;
670f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantHeight;
671f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumWidth;
672f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumHeight;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
674f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedOpacity;
675f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mOpacity;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
677f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedStateful;
678f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mStateful;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
680f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedConstantState;
681f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCanConstantState;
6825140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy
683f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mDither = DEFAULT_DITHER;
684f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
685f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mMutated;
686f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mLayoutDirection;
687f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
688d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mEnterFadeDuration = 0;
689d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mExitFadeDuration = 0;
690079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
6913f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        boolean mAutoMirrored;
6923f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
693d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette        ColorFilter mColorFilter;
694729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        boolean mHasColorFilter;
695d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette
696bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        ColorStateList mTintList;
697b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        Mode mTintMode;
698bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintList;
699bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintMode;
700b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
701c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
702c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                Resources res) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOwner = owner;
704f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
705f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final Resources sourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);
706f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mSourceRes = sourceRes;
707f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
708f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final int densityDpi = sourceRes == null ? 0 : sourceRes.getDisplayMetrics().densityDpi;
709f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final int sourceDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
710f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mDensity = sourceDensity;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orig != null) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChangingConfigurations = orig.mChangingConfigurations;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
716f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCheckedConstantState = true;
717f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCanConstantState = true;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mVariablePadding = orig.mVariablePadding;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mConstantSize = orig.mConstantSize;
721a41581ed4033004c73115113f45b9844e9b0210fRomain Guy                mDither = orig.mDither;
722f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mMutated = orig.mMutated;
723f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mLayoutDirection = orig.mLayoutDirection;
724079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mEnterFadeDuration = orig.mEnterFadeDuration;
725079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitFadeDuration = orig.mExitFadeDuration;
7263f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                mAutoMirrored = orig.mAutoMirrored;
727d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette                mColorFilter = orig.mColorFilter;
728729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette                mHasColorFilter = orig.mHasColorFilter;
729bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mTintList = orig.mTintList;
730b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = orig.mTintMode;
731bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintList = orig.mHasTintList;
732bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintMode = orig.mHasTintMode;
733079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
734f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mDensity == sourceDensity) {
735f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedPadding) {
736f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantPadding = new Rect(orig.mConstantPadding);
737f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedPadding = true;
738f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
739f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
740f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedConstantSize) {
741f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantWidth = orig.mConstantWidth;
742f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantHeight = orig.mConstantHeight;
743f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumWidth = orig.mConstantMinimumWidth;
744f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumHeight = orig.mConstantMinimumHeight;
745f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedConstantSize = true;
746f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
747f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
748f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
749f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedOpacity) {
750f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mOpacity = orig.mOpacity;
751f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedOpacity = true;
752f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
753f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
754f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedStateful) {
755f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mStateful = orig.mStateful;
756f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedStateful = true;
757f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
758f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
759f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // Postpone cloning children and futures until we're absolutely
760f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // sure that we're done computing values for the original state.
761f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable[] origDr = orig.mDrawables;
762f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawables = new Drawable[origDr.length];
763f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mNumChildren = orig.mNumChildren;
764f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
765f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final SparseArray<ConstantStateFuture> origDf = orig.mDrawableFutures;
766f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (origDf != null) {
767f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures = origDf.clone();
768f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                } else {
76906ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    mDrawableFutures = new SparseArray<>(mNumChildren);
770f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
771f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
77262b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // Create futures for drawables with constant states. If a
77362b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // drawable doesn't have a constant state, then we can't clone
77462b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // it and we'll have to reference the original.
775f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int N = mNumChildren;
776f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int i = 0; i < N; i++) {
777f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    if (origDr[i] != null) {
77862b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        if (origDr[i].getConstantState() != null) {
77962b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                            mDrawableFutures.put(i, new ConstantStateFuture(origDr[i]));
78062b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        } else {
78162b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                            mDrawables[i] = origDr[i];
78262b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        }
783f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    }
784f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDrawables = new Drawable[10];
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumChildren = 0;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
790f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getChangingConfigurations() {
793dc25d25333d3fac96dccfb9bd31d2474d6bc2d78Fabrice Di Meglio            return mChangingConfigurations | mChildrenChangingConfigurations;
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final int addChild(Drawable dr) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pos = mNumChildren;
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pos >= mDrawables.length) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                growArray(pos, pos+10);
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setVisible(false, true);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setCallback(mOwner);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables[pos] = dr;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNumChildren++;
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
809f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedStateful = false;
810f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedOpacity = false;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantPadding = null;
813f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = false;
814f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = false;
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pos;
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81972146433322588c1116ee06c27ac758ad09d869cAlan Viverette        final int getCapacity() {
82072146433322588c1116ee06c27ac758ad09d869cAlan Viverette            return mDrawables.length;
82172146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
82272146433322588c1116ee06c27ac758ad09d869cAlan Viverette
823f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        private final void createAllFutures() {
824f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
825f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int futureCount = mDrawableFutures.size();
826f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
827f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    final int index = mDrawableFutures.keyAt(keyIndex);
828f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawables[index] = mDrawableFutures.valueAt(keyIndex).get(this);
829f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
830f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
831f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawableFutures = null;
832f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
833f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
834f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
83583b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getChildCount() {
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNumChildren;
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
83972146433322588c1116ee06c27ac758ad09d869cAlan Viverette        /*
84072146433322588c1116ee06c27ac758ad09d869cAlan Viverette         * @deprecated Use {@link #getChild} instead.
84172146433322588c1116ee06c27ac758ad09d869cAlan Viverette         */
84283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Drawable[] getChildren() {
843f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Create all futures for backwards compatibility.
844f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
845f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawables;
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84972146433322588c1116ee06c27ac758ad09d869cAlan Viverette        public final Drawable getChild(int index) {
850f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable result = mDrawables[index];
851f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (result != null) {
852f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return result;
853f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
854f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
855f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Prepare future drawable if necessary.
856f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
857f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int keyIndex = mDrawableFutures.indexOfKey(index);
858f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (keyIndex >= 0) {
859f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    final Drawable prepared = mDrawableFutures.valueAt(keyIndex).get(this);
860f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawables[index] = prepared;
861f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures.removeAt(keyIndex);
86206ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    if (mDrawableFutures.size() == 0) {
86306ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                        mDrawableFutures = null;
86406ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    }
865f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return prepared;
866f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
867f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
868f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
869f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return null;
870f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
871f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
872a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        final boolean setLayoutDirection(int layoutDirection, int currentIndex) {
873a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            boolean changed = false;
874a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
875f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
876f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // change layout direction when they are prepared.
877f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
878f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
879f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
880f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
881a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    final boolean childChanged = drawables[i].setLayoutDirection(layoutDirection);
882a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    if (i == currentIndex) {
883a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                        changed = childChanged;
884a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    }
885f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
886f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
887f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
888f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mLayoutDirection = layoutDirection;
889a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
890a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            return changed;
89172146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
89272146433322588c1116ee06c27ac758ad09d869cAlan Viverette
893f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        /**
894f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * Updates the source density based on the resources used to inflate
895f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * density-dependent values.
896f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         *
897f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * @param res the resources used to inflate density-dependent values
898f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         */
899f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        final void updateDensity(Resources res) {
900f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (mSourceRes != null) {
901f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                mSourceRes = res;
902f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            }
903f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
904f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            // The density may have changed since the last update (if any). Any
905f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            // dimension-type attributes will need their default values scaled.
906f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final int densityDpi = res.getDisplayMetrics().densityDpi;
907f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final int newSourceDensity = densityDpi == 0 ?
908f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    DisplayMetrics.DENSITY_DEFAULT : densityDpi;
909f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            final int oldSourceDensity = mDensity;
910f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mDensity = newSourceDensity;
911f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
912f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (oldSourceDensity != newSourceDensity) {
913f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                mCheckedConstantSize = false;
914f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                mCheckedPadding = false;
915f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            }
916f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        }
917f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
91852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final void applyTheme(Theme theme) {
91917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            if (theme != null) {
92017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                createAllFutures();
92117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
92217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final int N = mNumChildren;
92317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final Drawable[] drawables = mDrawables;
92417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                for (int i = 0; i < N; i++) {
92517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    if (drawables[i] != null && drawables[i].canApplyTheme()) {
92617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        drawables[i].applyTheme(theme);
927e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
928e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        // Update cached mask of child changing configurations.
929e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        mChildrenChangingConfigurations |= drawables[i].getChangingConfigurations();
93017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    }
93152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
932f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
933f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                updateDensity(theme.getResources());
93452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
93552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
93652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
93752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
93852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
93952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final int N = mNumChildren;
94052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final Drawable[] drawables = mDrawables;
94152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            for (int i = 0; i < N; i++) {
942b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                final Drawable d = drawables[i];
94352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (d != null) {
94452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (d.canApplyTheme()) {
94552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
94652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
94752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                } else {
94852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    final ConstantStateFuture future = mDrawableFutures.get(i);
94952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (future != null && future.canApplyTheme()) {
95052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
95152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
95252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
95352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
95452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
95552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            return false;
95652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
95752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
9588dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        private void mutate() {
959f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
960f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // mutate when they are prepared.
961f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
96272146433322588c1116ee06c27ac758ad09d869cAlan Viverette            final Drawable[] drawables = mDrawables;
96372146433322588c1116ee06c27ac758ad09d869cAlan Viverette            for (int i = 0; i < N; i++) {
964f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
965f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    drawables[i].mutate();
966f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
96772146433322588c1116ee06c27ac758ad09d869cAlan Viverette            }
968f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
969f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mMutated = true;
97072146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
97172146433322588c1116ee06c27ac758ad09d869cAlan Viverette
972727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        final void clearMutated() {
973727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final int N = mNumChildren;
974727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final Drawable[] drawables = mDrawables;
975727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            for (int i = 0; i < N; i++) {
976727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                if (drawables[i] != null) {
977727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                    drawables[i].clearMutated();
978727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                }
979727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            }
980727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
981727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            mMutated = false;
982727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        }
983727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
984f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        /**
985f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * A boolean value indicating whether to use the maximum padding value
986f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * of all frames in the set (false), or to use the padding value of the
987f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * frame being shown (true). Default value is false.
988f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         */
98983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setVariablePadding(boolean variable) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVariablePadding = variable;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Rect getConstantPadding() {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mVariablePadding) {
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
997f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
998f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if ((mConstantPadding != null) || mCheckedPadding) {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mConstantPadding;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1002f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1003f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
10045140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            Rect r = null;
100583b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Rect t = new Rect();
1006f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
100783b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
100883b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
100983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                if (drawables[i].getPadding(t)) {
10105140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy                    if (r == null) r = new Rect(0, 0, 0, 0);
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.left > r.left) r.left = t.left;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.top > r.top) r.top = t.top;
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.right > r.right) r.right = t.right;
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.bottom > r.bottom) r.bottom = t.bottom;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1017f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1018f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = true;
10195140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            return (mConstantPadding = r);
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setConstantSize(boolean constant) {
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantSize = constant;
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final boolean isConstantSize() {
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantSize;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantWidth() {
1031f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantWidth;
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103883b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantHeight() {
1039f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantHeight;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumWidth() {
1047f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumWidth;
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumHeight() {
1055f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumHeight;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106278aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne        protected void computeConstantSize() {
1063f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = true;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1065f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1066f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1067f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
106883b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
106978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne            mConstantWidth = mConstantHeight = -1;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantMinimumWidth = mConstantMinimumHeight = 0;
107183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
1072f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable dr = drawables[i];
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int s = dr.getIntrinsicWidth();
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantWidth) mConstantWidth = s;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getIntrinsicHeight();
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantHeight) mConstantHeight = s;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumWidth();
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumWidth) mConstantMinimumWidth = s;
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumHeight();
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumHeight) mConstantMinimumHeight = s;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1084079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setEnterFadeDuration(int duration) {
1085079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterFadeDuration = duration;
1086079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1087079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1088079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getEnterFadeDuration() {
1089079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mEnterFadeDuration;
1090079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1091079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1092079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setExitFadeDuration(int duration) {
1093079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitFadeDuration = duration;
1094079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1095079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1096079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getExitFadeDuration() {
1097079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mExitFadeDuration;
1098079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1099079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
110083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getOpacity() {
1101f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedOpacity) {
1102f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mOpacity;
1103f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1104f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1105f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1106f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1107f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedOpacity = true;
1108f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1109f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
111083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
1111f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            int op = (N > 0) ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
111283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 1; i < N; i++) {
111383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1115f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOpacity = op;
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return op;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
111983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final boolean isStateful() {
1121f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedStateful) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mStateful;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1124f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1125f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1126f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1127f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedStateful = true;
1128f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1129f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1130f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
1132f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].isStateful()) {
1133f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mStateful = true;
1134f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return true;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1137f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1138f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mStateful = false;
1139f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return false;
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
114283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public void growArray(int oldSize, int newSize) {
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Drawable[] newDrawables = new Drawable[newSize];
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.arraycopy(mDrawables, 0, newDrawables, 0, oldSize);
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables = newDrawables;
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized boolean canConstantState() {
1149f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedConstantState) {
1150f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mCanConstantState;
1151f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1152f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1153f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1154f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1155f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedConstantState = true;
1156f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1157f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1158f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
1159f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
1160f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].getConstantState() == null) {
1161f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mCanConstantState = false;
1162f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return false;
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1166f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCanConstantState = true;
1167f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return true;
1168f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
1169f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1170dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck        /** @hide */
1171dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck        @Override
1172dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
1173dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck            final int N = mNumChildren;
1174dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck            int pixelCount = 0;
1175dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck            for (int i = 0; i < N; i++) {
1176dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck                final ConstantState state = getChild(i).getConstantState();
1177dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck                if (state != null) {
1178dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck                    pixelCount += state.addAtlasableBitmaps(atlasList);
1179dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck                }
1180dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck            }
1181dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck            return pixelCount;
1182dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck        }
1183dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck
1184f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        /**
1185f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * Class capable of cloning a Drawable from another Drawable's
1186f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * ConstantState.
1187f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         */
1188f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        private static class ConstantStateFuture {
1189f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            private final ConstantState mConstantState;
1190f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1191f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            private ConstantStateFuture(Drawable source) {
1192f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mConstantState = source.getConstantState();
1193f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1194f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1195f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            /**
1196f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette             * Obtains and prepares the Drawable represented by this future.
1197f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette             *
1198f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette             * @param state the container into which this future will be placed
1199f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette             * @return a prepared Drawable
1200f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette             */
1201f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            public Drawable get(DrawableContainerState state) {
120252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                final Drawable result;
1203f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (state.mSourceRes == null) {
120452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    result = mConstantState.newDrawable();
120552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                } else {
1206f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    result = mConstantState.newDrawable(state.mSourceRes);
120752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
1208f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                result.setLayoutDirection(state.mLayoutDirection);
1209f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                result.setCallback(state.mOwner);
1210f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1211f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (state.mMutated) {
1212f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    result.mutate();
1213f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
1214f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1215f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return result;
1216f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
121752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
121852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            /**
121952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette             * Whether the constant state wrapped by this future can apply a
122052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette             * theme.
122152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette             */
122252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            public boolean canApplyTheme() {
122352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                return mConstantState.canApplyTheme();
122452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1228f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette    protected void setConstantState(DrawableContainerState state) {
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDrawableContainerState = state;
1230ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette
1231ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        // The locally cached drawables may have changed.
1232ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        if (mCurIndex >= 0) {
1233ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mCurrDrawable = state.getChild(mCurIndex);
1234419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            if (mCurrDrawable != null) {
1235419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(mCurrDrawable);
1236419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
1237ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        }
1238419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
1239419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // Clear out the last drawable. We don't have enough information to
1240419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // propagate local state from the past.
1241419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastIndex = -1;
1242419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastDrawable = null;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1245