DrawableContainer.java revision f380072eeffdb5f993e5bd1c31571afe11d1a82e
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.
213079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
214079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
215079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setEnterFadeDuration(int ms) {
216079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mEnterFadeDuration = ms;
217079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
218f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
219079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    /**
220079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * Change the global fade duration when a new drawable is leaving
221079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * the scene.
222079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     * @param ms The amount of time to fade in milliseconds.
223079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn     */
224079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void setExitFadeDuration(int ms) {
225079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        mDrawableContainerState.mExitFadeDuration = ms;
226079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
227f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect bounds) {
230079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
231079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setBounds(bounds);
232079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setBounds(bounds);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
237f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isStateful() {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDrawableContainerState.isStateful();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
242f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
243f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    /** @hide */
244f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    @Override
245f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    public boolean hasFocusStateSpecified() {
246f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        if (mCurrDrawable != null) {
247f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He            return mCurrDrawable.hasFocusStateSpecified();
248f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        }
249f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        if (mLastDrawable != null) {
250f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He            return mLastDrawable.hasFocusStateSpecified();
251f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        }
252f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He        return false;
253f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He    }
254f380072eeffdb5f993e5bd1c31571afe11d1a82eJiaquan He
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public void setAutoMirrored(boolean mirrored) {
257729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        if (mDrawableContainerState.mAutoMirrored != mirrored) {
258729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            mDrawableContainerState.mAutoMirrored = mirrored;
259729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mCurrDrawable != null) {
2609b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
261729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
2623f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
2633f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2643f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2653f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
2663f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public boolean isAutoMirrored() {
2673f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return mDrawableContainerState.mAutoMirrored;
2683f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
2693f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
2703f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
271079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    public void jumpToCurrentState() {
272079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean changed = false;
273079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
274079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.jumpToCurrentState();
275079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable = null;
276ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mLastIndex = -1;
277079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
278079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
279079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
280079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.jumpToCurrentState();
281729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            if (mHasAlpha) {
2829b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                mCurrDrawable.setAlpha(mAlpha);
283729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette            }
284079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
285079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mExitAnimationEnd != 0) {
286079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
287079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
288079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
289079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0) {
290079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
291079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            changed = true;
292079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
293079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (changed) {
294079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            invalidateSelf();
295079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
296079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
297079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
298079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    @Override
299c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette    public void setHotspot(float x, float y) {
300307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        if (mCurrDrawable != null) {
301c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette            mCurrDrawable.setHotspot(x, y);
302307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette        }
303307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    }
304307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette
305307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette    @Override
30653a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    public void setHotspotBounds(int left, int top, int right, int bottom) {
3077068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds == null) {
30827cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds = new Rect(left, top, right, bottom);
3097068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
31027cf86939d918b2d6b32a0650a48b8a2afaa26b6Alexander Martinz            mHotspotBounds.set(left, top, right, bottom);
3117068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
3127068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
31353a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        if (mCurrDrawable != null) {
31453a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette            mCurrDrawable.setHotspotBounds(left, top, right, bottom);
31553a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette        }
31653a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    }
31753a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette
3187068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    @Override
3197068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    public void getHotspotBounds(Rect outRect) {
3207068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        if (mHotspotBounds != null) {
3217068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            outRect.set(mHotspotBounds);
3227068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        } else {
3237068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette            super.getHotspotBounds(outRect);
3247068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette        }
3257068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette    }
3267068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette
32753a3ed7c46c12c2e578d1b1df8b039c6db690eaaAlan Viverette    @Override
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean onStateChange(int[] state) {
329079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
330079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setState(state);
331079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setState(state);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3390b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
340079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
341079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mLastDrawable.setLevel(level);
342079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mCurrDrawable.setLevel(level);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
350dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viverette    public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
351a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // Let the container handle setting its own layout direction. Otherwise,
352a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        // we're accessing potentially unused states.
353a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        return mDrawableContainerState.setLayoutDirection(layoutDirection, getCurrentIndex());
354a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    }
355a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
356a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    @Override
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantWidth();
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicWidth() : -1;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantHeight();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getIntrinsicHeight() : -1;
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
371f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumWidth() {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumWidth();
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumWidth() : 0;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumHeight() {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.isConstantSize()) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState.getConstantMinimumHeight();
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable != null ? mCurrDrawable.getMinimumHeight() : 0;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38872146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
389f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void invalidateDrawable(@NonNull Drawable who) {
390f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
391f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().invalidateDrawable(this);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39572146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
396f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
397f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
398f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().scheduleDrawable(this, what, when);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
40272146433322588c1116ee06c27ac758ad09d869cAlan Viverette    @Override
403f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
404f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy        if (who == mCurrDrawable && getCallback() != null) {
405f2a47782f31b58d2d31bd00b50fe43604af8b9c2Romain Guy            getCallback().unscheduleDrawable(this, what);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setVisible(boolean visible, boolean restart) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changed = super.setVisible(visible, restart);
412079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
413079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mLastDrawable.setVisible(visible, restart);
414079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrDrawable != null) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable.setVisible(visible, restart);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return changed;
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
42383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        return mCurrDrawable == null || !mCurrDrawable.isVisible() ? PixelFormat.TRANSPARENT :
42483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                mDrawableContainerState.getOpacity();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4275e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4285e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public void setCurrentIndex(int index) {
4295e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        selectDrawable(index);
4305e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4315e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
4325e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    /** @hide */
4335e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    public int getCurrentIndex() {
4345e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette        return mCurIndex;
4355e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette    }
4365e92c95d847a68178cf6099c801f82dcb7e4fa47Alan Viverette
437a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    /**
438a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * Sets the currently displayed drawable by index.
439a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * <p>
440a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * If an invalid index is specified, the current drawable will be set to
441a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * {@code null} and the index will be set to {@code -1}.
442a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     *
443a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @param index the index of the drawable to display
444a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     * @return {@code true} if the drawable changed, {@code false} otherwise
445a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette     */
446a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette    public boolean selectDrawable(int index) {
447a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index == mCurIndex) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
450079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
451079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
452079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
453a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (DEBUG) android.util.Log.i(TAG, toString() + " from " + mCurIndex + " to " + index
454079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + ": exit=" + mDrawableContainerState.mExitFadeDuration
455079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                + " enter=" + mDrawableContainerState.mEnterFadeDuration);
456079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
457079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mDrawableContainerState.mExitFadeDuration > 0) {
458079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mLastDrawable != null) {
459079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable.setVisible(false, false);
460079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurrDrawable != null) {
462079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = mCurrDrawable;
463ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = mCurIndex;
464079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = now + mDrawableContainerState.mExitFadeDuration;
465079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
466079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mLastDrawable = null;
467ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                mLastIndex = -1;
468079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitAnimationEnd = 0;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
470079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else if (mCurrDrawable != null) {
471079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mCurrDrawable.setVisible(false, false);
472079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
473079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
474a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette        if (index >= 0 && index < mDrawableContainerState.mNumChildren) {
475a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            final Drawable d = mDrawableContainerState.getChild(index);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = d;
477a02d2748be353393b7b593d5adbd37d80dee427dAlan Viverette            mCurIndex = index;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (d != null) {
479079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mDrawableContainerState.mEnterFadeDuration > 0) {
480079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
4817068c39526459c18a020e29c1ebfa6aed54e2d0fAlan Viverette                }
482419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(d);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrDrawable = null;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIndex = -1;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
488079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
489079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mEnterAnimationEnd != 0 || mExitAnimationEnd != 0) {
490079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mAnimationRunnable == null) {
491079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mAnimationRunnable = new Runnable() {
492079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    @Override public void run() {
493079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        animate(true);
494079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                        invalidateSelf();
495079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    }
496079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                };
497079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            } else {
498079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                unscheduleSelf(mAnimationRunnable);
499079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
500079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            // Compute first frame and schedule next animation.
501079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            animate(true);
502079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
503079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
505079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
508f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
509419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    /**
510419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * Initializes a drawable for display in this container.
511419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     *
512419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     * @param d The drawable to initialize.
513419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette     */
514419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    private void initializeDrawableForDisplay(Drawable d) {
5156d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        if (mBlockInvalidateCallback == null) {
5166d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mBlockInvalidateCallback = new BlockInvalidateCallback();
5176d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
5186d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
5192b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // Temporary fix for suspending callbacks during initialization. We
5202b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // don't want any of these setters causing an invalidate() since that
5212b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        // may call back into DrawableContainer.
5226d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        d.setCallback(mBlockInvalidateCallback.wrap(d.getCallback()));
5232b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette
5242b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        try {
5252b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
5262b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setAlpha(mAlpha);
527419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
528419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
5292b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (mDrawableContainerState.mHasColorFilter) {
5302b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                // Color filter always overrides tint.
5312b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setColorFilter(mDrawableContainerState.mColorFilter);
5322b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            } else {
5332b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                if (mDrawableContainerState.mHasTintList) {
5342b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                    d.setTintList(mDrawableContainerState.mTintList);
5352b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                }
5362b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                if (mDrawableContainerState.mHasTintMode) {
5372b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                    d.setTintMode(mDrawableContainerState.mTintMode);
5382b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                }
5392b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            }
540419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
5412b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setVisible(isVisible(), true);
5422b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setDither(mDrawableContainerState.mDither);
5432b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setState(getState());
5442b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setLevel(getLevel());
5452b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setBounds(getBounds());
5462b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setLayoutDirection(getLayoutDirection());
5472b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
5482b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette
5492b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            final Rect hotspotBounds = mHotspotBounds;
5502b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            if (hotspotBounds != null) {
5512b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
5522b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette                        hotspotBounds.right, hotspotBounds.bottom);
5532b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette            }
5542b561f1c352df95df23e17e7fce2acc3144df159Alan Viverette        } finally {
5556d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            d.setCallback(mBlockInvalidateCallback.unwrap());
556419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        }
557419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette    }
558419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
559079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    void animate(boolean schedule) {
560729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        mHasAlpha = true;
561729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette
562079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        final long now = SystemClock.uptimeMillis();
563079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        boolean animating = false;
564079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mCurrDrawable != null) {
565079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mEnterAnimationEnd != 0) {
566079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mEnterAnimationEnd <= now) {
5679b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mCurrDrawable.setAlpha(mAlpha);
568079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mEnterAnimationEnd = 0;
569079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
570079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mEnterAnimationEnd-now)*255)
571079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mEnterFadeDuration;
5729b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
573079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
574079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
575079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
576079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
577079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterAnimationEnd = 0;
578079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
579079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (mLastDrawable != null) {
580079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            if (mExitAnimationEnd != 0) {
581079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (mExitAnimationEnd <= now) {
582079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable.setVisible(false, false);
583079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mLastDrawable = null;
584ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette                    mLastIndex = -1;
585079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    mExitAnimationEnd = 0;
586079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                } else {
587079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    int animAlpha = (int)((mExitAnimationEnd-now)*255)
588079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                            / mDrawableContainerState.mExitFadeDuration;
5899b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette                    mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
590079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    animating = true;
591079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                }
592079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            }
593079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        } else {
594079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitAnimationEnd = 0;
595079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
596079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
597079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (schedule && animating) {
5988dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette            scheduleSelf(mAnimationRunnable, now + 1000 / 60);
599079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
600079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn    }
601079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getCurrent() {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCurrDrawable;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
607f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    /**
608f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * Updates the source density based on the resources used to inflate
609f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * density-dependent values. Implementing classes should call this method
610f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * during inflation.
611f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     *
612f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     * @param res the resources used to inflate density-dependent values
6130c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu     * @hide
614f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette     */
6150c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu    protected final void updateDensity(Resources res) {
616f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        mDrawableContainerState.updateDensity(res);
617f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette    }
618f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
62052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void applyTheme(Theme theme) {
62152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        mDrawableContainerState.applyTheme(theme);
62252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
62352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
62452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
62552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
62652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        return mDrawableContainerState.canApplyTheme();
62752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
62852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
62952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDrawableContainerState.canConstantState()) {
6326efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais            mDrawableContainerState.mChangingConfigurations = getChangingConfigurations();
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawableContainerState;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
6415ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            final DrawableContainerState clone = cloneConstantState();
6425ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            clone.mutate();
6435ed8f27858dbdf85203068eca46eef0a65f3344eAlan Viverette            setConstantState(clone);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne    /**
6508dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * Returns a shallow copy of the container's constant state to be used as
6518dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * the base state for {@link #mutate()}.
6528dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     *
6538dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     * @return a shallow copy of the constant state
6548dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette     */
6558dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    DrawableContainerState cloneConstantState() {
6568dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        return mDrawableContainerState;
6578dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    }
6588dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette
6598dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette    /**
660727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
661727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
662727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
663727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
664727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mDrawableContainerState.clearMutated();
665727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
666727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
667727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
668727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
66978aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * A ConstantState that can contain several {@link Drawable}s.
67078aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     *
67178aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * This class was made public to enable testing, and its visibility may change in a future
67278aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     * release.
67378aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne     */
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract static class DrawableContainerState extends ConstantState {
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final DrawableContainer mOwner;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
677f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        Resources mSourceRes;
678f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        int mDensity = DisplayMetrics.DENSITY_DEFAULT;
679ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int mChangingConfigurations;
680ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int mChildrenChangingConfigurations;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6821259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        SparseArray<ConstantState> mDrawableFutures;
683f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Drawable[] mDrawables;
684f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mNumChildren;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
686d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mVariablePadding = false;
687f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedPadding;
688f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        Rect mConstantPadding;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
690d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        boolean mConstantSize = false;
691f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        boolean mCheckedConstantSize;
692f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantWidth;
693f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantHeight;
694f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumWidth;
695f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mConstantMinimumHeight;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
697f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedOpacity;
698f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mOpacity;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
700f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedStateful;
701f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mStateful;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
703f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCheckedConstantState;
704f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mCanConstantState;
7055140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy
706f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mDither = DEFAULT_DITHER;
707f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
708f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        boolean mMutated;
709f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        int mLayoutDirection;
710f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
711d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mEnterFadeDuration = 0;
712d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        int mExitFadeDuration = 0;
713079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
7143f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        boolean mAutoMirrored;
7153f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
716d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette        ColorFilter mColorFilter;
717729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette        boolean mHasColorFilter;
718d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette
719bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        ColorStateList mTintList;
720b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        Mode mTintMode;
721bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintList;
722bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette        boolean mHasTintMode;
723b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
7240c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu        /**
7250c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu         * @hide
7260c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu         */
7270c03664fa6acbe5c3fd11d54ab9a6792f43dda07Teng-Hui Zhu        protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
728c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                Resources res) {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOwner = owner;
730ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);
731ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDensity = Drawable.resolveDensity(res, orig != null ? orig.mDensity : 0);
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (orig != null) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChangingConfigurations = orig.mChangingConfigurations;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
737f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCheckedConstantState = true;
738f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mCanConstantState = true;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mVariablePadding = orig.mVariablePadding;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mConstantSize = orig.mConstantSize;
742a41581ed4033004c73115113f45b9844e9b0210fRomain Guy                mDither = orig.mDither;
743f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mMutated = orig.mMutated;
744f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mLayoutDirection = orig.mLayoutDirection;
745079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mEnterFadeDuration = orig.mEnterFadeDuration;
746079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mExitFadeDuration = orig.mExitFadeDuration;
7473f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                mAutoMirrored = orig.mAutoMirrored;
748d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette                mColorFilter = orig.mColorFilter;
749729427d451bc4d4d268335b8dc1ff6404bc1c91eAlan Viverette                mHasColorFilter = orig.mHasColorFilter;
750bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mTintList = orig.mTintList;
751b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = orig.mTintMode;
752bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintList = orig.mHasTintList;
753bddb843e793a279db99888dd78b4f74a362cbb8bAlan Viverette                mHasTintMode = orig.mHasTintMode;
754079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
755ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                if (orig.mDensity == mDensity) {
756f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedPadding) {
757f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantPadding = new Rect(orig.mConstantPadding);
758f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedPadding = true;
759f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
760f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
761f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    if (orig.mCheckedConstantSize) {
762f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantWidth = orig.mConstantWidth;
763f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantHeight = orig.mConstantHeight;
764f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumWidth = orig.mConstantMinimumWidth;
765f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mConstantMinimumHeight = orig.mConstantMinimumHeight;
766f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                        mCheckedConstantSize = true;
767f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    }
768f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
769f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
770f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedOpacity) {
771f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mOpacity = orig.mOpacity;
772f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedOpacity = true;
773f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
774f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
775f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                if (orig.mCheckedStateful) {
776f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mStateful = orig.mStateful;
777f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                    mCheckedStateful = true;
778f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                }
779f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
780f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // Postpone cloning children and futures until we're absolutely
781f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                // sure that we're done computing values for the original state.
782f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable[] origDr = orig.mDrawables;
783f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawables = new Drawable[origDr.length];
784f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mNumChildren = orig.mNumChildren;
785f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
7861259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                final SparseArray<ConstantState> origDf = orig.mDrawableFutures;
787f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (origDf != null) {
788f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures = origDf.clone();
789f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                } else {
79006ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    mDrawableFutures = new SparseArray<>(mNumChildren);
791f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
792f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
79362b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // Create futures for drawables with constant states. If a
79462b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // drawable doesn't have a constant state, then we can't clone
79562b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                // it and we'll have to reference the original.
796f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int N = mNumChildren;
797f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int i = 0; i < N; i++) {
798f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    if (origDr[i] != null) {
7991259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                        final ConstantState cs = origDr[i].getConstantState();
8001259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                        if (cs != null) {
8011259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                            mDrawableFutures.put(i, cs);
80262b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        } else {
80362b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                            mDrawables[i] = origDr[i];
80462b780e85ff2fcefd4324c3bfbf49b14963cf58bAlan Viverette                        }
805f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    }
806f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDrawables = new Drawable[10];
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumChildren = 0;
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
812f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
814ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int getChangingConfigurations() {
815dc25d25333d3fac96dccfb9bd31d2474d6bc2d78Fabrice Di Meglio            return mChangingConfigurations | mChildrenChangingConfigurations;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
818a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette        /**
819a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * Adds the drawable to the end of the list of contained drawables.
820a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         *
821a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * @param dr the drawable to add
822a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         * @return the position of the drawable within the container
823a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette         */
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final int addChild(Drawable dr) {
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int pos = mNumChildren;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pos >= mDrawables.length) {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                growArray(pos, pos+10);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
830a24c9b4791dddc2dbc233dfe8dac1ae682beb272Alan Viverette            dr.mutate();
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setVisible(false, true);
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dr.setCallback(mOwner);
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables[pos] = dr;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNumChildren++;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
837f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedStateful = false;
838f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedOpacity = false;
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantPadding = null;
841f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = false;
842f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = false;
8435291a9571580d5147331adbdefb017fa395df505Alan Viverette            mCheckedConstantState = false;
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return pos;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84872146433322588c1116ee06c27ac758ad09d869cAlan Viverette        final int getCapacity() {
84972146433322588c1116ee06c27ac758ad09d869cAlan Viverette            return mDrawables.length;
85072146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
85172146433322588c1116ee06c27ac758ad09d869cAlan Viverette
8521259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        private void createAllFutures() {
853f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
854f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int futureCount = mDrawableFutures.size();
855f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
856f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    final int index = mDrawableFutures.keyAt(keyIndex);
8571259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState cs = mDrawableFutures.valueAt(keyIndex);
8581259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    mDrawables[index] = prepareDrawable(cs.newDrawable(mSourceRes));
859f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
860f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
861f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                mDrawableFutures = null;
862f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
863f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
864f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8651259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        private Drawable prepareDrawable(Drawable child) {
8661259f616c26f89dd5000745d7c364fae41b23682Alan Viverette            child.setLayoutDirection(mLayoutDirection);
8679b4bdeff6dea5a24a3085a17d2dde9003642af79Alan Viverette            child = child.mutate();
868b46ba3b2b0268688852cdf3d1fb4afe4873d63beAlan Viverette            child.setCallback(mOwner);
8691259f616c26f89dd5000745d7c364fae41b23682Alan Viverette            return child;
8701259f616c26f89dd5000745d7c364fae41b23682Alan Viverette        }
8711259f616c26f89dd5000745d7c364fae41b23682Alan Viverette
87283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getChildCount() {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNumChildren;
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87672146433322588c1116ee06c27ac758ad09d869cAlan Viverette        /*
87772146433322588c1116ee06c27ac758ad09d869cAlan Viverette         * @deprecated Use {@link #getChild} instead.
87872146433322588c1116ee06c27ac758ad09d869cAlan Viverette         */
87983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Drawable[] getChildren() {
880f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Create all futures for backwards compatibility.
881f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
882f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mDrawables;
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
88672146433322588c1116ee06c27ac758ad09d869cAlan Viverette        public final Drawable getChild(int index) {
887f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable result = mDrawables[index];
888f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (result != null) {
889f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return result;
890f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
891f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
892f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // Prepare future drawable if necessary.
893f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mDrawableFutures != null) {
894f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final int keyIndex = mDrawableFutures.indexOfKey(index);
895f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (keyIndex >= 0) {
8961259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState cs = mDrawableFutures.valueAt(keyIndex);
8971259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final Drawable prepared = prepareDrawable(cs.newDrawable(mSourceRes));
898f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawables[index] = prepared;
899f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mDrawableFutures.removeAt(keyIndex);
90006ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    if (mDrawableFutures.size() == 0) {
90106ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                        mDrawableFutures = null;
90206ff2af68aa1041eeb26778e994e0fe196bf8b1eAlan Viverette                    }
903f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return prepared;
904f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
905f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
906f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
907f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return null;
908f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
909f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
910a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        final boolean setLayoutDirection(int layoutDirection, int currentIndex) {
911a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            boolean changed = false;
912a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
913f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
914f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // change layout direction when they are prepared.
915f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
916f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
917f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
918f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
919a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    final boolean childChanged = drawables[i].setLayoutDirection(layoutDirection);
920a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    if (i == currentIndex) {
921a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                        changed = childChanged;
922a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette                    }
923f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
924f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
925f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
926f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mLayoutDirection = layoutDirection;
927a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
928a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette            return changed;
92972146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
93072146433322588c1116ee06c27ac758ad09d869cAlan Viverette
931f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        /**
932f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * Updates the source density based on the resources used to inflate
933f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * density-dependent values.
934f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         *
935f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         * @param res the resources used to inflate density-dependent values
936f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette         */
937f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        final void updateDensity(Resources res) {
9382d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette            if (res != null) {
939f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                mSourceRes = res;
940f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
9412d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                // The density may have changed since the last update (if any). Any
9422d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                // dimension-type attributes will need their default values scaled.
9432d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                final int targetDensity = Drawable.resolveDensity(res, mDensity);
9442d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                final int sourceDensity = mDensity;
9452d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                mDensity = targetDensity;
946f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
9472d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                if (sourceDensity != targetDensity) {
9482d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                    mCheckedConstantSize = false;
9492d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                    mCheckedPadding = false;
9502d3ca47ef83c097e3a1aaa66f2d119be0e93e677Alan Viverette                }
951f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            }
952f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette        }
953f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
95452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final void applyTheme(Theme theme) {
95517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            if (theme != null) {
95617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                createAllFutures();
95717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
95817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final int N = mNumChildren;
95917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                final Drawable[] drawables = mDrawables;
96017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                for (int i = 0; i < N; i++) {
96117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    if (drawables[i] != null && drawables[i].canApplyTheme()) {
96217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        drawables[i].applyTheme(theme);
963e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette
964e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        // Update cached mask of child changing configurations.
965e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        mChildrenChangingConfigurations |= drawables[i].getChangingConfigurations();
96617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    }
96752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
968f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette
969f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette                updateDensity(theme.getResources());
97052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
97152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
97252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
97352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
97452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
97552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final int N = mNumChildren;
97652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final Drawable[] drawables = mDrawables;
97752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            for (int i = 0; i < N; i++) {
978b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                final Drawable d = drawables[i];
97952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (d != null) {
98052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (d.canApplyTheme()) {
98152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
98252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
98352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                } else {
9841259f616c26f89dd5000745d7c364fae41b23682Alan Viverette                    final ConstantState future = mDrawableFutures.get(i);
98552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (future != null && future.canApplyTheme()) {
98652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        return true;
98752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
98852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
98952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
99052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
99152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            return false;
99252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
99352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
9948dcd533786df8d824f1e040230ee9e7e5b083998Alan Viverette        private void mutate() {
995f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // No need to call createAllFutures, since future drawables will
996f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            // mutate when they are prepared.
997f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
99872146433322588c1116ee06c27ac758ad09d869cAlan Viverette            final Drawable[] drawables = mDrawables;
99972146433322588c1116ee06c27ac758ad09d869cAlan Viverette            for (int i = 0; i < N; i++) {
1000f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i] != null) {
1001f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    drawables[i].mutate();
1002f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                }
100372146433322588c1116ee06c27ac758ad09d869cAlan Viverette            }
1004f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1005f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mMutated = true;
100672146433322588c1116ee06c27ac758ad09d869cAlan Viverette        }
100772146433322588c1116ee06c27ac758ad09d869cAlan Viverette
1008727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        final void clearMutated() {
1009727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final int N = mNumChildren;
1010727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            final Drawable[] drawables = mDrawables;
1011727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            for (int i = 0; i < N; i++) {
1012727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                if (drawables[i] != null) {
1013727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                    drawables[i].clearMutated();
1014727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette                }
1015727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            }
1016727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
1017727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette            mMutated = false;
1018727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        }
1019727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
1020f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        /**
1021f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * A boolean value indicating whether to use the maximum padding value
1022f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * of all frames in the set (false), or to use the padding value of the
1023f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         * frame being shown (true). Default value is false.
1024f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette         */
102583b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setVariablePadding(boolean variable) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVariablePadding = variable;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102983b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final Rect getConstantPadding() {
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mVariablePadding) {
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1033f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1034f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if ((mConstantPadding != null) || mCheckedPadding) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mConstantPadding;
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1038f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1039f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
10405140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            Rect r = null;
104183b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Rect t = new Rect();
1042f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
104383b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
104483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
104583b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                if (drawables[i].getPadding(t)) {
10465140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy                    if (r == null) r = new Rect(0, 0, 0, 0);
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.left > r.left) r.left = t.left;
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.top > r.top) r.top = t.top;
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.right > r.right) r.right = t.right;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (t.bottom > r.bottom) r.bottom = t.bottom;
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1053f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1054f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedPadding = true;
10555140141c2637b89ad0d86c3b715459a1e7b92729Romain Guy            return (mConstantPadding = r);
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105883b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final void setConstantSize(boolean constant) {
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantSize = constant;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final boolean isConstantSize() {
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantSize;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantWidth() {
1067f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantWidth;
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantHeight() {
1075f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantHeight;
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
108283b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumWidth() {
1083f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumWidth;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109083b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getConstantMinimumHeight() {
1091f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            if (!mCheckedConstantSize) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                computeConstantSize();
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mConstantMinimumHeight;
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109878aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne        protected void computeConstantSize() {
1099f1f5f6fcaa768c5b88e9a56f18cbd6ecf72755a8Alan Viverette            mCheckedConstantSize = true;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1101f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1102f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1103f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
110483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
110578aaa97b77d56e35e994611406deb398eb9005dbGilles Debunne            mConstantWidth = mConstantHeight = -1;
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mConstantMinimumWidth = mConstantMinimumHeight = 0;
110783b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 0; i < N; i++) {
1108f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                final Drawable dr = drawables[i];
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int s = dr.getIntrinsicWidth();
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantWidth) mConstantWidth = s;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getIntrinsicHeight();
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantHeight) mConstantHeight = s;
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumWidth();
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumWidth) mConstantMinimumWidth = s;
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                s = dr.getMinimumHeight();
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (s > mConstantMinimumHeight) mConstantMinimumHeight = s;
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1120079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setEnterFadeDuration(int duration) {
1121079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mEnterFadeDuration = duration;
1122079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1123079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1124079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getEnterFadeDuration() {
1125079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mEnterFadeDuration;
1126079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1127079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1128079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final void setExitFadeDuration(int duration) {
1129079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            mExitFadeDuration = duration;
1130079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1131079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1132079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        public final int getExitFadeDuration() {
1133079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            return mExitFadeDuration;
1134079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
1135079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
113683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public final int getOpacity() {
1137f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedOpacity) {
1138f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mOpacity;
1139f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1140f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1141f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1142f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1143f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
114483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            final Drawable[] drawables = mDrawables;
1145f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            int op = (N > 0) ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
114683b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy            for (int i = 1; i < N; i++) {
114783b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy                op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1149f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOpacity = op;
1151eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mCheckedOpacity = true;
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return op;
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
115483b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final boolean isStateful() {
1156f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedStateful) {
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mStateful;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1159f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1160f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1161f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1162f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1163f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
1164eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            boolean isStateful = false;
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
1166f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].isStateful()) {
1167eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette                    isStateful = true;
1168eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette                    break;
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1171f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1172eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mStateful = isStateful;
1173eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            mCheckedStateful = true;
1174eb7277590a2c2bdd64534da4c822a69440df32dfAlan Viverette            return isStateful;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117783b2107c4d2f07f46b6ae663115421749486f8b1Romain Guy        public void growArray(int oldSize, int newSize) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Drawable[] newDrawables = new Drawable[newSize];
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.arraycopy(mDrawables, 0, newDrawables, 0, oldSize);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDrawables = newDrawables;
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized boolean canConstantState() {
1184f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            if (mCheckedConstantState) {
1185f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                return mCanConstantState;
1186f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            }
1187f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1188f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            createAllFutures();
1189f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1190f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCheckedConstantState = true;
1191f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
1192f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final int N = mNumChildren;
1193f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            final Drawable[] drawables = mDrawables;
1194f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            for (int i = 0; i < N; i++) {
1195f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                if (drawables[i].getConstantState() == null) {
1196f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    mCanConstantState = false;
1197f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette                    return false;
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1201f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            mCanConstantState = true;
1202f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette            return true;
1203f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette        }
1204f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1207f390f770ee570f1f4def41b165cb9492e381be40Alan Viverette    protected void setConstantState(DrawableContainerState state) {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDrawableContainerState = state;
1209ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette
1210ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        // The locally cached drawables may have changed.
1211ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        if (mCurIndex >= 0) {
1212ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette            mCurrDrawable = state.getChild(mCurIndex);
1213419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            if (mCurrDrawable != null) {
1214419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette                initializeDrawableForDisplay(mCurrDrawable);
1215419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette            }
1216ebc9f2e773c3ebb4d4af3025fc6770844cc8fdefAlan Viverette        }
1217419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette
1218419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // Clear out the last drawable. We don't have enough information to
1219419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        // propagate local state from the past.
1220419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastIndex = -1;
1221419aa7ad14926a30220aa3b71d045855ea54040aAlan Viverette        mLastDrawable = null;
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12236d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12246d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    /**
12256d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette     * Callback that blocks drawable invalidation.
12266d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette     */
12276d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    private static class BlockInvalidateCallback implements Drawable.Callback {
12286d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        private Drawable.Callback mCallback;
12296d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12306d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public BlockInvalidateCallback wrap(Drawable.Callback callback) {
12316d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mCallback = callback;
12326d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            return this;
12336d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12346d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12356d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public Drawable.Callback unwrap() {
12366d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            final Drawable.Callback callback = mCallback;
12376d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            mCallback = null;
12386d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            return callback;
12396d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12406d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12416d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12426d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void invalidateDrawable(@NonNull Drawable who) {
12436d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            // Ignore invalidation.
12446d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12456d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12466d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12476d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
12486d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            if (mCallback != null) {
12496d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette                mCallback.scheduleDrawable(who, what, when);
12506d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            }
12516d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12526d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette
12536d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        @Override
12546d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
12556d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            if (mCallback != null) {
12566d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette                mCallback.unscheduleDrawable(who, what);
12576d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette            }
12586d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette        }
12596d823891bbfc043f2a8ba6b5d6e6baa84cf750f6Alan Viverette    }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1261