/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.widget.multiwaveview; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.util.Log; public class TargetDrawable { private static final String TAG = "TargetDrawable"; private static final boolean DEBUG = false; public static final int[] STATE_ACTIVE = { android.R.attr.state_enabled, android.R.attr.state_active }; public static final int[] STATE_INACTIVE = { android.R.attr.state_enabled, -android.R.attr.state_active }; public static final int[] STATE_FOCUSED = { android.R.attr.state_enabled, -android.R.attr.state_active, android.R.attr.state_focused }; private float mTranslationX = 0.0f; private float mTranslationY = 0.0f; private float mPositionX = 0.0f; private float mPositionY = 0.0f; private float mScaleX = 1.0f; private float mScaleY = 1.0f; private float mAlpha = 1.0f; private Drawable mDrawable; private boolean mEnabled = true; private final int mResourceId; /* package */ static class DrawableWithAlpha extends Drawable { private float mAlpha = 1.0f; private Drawable mRealDrawable; public DrawableWithAlpha(Drawable realDrawable) { mRealDrawable = realDrawable; } public void setAlpha(float alpha) { mAlpha = alpha; } public float getAlpha() { return mAlpha; } public void draw(Canvas canvas) { mRealDrawable.setAlpha((int) Math.round(mAlpha * 255f)); mRealDrawable.draw(canvas); } @Override public void setAlpha(int alpha) { mRealDrawable.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { mRealDrawable.setColorFilter(cf); } @Override public int getOpacity() { return mRealDrawable.getOpacity(); } } public TargetDrawable(Resources res, int resId) { mResourceId = resId; setDrawable(res, resId); } public void setDrawable(Resources res, int resId) { // Note we explicitly don't set mResourceId to resId since we allow the drawable to be // swapped at runtime and want to re-use the existing resource id for identification. Drawable drawable = resId == 0 ? null : res.getDrawable(resId); // Mutate the drawable so we can animate shared drawable properties. mDrawable = drawable != null ? drawable.mutate() : null; resizeDrawables(); setState(STATE_INACTIVE); } public TargetDrawable(TargetDrawable other) { mResourceId = other.mResourceId; // Mutate the drawable so we can animate shared drawable properties. mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null; resizeDrawables(); setState(STATE_INACTIVE); } public void setState(int [] state) { if (mDrawable instanceof StateListDrawable) { StateListDrawable d = (StateListDrawable) mDrawable; d.setState(state); } } public boolean hasState(int [] state) { if (mDrawable instanceof StateListDrawable) { StateListDrawable d = (StateListDrawable) mDrawable; // TODO: this doesn't seem to work return d.getStateDrawableIndex(state) != -1; } return false; } /** * Returns true if the drawable is a StateListDrawable and is in the focused state. * * @return */ public boolean isActive() { if (mDrawable instanceof StateListDrawable) { StateListDrawable d = (StateListDrawable) mDrawable; int[] states = d.getState(); for (int i = 0; i < states.length; i++) { if (states[i] == android.R.attr.state_focused) { return true; } } } return false; } /** * Returns true if this target is enabled. Typically an enabled target contains a valid * drawable in a valid state. Currently all targets with valid drawables are valid. * * @return */ public boolean isEnabled() { return mDrawable != null && mEnabled; } /** * Makes drawables in a StateListDrawable all the same dimensions. * If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the * drawable. */ private void resizeDrawables() { if (mDrawable instanceof StateListDrawable) { StateListDrawable d = (StateListDrawable) mDrawable; int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < d.getStateCount(); i++) { Drawable childDrawable = d.getStateDrawable(i); maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth()); maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight()); } if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: " + maxWidth + "x" + maxHeight); d.setBounds(0, 0, maxWidth, maxHeight); for (int i = 0; i < d.getStateCount(); i++) { Drawable childDrawable = d.getStateDrawable(i); if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: " + maxWidth + "x" + maxHeight); childDrawable.setBounds(0, 0, maxWidth, maxHeight); } } else if (mDrawable != null) { mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } } public void setX(float x) { mTranslationX = x; } public void setY(float y) { mTranslationY = y; } public void setScaleX(float x) { mScaleX = x; } public void setScaleY(float y) { mScaleY = y; } public void setAlpha(float alpha) { mAlpha = alpha; } public float getX() { return mTranslationX; } public float getY() { return mTranslationY; } public float getScaleX() { return mScaleX; } public float getScaleY() { return mScaleY; } public float getAlpha() { return mAlpha; } public void setPositionX(float x) { mPositionX = x; } public void setPositionY(float y) { mPositionY = y; } public float getPositionX() { return mPositionX; } public float getPositionY() { return mPositionY; } public int getWidth() { return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0; } public int getHeight() { return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0; } public void draw(Canvas canvas) { if (mDrawable == null || !mEnabled) { return; } canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY); canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY); canvas.translate(-0.5f * getWidth(), -0.5f * getHeight()); mDrawable.setAlpha((int) Math.round(mAlpha * 255f)); mDrawable.draw(canvas); canvas.restore(); } public void setEnabled(boolean enabled) { mEnabled = enabled; } public int getResourceId() { return mResourceId; } }