TargetDrawable.java revision 4c351d62e7a09bcc29e7d0329bcdd947a302cf40
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.widget.multiwaveview;
18
19import android.content.res.Resources;
20import android.graphics.Canvas;
21import android.graphics.ColorFilter;
22import android.graphics.drawable.Drawable;
23import android.graphics.drawable.StateListDrawable;
24import android.util.Log;
25
26public class TargetDrawable {
27    private static final String TAG = "TargetDrawable";
28    private static final boolean DEBUG = false;
29
30    public static final int[] STATE_ACTIVE =
31            { android.R.attr.state_enabled, android.R.attr.state_active };
32    public static final int[] STATE_INACTIVE =
33            { android.R.attr.state_enabled, -android.R.attr.state_active };
34    public static final int[] STATE_FOCUSED =
35            { android.R.attr.state_enabled, -android.R.attr.state_active,
36                android.R.attr.state_focused };
37
38    private float mTranslationX = 0.0f;
39    private float mTranslationY = 0.0f;
40    private float mPositionX = 0.0f;
41    private float mPositionY = 0.0f;
42    private float mScaleX = 1.0f;
43    private float mScaleY = 1.0f;
44    private float mAlpha = 1.0f;
45    private Drawable mDrawable;
46    private boolean mEnabled = true;
47    private int mResourceId;
48
49    /* package */ static class DrawableWithAlpha extends Drawable {
50        private float mAlpha = 1.0f;
51        private Drawable mRealDrawable;
52        public DrawableWithAlpha(Drawable realDrawable) {
53            mRealDrawable = realDrawable;
54        }
55        public void setAlpha(float alpha) {
56            mAlpha = alpha;
57        }
58        public float getAlpha() {
59            return mAlpha;
60        }
61        public void draw(Canvas canvas) {
62            mRealDrawable.setAlpha((int) Math.round(mAlpha * 255f));
63            mRealDrawable.draw(canvas);
64        }
65        @Override
66        public void setAlpha(int alpha) {
67            mRealDrawable.setAlpha(alpha);
68        }
69        @Override
70        public void setColorFilter(ColorFilter cf) {
71            mRealDrawable.setColorFilter(cf);
72        }
73        @Override
74        public int getOpacity() {
75            return mRealDrawable.getOpacity();
76        }
77    }
78
79    public TargetDrawable(Resources res, int resId) {
80        mResourceId = resId;
81        Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
82        // Mutate the drawable so we can animate shared drawable properties.
83        mDrawable = drawable != null ? drawable.mutate() : null;
84        resizeDrawables();
85        setState(STATE_INACTIVE);
86    }
87
88    public TargetDrawable(TargetDrawable other) {
89        mResourceId = other.mResourceId;
90        // Mutate the drawable so we can animate shared drawable properties.
91        mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null;
92        resizeDrawables();
93        setState(STATE_INACTIVE);
94    }
95
96    public void setState(int [] state) {
97        if (mDrawable instanceof StateListDrawable) {
98            StateListDrawable d = (StateListDrawable) mDrawable;
99            d.setState(state);
100        }
101    }
102
103    public boolean hasState(int [] state) {
104        if (mDrawable instanceof StateListDrawable) {
105            StateListDrawable d = (StateListDrawable) mDrawable;
106            // TODO: this doesn't seem to work
107            return d.getStateDrawableIndex(state) != -1;
108        }
109        return false;
110    }
111
112    /**
113     * Returns true if the drawable is a StateListDrawable and is in the focused state.
114     *
115     * @return
116     */
117    public boolean isActive() {
118        if (mDrawable instanceof StateListDrawable) {
119            StateListDrawable d = (StateListDrawable) mDrawable;
120            int[] states = d.getState();
121            for (int i = 0; i < states.length; i++) {
122                if (states[i] == android.R.attr.state_focused) {
123                    return true;
124                }
125            }
126        }
127        return false;
128    }
129
130    /**
131     * Returns true if this target is enabled. Typically an enabled target contains a valid
132     * drawable in a valid state. Currently all targets with valid drawables are valid.
133     *
134     * @return
135     */
136    public boolean isEnabled() {
137        return mDrawable != null && mEnabled;
138    }
139
140    /**
141     * Makes drawables in a StateListDrawable all the same dimensions.
142     * If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the
143     * drawable.
144     */
145    private void resizeDrawables() {
146        if (mDrawable instanceof StateListDrawable) {
147            StateListDrawable d = (StateListDrawable) mDrawable;
148            int maxWidth = 0;
149            int maxHeight = 0;
150            for (int i = 0; i < d.getStateCount(); i++) {
151                Drawable childDrawable = d.getStateDrawable(i);
152                maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
153                maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
154            }
155            if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
156                        + maxWidth + "x" + maxHeight);
157            d.setBounds(0, 0, maxWidth, maxHeight);
158            for (int i = 0; i < d.getStateCount(); i++) {
159                Drawable childDrawable = d.getStateDrawable(i);
160                if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
161                            + maxWidth + "x" + maxHeight);
162                childDrawable.setBounds(0, 0, maxWidth, maxHeight);
163            }
164        } else if (mDrawable != null) {
165            mDrawable.setBounds(0, 0,
166                    mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
167        }
168    }
169
170    public void setX(float x) {
171        mTranslationX = x;
172    }
173
174    public void setY(float y) {
175        mTranslationY = y;
176    }
177
178    public void setScaleX(float x) {
179        mScaleX = x;
180    }
181
182    public void setScaleY(float y) {
183        mScaleY = y;
184    }
185
186    public void setAlpha(float alpha) {
187        mAlpha = alpha;
188    }
189
190    public float getX() {
191        return mTranslationX;
192    }
193
194    public float getY() {
195        return mTranslationY;
196    }
197
198    public float getScaleX() {
199        return mScaleX;
200    }
201
202    public float getScaleY() {
203        return mScaleY;
204    }
205
206    public float getAlpha() {
207        return mAlpha;
208    }
209
210    public void setPositionX(float x) {
211        mPositionX = x;
212    }
213
214    public void setPositionY(float y) {
215        mPositionY = y;
216    }
217
218    public float getPositionX() {
219        return mPositionX;
220    }
221
222    public float getPositionY() {
223        return mPositionY;
224    }
225
226    public int getWidth() {
227        return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0;
228    }
229
230    public int getHeight() {
231        return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
232    }
233
234    public void draw(Canvas canvas) {
235        if (mDrawable == null || !mEnabled) {
236            return;
237        }
238        canvas.save(Canvas.MATRIX_SAVE_FLAG);
239        canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY);
240        canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY);
241        canvas.translate(-0.5f * getWidth(), -0.5f * getHeight());
242        mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
243        mDrawable.draw(canvas);
244        canvas.restore();
245    }
246
247    public void setEnabled(boolean enabled) {
248        mEnabled  = enabled;
249    }
250
251    public int getResourceId() {
252        return mResourceId;
253    }
254}
255