/*
* Copyright 2015 Hippo Seven
*
* 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.hippo.nimingban.widget;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import com.hippo.conaco.Conaco;
import com.hippo.conaco.ConacoTask;
import com.hippo.conaco.DataContainer;
import com.hippo.conaco.Unikery;
import com.hippo.conaco.ValueHolder;
import com.hippo.drawable.ImageDrawable;
import com.hippo.drawable.ImageWrapper;
import com.hippo.nimingban.NMBApplication;
import com.hippo.nimingban.R;
import com.hippo.widget.ProgressView;
import uk.co.senab.photoview.PhotoView;
public final class GalleryPage extends FrameLayout implements Unikery<ImageWrapper>, View.OnClickListener {
private int mTaskId = Unikery.INVALID_ID;
private Conaco<ImageWrapper> mConaco;
private ProgressView mProgressView;
private View mFailed;
private PhotoView mPhotoView;
private String mKey;
private String mUrl;
private DataContainer mContainer;
private ValueHolder<ImageWrapper> mHolder;
public GalleryPage(Context context) {
super(context);
init(context);
}
public GalleryPage(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GalleryPage(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mConaco = NMBApplication.getConaco(context);
LayoutInflater.from(context).inflate(R.layout.widget_gallery_page, this);
mProgressView = (ProgressView) findViewById(R.id.progress_view);
mFailed = findViewById(R.id.failed);
mPhotoView = (PhotoView) findViewById(R.id.image_view);
}
private void addRetry() {
setOnClickListener(this);
}
private void removeRetry() {
setOnClickListener(null);
setClickable(false);
}
private void updateMaximumScale() {
Drawable drawable = mPhotoView.getDrawable();
if (drawable != null && drawable.getIntrinsicHeight() > 0) {
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();
int width = getWidth();
int height = getHeight();
float scaleX = 1.0f;
float scaleY = 1.0f;
if (drawableWidth > 0 && width > 0) {
scaleX = ((float) width / (float) drawableWidth);
}
if (drawableHeight > 0 && height > 0) {
scaleY = ((float) height / (float) drawableHeight);
}
float midScale;
float maxScale;
if (scaleX > scaleY) {
midScale = scaleX / scaleY;
} else if (scaleX == scaleY) {
midScale = 1.75f;
} else {
midScale = scaleY / scaleX;
}
maxScale = midScale * 3;
mPhotoView.setScaleLevels(1.0f, midScale, maxScale);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
updateMaximumScale();
}
private void removeDrawableAndHolder() {
// Remove drawable
Drawable drawable = mPhotoView.getDrawable();
if (drawable instanceof ImageDrawable) {
((ImageDrawable) drawable).recycle();
}
mPhotoView.setImageDrawable(null);
// Remove holder
if (mHolder != null) {
mHolder.release(this);
ImageWrapper imageWrapper = mHolder.getValue();
if (mHolder.isFree()) {
// ImageWrapper is free, stop animate
imageWrapper.stop();
if (!mHolder.isInMemoryCache()) {
// ImageWrapper is not needed any more, recycle it
imageWrapper.recycle();
}
}
mHolder = null;
}
}
private void setImageDrawable(Drawable drawable) {
mPhotoView.setImageDrawable(drawable);
updateMaximumScale();
}
@Override
public void onClick(View v) {
if (mUrl != null) {
load(mKey, mUrl, mContainer);
}
}
@Override
public void setTaskId(int id) {
mTaskId = id;
}
@Override
public int getTaskId() {
return mTaskId;
}
@Override
public void onMiss(Conaco.Source source) {
}
public void load(String key, String url, DataContainer container) {
removeRetry();
if (url == null) {
return;
}
mKey = key;
mUrl = url;
mContainer = container;
mProgressView.setVisibility(VISIBLE);
mProgressView.setIndeterminate(true);
mFailed.setVisibility(GONE);
mPhotoView.setVisibility(GONE);
removeDrawableAndHolder();
ConacoTask.Builder<ImageWrapper> builder = new ConacoTask.Builder<ImageWrapper>()
.setUnikery(this)
.setKey(key)
.setUrl(url)
.setDataContainer(container)
.setUseMemoryCache(false);
mConaco.load(builder);
}
public void unload() {
mConaco.cancel(this);
removeRetry();
mKey = null;
mUrl = null;
mContainer = null;
removeDrawableAndHolder();
}
@Override
public void onRequest() {
}
@Override
public void onProgress(long singleReceivedSize, long receivedSize, long totalSize) {
mProgressView.setIndeterminate(false);
if (totalSize >= 0) {
mProgressView.setProgress((float) receivedSize / (float) totalSize);
}
}
@Override
public boolean onGetObject(@NonNull ValueHolder<ImageWrapper> holder, Conaco.Source source) {
// Release
mKey = null;
mUrl = null;
mContainer = null;
holder.obtain(this);
removeDrawableAndHolder();
mHolder = holder;
ImageWrapper imageWrapper = holder.getValue();
Drawable drawable = new ImageDrawable(imageWrapper);
imageWrapper.start();
setImageDrawable(drawable);
mProgressView.setVisibility(GONE);
mProgressView.setIndeterminate(false);
mFailed.setVisibility(GONE);
mPhotoView.setVisibility(VISIBLE);
return true;
}
@Override
public void onSetDrawable(Drawable drawable) {
}
@Override
public void onFailure() {
mProgressView.setVisibility(GONE);
mProgressView.setIndeterminate(false);
mFailed.setVisibility(VISIBLE);
mPhotoView.setVisibility(GONE);
removeDrawableAndHolder();
addRetry();
}
@Override
public void onCancel() {
removeRetry();
mKey = null;
mUrl = null;
mContainer = null;
}
public void showDrawable(@NonNull Drawable drawable) {
mProgressView.setVisibility(GONE);
mProgressView.setIndeterminate(false);
mFailed.setVisibility(GONE);
mPhotoView.setVisibility(VISIBLE);
removeDrawableAndHolder();
setImageDrawable(drawable);
}
public void showFailedText() {
mProgressView.setVisibility(GONE);
mProgressView.setIndeterminate(false);
mFailed.setVisibility(VISIBLE);
mPhotoView.setVisibility(GONE);
removeDrawableAndHolder();
}
public boolean isLoaded() {
return mPhotoView.getDrawable() != null;
}
}