/* Copyright (c) 2002-2011 by XMLVM.org
*
* Project Info: http://www.xmlvm.org
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package android.widget;
import java.util.HashMap;
import java.util.Map;
import org.xmlvm.acl.common.adapter.BitmapDrawableAdapter;
import org.xmlvm.acl.common.adapter.ImageViewAdapter;
import org.xmlvm.acl.common.objects.CommonView;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.internal.Assert;
import android.internal.CommonDeviceAPIFinder;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout.LayoutParams;
public class ImageView extends View {
private static Map<String, ScaleType> scaleTypes = new HashMap<String, ImageView.ScaleType>();
static {
scaleTypes.put("matrix", ScaleType.MATRIX);
scaleTypes.put("fitXY", ScaleType.FIT_XY);
scaleTypes.put("fitStart", ScaleType.FIT_START);
scaleTypes.put("fitCenter", ScaleType.FIT_CENTER);
scaleTypes.put("fitEnd", ScaleType.FIT_END);
scaleTypes.put("center", ScaleType.CENTER);
scaleTypes.put("centerCrop", ScaleType.CENTER_CROP);
scaleTypes.put("centerInside", ScaleType.CENTER_INSIDE);
}
/**
* Options for scaling the bounds of an image to the bounds of this view.
* <p>
* <i>(This enum is taken from Android's source code.)</i>
*/
public enum ScaleType {
/**
* Scale using the image matrix when drawing. The image matrix can be
* set using {@link ImageView#setImageMatrix(Matrix)}. From XML, use
* this syntax: <code>android:scaleType="matrix"</code>.
*/
MATRIX(0),
/**
* Scale the image using {@link Matrix.ScaleToFit#FILL}. From XML, use
* this syntax: <code>android:scaleType="fitXY"</code>.
*/
FIT_XY(1),
/**
* Scale the image using {@link Matrix.ScaleToFit#START}. From XML, use
* this syntax: <code>android:scaleType="fitStart"</code>.
*/
FIT_START(2),
/**
* Scale the image using {@link Matrix.ScaleToFit#CENTER}. From XML, use
* this syntax: <code>android:scaleType="fitCenter"</code>.
*/
FIT_CENTER(3),
/**
* Scale the image using {@link Matrix.ScaleToFit#END}. From XML, use
* this syntax: <code>android:scaleType="fitEnd"</code>.
*/
FIT_END(4),
/**
* Center the image in the view, but perform no scaling. From XML, use
* this syntax: <code>android:scaleType="center"</code>.
*/
CENTER(5),
/**
* Scale the image uniformly (maintain the image's aspect ratio) so that
* both dimensions (width and height) of the image will be equal to or
* larger than the corresponding dimension of the view (minus padding).
* The image is then centered in the view. From XML, use this syntax:
* <code>android:scaleType="centerCrop"</code>.
*/
CENTER_CROP(6),
/**
* Scale the image uniformly (maintain the image's aspect ratio) so that
* both dimensions (width and height) of the image will be equal to or
* less than the corresponding dimension of the view (minus padding).
* The image is then centered in the view. From XML, use this syntax:
* <code>android:scaleType="centerInside"</code>.
*/
CENTER_INSIDE(7);
ScaleType(int ni) {
nativeInt = ni;
}
final int nativeInt;
}
protected Drawable drawable;
private int type;
public ImageView(Context c) {
super(c);
initImageView(c, null);
}
public ImageView(Context c, AttributeSet attrs) {
super(c, attrs);
initImageView(c, attrs);
}
public ImageView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
Assert.NOT_IMPLEMENTED();
}
private void initImageView(Context c, AttributeSet attrs) {
setScaleType(ScaleType.FIT_CENTER);
if (attrs != null && attrs.getAttributeCount() > 0) {
parseImageViewAttributes(attrs);
}
}
public void setImageResource(int resId) {
Drawable d = getContext().getResources().getDrawable(resId);
setImageDrawable(d);
}
public void setImageDrawable(Drawable drawable) {
this.drawable = drawable;
if (drawable instanceof BitmapDrawable) {
((ImageViewAdapter) getCommonView()).setImage(((BitmapDrawable) drawable)
.xmlvmGetImage());
getCommonView().setContentMode(this.type);
refreshBackground();
} else if (drawable instanceof StateListDrawable) {
refreshImageStateDrawable();
} else if (drawable == null) {
((ImageViewAdapter) getCommonView()).setImage(null);
} else {
Assert.NOT_IMPLEMENTED();
}
requestLayout();
}
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
return super.setFrame(left + paddingLeft, top + paddingTop, right - paddingRight, bottom
- paddingBottom);
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams l) {
layoutParams = l;
int width = l.width;
int height = l.height;
BitmapDrawableAdapter img = ((ImageViewAdapter) getCommonView()).getImage();
if (width == LayoutParams.WRAP_CONTENT) {
width = img != null ? (int) img.getWidth() : 0;
}
if (height == LayoutParams.WRAP_CONTENT) {
height = img != null ? (int) img.getHeight() : 0;
}
int x = l instanceof AbsoluteLayout.LayoutParams ? ((AbsoluteLayout.LayoutParams) l).x : 0;
int y = l instanceof AbsoluteLayout.LayoutParams ? ((AbsoluteLayout.LayoutParams) l).y : 0;
getCommonView().setFrame(new RectF(x, y, x + width, y + height));
}
public void setScaleType(ScaleType type) {
CommonView view = getCommonView();
switch (type) {
case CENTER:
view.setContentMode(CommonView.CENTER);
this.type = CommonView.CENTER;
break;
case CENTER_CROP:
view.setContentMode(CommonView.SCALE_ASPECT_FILL);
this.type = CommonView.SCALE_ASPECT_FILL;
break;
case CENTER_INSIDE:
view.setContentMode(CommonView.SCALE_ASPECT_FIT);
this.type = CommonView.SCALE_ASPECT_FIT;
break;
case FIT_CENTER:
view.setContentMode(CommonView.SCALE_ASPECT_FIT);
this.type = CommonView.SCALE_ASPECT_FIT;
break;
case FIT_END:
Assert.NOT_IMPLEMENTED();
break;
case FIT_START:
Assert.NOT_IMPLEMENTED();
break;
case FIT_XY:
view.setContentMode(CommonView.SCALE_TO_FILL);
this.type = CommonView.SCALE_TO_FILL;
break;
case MATRIX:
Assert.NOT_IMPLEMENTED();
break;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = 0;
int height = 0;
if (drawable != null) {
Rect r = drawable.getBounds();
width = r.width();
height = r.height();
}
width = Math.max(getSuggestedMinimumWidth(), width + paddingLeft + paddingRight);
height = Math.max(getSuggestedMinimumHeight(), height + paddingTop + paddingBottom);
int w = resolveSize(width, widthMeasureSpec);
int h = resolveSize(height, heightMeasureSpec);
setMeasuredDimension(w, h);
}
private void parseImageViewAttributes(AttributeSet attrs) {
setIgnoreRequestLayout(true);
// Resolve drawable background
String str = attrs.getAttributeValue(null, "src");
if (str != null) {
int srcId = attrs.getAttributeResourceValue(null, "src", -1);
if (srcId != -1) {
setImageResource(srcId);
}
}
// Resolve scale type
str = attrs.getAttributeValue(null, "scaleType");
if (str != null) {
setScaleType(resolveScaleType(str));
}
setIgnoreRequestLayout(false);
}
private ScaleType resolveScaleType(String str) {
return scaleTypes.get(str);
}
@Override
protected CommonView xmlvmNewCommonDeviceView(AttributeSet attrs) {
return CommonDeviceAPIFinder.instance().getWidgetFactory().createImageView(this);
}
@Override
public void xmlvmSetDrawableState(int[] drawableState) {
super.xmlvmSetDrawableState(drawableState);
refreshImageStateDrawable();
}
private void refreshImageStateDrawable() {
if (drawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) drawable;
int i = d.getStateDrawableIndex(getDrawableState());
d.selectDrawable(i);
Drawable currentStateDrawable = d.getStateDrawable(i);
BitmapDrawableAdapter newImg = ((BitmapDrawable) currentStateDrawable).xmlvmGetImage();
BitmapDrawableAdapter currentImg = ((ImageViewAdapter) getCommonView()).getImage();
if (currentImg != newImg) {
boolean relayout = currentImg != null && newImg != null
&& !currentImg.getSize().equals(newImg.getSize());
((ImageViewAdapter) getCommonView()).setImage(newImg);
if (relayout) {
requestLayout();
}
}
}
}
}