19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 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
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.*;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
23dfab363807b3b44be4032e410f016e0a0d018426Romain Guyimport android.view.ViewDebug;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3095930e13faac8c17dabfaa1478089baa772f091bRomain Guy * A specialized Drawable that fills the Canvas with a specified color.
3195930e13faac8c17dabfaa1478089baa772f091bRomain Guy * Note that a ColorDrawable ignores the ColorFilter.
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>It can be defined in an XML file with the <code>&lt;color></code> element.</p>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ColorDrawable_color
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ColorDrawable extends Drawable {
38dfab363807b3b44be4032e410f016e0a0d018426Romain Guy    @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ColorState mState;
4095930e13faac8c17dabfaa1478089baa772f091bRomain Guy    private final Paint mPaint = new Paint();
415f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    private boolean mMutated;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new black ColorDrawable.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ColorDrawable() {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null);
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new ColorDrawable with the specified color.
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param color The color to draw.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ColorDrawable(int color) {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null);
5770d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase        setColor(color);
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ColorDrawable(ColorState state) {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState = new ColorState(state);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChangingConfigurations() {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.getChangingConfigurations() | mState.mChangingConfigurations;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
695f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    /**
705f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy     * A mutable BitmapDrawable still shares its Bitmap with any other Drawable
715f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy     * that comes from the same resource.
725f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy     *
735f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy     * @return This drawable.
745f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy     */
755f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    @Override
765f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    public Drawable mutate() {
775f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy        if (!mMutated && super.mutate() == this) {
785f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy            mState = new ColorState(mState);
795f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy            mMutated = true;
805f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy        }
815f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy        return this;
825f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    }
835f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
8695930e13faac8c17dabfaa1478089baa772f091bRomain Guy        if ((mState.mUseColor >>> 24) != 0) {
8795930e13faac8c17dabfaa1478089baa772f091bRomain Guy            mPaint.setColor(mState.mUseColor);
8895930e13faac8c17dabfaa1478089baa772f091bRomain Guy            canvas.drawRect(getBounds(), mPaint);
8995930e13faac8c17dabfaa1478089baa772f091bRomain Guy        }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9370d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     * Gets the drawable's color value.
9470d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     *
9570d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     * @return int The color to draw.
9670d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     */
9770d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    public int getColor() {
9870d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase        return mState.mUseColor;
9970d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    }
10070d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase
10170d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    /**
10270d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     * Sets the drawable's color value. This action will clobber the results of prior calls to
10370d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     * {@link #setAlpha(int)} on this object, which side-affected the underlying color.
10470d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     *
10570d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     * @param color The color to draw.
10670d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase     */
10770d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    public void setColor(int color) {
1089891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (mState.mBaseColor != color || mState.mUseColor != color) {
1099891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
1109891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mState.mBaseColor = mState.mUseColor = color;
1119891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
11270d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    }
11370d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase
11470d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase    /**
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the alpha value of this drawable's color.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A value between 0 and 255.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAlpha() {
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mState.mUseColor >>> 24;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the color's alpha value.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param alpha The alpha value to set, between 0 and 255.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        alpha += alpha >> 7;   // make it 0..256
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int baseAlpha = mState.mBaseColor >>> 24;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int useAlpha = baseAlpha * alpha >> 8;
13241bff38d3060dbcb55133cedaf5d962c3082efc2Chet Haase        int oldUseColor = mState.mUseColor;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState.mUseColor = (mState.mBaseColor << 8 >>> 8) | (useAlpha << 24);
13441bff38d3060dbcb55133cedaf5d962c3082efc2Chet Haase        if (oldUseColor != mState.mUseColor) {
13541bff38d3060dbcb55133cedaf5d962c3082efc2Chet Haase            invalidateSelf();
13641bff38d3060dbcb55133cedaf5d962c3082efc2Chet Haase        }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Setting a color filter on a ColorDrawable has no effect.
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param colorFilter Ignore.
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setColorFilter(ColorFilter colorFilter) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (mState.mUseColor >>> 24) {
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 255:
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return PixelFormat.OPAQUE;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case 0:
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return PixelFormat.TRANSPARENT;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return PixelFormat.TRANSLUCENT;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.inflate(r, parser, attrs);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.ColorDrawable);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int color = mState.mBaseColor;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        color = a.getColor(com.android.internal.R.styleable.ColorDrawable_color, color);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState.mBaseColor = mState.mUseColor = color;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
1736efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mState.mChangingConfigurations = getChangingConfigurations();
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mState;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final static class ColorState extends ConstantState {
17870d4ba15b1f0c1133c5aabc86de828b41e482fffChet Haase        int mBaseColor; // base color, independent of setAlpha()
179dfab363807b3b44be4032e410f016e0a0d018426Romain Guy        @ViewDebug.ExportedProperty
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mUseColor;  // basecolor modulated by setAlpha()
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mChangingConfigurations;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ColorState(ColorState state) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state != null) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBaseColor = state.mBaseColor;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUseColor = state.mUseColor;
1875f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy                mChangingConfigurations = state.mChangingConfigurations;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ColorDrawable(this);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
197c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
198c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new ColorDrawable(this);
199c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
200c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
201c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getChangingConfigurations() {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mChangingConfigurations;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
207