package com.koushikdutta.ion;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Looper;
import android.view.animation.Animation;
import android.widget.ImageView;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.ion.bitmap.BitmapInfo;
import com.koushikdutta.ion.builder.AnimateGifMode;
import com.koushikdutta.ion.builder.Builders;
import com.koushikdutta.ion.builder.ImageViewFutureBuilder;
import com.koushikdutta.ion.future.ImageViewFuture;
/**
* Created by koush on 7/4/14.
*/
public class IonImageViewRequestBuilder extends IonBitmapRequestBuilder implements Builders.IV.F, ImageViewFutureBuilder {
Drawable placeholderDrawable;
int placeholderResource;
Drawable errorDrawable;
int errorResource;
Animation inAnimation;
Animation loadAnimation;
int loadAnimationResource;
int inAnimationResource;
ContextReference.ImageViewContextReference imageViewPostRef;
boolean fadeIn = true;
boolean crossfade;
BitmapDrawableFactory bitmapDrawableFactory = BitmapDrawableFactory.DEFAULT;
public IonImageViewRequestBuilder(IonRequestBuilder builder) {
super(builder);
}
public IonImageViewRequestBuilder(Ion ion) {
super(ion);
}
@Override
void reset() {
super.reset();
fadeIn = true;
crossfade = false;
imageViewPostRef = null;
placeholderDrawable = null;
bitmapDrawableFactory = BitmapDrawableFactory.DEFAULT;
placeholderResource = 0;
errorDrawable = null;
errorResource = 0;
inAnimation = null;
inAnimationResource = 0;
loadAnimation = null;
loadAnimationResource = 0;
}
@Override
protected IonRequestBuilder ensureBuilder() {
if (builder == null)
builder = new IonRequestBuilder(ContextReference.fromContext(imageViewPostRef.getContext().getApplicationContext()), ion);
return builder;
}
@Override
public ImageViewFuture load(String uri) {
ensureBuilder();
builder.load(uri);
return intoImageView(imageViewPostRef.get());
}
@Override
public Future<ImageView> load(String method, String url) {
ensureBuilder();
builder.load(method, url);
return intoImageView(imageViewPostRef.get());
}
IonImageViewRequestBuilder withImageView(ImageView imageView) {
if (imageViewPostRef == null || imageViewPostRef.get() != imageView)
imageViewPostRef = new ContextReference.ImageViewContextReference(imageView);
return this;
}
private IonDrawable setIonDrawable(ImageView imageView, BitmapFetcher bitmapFetcher, ResponseServedFrom servedFrom) {
BitmapInfo info = null;
if (bitmapFetcher != null)
info = bitmapFetcher.info;
if (info != null)
bitmapFetcher = null;
IonDrawable ret = IonDrawable.getOrCreateIonDrawable(imageView)
.ion(ion)
.setBitmap(info, servedFrom)
.setBitmapFetcher(bitmapFetcher)
.setRepeatAnimation(animateGifMode == AnimateGifMode.ANIMATE)
.setSize(resizeWidth, resizeHeight)
.setError(errorResource, errorDrawable)
.setPlaceholder(placeholderResource, placeholderDrawable)
.setFadeIn(fadeIn || crossfade)
.setBitmapDrawableFactory(bitmapDrawableFactory)
.updateLayers();
imageView.setImageDrawable(ret);
return ret;
}
@Override
public IonBitmapRequestBuilder fadeIn(boolean fadeIn) {
this.fadeIn = fadeIn;
return this;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static boolean getAdjustViewBounds_16(ImageView imageView) {
return imageView.getAdjustViewBounds();
}
private static boolean getAdjustViewBounds(ImageView imageView) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && getAdjustViewBounds_16(imageView);
}
@Override
public ImageViewFuture intoImageView(ImageView imageView) {
assert Thread.currentThread() == Looper.getMainLooper().getThread();
if (imageView == null)
throw new NullPointerException("imageView");
// no uri? just set a placeholder and bail
if (builder.uri == null) {
setIonDrawable(imageView, null, ResponseServedFrom.LOADED_FROM_NETWORK).cancel();
return ImageViewFutureImpl.FUTURE_IMAGEVIEW_NULL_URI;
}
withImageView(imageView);
if (crossfade) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof IonDrawable) {
IonDrawable ionDrawable = (IonDrawable)drawable;
drawable = ionDrawable.getCurrentDrawable();
}
placeholder(drawable);
}
int sampleWidth = resizeWidth;
int sampleHeight = resizeHeight;
// see if we need default transforms, or this if the imageview
// will request the actual size on measure
if (resizeHeight == 0 && resizeWidth == 0 && !getAdjustViewBounds(imageView)) {
// set the sample size hints from the current dimensions
// but don't actually apply a transform.
// this may be zero, in which case IonDrawable
// will eventually try again with real dimensions
// during draw.
sampleWidth = imageView.getMeasuredWidth();
sampleHeight = imageView.getMeasuredHeight();
}
else {
addDefaultTransform();
}
// executeCache the request, see if we get a bitmap from cache.
BitmapFetcher bitmapFetcher = executeCache(sampleWidth, sampleHeight);
if (bitmapFetcher.info != null) {
doAnimation(imageView, null, 0);
IonDrawable drawable = setIonDrawable(imageView, bitmapFetcher, ResponseServedFrom.LOADED_FROM_MEMORY);
drawable.cancel();
ImageViewFutureImpl imageViewFuture = ImageViewFutureImpl.getOrCreateImageViewFuture(imageViewPostRef, drawable)
.setInAnimation(inAnimation, inAnimationResource)
.setScaleMode(scaleMode);
ImageViewFutureImpl.applyScaleMode(imageView, scaleMode);
imageViewFuture.reset();
imageViewFuture.setComplete(bitmapFetcher.info.exception, imageView);
return imageViewFuture;
}
IonDrawable drawable = setIonDrawable(imageView, bitmapFetcher, ResponseServedFrom.LOADED_FROM_NETWORK);
doAnimation(imageView, loadAnimation, loadAnimationResource);
ImageViewFutureImpl imageViewFuture = ImageViewFutureImpl.getOrCreateImageViewFuture(imageViewPostRef, drawable)
.setInAnimation(inAnimation, inAnimationResource)
.setScaleMode(scaleMode);
imageViewFuture.reset();
return imageViewFuture;
}
private Drawable getImageViewDrawable() {
ImageView iv = imageViewPostRef.get();
if (iv == null)
return null;
return iv.getDrawable();
}
@Override
public Bitmap getBitmap() {
Drawable d = getImageViewDrawable();
if (d == null)
return null;
if (d instanceof BitmapDrawable)
return ((BitmapDrawable)d).getBitmap();
if (!(d instanceof IonDrawable))
return null;
IonDrawable id = (IonDrawable)d;
d = id.getCurrentDrawable();
if (d instanceof BitmapDrawable)
return ((BitmapDrawable)d).getBitmap();
return null;
}
@Override
public BitmapInfo getBitmapInfo() {
Drawable d = getImageViewDrawable();
if (d == null)
return null;
if (!(d instanceof IonDrawable))
return null;
IonDrawable id = (IonDrawable)d;
return id.getBitmapInfo();
}
@Override
public IonImageViewRequestBuilder crossfade(boolean crossfade) {
this.crossfade = crossfade;
return this;
}
@Override
public IonImageViewRequestBuilder placeholder(Drawable drawable) {
placeholderDrawable = drawable;
return this;
}
@Override
public IonImageViewRequestBuilder placeholder(int resourceId) {
placeholderResource = resourceId;
return this;
}
@Override
public IonImageViewRequestBuilder error(Drawable drawable) {
errorDrawable = drawable;
return this;
}
@Override
public IonImageViewRequestBuilder error(int resourceId) {
errorResource = resourceId;
return this;
}
@Override
public IonImageViewRequestBuilder animateIn(Animation in) {
inAnimation = in;
return this;
}
@Override
public IonImageViewRequestBuilder animateLoad(Animation load) {
loadAnimation = load;
return this;
}
@Override
public IonImageViewRequestBuilder animateLoad(int animationResource) {
loadAnimationResource = animationResource;
return this;
}
@Override
public IonImageViewRequestBuilder animateIn(int animationResource) {
inAnimationResource = animationResource;
return this;
}
@Override
public IonImageViewRequestBuilder bitmapDrawableFactory(BitmapDrawableFactory bitmapDrawableFactory) {
this.bitmapDrawableFactory = bitmapDrawableFactory;
return this;
}
}