/**
* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
* This file is part of CSipSimple.
*
* CSipSimple is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* If you own a pjsip commercial license you can also redistribute it
* and/or modify it under the terms of the GNU Lesser General Public License
* as an android library.
*
* CSipSimple is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CSipSimple. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This file contains relicensed code from Apache copyright of
* Copyright (C) 2012 The Android Open Source Project
*/
package com.csipsimple.ui.incall.locker.multiwaveview;
import android.annotation.TargetApi;
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.os.Build;
import java.util.ArrayList;
import java.util.List;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class TargetDrawable {
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 int mAlpha = 255;
private Drawable mRealDrawable;
public DrawableWithAlpha(Drawable realDrawable) {
mRealDrawable = realDrawable;
}
public int getAlpha() {
return mAlpha;
}
public void draw(Canvas canvas) {
mRealDrawable.setAlpha(mAlpha);
mRealDrawable.draw(canvas);
}
@Override
public void setAlpha(int alpha) {
mAlpha = 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 true;
}
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) {
List<int[]> possiblesStates = new ArrayList<int[]>();
possiblesStates.add(STATE_ACTIVE);
possiblesStates.add(STATE_INACTIVE);
possiblesStates.add(STATE_FOCUSED);
StateListDrawable d = (StateListDrawable) mDrawable;
int maxWidth = 0;
int maxHeight = 0;
for (int[] possState : possiblesStates) {
d.setState(possState);
Drawable childDrawable = d.getCurrent();
if(childDrawable != null) {
maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
}
}
d.setBounds(0, 0, maxWidth, maxHeight);
for (int[] possState : possiblesStates) {
d.setState(possState);
Drawable childDrawable = d.getCurrent();
if(childDrawable != null) {
maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
}
}
} 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;
}
}