blob: b03d740457e8645c94bb1ad5e8b9c43b065f1f91 [file] [log] [blame]
package org.wordpress.android.util.helpers;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.TextUtils;
import android.widget.TextView;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;
import org.wordpress.android.util.PhotonUtils;
import java.lang.ref.WeakReference;
/**
* ImageGetter for Html.fromHtml()
* adapted from existing ImageGetter code in NoteCommentFragment
*/
public class WPImageGetter implements Html.ImageGetter {
private final WeakReference<TextView> mWeakView;
private final int mMaxSize;
private ImageLoader mImageLoader;
private Drawable mLoadingDrawable;
private Drawable mFailedDrawable;
public WPImageGetter(TextView view) {
this(view, 0);
}
public WPImageGetter(TextView view, int maxSize) {
mWeakView = new WeakReference<TextView>(view);
mMaxSize = maxSize;
}
public WPImageGetter(TextView view, int maxSize, ImageLoader imageLoader, Drawable loadingDrawable,
Drawable failedDrawable) {
mWeakView = new WeakReference<TextView>(view);
mMaxSize = maxSize;
mImageLoader = imageLoader;
mLoadingDrawable = loadingDrawable;
mFailedDrawable = failedDrawable;
}
private TextView getView() {
return mWeakView.get();
}
@Override
public Drawable getDrawable(String source) {
if (mImageLoader == null || mLoadingDrawable == null || mFailedDrawable == null) {
throw new RuntimeException("Developer, you need to call setImageLoader, setLoadingDrawable and setFailedDrawable");
}
if (TextUtils.isEmpty(source)) {
return null;
}
// images in reader comments may skip "http:" (no idea why) so make sure to add protocol here
if (source.startsWith("//")) {
source = "http:" + source;
}
// use Photon if a max size is requested (otherwise the full-sized image will be downloaded
// and then resized)
if (mMaxSize > 0) {
source = PhotonUtils.getPhotonImageUrl(source, mMaxSize, 0);
}
final RemoteDrawable remote = new RemoteDrawable(mLoadingDrawable, mFailedDrawable);
mImageLoader.get(source, new ImageLoader.ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
remote.displayFailed();
TextView view = getView();
if (view != null) {
view.invalidate();
}
}
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
if (response.getBitmap() == null) {
AppLog.w(T.UTILS, "WPImageGetter null bitmap");
}
TextView view = getView();
if (view == null) {
AppLog.w(T.UTILS, "WPImageGetter view is invalid");
return;
}
int maxWidth = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight();
if (mMaxSize > 0 && (maxWidth > mMaxSize || maxWidth == 0)) {
maxWidth = mMaxSize;
}
Drawable drawable = new BitmapDrawable(view.getContext().getResources(), response.getBitmap());
remote.setRemoteDrawable(drawable, maxWidth);
// force textView to resize correctly if image isn't cached by resetting the content
// to itself - this way the textView will use the cached image, and resizing to
// accommodate the image isn't necessary
if (!isImmediate) {
view.setText(view.getText());
}
}
});
return remote;
}
public static class RemoteDrawable extends BitmapDrawable {
Drawable mRemoteDrawable;
final Drawable mLoadingDrawable;
final Drawable mFailedDrawable;
private boolean mDidFail = false;
public RemoteDrawable(Drawable loadingDrawable, Drawable failedDrawable) {
mLoadingDrawable = loadingDrawable;
mFailedDrawable = failedDrawable;
setBounds(0, 0, mLoadingDrawable.getIntrinsicWidth(), mLoadingDrawable.getIntrinsicHeight());
}
public void displayFailed() {
mDidFail = true;
}
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
if (mRemoteDrawable != null) {
mRemoteDrawable.setBounds(x, y, width, height);
return;
}
if (mLoadingDrawable != null) {
mLoadingDrawable.setBounds(x, y, width, height);
mFailedDrawable.setBounds(x, y, width, height);
}
}
public void setRemoteDrawable(Drawable remote, int maxWidth) {
// null sentinel for now
if (remote == null) {
// throw error
return;
}
mRemoteDrawable = remote;
// determine if we need to scale the image to fit in view
int imgWidth = remote.getIntrinsicWidth();
int imgHeight = remote.getIntrinsicHeight();
float xScale = (float) imgWidth / (float) maxWidth;
if (xScale > 1.0f) {
setBounds(0, 0, Math.round(imgWidth / xScale), Math.round(imgHeight / xScale));
} else {
setBounds(0, 0, imgWidth, imgHeight);
}
}
public boolean didFail() {
return mDidFail;
}
public void draw(Canvas canvas) {
if (mRemoteDrawable != null) {
mRemoteDrawable.draw(canvas);
} else if (didFail()) {
mFailedDrawable.draw(canvas);
} else {
mLoadingDrawable.draw(canvas);
}
}
}
}