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