]*>)?
]*href=\"([^<>\"]+)\"[^<>]*>");
- Matcher m = p.matcher(pageContent);
- if (m.find()) {
- pageSum = Integer.parseInt(m.group(1).replace(",", ""));
- firstPage = m.group(2);
- return true;
- }
- return false;
- }
-
- /**
- * Get page info, previous page, next page, image url
- *
- * @param pageUrlStr
- * @return True if get
- */
- public boolean getPageInfoSumForPage(String pageUrlStr) {
- HttpHelper hp = new HttpHelper(mAppContext);
- String pageContent = hp.get(pageUrlStr);
- if (pageContent == null)
- return false;
-
- Pattern p = Pattern.compile("]*id=\"prev\"[^<>]*href=\"([^<>\"]+)\">
]*/>.+
]id=\"next\"[^<>]*href=\"([^<>\"]+)\">
]*/>.+
![]()
]*src=\"([^<>\"]+?)\"[^<>]*style=\"[^<>\"]*\"[^<>]*/>");
- Matcher m = p.matcher(pageContent);
- if (m.find()) {
- prePage = m.group(1);
- nextPage = m.group(2);
- imageUrlStr = Utils.unescapeXml(m.group(3));
- return true;
- }
- return false;
- }
-
-
- }
-
// Post comment
public interface OnCommentListener {
void onSuccess(List
comments);
diff --git a/src/com/hippo/ehviewer/ehclient/ExDownloader.java b/src/com/hippo/ehviewer/ehclient/ExDownloader.java
index 5e5d987d6..7f7e3076a 100644
--- a/src/com/hippo/ehviewer/ehclient/ExDownloader.java
+++ b/src/com/hippo/ehviewer/ehclient/ExDownloader.java
@@ -23,8 +23,10 @@ import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashSet;
import java.util.List;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import android.content.Context;
@@ -33,7 +35,7 @@ import android.os.Process;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.network.HttpHelper;
import com.hippo.ehviewer.util.AutoExpandArray;
-import com.hippo.ehviewer.util.Config;
+import com.hippo.ehviewer.util.EhUtils;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
@@ -44,55 +46,74 @@ public class ExDownloader implements Runnable {
private static final int WORKER_NUM = 3;
private final Context mContext;
- private final ExDownloadManager mManager;
+ private final ExDownloaderManager mManager;
private final int mGid;
private final String mToken;
private final String mTitle;
private final int mMode;
- private int mPreviewPageNum = -1;
- private int mPreviewPerPage = -1;
- private int mImageNum = -1;
+ private volatile int mPreviewPageNum = -1;
+ private volatile int mPreviewPerPage = -1;
+ private volatile int mImageNum = -1;
private final AutoExpandArray mPageTokeArray = new AutoExpandArray();
+ private final AutoExpandArray mImageFilenameArray = new AutoExpandArray();
private volatile int mOwnerNum = 0;
private Thread mMainThread = null;
- /** Only work for EhClient.MODE_LOFI **/
+ /** Only work for EhClient.MODE_LOFI when do not know image number **/
private int mCurMaxPreviewPage = -1;
private volatile int mStartIndex = 0;
private final Queue mRequestIndexArray = new ConcurrentLinkedQueue();
private final Queue mNoTokenIndexArray = new ConcurrentLinkedQueue();
private final Queue mRequestPageIndexArray = new ConcurrentLinkedQueue();
+
+ /** The set contains the requsting index **/
+ private final Set mRequstingIndexSet = new HashSet();
+
private volatile int mCurRequestPageIndex = -1;
private final Worker[] mWorkerArray = new Worker[WORKER_NUM];
+ private final HttpHelper.DownloadControlor[] mControlorArray = new HttpHelper.DownloadControlor[WORKER_NUM];
private final Object mPageTokenLock = new Object();
private final Object mWorkerLock = new Object();
private final Object mWorkerGetIndexLock = new Object();
+ private volatile boolean mPauseWork = false;
+ private volatile boolean mStopWork = false;
+
private final File mDir;
+ private ListenerForImageSet mLfis;
private static final int IO_BUFFER_SIZE = 8 * 1024;
+ public interface ListenerForImageSet {
+ public void onDownloadStart(int index);
+ public void onDownloading(int index, float percent);
+ public void onDownloadComplete(int index);
+ public void onDownloadFail(int index);
+ }
+
+ public interface ListenerForDownload {
+ public void onDownloading(int index);
+ }
+
ExDownloader(int gid, String token, String title, int mode) {
mContext = AppContext.getInstance();
- mManager = ExDownloadManager.getInstance();
+ mManager = ExDownloaderManager.getInstance();
mGid = gid;
mToken = token;
mTitle = title;
mMode = mode;
// Make sure dir
- mDir = new File(Config.getDownloadPath(),
- Utils.standardizeFilename(mGid + "-" + mTitle));
- if (!mDir.exists()) {
- mDir.mkdirs();
- } else if (mDir.isFile()) {
- mDir.delete();
- mDir.mkdirs();
- }
+ mDir = EhUtils.getGalleryDir(mGid, mTitle);
+ Utils.ensureDir(mDir, true);
+ }
+
+ public void setListenerForImageSet(ListenerForImageSet l) {
+ mLfis = l;
}
void occupy() {
@@ -107,6 +128,39 @@ public class ExDownloader implements Runnable {
return mOwnerNum == 0;
}
+ void stop() {
+ // TODO stop all thread, release all resources
+ mStopWork = true;
+ // Stop download
+ for (HttpHelper.DownloadControlor c : mControlorArray) {
+ if (c != null)
+ c.stop();
+ }
+ // Wake all thread
+ synchronized(mPageTokenLock) {mPageTokenLock.notifyAll();}
+ synchronized(mWorkerGetIndexLock) {mWorkerGetIndexLock.notifyAll();}
+ synchronized(mWorkerLock) {mWorkerLock.notifyAll();}
+ }
+
+ void pause(boolean pause) {
+ mPauseWork = pause;
+ if (mPauseWork) {
+ // Stop download
+ for (HttpHelper.DownloadControlor c : mControlorArray)
+ if (c != null) c.stop();
+ // Wake all thread
+ synchronized(mPageTokenLock) {mPageTokenLock.notifyAll();}
+ synchronized(mWorkerGetIndexLock) {mWorkerGetIndexLock.notifyAll();}
+ synchronized(mWorkerLock) {mWorkerLock.notifyAll();}
+ } else {
+ // Reset download
+ for (HttpHelper.DownloadControlor c : mControlorArray)
+ if (c != null) c.reset();
+ ensureStart();
+ ensureWorkers();
+ }
+ }
+
public int getGid() {
return mGid;
}
@@ -116,7 +170,7 @@ public class ExDownloader implements Runnable {
}
public void setStartIndex(int startIndex) {
- if (mImageNum != -1 && mStartIndex >= mImageNum)
+ if (mImageNum != -1 && startIndex >= mImageNum)
mStartIndex = 0;
else
mStartIndex = startIndex;
@@ -125,14 +179,49 @@ public class ExDownloader implements Runnable {
ensureWorkers();
}
- public void setTargetIndex(int startIndex) {
- if (mImageNum != -1 && mStartIndex >= mImageNum) {
- mRequestIndexArray.offer(startIndex);
- ensureStart();
- ensureWorkers();
+ public void setTargetIndex(int index) {
+ if (mImageNum != -1 && index >= mImageNum)
+ return;
+
+ mRequestIndexArray.offer(index);
+ ensureStart();
+ ensureWorkers();
+ }
+
+ public int getMaxEnsureIndex() {
+ if (mImageNum != -1) {
+ return mImageNum;
+ } else {
+ return Math.max(Math.max(mStartIndex - 1,
+ Math.max(mCurMaxPreviewPage, mPreviewPageNum - 1) * mPreviewPerPage),
+ mPageTokeArray.maxValidIndex());
}
}
+ /**
+ * If do not know image num, return -1.
+ * You should call getMaxEnsureIndex().
+ *
+ * @return
+ */
+ public int getImageNum() {
+ return mImageNum;
+ }
+
+ public AutoExpandArray getImageFilenameArray() {
+ return mImageFilenameArray;
+ }
+
+ /**
+ * If targer index image is downloading, return true
+ *
+ * @param index
+ * @return
+ */
+ public boolean isDownloading(int index) {
+ return mRequstingIndexSet.contains(index);
+ }
+
private synchronized void ensureStart() {
if (mMainThread != null)
return;
@@ -196,10 +285,14 @@ public class ExDownloader implements Runnable {
}
mImageNum = Integer.parseInt(Utils.readAsciiLine(is));
- if (mImageNum != -1)
+ if (mImageNum != -1) {
mPageTokeArray.setCapacity(mImageNum);
- else if (mPreviewPageNum != -1 && mPreviewPerPage != -1)
+ mImageFilenameArray.setCapacity(mImageNum);
+ }
+ else if (mPreviewPageNum != -1 && mPreviewPerPage != -1) {
mPageTokeArray.setCapacity(mPreviewPageNum * mPreviewPerPage);
+ mImageFilenameArray.setCapacity(mPreviewPageNum * mPreviewPerPage);
+ }
// read page token info
try {
@@ -288,6 +381,7 @@ public class ExDownloader implements Runnable {
mPreviewPageNum = edp.previewPageNum;
mImageNum = edp.imageNum;
mPageTokeArray.setCapacity(mPreviewPageNum * mPreviewPerPage);
+ mImageFilenameArray.setCapacity(mPreviewPageNum * mPreviewPerPage);
}
}
for (int i = 0; i < pageTokenArray.size(); i++)
@@ -301,27 +395,21 @@ public class ExDownloader implements Runnable {
}
private void ensureWorkers() {
+ if (mPreviewPerPage == -1)
+ return;
+
synchronized(mWorkerArray) {
for (int i = 0; i < mWorkerArray.length; i++) {
if (mWorkerArray[i] == null) {
- Worker worker = new Worker();
+ Worker worker = new Worker(i);
worker.start();
mWorkerArray[i] = worker;
+ mControlorArray[i] = new HttpHelper.DownloadControlor();
}
}
}
}
- public int getMaxEnsureIndex() {
- if (mImageNum != -1) {
- return mImageNum;
- } else {
- return Math.max(Math.max(mStartIndex - 1,
- Math.max(mCurMaxPreviewPage, mPreviewPageNum - 1) * mPreviewPerPage),
- mPageTokeArray.maxValidIndex());
- }
- }
-
// TODO for download , when to claim download completed
@Override
public void run() {
@@ -337,7 +425,10 @@ public class ExDownloader implements Runnable {
// A loop to get page token
while (true) {
- Log.d(TAG, "A new loop to get page token");
+
+ // Check stop
+ if (mStopWork)
+ break;
int noTokenIndex = -1;
int pageIndex = -1;
@@ -357,6 +448,9 @@ public class ExDownloader implements Runnable {
}
}
+ Log.d(TAG, "noTokenIndex = " + noTokenIndex);
+ Log.d(TAG, "pageIndex = " + pageIndex);
+
if (noTokenIndex != -1) {
if (mPageTokeArray.get(noTokenIndex) == null) {
getDetailInfo(noTokenIndex / mPreviewPerPage, ediFile, false);
@@ -373,18 +467,22 @@ public class ExDownloader implements Runnable {
}
} catch (Throwable e) {
// TODO handle error here
-
} finally {
synchronized (this) {
mMainThread = null;
}
}
+
+ Log.d(TAG, "ExDownloader over");
}
private class Worker extends Thread {
- public Worker() {
+ private final int mIndex;
+
+ public Worker(int index) {
super();
+ mIndex = index;
setPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
@@ -408,12 +506,20 @@ public class ExDownloader implements Runnable {
private int getTargetIndex() {
synchronized(mWorkerGetIndexLock) {
while (true) {
+
+ // Check stop
+ if (mStopWork || mPauseWork)
+ return -1;
+
if (!mRequestIndexArray.isEmpty()) {
return mRequestIndexArray.poll();
} else if (mImageNum != -1 && mStartIndex == mImageNum) {
return -1;
} else if (mImageNum == -1 && mStartIndex > getMaxEnsureIndex()) {
// If do not sure the index is valid
+
+ Log.d(TAG, "mPreviewPerPage = " + mPreviewPerPage);
+
addRequstPageIndex(getMaxEnsureIndex() / mPreviewPerPage);
try {
mWorkerGetIndexLock.wait();
@@ -425,47 +531,57 @@ public class ExDownloader implements Runnable {
}
}
- private String getExtension(String name, String defautl) {
- int index = name.lastIndexOf('.');
- if (index == -1 || index == name.length() - 1)
- return defautl;
- else
- return name.substring(index + 1);
- }
-
- private String getImageName(int index, String url) {
- return String.format("%08d.%s", index + 1, getExtension(url, "jpg"));
- }
-
- private String[] getPossibleFilenames(int index) {
- String prefix = String.format("%08d.", index + 1);
- return new String[]{prefix + "jpg", prefix + "jpeg", prefix + "png", prefix + "gif"};
- }
-
@Override
public void run() {
+ HttpDownloadListener listener = new HttpDownloadListener();
HttpHelper hh = new HttpHelper(mContext);
ImagePageParser ipp = new ImagePageParser();
while (true) {
+ // Check stop
+ if (mStopWork || mPauseWork)
+ break;
+
int targetIndex = getTargetIndex();
if (targetIndex == -1)
break;
+ // Check is the index is requsted
+ if (mRequstingIndexSet.contains(targetIndex))
+ continue;
+
// Check is this already downloaded
boolean isAlreadyDownloaded = false;
- for (String possibleFilename : getPossibleFilenames(targetIndex)) {
- File file = new File(mDir, possibleFilename);
- if (file.exists()) {
+ // First check mImageFilenameArray
+ String imageFilename = mImageFilenameArray.get(targetIndex);
+ if (imageFilename != null) {
+ File file = new File(mDir, imageFilename);
+ if (file.exists())
isAlreadyDownloaded = true;
- break;
+ } else {
+ // Can not find image file name, just guess
+ for (String possibleFilename : EhUtils.getPossibleImageFilenames(targetIndex)) {
+ File file = new File(mDir, possibleFilename);
+ if (file.exists()) {
+ isAlreadyDownloaded = true;
+ mImageFilenameArray.set(targetIndex, possibleFilename);
+ break;
+ }
}
}
if (isAlreadyDownloaded)
continue;
- String pageToken;
+ mRequstingIndexSet.add(targetIndex);
+
+ listener.index = targetIndex;
+
+ String pageToken = null;
while (true) {
+ // Check stop
+ if (mStopWork || mPauseWork)
+ break;
+
pageToken = mPageTokeArray.get(targetIndex);
if (pageToken == null) {
addNoTokenIndex(targetIndex);
@@ -474,75 +590,106 @@ public class ExDownloader implements Runnable {
catch (InterruptedException e) {}
}
} else {
- // Jump out of loop
+ // Get valid page token, jump out of loop
break;
}
}
- for (int i = 0; i < 2; i++) {
- // i == 1, add "?nl=48"
- hh.reset();
- ipp.reset();
- String body = hh.get(EhClient.getPageUrl(mGid, pageToken, targetIndex + 1, mMode)
- + (i == 1 ? "?nl=48" : ""));
- if (ipp.parser(body)) {
- String imageUrl = ipp.imageUrl;
- String filename = getImageName(targetIndex, imageUrl);
- for (int j = 0; j < 2; j++) {
- // j == 0, use proxy
-
- }
- } else {
- // TODO parser error, Do somthing
- break;
- }
- }
-
-
-
// Parser image page
- for (int i = 0; i < 2; i++) {
+ for (int i = 0; i < 2 && !mStopWork && !mPauseWork; i++) {
hh.reset();
ipp.reset();
String body = hh.get(EhClient.getPageUrl(mGid, pageToken, targetIndex + 1, mMode)
+ (i == 1 ? "?nl=48" : ""));
- if (ipp.parser(body)) {
+ if (ipp.parser(body, mMode)) {
// Download image
+ HttpHelper.DownloadControlor c = mControlorArray[mIndex];
String imageUrl = ipp.imageUrl;
- String filename = getImageName(targetIndex, imageUrl);
+ String filename = EhUtils.getImageFilename(targetIndex, Utils.getExtension(imageUrl, "jpg"));
+ // Just put filename to mImageFilenameArray
+ mImageFilenameArray.set(targetIndex, filename);
hh.reset();
- if (hh.download(imageUrl, mDir, filename, false, null, null) == null) {
+ if (hh.download(imageUrl, mDir, filename, false, c, listener) == null) {
hh.reset();
- if (hh.download(imageUrl, mDir, filename, true, null, null) == null) {
+ if (hh.download(imageUrl, mDir, filename, true, c, listener) == null) {
if (i == 1) {
// TODO download error
+ Log.d(TAG, "download error");
}
} else {
// download ok
+ Log.d(TAG, "download ok proxy");
break;
}
} else {
// download ok
+ Log.d(TAG, "download ok");
break;
}
} else {
// TODO parser error, Do somthing
+ Log.d(TAG, "parser error");
break;
}
}
+
+ // Remove from requsting set
+ mRequstingIndexSet.remove(targetIndex);
}
// Worker over
synchronized(mWorkerArray) {
// Remove from mWorkerArray
- for (int i = 0; i < mWorkerArray.length; i++) {
- if (mWorkerArray[i] == this) {
- mWorkerArray[i] = null;
- break;
- }
- }
+ mWorkerArray[mIndex] = null;
+ mControlorArray[mIndex] = null;
}
- Log.d(TAG, "Worker over");
+ Log.d(TAG, "ExDownloader Worker over");
+ }
+ }
+
+ public class HttpDownloadListener implements HttpHelper.OnDownloadListener {
+
+ public int index;
+ private float lastPercent;
+
+ @Override
+ public void onDownloadStartConnect() {
+ lastPercent = 0.0f;
+
+ if (mLfis != null)
+ mLfis.onDownloadStart(index);
+ }
+
+ @Override
+ public void onDownloadStartDownload(int totalSize) {
+ lastPercent = 0.0f;
+ }
+
+ @Override
+ public void onDownloadStatusUpdate(int downloadSize, int totalSize) {
+ if (totalSize == -1)
+ return;
+
+ float percent = (float)downloadSize / totalSize;
+ if (percent - lastPercent >= 0.05f) {
+ lastPercent = percent;
+
+ if (mLfis != null)
+ mLfis.onDownloading(index, percent);
+ }
+ }
+
+ @Override
+ public void onDownloadOver(int status, String eMsg) {
+ if (status == HttpHelper.DOWNLOAD_OK_CODE)
+ mRequstingIndexSet.remove(index);
+
+ if (mLfis != null && status == HttpHelper.DOWNLOAD_OK_CODE)
+ mLfis.onDownloadComplete(index);
+ else if (mLfis != null && status == HttpHelper.DOWNLOAD_FAIL_CODE)
+ mLfis.onDownloadFail(index);
+
+ lastPercent = 0.0f;
}
}
}
diff --git a/src/com/hippo/ehviewer/ehclient/ExDownloadManager.java b/src/com/hippo/ehviewer/ehclient/ExDownloaderManager.java
similarity index 84%
rename from src/com/hippo/ehviewer/ehclient/ExDownloadManager.java
rename to src/com/hippo/ehviewer/ehclient/ExDownloaderManager.java
index aced35d8b..5612aa43a 100644
--- a/src/com/hippo/ehviewer/ehclient/ExDownloadManager.java
+++ b/src/com/hippo/ehviewer/ehclient/ExDownloaderManager.java
@@ -23,25 +23,25 @@ import android.util.SparseArray;
import com.hippo.ehviewer.AppContext;
-public class ExDownloadManager {
+public class ExDownloaderManager {
- private static final String TAG = ExDownloadManager.class.getSimpleName();
+ private static final String TAG = ExDownloaderManager.class.getSimpleName();
private final Context mContext;
private final SparseArray mExDownloadList;
private final File mExDownloadInfoDir;
- private static ExDownloadManager sInstance;
+ private static ExDownloaderManager sInstance;
public static void createInstance() {
- sInstance = new ExDownloadManager();
+ sInstance = new ExDownloaderManager();
}
- public static ExDownloadManager getInstance() {
+ public static ExDownloaderManager getInstance() {
return sInstance;
}
- private ExDownloadManager() {
+ private ExDownloaderManager() {
mContext = AppContext.getInstance();
mExDownloadList = new SparseArray();
// Init download info dir
@@ -70,7 +70,9 @@ public class ExDownloadManager {
public synchronized void freeExDownloader(ExDownloader exDownloader) {
exDownloader.free();
- if (exDownloader.isOrphans())
+ if (exDownloader.isOrphans()) {
+ exDownloader.stop();
mExDownloadList.remove(exDownloader.getGid());
+ }
}
}
diff --git a/src/com/hippo/ehviewer/ehclient/ImagePageParser.java b/src/com/hippo/ehviewer/ehclient/ImagePageParser.java
index 3e499804d..830d17e5d 100644
--- a/src/com/hippo/ehviewer/ehclient/ImagePageParser.java
+++ b/src/com/hippo/ehviewer/ehclient/ImagePageParser.java
@@ -33,19 +33,42 @@ public class ImagePageParser {
token = null;
}
- public boolean parser(String body) {
- Pattern p = Pattern.compile(".+?
\"")
]+>");
+ m = p.matcher(body);
+ if (m.find())
+ imageUrl = Utils.unescapeXml(m.group(1));
+ else
+ return false;
+
+ p = Pattern.compile("Back");
+ m = p.matcher(body);
+ if (m.find()) {
+ gid = Integer.parseInt(m.group(1));
+ token = m.group(2);
+ return true;
+ } else {
+ return false;
+ }
- if (m.find()) {
- imageUrl = Utils.unescapeXml(m.group(1));
- gid = Integer.parseInt(m.group(2));
- token = m.group(3);
- return true;
} else {
- return false;
+ p = Pattern.compile("
.+?
\"")
= mSize)
- mCurIndex = 0;
-
+ mCurIndex = MathUtils.clamp(mCurIndex, 0, mSize - 1);
+
setState();
-
+
mGestureRecognizer = new GestureRecognizer(mContext, new MyGestureListener());
setBackgroundColor(GalleryUtils.intColorToFloatARGBArray(BACKGROUND_COLOR));
-
+
showItems = new ShowItem[TARGET_INDEX_SIZE];
-
+
// Init config
scaleMode = Config.getPageScalingMode();
startMode = Config.getStartPosition();
-
- //
- imageSet.setOnStateChangeListener(new ImageSet.OnStateChangeListener() {
- @Override
- public void onStateChange(int index, int state) {
- int targetIndex = index - mCurIndex + 1;
- if (targetIndex >= PRE_TARGET_INDEX
- && targetIndex <= NEXT_TARGET_INDEX) {
- loadImage(index);
- }
- }
- });
+
+ mImageSet.setImageListener(this);
+
+ // Start task to check size
+ AppHandler.getInstance().postDelayed(this, 500);
+
+ // Try to make current index show image
+ if (mCurIndex != startIndex)
+ mImageSet.setTargetIndex(mCurIndex);
+
+ // First time to load image in onLayout()
}
-
+
+ // The task to update size
+ @Override
+ public void run() {
+ checkSize();
+ if (!isEnsureSize && !mImageSet.isStop())
+ AppHandler.getInstance().postDelayed(this, 500);
+ }
+
+ /**
+ * Check size
+ */
+ private void checkSize() {
+ int size = mImageSet.getSize();
+ if (size == -1) {
+ isEnsureSize = false;
+ mSize = mImageSet.getEnsureSize();
+ } else {
+ isEnsureSize = true;
+ mSize = size;
+ }
+ }
+
+ /**
+ * Set current page state, first page or last page
+ */
private void setState() {
mState = STATE_NONE;
if (mCurIndex == 0)
- mState |= STATE_FIRST;
+ mState = STATE_FIRST;
if (mCurIndex == mSize - 1)
- mState |= STATE_LAST;
+ mState = STATE_LAST;
}
-
+
+ private boolean checkIndex(int index) {
+ int targetIndex = index - mCurIndex + 1;
+ return targetIndex == CUR_TARGET_INDEX ||
+ (mState != STATE_FIRST && targetIndex == PRE_TARGET_INDEX) ||
+ (mState != STATE_LAST && targetIndex == NEXT_TARGET_INDEX);
+ }
+
+ @Override
+ public void onGetImage(int index) {
+ if (checkIndex(index)) {
+ loadImage(index);
+ }
+ }
+
+ @Override
+ public void onDownloading(int index, float percent) {
+ int targetIndex = index - mCurIndex + 1;
+ if (checkIndex(index)) {
+ // Free what do not need
+ ShowItem showItem = showItems[targetIndex];
+ if (showItem != null)
+ showItem.recycle();
+
+ showItems[targetIndex] = new Text(
+ String.format("正在加载 %d%%", Math.round(percent * 100)));
+ resetSizePosition(targetIndex);
+ }
+ }
+
+ @Override
+ public void onDecodeOver(int index, Object res) {
+ int targetIndex = index - mCurIndex + 1;
+
+ if (!checkIndex(index)) {
+ // If it do not need any more, free
+ if (res != null && res instanceof Bitmap)
+ ((Bitmap)res).recycle();
+ } else {
+ // Free what do not need
+ ShowItem showItem = showItems[targetIndex];
+ if (showItem != null)
+ showItem.recycle();
+
+ if (res == null) {
+ showItems[targetIndex] = new Text("读取图片错误"); // TODO
+ } else {
+ if (res instanceof Bitmap) {
+ BitmapImage bi = new BitmapImage();
+ bi.load((Bitmap)res);
+ showItems[targetIndex] = bi;
+ } else {
+ MovieImage mi = new MovieImage();
+ mi.load((Movie)res);
+ showItems[targetIndex] = mi;
+ }
+ }
+ resetSizePosition(targetIndex);
+ }
+ }
+
private void drawTapArea(GLCanvas canvas) {
// Background
canvas.fillRect(0, 0, mWidth, mHeight, TAP_AREA_MASK_COLOR);
-
+
drawRect(canvas, leftArea);
drawRect(canvas, topArea);
drawRect(canvas, rightArea);
@@ -245,25 +328,25 @@ public class GalleryView extends GLView {
bottomText.draw(canvas);
centerText.draw(canvas);
}
-
+
private void drawRect(GLCanvas canvas, int[] rect) {
-
+
int left = rect[0];
int top = rect[1];
int right = rect[2];
int bottom = rect[3];
-
+
GLPaint paint = new GLPaint(LINE_COLOR, LINE_WIDTH);
canvas.drawLine(left, top, right, top, paint);
canvas.drawLine(left, bottom, right, bottom, paint);
canvas.drawLine(left, top, left, bottom, paint);
canvas.drawLine(right, top, right, bottom, paint);
}
-
+
@Override
protected void render(GLCanvas canvas) {
super.render(canvas);
-
+
boolean hasMovie = false;
ShowItem item;
switch (mScrollState) {
@@ -274,7 +357,7 @@ public class GalleryView extends GLView {
if (item instanceof MovieImage)
hasMovie |= true;
break;
-
+
case SCROLL_LEFT:
case SCROLL_ANIME_LEFT:
item = showItems[PRE_TARGET_INDEX];
@@ -282,14 +365,14 @@ public class GalleryView extends GLView {
item.draw(canvas, scrollXOffset, scrollYOffset);
if (item instanceof MovieImage)
hasMovie |= true;
-
+
item = showItems[CUR_TARGET_INDEX];
if (item != null)
item.draw(canvas, scrollXOffset, scrollYOffset);
if (item instanceof MovieImage)
hasMovie |= true;
break;
-
+
case SCROLL_RIGHT:
case SCROLL_ANIME_RIGHT:
item = showItems[CUR_TARGET_INDEX];
@@ -297,7 +380,7 @@ public class GalleryView extends GLView {
item.draw(canvas, scrollXOffset, scrollYOffset);
if (item instanceof MovieImage)
hasMovie |= true;
-
+
item = showItems[NEXT_TARGET_INDEX];
if (item != null)
item.draw(canvas, scrollXOffset, scrollYOffset);
@@ -305,30 +388,29 @@ public class GalleryView extends GLView {
hasMovie |= true;
break;
}
-
+
// Add mInit to make show the leftArea or other is not null
if (mShowTapArea && mInit)
drawTapArea(canvas);
-
+
// TODO Mask to reduce brightness
//canvas.fillRect(0, 0, mWidth, mHeight, MASK_COLOR);
-
-
+
if (hasMovie)
invalidate();
}
-
+
private void resetSizePosition() {
resetSizePosition(PRE_TARGET_INDEX);
resetSizePosition(CUR_TARGET_INDEX);
resetSizePosition(NEXT_TARGET_INDEX);
}
-
+
private void resetSizePosition(int targeIndex) {
ShowItem showItem = showItems[targeIndex];
if (showItem == null)
return;
-
+
int sumXOffset;
switch (targeIndex) {
case PRE_TARGET_INDEX:
@@ -342,7 +424,7 @@ public class GalleryView extends GLView {
sumXOffset = 0;
break;
}
-
+
if (showItem instanceof Text) {
Text text = (Text)showItem;
int xOffset;
@@ -354,12 +436,9 @@ public class GalleryView extends GLView {
rect.top = yOffset;
rect.right = rect.left + text.width;
rect.bottom = rect.top + text.height;
- return;
- }
-
- if (showItem instanceof Image) {
+ } else if (showItem instanceof Image) {
Image image = (Image)showItem;
-
+
// Set scale
int showWidth = 0;
int showHeight = 0;
@@ -401,7 +480,7 @@ public class GalleryView extends GLView {
showHeight = (int)(image.height * mScale);
break;
}
-
+
// adjust scale
if (image.imageScale < SCALE_MIN) {
image.imageScale = SCALE_MIN;
@@ -412,7 +491,7 @@ public class GalleryView extends GLView {
showWidth = (int)(image.width * SCALE_MAX);
showHeight = (int)(image.height * SCALE_MAX);
}
-
+
// set start position
int xOffset;
int yOffset;
@@ -439,31 +518,31 @@ public class GalleryView extends GLView {
yOffset = (mHeight - showHeight)/2;
break;
}
-
+
rect.left = sumXOffset + xOffset;
rect.right = rect.left + showWidth;
rect.top = yOffset;
rect.bottom = rect.top + showHeight;
-
+
// adjust position
adjustPosition(image);
}
-
+
invalidate();
}
-
+
private void setCenterInArea(int[] area, ShowItem showItem) {
int xOffset = ((area[2] - area[0]) - showItem.width)/2;
int yOffset = ((area[3] - area[1]) - showItem.height)/2;
-
+
Rect rect = showItem.mRect;
-
+
rect.left = area[0] + xOffset;
rect.right = rect.left + showItem.width;
rect.top = area[1] + yOffset;
rect.bottom = rect.top + showItem.height;
}
-
+
private void setTapArea() {
leftArea = new int[]{
(int)(LEFT_AREA_SCALE[0] * mWidth),
@@ -490,7 +569,7 @@ public class GalleryView extends GLView {
(int)(CENTER_AREA_SCALE[1] * mHeight),
(int)(CENTER_AREA_SCALE[2] * mWidth),
(int)(CENTER_AREA_SCALE[3] * mHeight)};
-
+
if (leftText == null)
leftText = new Text(mContext.getString(R.string.pre_page),
TAP_AREA_TEXT_SIZE, TAP_AREA_TEXT_COLOR);
@@ -506,20 +585,21 @@ public class GalleryView extends GLView {
if (centerText == null)
centerText = new Text(mContext.getString(R.string.menu),
TAP_AREA_TEXT_SIZE, TAP_AREA_TEXT_COLOR);
-
+
setCenterInArea(leftArea, leftText);
setCenterInArea(topArea, topText);
setCenterInArea(rightArea, rightText);
setCenterInArea(bottomArea, bottomText);
setCenterInArea(centerArea, centerText);
}
-
+
@Override
protected void onLayout(
boolean changeSize, int left, int top, int right, int bottom) {
+ // Get View size
mWidth = right - left;
mHeight = bottom - top;
-
+
if (!mInit) {
mInit = true;
loadImage(mCurIndex);
@@ -530,39 +610,46 @@ public class GalleryView extends GLView {
} else {
resetSizePosition();
}
+
+ // When screen orientation change, need to reset tap area
setTapArea();
+
invalidate();
}
-
+
+ /**
+ * Requset target image from ImageSet,
+ *
+ * @param index
+ */
private void loadImage(int index) {
+ if (!checkIndex(index))
+ return;
+
int targetIndex = index - mCurIndex + 1;
- int state = mImageSet.getImage(index, new DecodeImageListener());
- ShowItem showItem = showItems[targetIndex];
- if (showItem != null)
- showItem.recycle();
- if (state == ImageSet.STATE_LOADED)
- showItems[targetIndex] = new EmptyItem();
- else {
- showItems[targetIndex] = new Text(getErrorStateString(state));
+ Object obj = mImageSet.getImage(index);
+
+ if (showItems[targetIndex] != null)
+ showItems[targetIndex].recycle();
+
+ if (obj instanceof Integer) {
+ int state = (Integer)obj;
+ if (state == ImageSet.RESULT_DECODE) {
+ // TODO maybe i should show a decode text
+ showItems[targetIndex] = new EmptyItem();
+ } else if (state == ImageSet.RESULT_DOWNLOADING) {
+ showItems[targetIndex] = new Text("正在下载"); // TODO
+ } else if (state == ImageSet.RESULT_NONE) {
+ showItems[targetIndex] = new Text("尚未加载"); // TODO
+ }
+ } else if (obj instanceof Float) {
+ showItems[targetIndex] = new Text(
+ String.format("正在加载 %d%%", Math.round((Float)obj * 100)));
}
+
resetSizePosition(targetIndex);
}
-
- private String getErrorStateString(int state) {
- switch (state) {
- case ImageSet.INVALID_ID:
- return "无效的 index";
- case ImageSet.STATE_NONE:
- return "尚未加载";
- case ImageSet.STATE_LOADING:
- return "正在加载";
- case ImageSet.STATE_FAIL:
- return "加载失败";
- default:
- return "错误的代码";
- }
- }
-
+
/**
* If cur page is first page return true
* @return
@@ -570,7 +657,7 @@ public class GalleryView extends GLView {
private boolean isFirstPage() {
return (mState & STATE_FIRST) != 0;
}
-
+
/**
* If cur page is last page return true
* @return
@@ -578,37 +665,9 @@ public class GalleryView extends GLView {
private boolean isLastPage() {
return (mState & STATE_LAST) != 0;
}
-
- class DecodeImageListener implements ImageSet.OnDecodeOverListener {
- @Override
- public void onDecodeOver(Object res, int index) {
- int targetIndex = index - mCurIndex + 1;
-
- if (targetIndex < 0 || targetIndex > 2
- || !(showItems[targetIndex] instanceof EmptyItem)) {// If it do not need any more
- if (res != null && res instanceof Bitmap)
- ((Bitmap)res).recycle();
- } else {
- if (res == null) {
- showItems[targetIndex] = new Text("读取图片错误"); // TODO
- } else {
- if (res instanceof Bitmap) {
- BitmapImage bi = new BitmapImage();
- bi.load((Bitmap)res);
- showItems[targetIndex] = bi;
- } else {
- MovieImage mi = new MovieImage();
- mi.load((Movie)res);
- showItems[targetIndex] = mi;
- }
- }
- resetSizePosition(targetIndex);
- }
- }
- }
-
+
/**
- *
+ *
* @param mode
* true zoom in, false zoom out
* @return
@@ -616,7 +675,7 @@ public class GalleryView extends GLView {
private boolean zoom(boolean mode) {
ShowItem curShowItem;
curShowItem = showItems[CUR_TARGET_INDEX];
-
+
if (curShowItem == null || !(curShowItem instanceof Image))
return false;
Image image = (Image)curShowItem;
@@ -637,21 +696,21 @@ public class GalleryView extends GLView {
}
image.imageScale = newScale;
mScale = newScale;
-
+
Rect rect = image.mRect;
int width = (int)(image.width * newScale);
int height = (int)(image.height * newScale);
int xOffset = (width - rect.width())/2;
int yOffset = (height - rect.height())/2;
-
+
rect.set(rect.left - xOffset, rect.top - yOffset, rect.right + xOffset, rect.bottom + yOffset);
-
+
adjustPosition(curShowItem);
-
+
invalidate();
return true;
}
-
+
/**
* You'd better resetSizePosition(PRE_TARGET_INDEX) before
* @return
@@ -659,7 +718,7 @@ public class GalleryView extends GLView {
private boolean goToPrePage() {
if (isFirstPage())
return false;
-
+
ShowItem showItem;
showItem = showItems[NEXT_TARGET_INDEX];
if (showItem != null)
@@ -667,7 +726,7 @@ public class GalleryView extends GLView {
showItems[NEXT_TARGET_INDEX] = showItems[CUR_TARGET_INDEX];
showItems[CUR_TARGET_INDEX] = showItems[PRE_TARGET_INDEX];
showItems[PRE_TARGET_INDEX] = null;
-
+
// adjust rect
showItem = showItems[NEXT_TARGET_INDEX];
if (showItem != null) {
@@ -677,19 +736,19 @@ public class GalleryView extends GLView {
if (showItem != null) {
showItem.mRect.offset(mWidth, 0);
}
-
+
mCurIndex--;
setState();
loadImage(mCurIndex-1);
-
+
if (mOnScrollPageListener != null) {
mOnScrollPageListener.onScrollPage(mCurIndex);
}
-
+
invalidate();
return true;
}
-
+
/**
* You'd better resetSizePosition(NEXT_TARGET_INDEX) before
* @return
@@ -697,7 +756,7 @@ public class GalleryView extends GLView {
private boolean goToNextPage() {
if (isLastPage())
return false;
-
+
ShowItem showItem;
showItem = showItems[PRE_TARGET_INDEX];
if (showItem != null)
@@ -714,27 +773,53 @@ public class GalleryView extends GLView {
if (showItem != null) {
showItem.mRect.offset(-mWidth, 0);
}
-
+
mCurIndex++;
setState();
loadImage(mCurIndex+1);
-
+
if (mOnScrollPageListener != null) {
mOnScrollPageListener.onScrollPage(mCurIndex);
}
-
+
invalidate();
return true;
}
-
+
@Override
protected boolean onTouch(MotionEvent event) {
mGestureRecognizer.onTouchEvent(event);
return true;
}
-
+
private class MyGestureListener implements GestureRecognizer.Listener {
-
+
+ private boolean isScale = false;
+
+ private final TimeRunner mToPreTimeRunner = new TimeRunner() {
+ @Override
+ protected void run(float interpolatedTime, int runningTime) {
+ scrollXOffset = (int)(stopScrollXOffset + ((mWidth - stopScrollXOffset) * interpolatedTime));
+ invalidate();
+ }
+ };
+
+ private final TimeRunner mToNextTimeRunner = new TimeRunner() {
+ @Override
+ protected void run(float interpolatedTime, int runningTime) {
+ scrollXOffset = (int)(stopScrollXOffset + ((-mWidth - stopScrollXOffset) * interpolatedTime));
+ invalidate();
+ }
+ };
+
+ private final TimeRunner mReturnTimeRunner = new TimeRunner() {
+ @Override
+ protected void run(float interpolatedTime, int runningTime) {
+ scrollXOffset = (int)((1 - interpolatedTime) * stopScrollXOffset);
+ invalidate();
+ }
+ };
+
public MyGestureListener() {
mToPreTimeRunner.setOnTimerListener(new TimeRunner.OnTimeListener() {
@Override
@@ -767,17 +852,7 @@ public class GalleryView extends GLView {
}
});
}
-
- private boolean isInArea(int[] area, int x, int y) {
- if (area.length != 4)
- throw new IllegalArgumentException(
- "area's length should be 4, but it's length is " + area.length);
- if (x >= area[0] && x < area[2] && y >= area[1] && y < area[3])
- return true;
- else
- return false;
- }
-
+
@Override
public boolean onSingleTapConfirmed(float x, float y) {
if (mScrollState != SCROLL_NONE) {
@@ -787,77 +862,80 @@ public class GalleryView extends GLView {
mShowTapAreaTurn = false;
return false;
}
-
+
if ( showItems[CUR_TARGET_INDEX] == null
|| showItems[CUR_TARGET_INDEX] instanceof Text) {
if (mOnTapTextListener != null)
mOnTapTextListener.onTapText(mCurIndex);
//return true;
}
-
+
if (leftArea == null
|| topArea == null
|| rightArea == null
|| bottomArea == null
|| centerArea == null)
return true;
-
- if (isInArea(leftArea, (int)x, (int)y)) {
+
+ if (Utils.isInArea(leftArea, (int)x, (int)y)) {
// TODO goto bottom first the to pre page
resetSizePosition(PRE_TARGET_INDEX);
if (!goToPrePage() && mOnEdgeListener != null)
mOnEdgeListener.onFirstPageEdge();
- } else if (isInArea(topArea, (int)x, (int)y)) {
+ } else if (Utils.isInArea(topArea, (int)x, (int)y)) {
zoom(true);
- } else if (isInArea(rightArea, (int)x, (int)y)) {
+ } else if (Utils.isInArea(rightArea, (int)x, (int)y)) {
// TODO goto bottom first the to pre page
resetSizePosition(NEXT_TARGET_INDEX);
if (!goToNextPage() && mOnEdgeListener != null)
mOnEdgeListener.onLastPageEdge();
- } else if (isInArea(bottomArea, (int)x, (int)y)) {
+ } else if (Utils.isInArea(bottomArea, (int)x, (int)y)) {
zoom(false);
- } else if (isInArea(centerArea, (int)x, (int)y)) {
+ } else if (Utils.isInArea(centerArea, (int)x, (int)y)) {
mShowTapArea = true;
mShowTapAreaTurn = true;
invalidate();
} else {
// Can't catch tap
}
-
+
return true;
}
-
+
@Override
public boolean onDoubleTap(float x, float y) {
Log.d(TAG, "onDoubleTap");
return true;
}
-
+
@Override
public void onLongPress(MotionEvent e) {
- // TODO Auto-generated method stub
-
+ if (isScale)
+ return;
+
+ Utils.vibrator(mContext, 100);
+ mImageSet.setTargetIndex(mCurIndex);
}
-
+
@Override
public boolean onScrollBegin(float dx, float dy, float totalX,
float totalY) {
return this.onScroll(dx, dy, totalX, totalY);
}
-
+
/**
* dx 和 totalX 符号相反,为啥
*/
@Override
public boolean onScroll(float dx, float dy, float totalX, float totalY) {
-
+
if (isScale)
return false;
-
+
ShowItem curShowItem = showItems[CUR_TARGET_INDEX];
if (curShowItem == null) // If not load now
return true;
-
+
switch(mScrollState) {
case SCROLL_ANIME_LEFT:
case SCROLL_ANIME_RIGHT:
@@ -865,7 +943,7 @@ public class GalleryView extends GLView {
case SCROLL_NONE:
boolean changePage = false;
Rect rect = curShowItem.mRect;
-
+
// Check change page or not
if (curShowItem == null || !(curShowItem instanceof Image))
changePage = true;
@@ -912,12 +990,12 @@ public class GalleryView extends GLView {
if (rect.height() <= mHeight)
actDy = 0;
rect.offset(actDx, actDy);
-
+
// Fix position
adjustPosition(curShowItem);
}
break;
-
+
case SCROLL_LEFT:
scrollXOffset -= dx;
if (scrollXOffset <= 0) {
@@ -925,7 +1003,7 @@ public class GalleryView extends GLView {
mScrollState = SCROLL_NONE;
}
break;
-
+
case SCROLL_RIGHT:
scrollXOffset -= dx;
if (scrollXOffset >= 0) {
@@ -934,26 +1012,26 @@ public class GalleryView extends GLView {
}
break;
}
-
+
invalidate();
return true;
}
-
+
@Override
public boolean onScrollEnd() {
-
+
if (isScale)
return false;
-
+
switch(mScrollState) {
case SCROLL_ANIME_LEFT:
case SCROLL_ANIME_RIGHT:
return false;
-
+
case SCROLL_LEFT:
stopScrollXOffset = scrollXOffset;
stopScrollYOffset = scrollYOffset;
-
+
mScrollState = SCROLL_ANIME_LEFT;
if (stopScrollXOffset > mWidth * CHANGE_PAGE_PROPORTION) { // Go to pre page
mToPreTimeRunner.setDuration((int)(MILLSEC_PER_DIX * (mWidth-stopScrollXOffset)));
@@ -966,7 +1044,7 @@ public class GalleryView extends GLView {
case SCROLL_RIGHT:
stopScrollXOffset = scrollXOffset;
stopScrollYOffset = scrollYOffset;
-
+
mScrollState = SCROLL_ANIME_RIGHT;
if (-stopScrollXOffset > mWidth * CHANGE_PAGE_PROPORTION) { // Go to next page
mToNextTimeRunner.setDuration((int)(MILLSEC_PER_DIX * (mWidth+stopScrollXOffset)));
@@ -979,7 +1057,7 @@ public class GalleryView extends GLView {
}
return true;
}
-
+
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
@@ -996,39 +1074,39 @@ public class GalleryView extends GLView {
public boolean onScale(float focusX, float focusY, float scale) {
if (mScrollState == SCROLL_ANIME_LEFT || mScrollState == SCROLL_ANIME_RIGHT)
return true;
-
+
if (mScrollState == SCROLL_LEFT || mScrollState == SCROLL_RIGHT) {
scrollXOffset = 0;
scrollYOffset = 0;
mScrollState = SCROLL_NONE;
}
-
+
ShowItem curShowItem = showItems[CUR_TARGET_INDEX];
if (curShowItem == null || !(curShowItem instanceof Image))
return true;
-
+
Image image = (Image)curShowItem;
-
+
float newScale = image.imageScale * scale;
if (newScale > SCALE_MAX || newScale < SCALE_MIN)
return true;
image.imageScale = newScale;
mScale = newScale;
-
+
Rect rect = image.mRect;
int left = rect.left;
int top = rect.top;
-
+
left = (int)(focusX - ((focusX - left) * scale));
top = (int)(focusY - ((focusY - top) * scale));
-
+
rect.set(left, top, (int)(left + (image.width * image.imageScale)), (int)(top + (image.height * image.imageScale)));
-
+
// adjust
adjustPosition(image);
-
+
invalidate();
-
+
return true;
}
@@ -1046,55 +1124,30 @@ public class GalleryView extends GLView {
@Override
public void onUp() {
mShowEdegTip = true;
-
-
+
+
// if use onSingleTapUp, use below
/*
* if (mShowTapAreaTurn) {
mShowTapAreaTurn = false;
*/
}
-
- // *** TimeRunner *** //
- TimeRunner mToPreTimeRunner = new TimeRunner() {
- @Override
- protected void run(float interpolatedTime, int runningTime) {
- scrollXOffset = (int)(stopScrollXOffset + ((mWidth - stopScrollXOffset) * interpolatedTime));
- invalidate();
- }
- };
-
- TimeRunner mToNextTimeRunner = new TimeRunner() {
- @Override
- protected void run(float interpolatedTime, int runningTime) {
- scrollXOffset = (int)(stopScrollXOffset + ((-mWidth - stopScrollXOffset) * interpolatedTime));
- invalidate();
- }
- };
-
- TimeRunner mReturnTimeRunner = new TimeRunner() {
- @Override
- protected void run(float interpolatedTime, int runningTime) {
- scrollXOffset = (int)((1 - interpolatedTime) * stopScrollXOffset);
- invalidate();
- }
- };
}
-
+
/**
* If side is shorter then parent's, make it in parent's center
* If side is longer then parent's, make sure it fill parent
- *
+ *
* @param showItem
*/
private void adjustPosition(ShowItem showItem) {
Rect rect = showItem.mRect;
int showWidth = rect.width();
int showHeight = rect.height();
-
+
int sumXOffset;
int sumYOffset = 0;
-
+
int targetIndex = getTargetIndex(showItem);
switch (targetIndex) {
case PRE_TARGET_INDEX:
@@ -1107,7 +1160,7 @@ public class GalleryView extends GLView {
default:
sumXOffset = 0;
}
-
+
if (showWidth > mWidth) {
int fixXOffset = rect.left - sumXOffset;
if (fixXOffset > 0) {
@@ -1135,7 +1188,7 @@ public class GalleryView extends GLView {
rect.offsetTo(rect.left, top);
}
}
-
+
public int getTargetIndex(ShowItem showItem) {
if (mImageSet == null)
return INVALID_ID;
@@ -1145,7 +1198,7 @@ public class GalleryView extends GLView {
}
return INVALID_ID;
}
-
+
private abstract class ShowItem {
protected int width = 1;
protected int height = 1;
@@ -1156,15 +1209,15 @@ public class GalleryView extends GLView {
public abstract void draw(GLCanvas canvas, int xOffset, int yOffset);
public abstract void recycle();
}
-
+
private class EmptyItem extends ShowItem{
-
+
private ColorTexture mTexture;
-
+
public EmptyItem() {
mTexture = new ColorTexture(BACKGROUND_COLOR);
}
-
+
@Override
public void recycle() {
mTexture = null;
@@ -1172,15 +1225,16 @@ public class GalleryView extends GLView {
@Override
public void draw(GLCanvas canvas, int xOffset, int yOffset) {
- mTexture.draw(canvas, xOffset, yOffset);
+ if (mTexture != null)
+ mTexture.draw(canvas, xOffset, yOffset);
}
}
-
-
+
+
private abstract class Image extends ShowItem{
private UploadedTexture mTexture;
public float imageScale = 1;
-
+
/**
* You must call init before draw
* @param texture
@@ -1189,92 +1243,92 @@ public class GalleryView extends GLView {
mTexture = texture;
imageScale = 1;
}
-
+
@Override
public void draw(GLCanvas canvas, int xOffset, int yOffset) {
- if (mTexture != null) {
- int targetIndex;
- if ((targetIndex = getTargetIndex(this)) == INVALID_ID)
- mTexture.draw(canvas, mRect.left + xOffset, mRect.top + yOffset, mRect.width(), mRect.height());
- else {
-
- int leftBound = mWidth;
- int topBound = 0;
- int rightBound = 2 * mWidth;
- int bottomBound = mHeight;
-
- switch (targetIndex) {
- case PRE_TARGET_INDEX:
- leftBound = -leftBound;
- rightBound = 0;
- break;
- case CUR_TARGET_INDEX:
- rightBound = leftBound;
- leftBound = 0;
- break;
- case NEXT_TARGET_INDEX:
- default:
- break;
- }
-
- int left = mRect.left;
- int top = mRect.top;
- int right = mRect.right;
- int bottom = mRect.bottom;
-
- // Only show what in the own box
- // TODO only what can be seen
- if (left < leftBound || top < topBound || right > rightBound || bottom > bottomBound) {
- RectF source = new RectF();
- RectF target = new RectF();
-
- if (left < leftBound) {
- target.left = leftBound;
- source.left = (leftBound - left) / imageScale;
- } else {
- target.left = left;
- source.left = 0;
- }
- if (top < topBound) {
- target.top = topBound;
- source.top = (topBound - top) / imageScale;
- } else {
- target.top = top;
- source.top = 0;
- }
- if (right > rightBound) {
- target.right = rightBound;
- source.right = width - ((right - rightBound) / imageScale);
- } else {
- target.right = right;
- source.right = width;
- }
- if (bottom > bottomBound) {
- target.bottom = bottomBound;
- source.bottom = height - ((bottom - bottomBound) / imageScale);
- } else {
- target.bottom = bottom;
- source.bottom = height;
- }
-
- target.left += xOffset;
- target.top += yOffset;
- target.right += xOffset;
- target.bottom += yOffset;
-
- mTexture.draw(canvas, source, target);
+ if (mTexture == null)
+ return;
+
+ int targetIndex;
+ if ((targetIndex = getTargetIndex(this)) == INVALID_ID)
+ mTexture.draw(canvas, mRect.left + xOffset, mRect.top + yOffset, mRect.width(), mRect.height());
+ else {
+ int leftBound = mWidth;
+ int topBound = 0;
+ int rightBound = 2 * mWidth;
+ int bottomBound = mHeight;
+
+ switch (targetIndex) {
+ case PRE_TARGET_INDEX:
+ leftBound = -leftBound;
+ rightBound = 0;
+ break;
+ case CUR_TARGET_INDEX:
+ rightBound = leftBound;
+ leftBound = 0;
+ break;
+ case NEXT_TARGET_INDEX:
+ default:
+ break;
+ }
+
+ int left = mRect.left;
+ int top = mRect.top;
+ int right = mRect.right;
+ int bottom = mRect.bottom;
+
+ // Only show what in the own box
+ // TODO only what can be seen
+ if (left < leftBound || top < topBound || right > rightBound || bottom > bottomBound) {
+ RectF source = new RectF();
+ RectF target = new RectF();
+
+ if (left < leftBound) {
+ target.left = leftBound;
+ source.left = (leftBound - left) / imageScale;
} else {
- mTexture.draw(canvas, left + xOffset, top + yOffset, right - left, bottom - top);
+ target.left = left;
+ source.left = 0;
}
+ if (top < topBound) {
+ target.top = topBound;
+ source.top = (topBound - top) / imageScale;
+ } else {
+ target.top = top;
+ source.top = 0;
+ }
+ if (right > rightBound) {
+ target.right = rightBound;
+ source.right = width - ((right - rightBound) / imageScale);
+ } else {
+ target.right = right;
+ source.right = width;
+ }
+ if (bottom > bottomBound) {
+ target.bottom = bottomBound;
+ source.bottom = height - ((bottom - bottomBound) / imageScale);
+ } else {
+ target.bottom = bottom;
+ source.bottom = height;
+ }
+
+ target.left += xOffset;
+ target.top += yOffset;
+ target.right += xOffset;
+ target.bottom += yOffset;
+
+ mTexture.draw(canvas, source, target);
+ } else {
+ mTexture.draw(canvas, left + xOffset, top + yOffset, right - left, bottom - top);
}
}
}
}
-
+
private class BitmapImage extends Image{
private BitmapTexture mTexture;
private Bitmap mContextBmp;
-
+
public void load(Bitmap bmp) {
if (mTexture != null)
recycle();
@@ -1282,66 +1336,66 @@ public class GalleryView extends GLView {
mTexture = new BitmapTexture(bmp);
width = mContextBmp.getWidth();
height = mContextBmp.getHeight();
-
+
super.init(mTexture);
}
-
+
@Override
public void recycle() {
if (mTexture == null)
return;
-
+
mTexture.recycle();
mContextBmp.recycle();
-
+
mTexture = null;
mContextBmp = null;
}
}
-
+
private class MovieImage extends Image{
private MovieTexture mTexture;
private Movie mContextMovie;
-
+
public void load(Movie movie) {
if (mTexture != null)
recycle();
mContextMovie = movie;
mTexture = MovieTexture.newInstance(mContextMovie);
-
+
width = mContextMovie.width();
height = mContextMovie.height();
-
+
super.init(mTexture);
}
-
+
@Override
public void recycle() {
if (mTexture == null)
return;
-
+
mTexture.recycle();
-
+
mTexture = null;
mContextMovie = null;
}
}
-
+
private class Text extends ShowItem{
private StringTexture mTexture;
-
+
public Text(String str) {
load(str);
}
-
+
public Text(String str, float size, int color) {
load(str, size, color);
}
-
+
public void load(String str) {
load(str, 100, -1);
}
-
+
public void load(String str, float size, int color) {
if (mTexture != null)
recycle();
@@ -1349,13 +1403,13 @@ public class GalleryView extends GLView {
width = mTexture.getWidth();
height = mTexture.getHeight();
}
-
+
@Override
public void draw(GLCanvas canvas, int xOffset, int yOffset) {
if (mTexture != null)
mTexture.draw(canvas, mRect.left + xOffset, mRect.top + yOffset);
}
-
+
@Override
public void recycle() {
if (mTexture == null)
@@ -1365,5 +1419,3 @@ public class GalleryView extends GLView {
}
}
-
-
diff --git a/src/com/hippo/ehviewer/gallery/anim/AlphaAnimation.java b/src/com/hippo/ehviewer/gallery/anim/AlphaAnimation.java
index 91422b77e..56baf5e49 100644
--- a/src/com/hippo/ehviewer/gallery/anim/AlphaAnimation.java
+++ b/src/com/hippo/ehviewer/gallery/anim/AlphaAnimation.java
@@ -16,8 +16,8 @@
package com.hippo.ehviewer.gallery.anim;
-import com.hippo.ehviewer.gallery.common.Utils;
import com.hippo.ehviewer.gallery.glrenderer.GLCanvas;
+import com.hippo.ehviewer.util.MathUtils;
public class AlphaAnimation extends CanvasAnimation {
private final float mStartAlpha;
@@ -42,7 +42,7 @@ public class AlphaAnimation extends CanvasAnimation {
@Override
protected void onCalculate(float progress) {
- mCurrentAlpha = Utils.clamp(mStartAlpha
+ mCurrentAlpha = MathUtils.clamp(mStartAlpha
+ (mEndAlpha - mStartAlpha) * progress, 0f, 1f);
}
}
diff --git a/src/com/hippo/ehviewer/gallery/anim/Animation.java b/src/com/hippo/ehviewer/gallery/anim/Animation.java
index 67b7623ae..5f2f1046d 100644
--- a/src/com/hippo/ehviewer/gallery/anim/Animation.java
+++ b/src/com/hippo/ehviewer/gallery/anim/Animation.java
@@ -18,7 +18,7 @@ package com.hippo.ehviewer.gallery.anim;
import android.view.animation.Interpolator;
-import com.hippo.ehviewer.gallery.common.Utils;
+import com.hippo.ehviewer.util.MathUtils;
// Animation calculates a value according to the current input time.
//
@@ -81,7 +81,7 @@ abstract public class Animation {
if (mStartTime == NO_ANIMATION) return false;
if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis;
int elapse = (int) (currentTimeMillis - mStartTime);
- float x = Utils.clamp((float) elapse / mDuration, 0f, 1f);
+ float x = MathUtils.clamp((float) elapse / mDuration, 0f, 1f);
Interpolator i = mInterpolator;
onCalculate(i != null ? i.getInterpolation(x) : x);
if (elapse >= mDuration) mStartTime = NO_ANIMATION;
diff --git a/src/com/hippo/ehviewer/gallery/common/Utils.java b/src/com/hippo/ehviewer/gallery/common/Utils.java
deleted file mode 100644
index 0110e4038..000000000
--- a/src/com/hippo/ehviewer/gallery/common/Utils.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * 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.ehviewer.gallery.common;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.database.Cursor;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.text.TextUtils;
-import com.hippo.ehviewer.util.Log;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-
-public class Utils {
- private static final String TAG = "Utils";
- private static final String DEBUG_TAG = "GalleryDebug";
-
- private static final long POLY64REV = 0x95AC9329AC4BC9B5L;
- private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL;
-
- private static long[] sCrcTable = new long[256];
-
- private static final boolean IS_DEBUG_BUILD =
- Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug");
-
- private static final String MASK_STRING = "********************************";
-
- // Throws AssertionError if the input is false.
- public static void assertTrue(boolean cond) {
- if (!cond) {
- throw new AssertionError();
- }
- }
-
- // Throws AssertionError with the message. We had a method having the form
- // assertTrue(boolean cond, String message, Object ... args);
- // However a call to that method will cause memory allocation even if the
- // condition is false (due to autoboxing generated by "Object ... args"),
- // so we don't use that anymore.
- public static void fail(String message, Object ... args) {
- throw new AssertionError(
- args.length == 0 ? message : String.format(message, args));
- }
-
- // Throws NullPointerException if the input is null.
- public static T checkNotNull(T object) {
- if (object == null) throw new NullPointerException();
- return object;
- }
-
- // Returns true if two input Object are both null or equal
- // to each other.
- public static boolean equals(Object a, Object b) {
- return (a == b) || (a == null ? false : a.equals(b));
- }
-
- // Returns the next power of two.
- // Returns the input if it is already power of 2.
- // Throws IllegalArgumentException if the input is <= 0 or
- // the answer overflows.
- public static int nextPowerOf2(int n) {
- if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n);
- n -= 1;
- n |= n >> 16;
- n |= n >> 8;
- n |= n >> 4;
- n |= n >> 2;
- n |= n >> 1;
- return n + 1;
- }
-
- // Returns the previous power of two.
- // Returns the input if it is already power of 2.
- // Throws IllegalArgumentException if the input is <= 0
- public static int prevPowerOf2(int n) {
- if (n <= 0) throw new IllegalArgumentException();
- return Integer.highestOneBit(n);
- }
-
- // Returns the input value x clamped to the range [min, max].
- public static int clamp(int x, int min, int max) {
- if (x > max) return max;
- if (x < min) return min;
- return x;
- }
-
- // Returns the input value x clamped to the range [min, max].
- public static float clamp(float x, float min, float max) {
- if (x > max) return max;
- if (x < min) return min;
- return x;
- }
-
- // Returns the input value x clamped to the range [min, max].
- public static long clamp(long x, long min, long max) {
- if (x > max) return max;
- if (x < min) return min;
- return x;
- }
-
- public static boolean isOpaque(int color) {
- return color >>> 24 == 0xFF;
- }
-
- public static void swap(int[] array, int i, int j) {
- int temp = array[i];
- array[i] = array[j];
- array[j] = temp;
- }
-
- /**
- * A function thats returns a 64-bit crc for string
- *
- * @param in input string
- * @return a 64-bit crc value
- */
- public static final long crc64Long(String in) {
- if (in == null || in.length() == 0) {
- return 0;
- }
- return crc64Long(getBytes(in));
- }
-
- static {
- // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c
- long part;
- for (int i = 0; i < 256; i++) {
- part = i;
- for (int j = 0; j < 8; j++) {
- long x = ((int) part & 1) != 0 ? POLY64REV : 0;
- part = (part >> 1) ^ x;
- }
- sCrcTable[i] = part;
- }
- }
-
- public static final long crc64Long(byte[] buffer) {
- long crc = INITIALCRC;
- for (int k = 0, n = buffer.length; k < n; ++k) {
- crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8);
- }
- return crc;
- }
-
- public static byte[] getBytes(String in) {
- byte[] result = new byte[in.length() * 2];
- int output = 0;
- for (char ch : in.toCharArray()) {
- result[output++] = (byte) (ch & 0xFF);
- result[output++] = (byte) (ch >> 8);
- }
- return result;
- }
-
- public static void closeSilently(Closeable c) {
- if (c == null) return;
- try {
- c.close();
- } catch (IOException t) {
- Log.w(TAG, "close fail ", t);
- }
- }
-
- public static int compare(long a, long b) {
- return a < b ? -1 : a == b ? 0 : 1;
- }
-
- public static int ceilLog2(float value) {
- int i;
- for (i = 0; i < 31; i++) {
- if ((1 << i) >= value) break;
- }
- return i;
- }
-
- public static int floorLog2(float value) {
- int i;
- for (i = 0; i < 31; i++) {
- if ((1 << i) > value) break;
- }
- return i - 1;
- }
-
- public static void closeSilently(ParcelFileDescriptor fd) {
- try {
- if (fd != null) fd.close();
- } catch (Throwable t) {
- Log.w(TAG, "fail to close", t);
- }
- }
-
- public static void closeSilently(Cursor cursor) {
- try {
- if (cursor != null) cursor.close();
- } catch (Throwable t) {
- Log.w(TAG, "fail to close", t);
- }
- }
-
- public static float interpolateAngle(
- float source, float target, float progress) {
- // interpolate the angle from source to target
- // We make the difference in the range of [-179, 180], this is the
- // shortest path to change source to target.
- float diff = target - source;
- if (diff < 0) diff += 360f;
- if (diff > 180) diff -= 360f;
-
- float result = source + diff * progress;
- return result < 0 ? result + 360f : result;
- }
-
- public static float interpolateScale(
- float source, float target, float progress) {
- return source + progress * (target - source);
- }
-
- public static String ensureNotNull(String value) {
- return value == null ? "" : value;
- }
-
- public static float parseFloatSafely(String content, float defaultValue) {
- if (content == null) return defaultValue;
- try {
- return Float.parseFloat(content);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- public static int parseIntSafely(String content, int defaultValue) {
- if (content == null) return defaultValue;
- try {
- return Integer.parseInt(content);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- public static boolean isNullOrEmpty(String exifMake) {
- return TextUtils.isEmpty(exifMake);
- }
-
- public static void waitWithoutInterrupt(Object object) {
- try {
- object.wait();
- } catch (InterruptedException e) {
- Log.w(TAG, "unexpected interrupt: " + object);
- }
- }
-
- public static boolean handleInterrruptedException(Throwable e) {
- // A helper to deal with the interrupt exception
- // If an interrupt detected, we will setup the bit again.
- if (e instanceof InterruptedIOException
- || e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- return true;
- }
- return false;
- }
-
- /**
- * @return String with special XML characters escaped.
- */
- public static String escapeXml(String s) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0, len = s.length(); i < len; ++i) {
- char c = s.charAt(i);
- switch (c) {
- case '<': sb.append("<"); break;
- case '>': sb.append(">"); break;
- case '\"': sb.append("""); break;
- case '\'': sb.append("'"); break;
- case '&': sb.append("&"); break;
- default: sb.append(c);
- }
- }
- return sb.toString();
- }
-
- public static String getUserAgent(Context context) {
- PackageInfo packageInfo;
- try {
- packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
- } catch (NameNotFoundException e) {
- throw new IllegalStateException("getPackageInfo failed");
- }
- return String.format("%s/%s; %s/%s/%s/%s; %s/%s/%s",
- packageInfo.packageName,
- packageInfo.versionName,
- Build.BRAND,
- Build.DEVICE,
- Build.MODEL,
- Build.ID,
- Build.VERSION.SDK_INT,
- Build.VERSION.RELEASE,
- Build.VERSION.INCREMENTAL);
- }
-
- public static String[] copyOf(String[] source, int newSize) {
- String[] result = new String[newSize];
- newSize = Math.min(source.length, newSize);
- System.arraycopy(source, 0, result, 0, newSize);
- return result;
- }
-
- // Mask information for debugging only. It returns info.toString() directly
- // for debugging build (i.e., 'eng' and 'userdebug') and returns a mask ("****")
- // in release build to protect the information (e.g. for privacy issue).
- public static String maskDebugInfo(Object info) {
- if (info == null) return null;
- String s = info.toString();
- int length = Math.min(s.length(), MASK_STRING.length());
- return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length);
- }
-
- // This method should be ONLY used for debugging.
- public static void debug(String message, Object ... args) {
- Log.v(DEBUG_TAG, String.format(message, args));
- }
-}
diff --git a/src/com/hippo/ehviewer/gallery/data/DownloadImageSet.java b/src/com/hippo/ehviewer/gallery/data/DownloadImageSet.java
deleted file mode 100644
index b5f143ecd..000000000
--- a/src/com/hippo/ehviewer/gallery/data/DownloadImageSet.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2014 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.ehviewer.gallery.data;
-
-import java.io.File;
-import java.util.Set;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-
-import com.hippo.ehviewer.service.DownloadService;
-
-public class DownloadImageSet extends ImageSet {
-
- public DownloadImageSet(Context context, int gid, File folder, int size,
- int startIndex, int endIndex, Set failIndexSet) {
- super(context, gid, folder, size, startIndex, endIndex, failIndexSet);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(DownloadService.ACTION_UPDATE);
- mContext.registerReceiver(mReceiver, filter);
- }
-
- public void unregisterReceiver() {
- mContext.unregisterReceiver(mReceiver);
- }
-
- private BroadcastReceiver mReceiver = new BroadcastReceiver(){
- @Override
- public void onReceive(Context context, Intent intent) {
- String gid;
- if(intent.getAction().equals(DownloadService.ACTION_UPDATE)
- && (gid = intent.getStringExtra(DownloadService.KEY_GID)) != null
- && gid.equals(mGid)) {
- int index = intent.getIntExtra(DownloadService.KEY_INDEX, -1);
- int state = intent.getIntExtra(DownloadService.KEY_STATE, -1);
- if (index != -1 && state != -1) {
- changeState(index, state);
- }
- }
- }
- };
-
-}
diff --git a/src/com/hippo/ehviewer/gallery/data/ImageSet.java b/src/com/hippo/ehviewer/gallery/data/ImageSet.java
index c4c95246a..965f5f59c 100644
--- a/src/com/hippo/ehviewer/gallery/data/ImageSet.java
+++ b/src/com/hippo/ehviewer/gallery/data/ImageSet.java
@@ -19,244 +19,252 @@ package com.hippo.ehviewer.gallery.data;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.util.Set;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
-import android.annotation.SuppressLint;
-import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Movie;
import android.util.SparseArray;
-import com.hippo.ehviewer.util.Future;
-import com.hippo.ehviewer.util.FutureListener;
-import com.hippo.ehviewer.util.ThreadPool;
-import com.hippo.ehviewer.util.ThreadPool.Job;
-import com.hippo.ehviewer.util.ThreadPool.JobContext;
+import com.hippo.ehviewer.AppHandler;
+import com.hippo.ehviewer.ehclient.ExDownloader;
+import com.hippo.ehviewer.ehclient.ExDownloaderManager;
+import com.hippo.ehviewer.util.AutoExpandArray;
+import com.hippo.ehviewer.util.Config;
+import com.hippo.ehviewer.util.EhUtils;
+import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
-// TODO 初期建立一个线程检索文件夹中所有文件以寻找到所有图片文件
-
-/**
- * @author Hippo
- *
- * ImageSet 用于记录漫画的下载信息
- * 对于已完成下载的则无特殊之处。
- * 对于未完成下载的要记录,开始下载之处,目前下载截止之处,
- * 以及下载失败之处。
- * 同时拥有检查该目录识别图片文件。
- */
-public class ImageSet {
+public class ImageSet implements ExDownloader.ListenerForImageSet {
@SuppressWarnings("unused")
- private static final String TAG = "ImageSet";
+ private static final String TAG = ImageSet.class.getSimpleName();
- private static final String GIF_EXTENSION = "gif";
+ /**
+ * These are code reture by getImage()
+ */
+ public static final int RESULT_NONE = 0x0;
+ public static final int RESULT_DOWNLOADING = 0x1;
+ public static final int RESULT_DECODE = 0x2;
- public static final int TYPE_NONE = 0x0;
- public static final int TYPE_BITMAP = 0x1;
- public static final int TYPE_MOVIE = 0x2;
+ private final ExDownloaderManager mEdManager;
+ private final ExDownloader mExDownloader;
- public static final int INVALID_ID = -1;
+ private final File mDir;
+ private final AutoExpandArray mImageFilenameArray;
+ private ImageListener mListener;
+ private final Queue mDecodeQueue = new ConcurrentLinkedQueue();
+ private final SparseArray mPercentMap = new SparseArray(5);
+ private final DecodeWorker mDecodeWorker;
+ /** If true, then wake Worker, worker will stop **/
+ private volatile boolean mStopWork = false;
- public static final int STATE_NONE = 0;
- public static final int STATE_LOADING = 1;
- public static final int STATE_LOADED = 2;
- public static final int STATE_FAIL = 3;
+ public class DecodeInfo {
+ public int index;
+ public String filename;
- protected Context mContext;
- protected int mGid;
- protected File mFolder;
- protected int mSize;
-
- private final SparseArray mImagesDate;
-
- private final ThreadPool mThreadPool;
- private OnStateChangeListener mOnStateChangeListener;
-
- public interface OnStateChangeListener {
- void onStateChange(int index, int state);
+ public DecodeInfo(int index, String filename) {
+ this.index = index;
+ this.filename = filename;
+ }
}
- public interface OnDecodeOverListener {
+ public interface ImageListener {
/**
- * May return Bitmap or Movie
+ * It will be invoke when ExDownloader download successful
*
- * @param res
* @param index
*/
- void onDecodeOver(Object res, int index);
+ void onGetImage(int index);
+
+ void onDownloading(int index, float percent);
+
+ /**
+ * It will be invoke when decode image over
+ *
+ * @param index
+ * @param res
+ */
+ void onDecodeOver(int index, Object res);
}
- private class ImageData {
- int state;
- String fileName;
- int type;
+ public ImageSet(int gid, String token, String title, int startIndex) {
- public ImageData() {
- state = STATE_NONE;
- fileName = null;
- type = TYPE_NONE;
- }
+ mDir = EhUtils.getGalleryDir(gid, title);
+ Utils.ensureDir(mDir, true);
+
+ // Init ExDownloader
+ mEdManager = ExDownloaderManager.getInstance();
+ mExDownloader = mEdManager.getExDownloader(gid, token, title, Config.getMode());
+ mExDownloader.setStartIndex(startIndex);
+ mExDownloader.setListenerForImageSet(this);
+
+ mImageFilenameArray = mExDownloader.getImageFilenameArray();
+
+ // Start decode worker
+ mDecodeWorker = new DecodeWorker();
+ mDecodeWorker.start();
}
- // [startIndex, endIndex)
- public ImageSet(Context context, int gid, File folder, int size, int startIndex, int endIndex,
- Set failIndexSet) {
-
- if (folder == null || !folder.isDirectory())
- size = 0;
-
-
- // TODO
- /*
- if (folder == null)
- throw new IllegalArgumentException("Folder is null");
- if (!folder.isDirectory())
- throw new IllegalArgumentException("Folder is not directory, path is " + folder.getPath());
- */
-
- if (size < 0)
- size = 0;
- if (endIndex > size)
- endIndex = size;
- if (startIndex < 0)
- startIndex = 0;
- if (startIndex > endIndex)
- startIndex = endIndex;
-
- // TODO
- /*
- if (size < 0 || startIndex < 0
- || startIndex > endIndex || endIndex > size)
- throw new IllegalArgumentException("size or index value error, size = "
- + size + ", startIndex = " + startIndex
- + ", endIndex = " + endIndex + ", path is " + folder.getPath());
- */
-
- mContext = context;
- mGid = gid;
- mFolder = folder;
- mSize = size;
-
- // TODO sometimes size is too large
- mImagesDate = new SparseArray(mSize);
- int i = 0;
- for (; i < startIndex; i++) {
- mImagesDate.append(i, new ImageData());
- }
- for (; i < endIndex; i++) {
- if (failIndexSet != null && failIndexSet.contains(i)) {
- ImageData imageData = new ImageData();
- imageData.state = STATE_FAIL;
- mImagesDate.append(i, imageData);
- }
- else {
- // Get file name only when you need it
- ImageData imageData = new ImageData();
- imageData.state = STATE_LOADED;
- mImagesDate.append(i, imageData);
- }
- }
- for (; i < size; i++) {
- mImagesDate.append(i, new ImageData());
- }
-
- mThreadPool = new ThreadPool(1, 1);
+ public boolean isStop() {
+ return mStopWork;
}
public int getSize() {
- return mSize;
+ return mExDownloader.getImageNum();
}
- public void setOnStateChangeListener(OnStateChangeListener l) {
- mOnStateChangeListener = l;
+ public int getEnsureSize() {
+ return mExDownloader.getMaxEnsureIndex() + 1;
}
- public int getImage(final int index, final OnDecodeOverListener listener) {
- final ImageData imageData = mImagesDate.get(index);
- int state;
- if (imageData == null)
- state = INVALID_ID;
- else
- state = imageData.state;
- if (state == STATE_LOADED && listener != null) {
- mThreadPool.submit(new Job