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