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;
20ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport android.content.pm.ActivityInfo.Config;
21b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList;
22c2974809373697147cbe5754835cc871fb93aef1Dianne Hackbornimport android.content.res.Resources;
2352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme;
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;
29b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
300c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhuimport android.graphics.Rect;
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
3778aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne/**
3878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne * A helper class that contains several {@link Drawable}s and selects which one to use.
3978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne *
4078aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne * You can subclass it to create your own DrawableContainers or directly use one its child classes.
4178aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne */
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class DrawableContainer extends Drawable implements Drawable.Callback {
43079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private static final boolean DEBUG = false;
44079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private static final String TAG = "DrawableContainer";
45211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed
46211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    /**
47211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * To be proper, we should have a getter for dither (and alpha, etc.)
48211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * so that proxy classes like this can save/restore their delegates'
49211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * values, but we don't have getters. Since we do have setters
50211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * (e.g. setDither), which this proxy forwards on, we have to have some
51211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * default/initial setting.
52211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     *
53211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * The initial setting for dither is now true, since it almost always seems
54211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     * to improve the quality at negligible cost.
55211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed     */
56211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    private static final boolean DEFAULT_DITHER = true;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private DrawableContainerState mDrawableContainerState;
587068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    private Rect mHotspotBounds;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mCurrDrawable;
60ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette    private Drawable mLastDrawable;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mAlpha = 0xFF;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
63729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette    /** Whether setAlpha() has been called at least once. */
64729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette    private boolean mHasAlpha;
65729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mCurIndex = -1;
67ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette    private int mLastIndex = -1;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMutated;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
70079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    // Animations.
71079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private Runnable mAnimationRunnable;
72079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private long mEnterAnimationEnd;
73079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    private long mExitAnimationEnd;
74079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
756d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    /** Callback that blocks invalidation. Used for drawable initialization. */
766d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    private BlockInvalidateCallback mBlockInvalidateCallback;
776d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // overrides from Drawable
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.draw(canvas);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
85079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
86079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.draw(canvas);
87079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
91ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    public @Config int getChangingConfigurations() {
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.getChangingConfigurations()
93e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                | mDrawableContainerState.getChangingConfigurations();
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
95f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
96600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio    private boolean needsMirroring() {
97600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
98600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio    }
99600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPadding(Rect padding) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect r = mDrawableContainerState.getConstantPadding();
103f7a93ef3847258157d144dfefaa5757128cc807dFabrice Di Meglio        boolean result;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r != null) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            padding.set(r);
106f7a93ef3847258157d144dfefaa5757128cc807dFabrice Di Meglio            result = (r.left | r.top | r.bottom | r.right) != 0;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
108600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            if (mCurrDrawable != null) {
109600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio                result = mCurrDrawable.getPadding(padding);
110600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            } else {
111600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio                result = super.getPadding(padding);
112600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
114600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        if (needsMirroring()) {
115600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            final int left = padding.left;
116600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            final int right = padding.right;
117600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            padding.left = right;
118600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio            padding.right = left;
119600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        }
120600d7dd1c6d9d1ff81b71085eff2a6be50d6f36cFabrice Di Meglio        return result;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1231557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    /**
1241557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * @hide
1251557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     */
1261557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    @Override
1277b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne    public Insets getOpticalInsets() {
1288de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        if (mCurrDrawable != null) {
1298de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette            return mCurrDrawable.getOpticalInsets();
1308de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        }
1318de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        return Insets.NONE;
1321557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    }
1331557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
13531ba192dd201df2cad96a8c503f730130ab0d80fChris Craik    public void getOutline(@NonNull Outline outline) {
13658945975b256739fdfe78435d7846d1e2fd29da1Chris Craik        if (mCurrDrawable != null) {
13731ba192dd201df2cad96a8c503f730130ab0d80fChris Craik            mCurrDrawable.getOutline(outline);
13858945975b256739fdfe78435d7846d1e2fd29da1Chris Craik        }
13958945975b256739fdfe78435d7846d1e2fd29da1Chris Craik    }
14058945975b256739fdfe78435d7846d1e2fd29da1Chris Craik
14158945975b256739fdfe78435d7846d1e2fd29da1Chris Craik    @Override
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
14334bd56b546bce47422a430d9d7806dc3cb4254bfAlan Viverette        if (!mHasAlpha || mAlpha != alpha) {
14434bd56b546bce47422a430d9d7806dc3cb4254bfAlan Viverette            mHasAlpha = true;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAlpha = alpha;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
147079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mEnterAnimationEnd == 0) {
1489b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mCurrDrawable.setAlpha(alpha);
149079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
150079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animate(false);
151079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
157b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
158b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mAlpha;
159b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
160b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
161b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
163a41581ed4033004c73115113f45b9844e9b0210fRomain Guy        if (mDrawableContainerState.mDither != dither) {
164a41581ed4033004c73115113f45b9844e9b0210fRomain Guy            mDrawableContainerState.mDither = dither;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
1669b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setDither(mDrawableContainerState.mDither);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
172bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik    public void setColorFilter(ColorFilter colorFilter) {
1736f51440a746ef4925ec329cd3a71a9689be2b10bAlan Viverette        mDrawableContainerState.mHasColorFilter = true;
174729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
175bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        if (mDrawableContainerState.mColorFilter != colorFilter) {
176bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mDrawableContainerState.mColorFilter = colorFilter;
177729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
1799b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setColorFilter(colorFilter);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
183f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
184b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
185a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintList(ColorStateList tint) {
186bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        mDrawableContainerState.mHasTintList = true;
187b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
188bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        if (mDrawableContainerState.mTintList != tint) {
189bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette            mDrawableContainerState.mTintList = tint;
190a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
191a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            if (mCurrDrawable != null) {
1929b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setTintList(tint);
193a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            }
194a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        }
195a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    }
196a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
197a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    @Override
198a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintMode(Mode tintMode) {
199bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        mDrawableContainerState.mHasTintMode = true;
200a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette
201a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (mDrawableContainerState.mTintMode != tintMode) {
202b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mDrawableContainerState.mTintMode = tintMode;
203b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
204b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            if (mCurrDrawable != null) {
2059b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setTintMode(tintMode);
206b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            }
207b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
208b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
209b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
210079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    /**
211079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * Change the global fade duration when a new drawable is entering
212079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * the scene.
213ad7e748543f69794bbc8114da660eed705a89087Alan Viverette     *
214079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
215079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
216079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setEnterFadeDuration(int ms) {
217079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mEnterFadeDuration = ms;
218079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
219f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
220079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    /**
221079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * Change the global fade duration when a new drawable is leaving
222079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * the scene.
223ad7e748543f69794bbc8114da660eed705a89087Alan Viverette     *
224079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
225079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
226079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setExitFadeDuration(int ms) {
227079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mExitFadeDuration = ms;
228079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
229f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect bounds) {
232079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
233079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setBounds(bounds);
234079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setBounds(bounds);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
239f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDrawableContainerState.isStateful();
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
244f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
245f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    /** @hide */
246f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    @Override
247f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    public boolean hasFocusStateSpecified() {
248f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        if (mCurrDrawable != null) {
249f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He            return mCurrDrawable.hasFocusStateSpecified();
250f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        }
251f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        if (mLastDrawable != null) {
252f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He            return mLastDrawable.hasFocusStateSpecified();
253f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        }
254f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        return false;
255f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    }
256f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2583f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public void setAutoMirrored(boolean mirrored) {
259729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        if (mDrawableContainerState.mAutoMirrored != mirrored) {
260729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            mDrawableContainerState.mAutoMirrored = mirrored;
261729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mCurrDrawable != null) {
2629b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
263729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
2643f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
2653f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2663f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2673f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
2683f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public boolean isAutoMirrored() {
2693f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return mDrawableContainerState.mAutoMirrored;
2703f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2713f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2723f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
273079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void jumpToCurrentState() {
274079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean changed = false;
275079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
276079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.jumpToCurrentState();
277079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable = null;
278ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mLastIndex = -1;
279079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
280079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
281079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
282079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.jumpToCurrentState();
283729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mHasAlpha) {
2849b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setAlpha(mAlpha);
285729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
286079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
287079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mExitAnimationEnd != 0) {
288079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
289079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
290079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
291079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0) {
292079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
293079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
294079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
295079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (changed) {
296079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            invalidateSelf();
297079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
298079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
299079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
300079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    @Override
301c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette    public void setHotspot(float x, float y) {
302307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        if (mCurrDrawable != null) {
303c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette            mCurrDrawable.setHotspot(x, y);
304307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        }
305307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    }
306307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette
307307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    @Override
30853a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    public void setHotspotBounds(int left, int top, int right, int bottom) {
3097068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds == null) {
31027cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds = new Rect(left, top, right, bottom);
3117068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
31227cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds.set(left, top, right, bottom);
3137068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
3147068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
31553a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        if (mCurrDrawable != null) {
31653a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette            mCurrDrawable.setHotspotBounds(left, top, right, bottom);
31753a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        }
31853a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    }
31953a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette
3207068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    @Override
3217068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    public void getHotspotBounds(Rect outRect) {
3227068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds != null) {
3237068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            outRect.set(mHotspotBounds);
3247068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
3257068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            super.getHotspotBounds(outRect);
3267068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
3277068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    }
3287068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
32953a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    @Override
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean onStateChange(int[] state) {
331079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
332079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setState(state);
333079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setState(state);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3410b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
342079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
343079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setLevel(level);
344079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setLevel(level);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
352dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viverette    public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
353a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // Let the container handle setting its own layout direction. Otherwise,
354a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // we're accessing potentially unused states.
355a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        return mDrawableContainerState.setLayoutDirection(layoutDirection, getCurrentIndex());
356a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    }
357a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
358a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    @Override
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantWidth();
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicWidth() : -1;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantHeight();
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicHeight() : -1;
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
373f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumWidth() {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumWidth();
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumWidth() : 0;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumHeight() {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumHeight();
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumHeight() : 0;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39072146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
391f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void invalidateDrawable(@NonNull Drawable who) {
392ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        // This may have been called as the result of a tint changing, in
393ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        // which case we may need to refresh the cached statefulness or
394ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        // opacity.
395ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        if (mDrawableContainerState != null) {
396ad7e748543f69794bbc8114da660eed705a89087Alan Viverette            mDrawableContainerState.invalidateCache();
397ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        }
398ad7e748543f69794bbc8114da660eed705a89087Alan Viverette
399f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
400f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().invalidateDrawable(this);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
40472146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
405f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
406f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
407f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().scheduleDrawable(this, what, when);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41172146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
412f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
413f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
414f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().unscheduleDrawable(this, what);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setVisible(boolean visible, boolean restart) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changed = super.setVisible(visible, restart);
421079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
422079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setVisible(visible, restart);
423079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setVisible(visible, restart);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return changed;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
43283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        return mCurrDrawable == null || !mCurrDrawable.isVisible() ? PixelFormat.TRANSPARENT :
43383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                mDrawableContainerState.getOpacity();
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4365e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4375e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public void setCurrentIndex(int index) {
4385e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        selectDrawable(index);
4395e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4405e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
4415e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4425e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public int getCurrentIndex() {
4435e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        return mCurIndex;
4445e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4455e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
446a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    /**
447a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * Sets the currently displayed drawable by index.
448a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * <p>
449a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * If an invalid index is specified, the current drawable will be set to
450a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * {@code null} and the index will be set to {@code -1}.
451a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     *
452a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @param index the index of the drawable to display
453a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @return {@code true} if the drawable changed, {@code false} otherwise
454a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     */
455a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    public boolean selectDrawable(int index) {
456a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index == mCurIndex) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
459079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
460079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
461079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
462a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (DEBUG) android.util.Log.i(TAG, toString() + " from " + mCurIndex + " to " + index
463079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + ": exit=" + mDrawableContainerState.mExitFadeDuration
464079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + " enter=" + mDrawableContainerState.mEnterFadeDuration);
465079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
466079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mDrawableContainerState.mExitFadeDuration > 0) {
467079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mLastDrawable != null) {
468079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable.setVisible(false, false);
469079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
471079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = mCurrDrawable;
472ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = mCurIndex;
473079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = now + mDrawableContainerState.mExitFadeDuration;
474079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
475079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = null;
476ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = -1;
477079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = 0;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
479079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else if (mCurrDrawable != null) {
480079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.setVisible(false, false);
481079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
482079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
483a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index >= 0 && index < mDrawableContainerState.mNumChildren) {
484a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            final Drawable d = mDrawableContainerState.getChild(index);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = d;
486a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            mCurIndex = index;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (d != null) {
488079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mDrawableContainerState.mEnterFadeDuration > 0) {
489079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
4907068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette                }
491419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(d);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = null;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIndex = -1;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
497079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
498079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0 || mExitAnimationEnd != 0) {
499079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mAnimationRunnable == null) {
500079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mAnimationRunnable = new Runnable() {
501079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    @Override public void run() {
502079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        animate(true);
503079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        invalidateSelf();
504079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    }
505079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                };
506079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
507079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                unscheduleSelf(mAnimationRunnable);
508079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
509079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            // Compute first frame and schedule next animation.
510079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            animate(true);
511079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
512079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
514079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
517f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
518419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    /**
519419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * Initializes a drawable for display in this container.
520419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     *
521419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * @param d The drawable to initialize.
522419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     */
523419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    private void initializeDrawableForDisplay(Drawable d) {
5246d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        if (mBlockInvalidateCallback == null) {
5256d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mBlockInvalidateCallback = new BlockInvalidateCallback();
5266d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
5276d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
5282b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // Temporary fix for suspending callbacks during initialization. We
5292b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // don't want any of these setters causing an invalidate() since that
5302b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // may call back into DrawableContainer.
5316d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        d.setCallback(mBlockInvalidateCallback.wrap(d.getCallback()));
5322b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette
5332b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        try {
5342b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
5352b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setAlpha(mAlpha);
536419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
537419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
5382b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (mDrawableContainerState.mHasColorFilter) {
5392b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                // Color filter always overrides tint.
5402b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setColorFilter(mDrawableContainerState.mColorFilter);
5412b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            } else {
5422b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                if (mDrawableContainerState.mHasTintList) {
5432b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                    d.setTintList(mDrawableContainerState.mTintList);
5442b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                }
5452b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                if (mDrawableContainerState.mHasTintMode) {
5462b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                    d.setTintMode(mDrawableContainerState.mTintMode);
5472b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                }
5482b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            }
549419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
5502b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setVisible(isVisible(), true);
5512b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setDither(mDrawableContainerState.mDither);
5522b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setState(getState());
5532b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setLevel(getLevel());
5542b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setBounds(getBounds());
5552b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setLayoutDirection(getLayoutDirection());
5562b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
5572b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette
5582b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            final Rect hotspotBounds = mHotspotBounds;
5592b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (hotspotBounds != null) {
5602b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
5612b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                        hotspotBounds.right, hotspotBounds.bottom);
5622b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            }
5632b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        } finally {
5646d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            d.setCallback(mBlockInvalidateCallback.unwrap());
565419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        }
566419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    }
567419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
568079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    void animate(boolean schedule) {
569729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        mHasAlpha = true;
570729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
571079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
572079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean animating = false;
573079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
574079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mEnterAnimationEnd != 0) {
575079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mEnterAnimationEnd <= now) {
5769b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mCurrDrawable.setAlpha(mAlpha);
577079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = 0;
578079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
579079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mEnterAnimationEnd-now)*255)
580079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mEnterFadeDuration;
5819b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
582079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
583079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
584079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
585079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
586079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
587079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
588079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
589079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mExitAnimationEnd != 0) {
590079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mExitAnimationEnd <= now) {
591079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable.setVisible(false, false);
592079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable = null;
593ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                    mLastIndex = -1;
594079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mExitAnimationEnd = 0;
595079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
596079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mExitAnimationEnd-now)*255)
597079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mExitFadeDuration;
5989b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
599079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
600079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
601079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
602079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
603079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
604079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
605079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
606079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (schedule && animating) {
6078dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            scheduleSelf(mAnimationRunnable, now + 1000 / 60);
608079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
609079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
610079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getCurrent() {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
616f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    /**
617f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * Updates the source density based on the resources used to inflate
618f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * density-dependent values. Implementing classes should call this method
619f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * during inflation.
620f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     *
621f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * @param res the resources used to inflate density-dependent values
6220c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu     * @hide
623f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     */
6240c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu    protected final void updateDensity(Resources res) {
625f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        mDrawableContainerState.updateDensity(res);
626f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    }
627f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
62952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void applyTheme(Theme theme) {
63052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        mDrawableContainerState.applyTheme(theme);
63152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
63252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
63352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
63452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
63552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        return mDrawableContainerState.canApplyTheme();
63652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
63752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
63852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.canConstantState()) {
6416efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais            mDrawableContainerState.mChangingConfigurations = getChangingConfigurations();
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
6505ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            final DrawableContainerState clone = cloneConstantState();
6515ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            clone.mutate();
6525ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            setConstantState(clone);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne    /**
6598dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * Returns a shallow copy of the container's constant state to be used as
6608dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * the base state for {@link #mutate()}.
6618dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     *
6628dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * @return a shallow copy of the constant state
6638dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     */
6648dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    DrawableContainerState cloneConstantState() {
6658dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        return mDrawableContainerState;
6668dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    }
6678dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
6688dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    /**
669727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
670727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
671727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
672727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
673727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mDrawableContainerState.clearMutated();
674727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
675727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
676727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
677727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
67878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * A ConstantState that can contain several {@link Drawable}s.
67978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     *
68078aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * This class was made public to enable testing, and its visibility may change in a future
68178aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * release.
68278aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     */
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract static class DrawableContainerState extends ConstantState {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final DrawableContainer mOwner;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
686f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        Resources mSourceRes;
687f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        int mDensity = DisplayMetrics.DENSITY_DEFAULT;
688ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int mChangingConfigurations;
689ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int mChildrenChangingConfigurations;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6911259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        SparseArray<ConstantState> mDrawableFutures;
692f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Drawable[] mDrawables;
693f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mNumChildren;
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
695d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mVariablePadding = false;
696f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedPadding;
697f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Rect mConstantPadding;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mConstantSize = false;
700f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedConstantSize;
701f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantWidth;
702f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantHeight;
703f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumWidth;
704f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumHeight;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
706f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedOpacity;
707f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mOpacity;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedStateful;
710f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mStateful;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
712f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedConstantState;
713f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCanConstantState;
7145140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy
715f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mDither = DEFAULT_DITHER;
716f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
717f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mMutated;
718f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mLayoutDirection;
719f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
720d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mEnterFadeDuration = 0;
721d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mExitFadeDuration = 0;
722079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
7233f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        boolean mAutoMirrored;
7243f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
725d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette        ColorFilter mColorFilter;
726729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        boolean mHasColorFilter;
727d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette
728bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        ColorStateList mTintList;
729b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        Mode mTintMode;
730bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintList;
731bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintMode;
732b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
7330c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu        /**
7340c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu         * @hide
7350c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu         */
7360c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu        protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
737c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                Resources res) {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOwner = owner;
739ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);
740ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDensity = Drawable.resolveDensity(res, orig != null ? orig.mDensity : 0);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orig != null) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChangingConfigurations = orig.mChangingConfigurations;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
746f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCheckedConstantState = true;
747f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCanConstantState = true;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mVariablePadding = orig.mVariablePadding;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mConstantSize = orig.mConstantSize;
751a41581ed4033004c73115113f45b9844e9b0210fRomain Guy                mDither = orig.mDither;
752f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mMutated = orig.mMutated;
753f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mLayoutDirection = orig.mLayoutDirection;
754079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mEnterFadeDuration = orig.mEnterFadeDuration;
755079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitFadeDuration = orig.mExitFadeDuration;
7563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                mAutoMirrored = orig.mAutoMirrored;
757d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette                mColorFilter = orig.mColorFilter;
758729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette                mHasColorFilter = orig.mHasColorFilter;
759bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mTintList = orig.mTintList;
760b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = orig.mTintMode;
761bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintList = orig.mHasTintList;
762bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintMode = orig.mHasTintMode;
763079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
764ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                if (orig.mDensity == mDensity) {
765f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedPadding) {
766f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantPadding = new Rect(orig.mConstantPadding);
767f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedPadding = true;
768f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
769f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
770f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedConstantSize) {
771f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantWidth = orig.mConstantWidth;
772f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantHeight = orig.mConstantHeight;
773f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumWidth = orig.mConstantMinimumWidth;
774f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumHeight = orig.mConstantMinimumHeight;
775f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedConstantSize = true;
776f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
777f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
778f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
779f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedOpacity) {
780f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mOpacity = orig.mOpacity;
781f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedOpacity = true;
782f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
783f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
784f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedStateful) {
785f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mStateful = orig.mStateful;
786f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedStateful = true;
787f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
788f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
789f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // Postpone cloning children and futures until we're absolutely
790f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // sure that we're done computing values for the original state.
791f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable[] origDr = orig.mDrawables;
792f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawables = new Drawable[origDr.length];
793f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mNumChildren = orig.mNumChildren;
794f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
7951259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                final SparseArray<ConstantState> origDf = orig.mDrawableFutures;
796f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (origDf != null) {
797f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures = origDf.clone();
798f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                } else {
79906ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    mDrawableFutures = new SparseArray<>(mNumChildren);
800f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
801f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
80262b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // Create futures for drawables with constant states. If a
80362b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // drawable doesn't have a constant state, then we can't clone
80462b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // it and we'll have to reference the original.
805f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int N = mNumChildren;
806f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int i = 0; i < N; i++) {
807f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    if (origDr[i] != null) {
8081259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                        final ConstantState cs = origDr[i].getConstantState();
8091259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                        if (cs != null) {
8101259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                            mDrawableFutures.put(i, cs);
81162b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        } else {
81262b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                            mDrawables[i] = origDr[i];
81362b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        }
814f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    }
815f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDrawables = new Drawable[10];
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumChildren = 0;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
821f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
823ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int getChangingConfigurations() {
824dc25d25333d3fac96dccfb9bd31d2474d6bc2d78Fabrice Di Meglio            return mChangingConfigurations | mChildrenChangingConfigurations;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
827a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette        /**
828a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * Adds the drawable to the end of the list of contained drawables.
829a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         *
830a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * @param dr the drawable to add
831a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * @return the position of the drawable within the container
832a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         */
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final int addChild(Drawable dr) {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pos = mNumChildren;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pos >= mDrawables.length) {
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                growArray(pos, pos+10);
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette            dr.mutate();
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setVisible(false, true);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setCallback(mOwner);
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables[pos] = dr;
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNumChildren++;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
846ad7e748543f69794bbc8114da660eed705a89087Alan Viverette
847ad7e748543f69794bbc8114da660eed705a89087Alan Viverette            invalidateCache();
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantPadding = null;
850f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = false;
851f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = false;
8525291a9571580d5147331adbdefb017fa395df505Alan Viverette            mCheckedConstantState = false;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pos;
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
857ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        /**
858ad7e748543f69794bbc8114da660eed705a89087Alan Viverette         * Invalidates the cached opacity and statefulness.
859ad7e748543f69794bbc8114da660eed705a89087Alan Viverette         */
860ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        void invalidateCache() {
861ad7e748543f69794bbc8114da660eed705a89087Alan Viverette            mCheckedOpacity = false;
862ad7e748543f69794bbc8114da660eed705a89087Alan Viverette            mCheckedStateful = false;
863ad7e748543f69794bbc8114da660eed705a89087Alan Viverette        }
864ad7e748543f69794bbc8114da660eed705a89087Alan Viverette
86572146433322588c1116ee06c27ac758ad09d869cAlan Viverette        final int getCapacity() {
86672146433322588c1116ee06c27ac758ad09d869cAlan Viverette            return mDrawables.length;
86772146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
86872146433322588c1116ee06c27ac758ad09d869cAlan Viverette
8691259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        private void createAllFutures() {
870f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
871f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int futureCount = mDrawableFutures.size();
872f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
873f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    final int index = mDrawableFutures.keyAt(keyIndex);
8741259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState cs = mDrawableFutures.valueAt(keyIndex);
8751259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    mDrawables[index] = prepareDrawable(cs.newDrawable(mSourceRes));
876f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
877f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
878f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawableFutures = null;
879f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
880f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
881f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8821259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        private Drawable prepareDrawable(Drawable child) {
8831259f616c26f89dd5000745d7c364fae41b23682Alan Viverette            child.setLayoutDirection(mLayoutDirection);
8849b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette            child = child.mutate();
885b46ba3b2b0268688852cdf3d1fb4afe4873d63beAlan Viverette            child.setCallback(mOwner);
8861259f616c26f89dd5000745d7c364fae41b23682Alan Viverette            return child;
8871259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        }
8881259f616c26f89dd5000745d7c364fae41b23682Alan Viverette
88983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getChildCount() {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNumChildren;
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
89372146433322588c1116ee06c27ac758ad09d869cAlan Viverette        /*
89472146433322588c1116ee06c27ac758ad09d869cAlan Viverette         * @deprecated Use {@link #getChild} instead.
89572146433322588c1116ee06c27ac758ad09d869cAlan Viverette         */
89683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Drawable[] getChildren() {
897f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Create all futures for backwards compatibility.
898f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
899f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawables;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90372146433322588c1116ee06c27ac758ad09d869cAlan Viverette        public final Drawable getChild(int index) {
904f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable result = mDrawables[index];
905f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (result != null) {
906f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return result;
907f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
908f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
909f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Prepare future drawable if necessary.
910f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
911f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int keyIndex = mDrawableFutures.indexOfKey(index);
912f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (keyIndex >= 0) {
9131259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState cs = mDrawableFutures.valueAt(keyIndex);
9141259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final Drawable prepared = prepareDrawable(cs.newDrawable(mSourceRes));
915f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawables[index] = prepared;
916f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures.removeAt(keyIndex);
91706ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    if (mDrawableFutures.size() == 0) {
91806ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                        mDrawableFutures = null;
91906ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    }
920f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return prepared;
921f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
922f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
923f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
924f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return null;
925f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
926f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
927a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        final boolean setLayoutDirection(int layoutDirection, int currentIndex) {
928a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            boolean changed = false;
929a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
930f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
931f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // change layout direction when they are prepared.
932f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
933f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
934f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
935f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
936a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    final boolean childChanged = drawables[i].setLayoutDirection(layoutDirection);
937a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    if (i == currentIndex) {
938a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                        changed = childChanged;
939a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    }
940f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
941f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
942f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
943f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mLayoutDirection = layoutDirection;
944a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
945a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            return changed;
94672146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
94772146433322588c1116ee06c27ac758ad09d869cAlan Viverette
948f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        /**
949f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * Updates the source density based on the resources used to inflate
950f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * density-dependent values.
951f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         *
952f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * @param res the resources used to inflate density-dependent values
953f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         */
954f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        final void updateDensity(Resources res) {
9552d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette            if (res != null) {
956f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                mSourceRes = res;
957f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
9582d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                // The density may have changed since the last update (if any). Any
9592d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                // dimension-type attributes will need their default values scaled.
9602d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                final int targetDensity = Drawable.resolveDensity(res, mDensity);
9612d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                final int sourceDensity = mDensity;
9622d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                mDensity = targetDensity;
963f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
9642d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                if (sourceDensity != targetDensity) {
9652d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                    mCheckedConstantSize = false;
9662d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                    mCheckedPadding = false;
9672d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                }
968f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            }
969f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        }
970f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
97152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final void applyTheme(Theme theme) {
97217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            if (theme != null) {
97317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                createAllFutures();
97417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
97517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final int N = mNumChildren;
97617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final Drawable[] drawables = mDrawables;
97717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                for (int i = 0; i < N; i++) {
97817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    if (drawables[i] != null && drawables[i].canApplyTheme()) {
97917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        drawables[i].applyTheme(theme);
980e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
981e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        // Update cached mask of child changing configurations.
982e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        mChildrenChangingConfigurations |= drawables[i].getChangingConfigurations();
98317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    }
98452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
985f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
986f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                updateDensity(theme.getResources());
98752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
98852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
98952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
99052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
99152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
99252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final int N = mNumChildren;
99352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final Drawable[] drawables = mDrawables;
99452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            for (int i = 0; i < N; i++) {
995b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                final Drawable d = drawables[i];
99652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (d != null) {
99752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (d.canApplyTheme()) {
99852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
99952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
100052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                } else {
10011259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState future = mDrawableFutures.get(i);
100252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (future != null && future.canApplyTheme()) {
100352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
100452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
100552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
100652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
100752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
100852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            return false;
100952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
101052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
10118dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        private void mutate() {
1012f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
1013f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // mutate when they are prepared.
1014f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
101572146433322588c1116ee06c27ac758ad09d869cAlan Viverette            final Drawable[] drawables = mDrawables;
101672146433322588c1116ee06c27ac758ad09d869cAlan Viverette            for (int i = 0; i < N; i++) {
1017f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
1018f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    drawables[i].mutate();
1019f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
102072146433322588c1116ee06c27ac758ad09d869cAlan Viverette            }
1021f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1022f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mMutated = true;
102372146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
102472146433322588c1116ee06c27ac758ad09d869cAlan Viverette
1025727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        final void clearMutated() {
1026727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final int N = mNumChildren;
1027727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final Drawable[] drawables = mDrawables;
1028727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            for (int i = 0; i < N; i++) {
1029727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                if (drawables[i] != null) {
1030727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                    drawables[i].clearMutated();
1031727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                }
1032727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            }
1033727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
1034727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            mMutated = false;
1035727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        }
1036727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
1037f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        /**
1038f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * A boolean value indicating whether to use the maximum padding value
1039f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * of all frames in the set (false), or to use the padding value of the
1040f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * frame being shown (true). Default value is false.
1041f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         */
104283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setVariablePadding(boolean variable) {
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVariablePadding = variable;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Rect getConstantPadding() {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mVariablePadding) {
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1050f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1051f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if ((mConstantPadding != null) || mCheckedPadding) {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mConstantPadding;
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1055f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1056f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
10575140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            Rect r = null;
105883b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Rect t = new Rect();
1059f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
106083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
106183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
106283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                if (drawables[i].getPadding(t)) {
10635140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy                    if (r == null) r = new Rect(0, 0, 0, 0);
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.left > r.left) r.left = t.left;
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.top > r.top) r.top = t.top;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.right > r.right) r.right = t.right;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.bottom > r.bottom) r.bottom = t.bottom;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1070f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1071f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = true;
10725140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            return (mConstantPadding = r);
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107583b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setConstantSize(boolean constant) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantSize = constant;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final boolean isConstantSize() {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantSize;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
108383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantWidth() {
1084f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantWidth;
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantHeight() {
1092f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantHeight;
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumWidth() {
1100f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumWidth;
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
110783b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumHeight() {
1108f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumHeight;
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
111578aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne        protected void computeConstantSize() {
1116f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = true;
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1118f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1119f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1120f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
112183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
112278aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne            mConstantWidth = mConstantHeight = -1;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantMinimumWidth = mConstantMinimumHeight = 0;
112483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
1125f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable dr = drawables[i];
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int s = dr.getIntrinsicWidth();
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantWidth) mConstantWidth = s;
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getIntrinsicHeight();
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantHeight) mConstantHeight = s;
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumWidth();
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumWidth) mConstantMinimumWidth = s;
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumHeight();
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumHeight) mConstantMinimumHeight = s;
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1137079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setEnterFadeDuration(int duration) {
1138079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterFadeDuration = duration;
1139079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1140079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1141079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getEnterFadeDuration() {
1142079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mEnterFadeDuration;
1143079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1144079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1145079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setExitFadeDuration(int duration) {
1146079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitFadeDuration = duration;
1147079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1148079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1149079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getExitFadeDuration() {
1150079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mExitFadeDuration;
1151079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1152079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
115383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getOpacity() {
1154f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedOpacity) {
1155f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mOpacity;
1156f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1157f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1158f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1159f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1160f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
116183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
1162f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            int op = (N > 0) ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
116383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 1; i < N; i++) {
116483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1166f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOpacity = op;
1168eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mCheckedOpacity = true;
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return op;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
117183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final boolean isStateful() {
1173f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedStateful) {
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mStateful;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1176f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1177f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1178f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1179f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1180f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
1181eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            boolean isStateful = false;
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
1183f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].isStateful()) {
1184eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette                    isStateful = true;
1185eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette                    break;
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1188f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1189eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mStateful = isStateful;
1190eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mCheckedStateful = true;
1191eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            return isStateful;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
119483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public void growArray(int oldSize, int newSize) {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Drawable[] newDrawables = new Drawable[newSize];
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.arraycopy(mDrawables, 0, newDrawables, 0, oldSize);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables = newDrawables;
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized boolean canConstantState() {
1201f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedConstantState) {
1202f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mCanConstantState;
1203f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1204f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1205f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1206f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1207f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedConstantState = true;
1208f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1209f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1210f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
1211f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
1212f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].getConstantState() == null) {
1213f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mCanConstantState = false;
1214f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return false;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1218f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCanConstantState = true;
1219f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return true;
1220f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
1221f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1224f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette    protected void setConstantState(DrawableContainerState state) {
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDrawableContainerState = state;
1226ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette
1227ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        // The locally cached drawables may have changed.
1228ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        if (mCurIndex >= 0) {
1229ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mCurrDrawable = state.getChild(mCurIndex);
1230419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            if (mCurrDrawable != null) {
1231419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(mCurrDrawable);
1232419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
1233ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        }
1234419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
1235419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // Clear out the last drawable. We don't have enough information to
1236419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // propagate local state from the past.
1237419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastIndex = -1;
1238419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastDrawable = null;
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12406d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12416d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    /**
12426d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette     * Callback that blocks drawable invalidation.
12436d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette     */
12446d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    private static class BlockInvalidateCallback implements Drawable.Callback {
12456d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        private Drawable.Callback mCallback;
12466d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12476d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public BlockInvalidateCallback wrap(Drawable.Callback callback) {
12486d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mCallback = callback;
12496d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            return this;
12506d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12516d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12526d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public Drawable.Callback unwrap() {
12536d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            final Drawable.Callback callback = mCallback;
12546d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mCallback = null;
12556d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            return callback;
12566d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12576d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12586d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12596d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void invalidateDrawable(@NonNull Drawable who) {
12606d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            // Ignore invalidation.
12616d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12626d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12636d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12646d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
12656d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            if (mCallback != null) {
12666d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette                mCallback.scheduleDrawable(who, what, when);
12676d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            }
12686d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12696d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12706d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12716d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
12726d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            if (mCallback != null) {
12736d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette                mCallback.unscheduleDrawable(who, what);
12746d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            }
12756d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12766d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    }
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1278