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