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 
17 package com.android.incallui.widget.multiwaveview;
18 
19 import android.content.res.Resources;
20 import android.graphics.Canvas;
21 import android.graphics.ColorFilter;
22 import android.graphics.drawable.Drawable;
23 import android.graphics.drawable.StateListDrawable;
24 import android.util.Log;
25 
26 public 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 final int mResourceId;
48     private int mNumDrawables = 1;
49 
50     /**
51      * This is changed from the framework version to pass in the number of drawables in the
52      * container. The framework version relies on private api's to get the count from
53      * StateListDrawable.
54      *
55      * @param res
56      * @param resId
57      * @param count The number of drawables in the resource.
58      */
TargetDrawable(Resources res, int resId, int count)59     public TargetDrawable(Resources res, int resId, int count) {
60         mResourceId = resId;
61         setDrawable(res, resId);
62         mNumDrawables = count;
63     }
64 
setDrawable(Resources res, int resId)65     public void setDrawable(Resources res, int resId) {
66         // Note we explicitly don't set mResourceId to resId since we allow the drawable to be
67         // swapped at runtime and want to re-use the existing resource id for identification.
68         Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
69         // Mutate the drawable so we can animate shared drawable properties.
70         mDrawable = drawable != null ? drawable.mutate() : null;
71         resizeDrawables();
72         setState(STATE_INACTIVE);
73     }
74 
TargetDrawable(TargetDrawable other)75     public TargetDrawable(TargetDrawable other) {
76         mResourceId = other.mResourceId;
77         // Mutate the drawable so we can animate shared drawable properties.
78         mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null;
79         resizeDrawables();
80         setState(STATE_INACTIVE);
81     }
82 
setState(int [] state)83     public void setState(int [] state) {
84         if (mDrawable instanceof StateListDrawable) {
85             StateListDrawable d = (StateListDrawable) mDrawable;
86             d.setState(state);
87         }
88     }
89 
90     /**
91      * Returns true if the drawable is a StateListDrawable and is in the focused state.
92      *
93      * @return
94      */
isActive()95     public boolean isActive() {
96         if (mDrawable instanceof StateListDrawable) {
97             StateListDrawable d = (StateListDrawable) mDrawable;
98             int[] states = d.getState();
99             for (int i = 0; i < states.length; i++) {
100                 if (states[i] == android.R.attr.state_focused) {
101                     return true;
102                 }
103             }
104         }
105         return false;
106     }
107 
108     /**
109      * Returns true if this target is enabled. Typically an enabled target contains a valid
110      * drawable in a valid state. Currently all targets with valid drawables are valid.
111      *
112      * @return
113      */
isEnabled()114     public boolean isEnabled() {
115         return mDrawable != null && mEnabled;
116     }
117 
118     /**
119      * Makes drawables in a StateListDrawable all the same dimensions.
120      * If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the
121      * drawable.
122      */
resizeDrawables()123     private void resizeDrawables() {
124         if (mDrawable instanceof StateListDrawable) {
125             StateListDrawable d = (StateListDrawable) mDrawable;
126             int maxWidth = 0;
127             int maxHeight = 0;
128 
129             for (int i = 0; i < mNumDrawables; i++) {
130                 d.selectDrawable(i);
131                 Drawable childDrawable = d.getCurrent();
132                 maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
133                 maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
134             }
135 
136             if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
137                     + maxWidth + "x" + maxHeight);
138             d.setBounds(0, 0, maxWidth, maxHeight);
139 
140             for (int i = 0; i < mNumDrawables; i++) {
141                 d.selectDrawable(i);
142                 Drawable childDrawable = d.getCurrent();
143                 if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
144                             + maxWidth + "x" + maxHeight);
145                 childDrawable.setBounds(0, 0, maxWidth, maxHeight);
146             }
147         } else if (mDrawable != null) {
148             mDrawable.setBounds(0, 0,
149                     mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
150         }
151     }
152 
setX(float x)153     public void setX(float x) {
154         mTranslationX = x;
155     }
156 
setY(float y)157     public void setY(float y) {
158         mTranslationY = y;
159     }
160 
setScaleX(float x)161     public void setScaleX(float x) {
162         mScaleX = x;
163     }
164 
setScaleY(float y)165     public void setScaleY(float y) {
166         mScaleY = y;
167     }
168 
setAlpha(float alpha)169     public void setAlpha(float alpha) {
170         mAlpha = alpha;
171     }
172 
getX()173     public float getX() {
174         return mTranslationX;
175     }
176 
getY()177     public float getY() {
178         return mTranslationY;
179     }
180 
getScaleX()181     public float getScaleX() {
182         return mScaleX;
183     }
184 
getScaleY()185     public float getScaleY() {
186         return mScaleY;
187     }
188 
getAlpha()189     public float getAlpha() {
190         return mAlpha;
191     }
192 
setPositionX(float x)193     public void setPositionX(float x) {
194         mPositionX = x;
195     }
196 
setPositionY(float y)197     public void setPositionY(float y) {
198         mPositionY = y;
199     }
200 
getPositionX()201     public float getPositionX() {
202         return mPositionX;
203     }
204 
getPositionY()205     public float getPositionY() {
206         return mPositionY;
207     }
208 
getWidth()209     public int getWidth() {
210         return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0;
211     }
212 
getHeight()213     public int getHeight() {
214         return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
215     }
216 
draw(Canvas canvas)217     public void draw(Canvas canvas) {
218         if (mDrawable == null || !mEnabled) {
219             return;
220         }
221         canvas.save(Canvas.MATRIX_SAVE_FLAG);
222         canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY);
223         canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY);
224         canvas.translate(-0.5f * getWidth(), -0.5f * getHeight());
225         mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
226         mDrawable.draw(canvas);
227         canvas.restore();
228     }
229 
setEnabled(boolean enabled)230     public void setEnabled(boolean enabled) {
231         mEnabled  = enabled;
232     }
233 
getResourceId()234     public int getResourceId() {
235         return mResourceId;
236     }
237 }
238