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