Add GLGallery library
This commit is contained in:
1 parent
94c50b27bf
commit
ebaba88cde
20 files changed
+159
-4900
No files matched your search
@@ -29,9 +29,8 @@ import android.util.Log;
|
||||
import com.hippo.ehviewer.client.EhConfig;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryView;
|
||||
import com.hippo.ehviewer.gallery.gl.ImageView;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.glgallery.GalleryView;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
@@ -434,7 +433,7 @@ public class Settings {
|
||||
}
|
||||
|
||||
private static final String KEY_READING_DIRECTION = "reading_direction";
|
||||
private static final int DEFAULT_READING_DIRECTION = GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT;
|
||||
private static final int DEFAULT_READING_DIRECTION = GalleryView.LAYOUT_RIGHT_TO_LEFT;
|
||||
|
||||
@GalleryView.LayoutMode
|
||||
public static int getReadingDirection() {
|
||||
@@ -446,11 +445,11 @@ public class Settings {
|
||||
}
|
||||
|
||||
private static final String KEY_PAGE_SCALING = "page_scaling";
|
||||
private static final int DEFAULT_PAGE_SCALING = ImageView.SCALE_FIT;
|
||||
private static final int DEFAULT_PAGE_SCALING = GalleryView.SCALE_FIT;
|
||||
|
||||
@ImageView.Scale
|
||||
@GalleryView.ScaleMode
|
||||
public static int getPageScaling() {
|
||||
return ImageView.sanitizeScaleMode(getIntFromStr(KEY_PAGE_SCALING, DEFAULT_PAGE_SCALING));
|
||||
return GalleryView.sanitizeScaleMode(getIntFromStr(KEY_PAGE_SCALING, DEFAULT_PAGE_SCALING));
|
||||
}
|
||||
|
||||
public static void putPageScaling(int value) {
|
||||
@@ -458,11 +457,11 @@ public class Settings {
|
||||
}
|
||||
|
||||
private static final String KEY_START_POSITION = "start_position";
|
||||
private static final int DEFAULT_START_POSITION = ImageView.START_POSITION_TOP_RIGHT;
|
||||
private static final int DEFAULT_START_POSITION = GalleryView.START_POSITION_TOP_RIGHT;
|
||||
|
||||
@ImageView.StartPosition
|
||||
@GalleryView.StartPosition
|
||||
public static int getStartPosition() {
|
||||
return ImageView.sanitizeStartPosition(getIntFromStr(KEY_START_POSITION, DEFAULT_START_POSITION));
|
||||
return GalleryView.sanitizeStartPosition(getIntFromStr(KEY_START_POSITION, DEFAULT_START_POSITION));
|
||||
}
|
||||
|
||||
public static void putStartPosition(int value) {
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.util.Log;
|
||||
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryPageView;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
@@ -41,7 +41,7 @@ import java.util.Stack;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class DirGalleryProvider extends GalleryProvider implements Runnable {
|
||||
public class DirGalleryProvider extends GalleryProvider2 implements Runnable {
|
||||
|
||||
private static final String TAG = DirGalleryProvider.class.getSimpleName();
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
|
||||
@@ -22,13 +22,14 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.spider.SpiderQueen;
|
||||
import com.hippo.glgallery.GalleryProvider;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class EhGalleryProvider extends GalleryProvider implements SpiderQueen.OnSpiderListener {
|
||||
public class EhGalleryProvider extends GalleryProvider2 implements SpiderQueen.OnSpiderListener {
|
||||
|
||||
private final Context mContext;
|
||||
private final GalleryInfo mGalleryInfo;
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import com.hippo.beerbelly.LruCache;
|
||||
import com.hippo.glview.glrenderer.GLCanvas;
|
||||
import com.hippo.glview.image.ImageWrapper;
|
||||
import com.hippo.glview.view.GLRoot;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.ConcurrentPool;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.OSUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public abstract class GalleryProvider {
|
||||
|
||||
public static final int STATE_WAIT = -1;
|
||||
public static final int STATE_ERROR = -2;
|
||||
|
||||
// With dot
|
||||
public static final String[] SUPPORT_IMAGE_EXTENSIONS = {
|
||||
".jpg", // Joint Photographic Experts Group
|
||||
".jpeg",
|
||||
".png", // Portable Network Graphics
|
||||
".gif", // Graphics Interchange Format
|
||||
};
|
||||
|
||||
private final ConcurrentPool<NotifyTask> mNotifyTaskPool = new ConcurrentPool<>(5);
|
||||
private volatile GalleryProviderListener mGalleryProviderListener;
|
||||
private volatile GLRoot mGLRoot;
|
||||
|
||||
private final ImageCache mImageCache = new ImageCache();
|
||||
|
||||
private boolean mStarted = false;
|
||||
|
||||
@UiThread
|
||||
public void start() {
|
||||
OSUtils.checkMainLoop();
|
||||
|
||||
if (mStarted) {
|
||||
throw new IllegalStateException("Can't start it twice");
|
||||
}
|
||||
mStarted = true;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void stop() {
|
||||
OSUtils.checkMainLoop();
|
||||
mImageCache.close();
|
||||
}
|
||||
|
||||
public void setGLRoot(GLRoot glRoot) {
|
||||
mGLRoot = glRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link #STATE_WAIT} for wait, 0 for empty
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
public final void request(int index) {
|
||||
ImageWrapper imageWrapper = mImageCache.get(index);
|
||||
if (imageWrapper != null) {
|
||||
notifyPageSucceed(index, imageWrapper);
|
||||
} else {
|
||||
onRequest(index);
|
||||
}
|
||||
}
|
||||
|
||||
public final void forceRequest(int index) {
|
||||
onForceRequest(index);
|
||||
}
|
||||
|
||||
protected abstract void onRequest(int index);
|
||||
|
||||
protected abstract void onForceRequest(int index);
|
||||
|
||||
public final void cancelRequest(int index) {
|
||||
onCancelRequest(index);
|
||||
}
|
||||
|
||||
protected abstract void onCancelRequest(int index);
|
||||
|
||||
public abstract String getError();
|
||||
|
||||
public int getStartPage() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return without extension
|
||||
*/
|
||||
@NonNull
|
||||
public abstract String getImageFilename(int index);
|
||||
|
||||
public abstract boolean save(int index, @NonNull UniFile file);
|
||||
|
||||
/**
|
||||
* @param filename without extension
|
||||
*/
|
||||
@Nullable
|
||||
public abstract UniFile save(int index, @NonNull UniFile dir, @NonNull String filename);
|
||||
|
||||
public void putStartPage(int page) {}
|
||||
|
||||
public void setGalleryProviderListener(GalleryProviderListener listener) {
|
||||
mGalleryProviderListener = listener;
|
||||
}
|
||||
|
||||
public void notifyDataChanged() {
|
||||
notify(NotifyTask.TYPE_DATA_CHANGED, -1, 0.0f, null, null);
|
||||
}
|
||||
|
||||
public void notifyDataChanged(int index) {
|
||||
notify(NotifyTask.TYPE_DATA_CHANGED, index, 0.0f, null, null);
|
||||
}
|
||||
|
||||
public void notifyPageWait(int index) {
|
||||
notify(NotifyTask.TYPE_WAIT, index, 0.0f, null, null);
|
||||
}
|
||||
|
||||
public void notifyPagePercent(int index, float percent) {
|
||||
notify(NotifyTask.TYPE_PERCENT, index, percent, null, null);
|
||||
}
|
||||
|
||||
public void notifyPageSucceed(int index, Image image) {
|
||||
ImageWrapper imageWrapper = new ImageWrapper(image);
|
||||
mImageCache.add(index, imageWrapper);
|
||||
notifyPageSucceed(index, imageWrapper);
|
||||
}
|
||||
|
||||
public void notifyPageSucceed(int index, ImageWrapper image) {
|
||||
notify(NotifyTask.TYPE_SUCCEED, index, 0.0f, image, null);
|
||||
}
|
||||
|
||||
public void notifyPageFailed(int index, String error) {
|
||||
notify(NotifyTask.TYPE_FAILED, index, 0.0f, null, error);
|
||||
}
|
||||
|
||||
private void notify(@NotifyTask.Type int type, int index, float percent, ImageWrapper image, String error) {
|
||||
GalleryProviderListener listener = mGalleryProviderListener;
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GLRoot glRoot = mGLRoot;
|
||||
if (glRoot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
NotifyTask task = mNotifyTaskPool.pop();
|
||||
if (task == null) {
|
||||
task = new NotifyTask(listener, mNotifyTaskPool);
|
||||
}
|
||||
task.setData(type, index, percent, image, error);
|
||||
glRoot.addOnGLIdleListener(task);
|
||||
}
|
||||
|
||||
private static class NotifyTask implements GLRoot.OnGLIdleListener {
|
||||
|
||||
@IntDef({TYPE_DATA_CHANGED, NotifyTask.TYPE_WAIT, TYPE_PERCENT, TYPE_SUCCEED, TYPE_FAILED})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Type {}
|
||||
|
||||
public static final int TYPE_DATA_CHANGED = 0;
|
||||
public static final int TYPE_WAIT = 1;
|
||||
public static final int TYPE_PERCENT = 2;
|
||||
public static final int TYPE_SUCCEED = 3;
|
||||
public static final int TYPE_FAILED = 4;
|
||||
|
||||
private final GalleryProviderListener mGalleryProviderListener;
|
||||
private final ConcurrentPool<NotifyTask> mPool;
|
||||
|
||||
@Type
|
||||
private int mType;
|
||||
private int mIndex;
|
||||
private float mPercent;
|
||||
private ImageWrapper mImage;
|
||||
private String mError;
|
||||
|
||||
public NotifyTask(GalleryProviderListener galleryProviderListener, ConcurrentPool<NotifyTask> pool) {
|
||||
mGalleryProviderListener = galleryProviderListener;
|
||||
mPool = pool;
|
||||
}
|
||||
|
||||
public void setData(@Type int type, int index, float percent, ImageWrapper image, String error) {
|
||||
mType = type;
|
||||
mIndex = index;
|
||||
mPercent = percent;
|
||||
mImage = image;
|
||||
mError = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
|
||||
switch (mType) {
|
||||
case TYPE_DATA_CHANGED:
|
||||
if (mIndex < 0) {
|
||||
mGalleryProviderListener.onDataChanged();
|
||||
} else {
|
||||
mGalleryProviderListener.onDataChanged(mIndex);
|
||||
}
|
||||
break;
|
||||
case TYPE_WAIT:
|
||||
mGalleryProviderListener.onPageWait(mIndex);
|
||||
break;
|
||||
case TYPE_PERCENT:
|
||||
mGalleryProviderListener.onPagePercent(mIndex, mPercent);
|
||||
break;
|
||||
case TYPE_SUCCEED:
|
||||
mGalleryProviderListener.onPageSucceed(mIndex, mImage);
|
||||
break;
|
||||
case TYPE_FAILED:
|
||||
mGalleryProviderListener.onPageFailed(mIndex, mError);
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean data
|
||||
mImage = null;
|
||||
mError = null;
|
||||
// Push back
|
||||
mPool.push(this);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImageCache extends LruCache<Integer, ImageWrapper> {
|
||||
|
||||
private static final long MAX_CACHE_SIZE = 128 * 1024 * 1024;
|
||||
private static final long MIN_CACHE_SIZE = 32 * 1024 * 1024;
|
||||
|
||||
public ImageCache() {
|
||||
super((int) MathUtils.clamp(OSUtils.getTotalMemory() / 16, MIN_CACHE_SIZE, MAX_CACHE_SIZE));
|
||||
}
|
||||
|
||||
public void add(Integer key, ImageWrapper value) {
|
||||
if (value.obtain()) {
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int sizeOf(Integer key, ImageWrapper value) {
|
||||
return value.getWidth() * value.getHeight() * 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entryRemoved(boolean evicted, Integer key, ImageWrapper oldValue, ImageWrapper newValue) {
|
||||
if (oldValue != null) {
|
||||
oldValue.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.hippo.glgallery.GalleryProvider;
|
||||
import com.hippo.unifile.UniFile;
|
||||
|
||||
public abstract class GalleryProvider2 extends GalleryProvider {
|
||||
|
||||
// With dot
|
||||
public static final String[] SUPPORT_IMAGE_EXTENSIONS = {
|
||||
".jpg", // Joint Photographic Experts Group
|
||||
".jpeg",
|
||||
".png", // Portable Network Graphics
|
||||
".gif", // Graphics Interchange Format
|
||||
};
|
||||
|
||||
public int getStartPage() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void putStartPage(int page) {}
|
||||
|
||||
/**
|
||||
* @return without extension
|
||||
*/
|
||||
@NonNull
|
||||
public abstract String getImageFilename(int index);
|
||||
|
||||
public abstract boolean save(int index, @NonNull UniFile file);
|
||||
|
||||
/**
|
||||
* @param filename without extension
|
||||
*/
|
||||
@Nullable
|
||||
public abstract UniFile save(int index, @NonNull UniFile dir, @NonNull String filename);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import com.hippo.glview.image.ImageWrapper;
|
||||
|
||||
public interface GalleryProviderListener {
|
||||
|
||||
void onDataChanged();
|
||||
|
||||
void onPageWait(int index);
|
||||
|
||||
void onPagePercent(int index, float percent);
|
||||
|
||||
void onPageSucceed(int index, ImageWrapper image);
|
||||
|
||||
void onPageFailed(int index, String error);
|
||||
|
||||
void onDataChanged(int index);
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import android.util.Log;
|
||||
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryPageView;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.StringUtils;
|
||||
@@ -43,7 +43,7 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class ZipGalleryProvider extends GalleryProvider implements Runnable {
|
||||
public class ZipGalleryProvider extends GalleryProvider2 implements Runnable {
|
||||
|
||||
private static final String TAG = ZipGalleryProvider.class.getSimpleName();
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class DownUpDetector {
|
||||
public interface DownUpListener {
|
||||
void onDown(MotionEvent e);
|
||||
void onUp(MotionEvent e);
|
||||
void onPointerDown(MotionEvent e);
|
||||
void onPointerUp(MotionEvent e);
|
||||
}
|
||||
|
||||
private boolean mStillDown;
|
||||
private DownUpListener mListener;
|
||||
|
||||
public DownUpDetector(DownUpListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
private void setState(boolean down, MotionEvent e) {
|
||||
if (down == mStillDown) return;
|
||||
mStillDown = down;
|
||||
if (down) {
|
||||
mListener.onDown(e);
|
||||
} else {
|
||||
mListener.onUp(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
setState(true, ev);
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
mListener.onPointerDown(ev);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
mListener.onPointerUp(ev);
|
||||
setState(false, ev);
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
setState(false, ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
return mStillDown;
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.SensorManager;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.hippo.glview.anim.Animation;
|
||||
|
||||
public abstract class Fling extends Animation {
|
||||
|
||||
private static final float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
|
||||
private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
|
||||
private static final float START_TENSION = 0.5f;
|
||||
private static final float END_TENSION = 1.0f;
|
||||
private static final float P1 = START_TENSION * INFLEXION;
|
||||
private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
|
||||
private static final float FLING_FRICTION = ViewConfiguration.getScrollFriction();
|
||||
|
||||
private static final int NB_SAMPLES = 100;
|
||||
private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
|
||||
private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
|
||||
|
||||
private float mPhysicalCoeff;
|
||||
|
||||
static {
|
||||
float x_min = 0.0f;
|
||||
float y_min = 0.0f;
|
||||
for (int i = 0; i < NB_SAMPLES; i++) {
|
||||
final float alpha = (float) i / NB_SAMPLES;
|
||||
|
||||
float x_max = 1.0f;
|
||||
float x, tx, coef;
|
||||
while (true) {
|
||||
x = x_min + (x_max - x_min) / 2.0f;
|
||||
coef = 3.0f * x * (1.0f - x);
|
||||
tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
|
||||
if (Math.abs(tx - alpha) < 1E-5) break;
|
||||
if (tx > alpha) x_max = x;
|
||||
else x_min = x;
|
||||
}
|
||||
SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;
|
||||
|
||||
float y_max = 1.0f;
|
||||
float y, dy;
|
||||
while (true) {
|
||||
y = y_min + (y_max - y_min) / 2.0f;
|
||||
coef = 3.0f * y * (1.0f - y);
|
||||
dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
|
||||
if (Math.abs(dy - alpha) < 1E-5) break;
|
||||
if (dy > alpha) y_max = y;
|
||||
else y_min = y;
|
||||
}
|
||||
SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
|
||||
}
|
||||
SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
|
||||
}
|
||||
|
||||
private static final Interpolator FLING_INTERPOLATOR = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float input) {
|
||||
final int index = (int) (NB_SAMPLES * input);
|
||||
float distanceCoef = 1.f;
|
||||
float velocityCoef = 0.f;
|
||||
if (index < NB_SAMPLES) {
|
||||
final float t_inf = (float) index / NB_SAMPLES;
|
||||
final float t_sup = (float) (index + 1) / NB_SAMPLES;
|
||||
final float d_inf = SPLINE_POSITION[index];
|
||||
final float d_sup = SPLINE_POSITION[index + 1];
|
||||
velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
|
||||
distanceCoef = d_inf + (input - t_inf) * velocityCoef;
|
||||
}
|
||||
return distanceCoef;
|
||||
}
|
||||
};
|
||||
|
||||
public Fling(Context context) {
|
||||
final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
|
||||
mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2)
|
||||
* 39.37f // inch/meter
|
||||
* ppi
|
||||
* 0.84f; // look and feel tuning
|
||||
setInterpolator(FLING_INTERPOLATOR);
|
||||
}
|
||||
|
||||
private double getSplineDeceleration(int velocity) {
|
||||
return Math.log(INFLEXION * Math.abs(velocity) / (FLING_FRICTION * mPhysicalCoeff));
|
||||
}
|
||||
|
||||
/* Returns the duration, expressed in milliseconds */
|
||||
protected int getSplineFlingDuration(int velocity) {
|
||||
final double l = getSplineDeceleration(velocity);
|
||||
final double decelMinusOne = DECELERATION_RATE - 1.0;
|
||||
return (int) (1000.0 * Math.exp(l / decelMinusOne));
|
||||
}
|
||||
|
||||
protected double getSplineFlingDistance(int velocity) {
|
||||
final double l = getSplineDeceleration(velocity);
|
||||
final double decelMinusOne = DECELERATION_RATE - 1.0;
|
||||
return FLING_FRICTION * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies mDuration to the duration it takes to get from start to newFinal using the
|
||||
* spline interpolation. The previous duration was needed to get to oldFinal.
|
||||
**/
|
||||
protected int adjustDuration(int start, int oldFinal, int newFinal, int duration) {
|
||||
final int oldDistance = oldFinal - start;
|
||||
final int newDistance = newFinal - start;
|
||||
final float x = Math.abs((float) newDistance / oldDistance);
|
||||
final int index = (int) (NB_SAMPLES * x);
|
||||
if (index < NB_SAMPLES) {
|
||||
final float x_inf = (float) index / NB_SAMPLES;
|
||||
final float x_sup = (float) (index + 1) / NB_SAMPLES;
|
||||
final float t_inf = SPLINE_TIME[index];
|
||||
final float t_sup = SPLINE_TIME[index + 1];
|
||||
final float timeCoef = t_inf + (x - x_inf) / (x_sup - x_inf) * (t_sup - t_inf);
|
||||
duration *= timeCoef;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.hippo.glview.glrenderer.BasicTexture;
|
||||
import com.hippo.glview.glrenderer.Texture;
|
||||
import com.hippo.glview.image.GLImageMovableTextView;
|
||||
import com.hippo.glview.image.ImageMovableTextTexture;
|
||||
import com.hippo.glview.image.ImageTexture;
|
||||
import com.hippo.glview.view.Gravity;
|
||||
import com.hippo.glview.widget.GLFrameLayout;
|
||||
import com.hippo.glview.widget.GLLinearLayout;
|
||||
import com.hippo.glview.widget.GLMovableTextView;
|
||||
import com.hippo.glview.widget.GLProgressView;
|
||||
import com.hippo.glview.widget.GLTextureView;
|
||||
import com.hippo.yorozuya.LayoutUtils;
|
||||
|
||||
public class GalleryPageView extends GLFrameLayout {
|
||||
|
||||
public static final int INVALID_INDEX = -1;
|
||||
|
||||
private static final int INFO_INTERVAL = 24;
|
||||
public static final float PROGRESS_GONE = -1.0f;
|
||||
public static final float PROGRESS_INDETERMINATE = -2.0f;
|
||||
private static final int PAGE_MIN_HEIGHT = 256;
|
||||
|
||||
private final ImageView mImage;
|
||||
private final GLLinearLayout mInfo;
|
||||
private final GLImageMovableTextView mPage;
|
||||
private final GLTextureView mError;
|
||||
private final GLProgressView mProgress;
|
||||
|
||||
private final int mPageMinHeight;
|
||||
|
||||
private int mIndex = INVALID_INDEX;
|
||||
|
||||
public GalleryPageView(Context context, ImageMovableTextTexture pageTextTexture,
|
||||
int progressColor, int progressSize) {
|
||||
// Add image
|
||||
mImage = new ImageView();
|
||||
GravityLayoutParams glp = new GravityLayoutParams(LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT);
|
||||
addComponent(mImage, glp);
|
||||
|
||||
// Add other panel
|
||||
mInfo = new GLLinearLayout();
|
||||
mInfo.setOrientation(GLLinearLayout.VERTICAL);
|
||||
mInfo.setInterval(LayoutUtils.dp2pix(context, INFO_INTERVAL));
|
||||
glp = new GravityLayoutParams(LayoutParams.WRAP_CONTENT,
|
||||
LayoutParams.WRAP_CONTENT);
|
||||
glp.gravity = Gravity.CENTER;
|
||||
addComponent(mInfo, glp);
|
||||
|
||||
// Add page
|
||||
mPage = new GLImageMovableTextView();
|
||||
mPage.setTextTexture(pageTextTexture);
|
||||
GLLinearLayout.LayoutParams lp = new GLLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
|
||||
LayoutParams.WRAP_CONTENT);
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
mInfo.addComponent(mPage, lp);
|
||||
|
||||
// Add error
|
||||
mError = new GLTextureView();
|
||||
lp = new GLLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
|
||||
LayoutParams.WRAP_CONTENT);
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
mInfo.addComponent(mError, lp);
|
||||
|
||||
// Add progress
|
||||
mProgress = new GLProgressView();
|
||||
mProgress.setBgColor(GalleryView.BACKGROUND_COLOR);
|
||||
mProgress.setColor(progressColor);
|
||||
mProgress.setMinimumWidth(progressSize);
|
||||
mProgress.setMinimumHeight(progressSize);
|
||||
lp = new GLLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
|
||||
LayoutParams.WRAP_CONTENT);
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
mInfo.addComponent(mProgress, lp);
|
||||
|
||||
mPageMinHeight = LayoutUtils.dp2pix(context, PAGE_MIN_HEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumHeight() {
|
||||
// The height of the actual image may be smaller than mPageMinHeight.
|
||||
// Set min height as 0 when the image is visible.
|
||||
// For PageLayoutManager, min height is useless.
|
||||
if (mImage.getVisibility() == VISIBLE) {
|
||||
return 0;
|
||||
} else {
|
||||
return mPageMinHeight;
|
||||
}
|
||||
}
|
||||
|
||||
int getIndex() {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
void setIndex(int index) {
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
public void showImage() {
|
||||
mImage.setVisibility(VISIBLE);
|
||||
mInfo.setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void showInfo() {
|
||||
// For image valid rect
|
||||
mImage.setVisibility(INVISIBLE);
|
||||
mInfo.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
private void unbindImage() {
|
||||
ImageTexture texture = mImage.getImageTexture();
|
||||
if (texture != null) {
|
||||
mImage.setImageTexture(null);
|
||||
texture.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
public void setImage(ImageTexture imageTexture) {
|
||||
unbindImage();
|
||||
if (imageTexture != null) {
|
||||
mImage.setImageTexture(imageTexture);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
mPage.setText(Integer.toString(page));
|
||||
}
|
||||
|
||||
public void setProgress(float progress) {
|
||||
if (progress == PROGRESS_GONE) {
|
||||
mProgress.setVisibility(GONE);
|
||||
} else if (progress == PROGRESS_INDETERMINATE) {
|
||||
mProgress.setVisibility(VISIBLE);
|
||||
mProgress.setIndeterminate(true);
|
||||
} else {
|
||||
mProgress.setVisibility(VISIBLE);
|
||||
mProgress.setIndeterminate(false);
|
||||
mProgress.setProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
private void unbindError() {
|
||||
Texture texture = mError.getTexture();
|
||||
if (texture != null) {
|
||||
mError.setTexture(null);
|
||||
if (texture instanceof BasicTexture) {
|
||||
((BasicTexture) texture).recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setError(String error, GalleryView galleryView) {
|
||||
unbindError();
|
||||
if (error == null) {
|
||||
mError.setVisibility(GONE);
|
||||
} else {
|
||||
mError.setVisibility(VISIBLE);
|
||||
galleryView.bindErrorView(mError, error);
|
||||
}
|
||||
}
|
||||
|
||||
public ImageView getImageView() {
|
||||
return mImage;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return mImage.getVisibility() == VISIBLE;
|
||||
}
|
||||
}
|
||||
@@ -1,991 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.glview.annotation.RenderThread;
|
||||
import com.hippo.glview.glrenderer.BasicTexture;
|
||||
import com.hippo.glview.glrenderer.GLCanvas;
|
||||
import com.hippo.glview.glrenderer.StringTexture;
|
||||
import com.hippo.glview.glrenderer.Texture;
|
||||
import com.hippo.glview.image.ImageMovableTextTexture;
|
||||
import com.hippo.glview.util.GalleryUtils;
|
||||
import com.hippo.glview.view.AnimationTime;
|
||||
import com.hippo.glview.view.GLRoot;
|
||||
import com.hippo.glview.view.GLView;
|
||||
import com.hippo.glview.widget.GLEdgeView;
|
||||
import com.hippo.glview.widget.GLProgressView;
|
||||
import com.hippo.glview.widget.GLTextureView;
|
||||
import com.hippo.yorozuya.LayoutUtils;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.Pool;
|
||||
import com.hippo.yorozuya.ResourcesUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class GalleryView extends GLView implements GestureRecognizer.Listener {
|
||||
|
||||
@IntDef({LAYOUT_MODE_LEFT_TO_RIGHT, LAYOUT_MODE_RIGHT_TO_LEFT, LAYOUT_MODE_TOP_TO_BOTTOM})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface LayoutMode {}
|
||||
|
||||
public static final int BACKGROUND_COLOR = 0xff212121;
|
||||
private static final int PROGRESS_SIZE_IN_DP = 48;
|
||||
|
||||
public static final int LAYOUT_MODE_LEFT_TO_RIGHT = 0;
|
||||
public static final int LAYOUT_MODE_RIGHT_TO_LEFT = 1;
|
||||
public static final int LAYOUT_MODE_TOP_TO_BOTTOM = 2;
|
||||
|
||||
private static final float[] LEFT_AREA = {0.0f, 0.0f, 1.0f / 3.0f, 1f};
|
||||
private static final float[] RIGHT_AREA = {2.0f / 3.0f, 0.0f, 1.0f, 1f};
|
||||
private static final float[] MENU_AREA = {1.0f / 3.0f, 0.0f, 2.0f / 3.0f, 1.0f / 2.0f};
|
||||
private static final float[] SLIDER_AREA = {1.0f / 3.0f, 1.0f / 2.0f, 2.0f / 3.0f, 1.0f};
|
||||
|
||||
private static final int METHOD_ON_SINGLE_TAP_UP = 0;
|
||||
private static final int METHOD_ON_SINGLE_TAP_CONFIRMED = 1;
|
||||
private static final int METHOD_ON_DOUBLE_TAP = 2;
|
||||
private static final int METHOD_ON_DOUBLE_TAP_CONFIRMED = 3;
|
||||
private static final int METHOD_ON_LONG_PRESS = 4;
|
||||
private static final int METHOD_ON_SCROLL = 5;
|
||||
private static final int METHOD_ON_FLING = 6;
|
||||
private static final int METHOD_ON_SCALE_BEGIN = 7;
|
||||
private static final int METHOD_ON_SCALE = 8;
|
||||
private static final int METHOD_ON_SCALE_END = 9;
|
||||
private static final int METHOD_ON_DOWN = 10;
|
||||
private static final int METHOD_ON_UP = 11;
|
||||
private static final int METHOD_ON_POINTER_DOWN = 12;
|
||||
private static final int METHOD_ON_POINTER_UP = 13;
|
||||
private static final int METHOD_SET_LAYOUT_MODE = 14;
|
||||
private static final int METHOD_SET_CURRENT_PAGE = 15;
|
||||
private static final int METHOD_PAGE_LEFT = 16;
|
||||
private static final int METHOD_PAGE_RIGHT = 17;
|
||||
private static final int METHOD_SET_SCALE_MODE = 18;
|
||||
private static final int METHOD_SET_START_POSITION = 19;
|
||||
private static final int METHOD_ON_ATTACH_TO_ROOT = 20;
|
||||
|
||||
private final Context mContext;
|
||||
private ImageMovableTextTexture mPageTextTexture;
|
||||
private final GestureRecognizer mGestureRecognizer;
|
||||
private Adapter mAdapter;
|
||||
|
||||
private PagerLayoutManager mPagerLayoutManager;
|
||||
private ScrollLayoutManager mScrollLayoutManager;
|
||||
@Nullable
|
||||
private LayoutManager mLayoutManager;
|
||||
|
||||
private final Pool<GalleryPageView> mGalleryPageViewPool = new Pool<>(5);
|
||||
private final GLEdgeView mEdgeView;
|
||||
private GLProgressView mProgressCache;
|
||||
private GLTextureView mErrorViewCache;
|
||||
|
||||
private final int mProgressColor;
|
||||
private final int mProgressSize;
|
||||
private final float mErrorSize;
|
||||
private final int mErrorColor;
|
||||
|
||||
private boolean mEnableRequestFill = true;
|
||||
private boolean mRequestFill = false;
|
||||
private boolean mWillFill = false;
|
||||
|
||||
private boolean mScale = false;
|
||||
private boolean mScroll = false;
|
||||
private boolean mFirstScroll = false;
|
||||
|
||||
private final Rect mLeftArea = new Rect();
|
||||
private final Rect mRightArea = new Rect();
|
||||
private final Rect mMenuArea = new Rect();
|
||||
private final Rect mSliderArea = new Rect();
|
||||
|
||||
private final String mDefaultErrorStr;
|
||||
private final String mEmptyStr;
|
||||
|
||||
@LayoutMode
|
||||
private int mLayoutMode = LAYOUT_MODE_RIGHT_TO_LEFT;
|
||||
@ImageView.Scale
|
||||
private int mScaleMode = ImageView.SCALE_FIT;
|
||||
@ImageView.StartPosition
|
||||
private int mStartPosition = ImageView.START_POSITION_TOP_LEFT;
|
||||
private int mIndex;
|
||||
|
||||
private final Listener mListener;
|
||||
|
||||
private final List<Integer> mMethodList = new ArrayList<>(5);
|
||||
private final List<Object[]> mArgsList = new ArrayList<>(5);
|
||||
private final List<Integer> mMethodListTemp = new ArrayList<>(5);
|
||||
private final List<Object[]> mArgsListTemp = new ArrayList<>(5);
|
||||
|
||||
private final AtomicInteger mCurrentIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public GalleryView(@NonNull Context context, @NonNull Adapter adapter,
|
||||
Listener listener, @LayoutMode int layoutMode, @ImageView.Scale int scaleMode,
|
||||
@ImageView.StartPosition int startPosition, int startPage) {
|
||||
mContext = context;
|
||||
mAdapter = adapter;
|
||||
mListener = listener;
|
||||
final int themeColor = ResourcesUtils.getAttrColor(context, R.attr.colorPrimary);
|
||||
final int edgeColor = (themeColor & 0xffffff) | 0x33000000;
|
||||
mEdgeView = new GLEdgeView(edgeColor);
|
||||
mGestureRecognizer = new GestureRecognizer(context, this);
|
||||
|
||||
adapter.setGalleryView(this);
|
||||
|
||||
mLayoutMode = layoutMode;
|
||||
mScaleMode = scaleMode;
|
||||
mStartPosition = startPosition;
|
||||
mIndex = MathUtils.clamp(startPage, 0, Integer.MAX_VALUE);
|
||||
mProgressColor = ResourcesUtils.getAttrColor(context, R.attr.colorPrimary);
|
||||
mProgressSize = LayoutUtils.dp2pix(context, PROGRESS_SIZE_IN_DP);
|
||||
mErrorSize = context.getResources().getDimension(R.dimen.text_large);
|
||||
mErrorColor = context.getResources().getColor(R.color.red_500);
|
||||
|
||||
mDefaultErrorStr = context.getResources().getString(R.string.error_unknown);
|
||||
mEmptyStr = context.getResources().getString(R.string.error_empty);
|
||||
|
||||
setBackgroundColor(BACKGROUND_COLOR);
|
||||
}
|
||||
|
||||
private void ensurePagerLayoutManager() {
|
||||
if (mPagerLayoutManager == null) {
|
||||
mPagerLayoutManager = new PagerLayoutManager(mContext, this, mScaleMode, mStartPosition, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureScrollLayoutManager() {
|
||||
if (mScrollLayoutManager == null) {
|
||||
mScrollLayoutManager = new ScrollLayoutManager(mContext, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void attachLayoutManager() {
|
||||
if (null != mLayoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mLayoutMode) {
|
||||
case LAYOUT_MODE_LEFT_TO_RIGHT:
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_LEFT_TO_RIGHT);
|
||||
mPagerLayoutManager.onAttach(mAdapter);
|
||||
mPagerLayoutManager.setCurrentIndex(mIndex);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
break;
|
||||
case LAYOUT_MODE_RIGHT_TO_LEFT:
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_RIGHT_TO_LEFT);
|
||||
mPagerLayoutManager.onAttach(mAdapter);
|
||||
mPagerLayoutManager.setCurrentIndex(mIndex);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
break;
|
||||
case LAYOUT_MODE_TOP_TO_BOTTOM:
|
||||
ensureScrollLayoutManager();
|
||||
mScrollLayoutManager.onAttach(mAdapter);
|
||||
mScrollLayoutManager.setCurrentIndex(mIndex);
|
||||
mAdapter = null;
|
||||
mLayoutManager = mScrollLayoutManager;
|
||||
break;
|
||||
}
|
||||
|
||||
requestFill();
|
||||
}
|
||||
|
||||
private void detachLayoutManager() {
|
||||
if (null == mLayoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIndex = mLayoutManager.getInternalCurrentIndex();
|
||||
mAdapter = mLayoutManager.onDetach();
|
||||
mLayoutManager = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void onAttachToRootInternal() {
|
||||
if (null == mPageTextTexture) {
|
||||
mPageTextTexture = ImageMovableTextTexture.create(Typeface.DEFAULT,
|
||||
mContext.getResources().getDimensionPixelSize(R.dimen.gallery_page_text),
|
||||
mContext.getResources().getColor(R.color.secondary_text_dark),
|
||||
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'});
|
||||
}
|
||||
attachLayoutManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachToRoot(GLRoot root) {
|
||||
super.onAttachToRoot(root);
|
||||
mEdgeView.onAttachToRoot(root);
|
||||
postMethod(METHOD_ON_ATTACH_TO_ROOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachFromRoot() {
|
||||
// When detached, render() will not be called. So do it here
|
||||
detachLayoutManager();
|
||||
if (null != mPageTextTexture) {
|
||||
mPageTextTexture.recycle();
|
||||
mPageTextTexture = null;
|
||||
}
|
||||
|
||||
super.onDetachFromRoot();
|
||||
mEdgeView.onDetachFromRoot();
|
||||
}
|
||||
|
||||
@LayoutMode
|
||||
public static int sanitizeLayoutMode(int layoutMode) {
|
||||
if (layoutMode != GalleryView.LAYOUT_MODE_LEFT_TO_RIGHT &&
|
||||
layoutMode != GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT &&
|
||||
layoutMode != GalleryView.LAYOUT_MODE_TOP_TO_BOTTOM) {
|
||||
return GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT;
|
||||
} else {
|
||||
return layoutMode;
|
||||
}
|
||||
}
|
||||
|
||||
public int getLayoutMode() {
|
||||
return mLayoutMode;
|
||||
}
|
||||
|
||||
public int getCurrentIndex() {
|
||||
return mCurrentIndex.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestLayout() {
|
||||
// Do not need requestLayout, because the size will not change
|
||||
requestFill();
|
||||
}
|
||||
|
||||
public void requestFill() {
|
||||
if (mEnableRequestFill) {
|
||||
mRequestFill = true;
|
||||
if (!mWillFill) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean dispatchTouchEvent(MotionEvent event) {
|
||||
// Do not pass event to component, so handle event here
|
||||
mGestureRecognizer.onTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
GLEdgeView getEdgeView() {
|
||||
return mEdgeView;
|
||||
}
|
||||
|
||||
String getDefaultErrorStr() {
|
||||
return mDefaultErrorStr;
|
||||
}
|
||||
|
||||
String getEmptyStr() {
|
||||
return mEmptyStr;
|
||||
}
|
||||
|
||||
boolean isFirstScroll() {
|
||||
boolean firstScroll = mFirstScroll;
|
||||
mFirstScroll = false;
|
||||
return firstScroll;
|
||||
}
|
||||
|
||||
// Make sure method run in render thread to ensure thread safe
|
||||
private void postMethod(int method, Object... args) {
|
||||
synchronized (this) {
|
||||
mMethodList.add(method);
|
||||
mArgsList.add(args);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setLayoutMode(@LayoutMode int layoutMode) {
|
||||
postMethod(METHOD_SET_LAYOUT_MODE, layoutMode);
|
||||
}
|
||||
|
||||
public void setCurrentPage(int page) {
|
||||
postMethod(METHOD_SET_CURRENT_PAGE, page);
|
||||
}
|
||||
|
||||
public void pageLeft() {
|
||||
postMethod(METHOD_PAGE_LEFT);
|
||||
}
|
||||
|
||||
public void pageRight() {
|
||||
postMethod(METHOD_PAGE_RIGHT);
|
||||
}
|
||||
|
||||
public void setScaleMode(@ImageView.Scale int scaleMode) {
|
||||
postMethod(METHOD_SET_SCALE_MODE, scaleMode);
|
||||
}
|
||||
|
||||
public void setStartPosition(@ImageView.StartPosition int startPosition) {
|
||||
postMethod(METHOD_SET_START_POSITION, startPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapUp(float x, float y) {
|
||||
postMethod(METHOD_ON_SINGLE_TAP_UP, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(float x, float y) {
|
||||
postMethod(METHOD_ON_SINGLE_TAP_CONFIRMED, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(float x, float y) {
|
||||
postMethod(METHOD_ON_DOUBLE_TAP, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTapConfirmed(float x, float y) {
|
||||
postMethod(METHOD_ON_DOUBLE_TAP_CONFIRMED, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(float x, float y) {
|
||||
if (mLayoutManager != null && !mLayoutManager.isTapOrPressEnable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
postMethod(METHOD_ON_LONG_PRESS, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(float dx, float dy, float totalX, float totalY, float x, float y) {
|
||||
postMethod(METHOD_ON_SCROLL, dx, dy, totalX, totalY, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
postMethod(METHOD_ON_FLING, velocityX, velocityY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(float focusX, float focusY) {
|
||||
postMethod(METHOD_ON_SCALE_BEGIN, focusX, focusY);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(float focusX, float focusY, float scale) {
|
||||
postMethod(METHOD_ON_SCALE, focusX, focusY, scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd() {
|
||||
postMethod(METHOD_ON_SCALE_END);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDown(float x, float y) {
|
||||
postMethod(METHOD_ON_DOWN, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUp() {
|
||||
postMethod(METHOD_ON_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerDown(float x, float y) {
|
||||
postMethod(METHOD_ON_POINTER_DOWN, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerUp() {
|
||||
postMethod(METHOD_ON_POINTER_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changeSize, int left, int top, int right, int bottom) {
|
||||
mEdgeView.layout(left, top, right, bottom);
|
||||
|
||||
fill();
|
||||
|
||||
if (changeSize) {
|
||||
int width = right - left;
|
||||
int height = bottom - top;
|
||||
mLeftArea.set((int) (LEFT_AREA[0] * width), (int) (LEFT_AREA[1] * height),
|
||||
(int) (LEFT_AREA[2] * width), (int) (LEFT_AREA[3] * height));
|
||||
mRightArea.set((int) (RIGHT_AREA[0] * width), (int) (RIGHT_AREA[1] * height),
|
||||
(int) (RIGHT_AREA[2] * width), (int) (RIGHT_AREA[3] * height));
|
||||
mMenuArea.set((int) (MENU_AREA[0] * width), (int) (MENU_AREA[1] * height),
|
||||
(int) (MENU_AREA[2] * width), (int) (MENU_AREA[3] * height));
|
||||
mSliderArea.set((int) (SLIDER_AREA[0] * width), (int) (SLIDER_AREA[1] * height),
|
||||
(int) (SLIDER_AREA[2] * width), (int) (SLIDER_AREA[3] * height));
|
||||
}
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
public void onDataChanged() {
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (mLayoutManager != null){
|
||||
mLayoutManager.onDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSingleTapUpInternal(float x, float y) {
|
||||
}
|
||||
|
||||
private void onSingleTapConfirmedInternal(float x, float y) {
|
||||
if (mLayoutManager == null || !mLayoutManager.isTapOrPressEnable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSliderArea.contains((int) x, (int) y)) {
|
||||
mListener.onTapSliderArea();
|
||||
} else if (mMenuArea.contains((int) x, (int) y)) {
|
||||
mListener.onTapMenuArea();
|
||||
} else if (mLeftArea.contains((int) x, (int) y)) {
|
||||
mLayoutManager.onPageLeft();
|
||||
} else if (mRightArea.contains((int) x, (int) y)) {
|
||||
mLayoutManager.onPageRight();
|
||||
}
|
||||
}
|
||||
|
||||
private void onDoubleTapInternal(float x, float y) {
|
||||
}
|
||||
|
||||
private void onDoubleTapConfirmedInternal(float x, float y) {
|
||||
if (mScale) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDoubleTapConfirmed(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLongPressInternal(float x, float y) {
|
||||
if (mScale) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLayoutManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = mLayoutManager.getIndexUnder(x, y);
|
||||
if (index == GalleryPageView.INVALID_INDEX) {
|
||||
return;
|
||||
}
|
||||
|
||||
mListener.onLongPressPage(index);
|
||||
}
|
||||
|
||||
private void onScrollInternal(float dx, float dy, float totalX, float totalY, float x, float y) {
|
||||
if (mScale) {
|
||||
return;
|
||||
}
|
||||
mScroll = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScroll(dx, dy, totalX, totalY, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFlingInternal(float velocityX, float velocityY) {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onFling(velocityX, velocityY);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScaleBeginInternal(float focusX, float focusY) {
|
||||
onScaleInternal(focusX, focusY, 1.0f);
|
||||
}
|
||||
|
||||
private void onScaleInternal(float focusX, float focusY, float scale) {
|
||||
if (mScroll || (mLayoutManager != null && !mLayoutManager.canScale())) {
|
||||
return;
|
||||
}
|
||||
mScale = true;
|
||||
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onScale(focusX, focusY, scale);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScaleEndInternal() {
|
||||
}
|
||||
|
||||
private void onDownInternal(float x, float y) {
|
||||
mScale = false;
|
||||
mScroll = false;
|
||||
mFirstScroll = true;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onDown();
|
||||
}
|
||||
}
|
||||
|
||||
private void onUpInternal() {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onUp();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPointerDownInternal(float x, float y) {
|
||||
if (!mScroll && (mLayoutManager != null && mLayoutManager.canScale())) {
|
||||
mScale = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void onPointerUpInternal() {
|
||||
}
|
||||
|
||||
private void setLayoutModeInternal(int layoutMode) {
|
||||
if (mLayoutMode == layoutMode) {
|
||||
return;
|
||||
}
|
||||
mLayoutMode = layoutMode;
|
||||
|
||||
if (mLayoutManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mLayoutMode) {
|
||||
case LAYOUT_MODE_LEFT_TO_RIGHT:
|
||||
if (mLayoutManager == mPagerLayoutManager) {
|
||||
// mPagerLayoutManager already attached, just change mode
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_LEFT_TO_RIGHT);
|
||||
} else {
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_LEFT_TO_RIGHT);
|
||||
int index = mLayoutManager.getInternalCurrentIndex();
|
||||
mPagerLayoutManager.onAttach(mLayoutManager.onDetach());
|
||||
mPagerLayoutManager.setCurrentIndex(index);
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
}
|
||||
break;
|
||||
case LAYOUT_MODE_RIGHT_TO_LEFT:
|
||||
if (mLayoutManager == mPagerLayoutManager) {
|
||||
// mPagerLayoutManager already attached, just change mode
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_RIGHT_TO_LEFT);
|
||||
} else {
|
||||
ensurePagerLayoutManager();
|
||||
mPagerLayoutManager.setMode(PagerLayoutManager.MODE_RIGHT_TO_LEFT);
|
||||
int index = mLayoutManager.getInternalCurrentIndex();
|
||||
mPagerLayoutManager.onAttach(mLayoutManager.onDetach());
|
||||
mPagerLayoutManager.setCurrentIndex(index);
|
||||
mLayoutManager = mPagerLayoutManager;
|
||||
}
|
||||
break;
|
||||
case LAYOUT_MODE_TOP_TO_BOTTOM:
|
||||
ensureScrollLayoutManager();
|
||||
int index = mLayoutManager.getInternalCurrentIndex();
|
||||
mScrollLayoutManager.onAttach(mLayoutManager.onDetach());
|
||||
mScrollLayoutManager.setCurrentIndex(index);
|
||||
mLayoutManager = mScrollLayoutManager;
|
||||
break;
|
||||
}
|
||||
|
||||
requestFill();
|
||||
}
|
||||
|
||||
private void setCurrentPageInternal(int page) {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.setCurrentIndex(page);
|
||||
} else {
|
||||
mIndex = page;
|
||||
}
|
||||
}
|
||||
|
||||
private void pageLeftInternal() {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onPageLeft();
|
||||
}
|
||||
}
|
||||
|
||||
private void pageRightInternal() {
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onPageRight();
|
||||
}
|
||||
}
|
||||
|
||||
private void setScaleModeInternal(int scaleMode) {
|
||||
mScaleMode = scaleMode;
|
||||
if (mPagerLayoutManager != null) {
|
||||
mPagerLayoutManager.setScaleMode(scaleMode);
|
||||
}
|
||||
}
|
||||
|
||||
private void setStartPositionInternal(int startPosition) {
|
||||
mStartPosition = startPosition;
|
||||
if (mPagerLayoutManager != null) {
|
||||
mPagerLayoutManager.setStartPosition(startPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
void forceFill() {
|
||||
mRequestFill = true;
|
||||
fill();
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
private void fill() {
|
||||
GalleryUtils.assertInRenderThread();
|
||||
|
||||
if (!mRequestFill) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable request layout
|
||||
mEnableRequestFill = false;
|
||||
if (mLayoutManager != null) {
|
||||
mLayoutManager.onFill();
|
||||
}
|
||||
mEnableRequestFill = true;
|
||||
mRequestFill = false;
|
||||
}
|
||||
|
||||
private void dispatchMethod() {
|
||||
List<Integer> methodListTemp = mMethodListTemp;
|
||||
List<Object[]> argsListTemp = mArgsListTemp;
|
||||
|
||||
synchronized (this) {
|
||||
if (mMethodList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
methodListTemp.addAll(mMethodList);
|
||||
argsListTemp.addAll(mArgsList);
|
||||
mMethodList.clear();
|
||||
mArgsList.clear();
|
||||
}
|
||||
|
||||
for (int i = 0, n = methodListTemp.size(); i < n; i++) {
|
||||
int method = methodListTemp.get(i);
|
||||
Object[] args = argsListTemp.get(i);
|
||||
|
||||
switch (method) {
|
||||
case METHOD_ON_SINGLE_TAP_UP:
|
||||
onSingleTapUpInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SINGLE_TAP_CONFIRMED:
|
||||
onSingleTapConfirmedInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_DOUBLE_TAP:
|
||||
onDoubleTapInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_DOUBLE_TAP_CONFIRMED:
|
||||
onDoubleTapConfirmedInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_LONG_PRESS:
|
||||
onLongPressInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCROLL:
|
||||
onScrollInternal((Float) args[0], (Float) args[1], (Float) args[2],
|
||||
(Float) args[3], (Float) args[4], (Float) args[5]);
|
||||
break;
|
||||
case METHOD_ON_FLING:
|
||||
onFlingInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCALE_BEGIN:
|
||||
onScaleBeginInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_SCALE:
|
||||
onScaleInternal((Float) args[0], (Float) args[1], (Float) args[2]);
|
||||
break;
|
||||
case METHOD_ON_SCALE_END:
|
||||
onScaleEndInternal();
|
||||
break;
|
||||
case METHOD_ON_DOWN:
|
||||
onDownInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_UP:
|
||||
onUpInternal();
|
||||
break;
|
||||
case METHOD_ON_POINTER_DOWN:
|
||||
onPointerDownInternal((Float) args[0], (Float) args[1]);
|
||||
break;
|
||||
case METHOD_ON_POINTER_UP:
|
||||
onPointerUpInternal();
|
||||
break;
|
||||
case METHOD_SET_LAYOUT_MODE:
|
||||
setLayoutModeInternal((Integer) args[0]);
|
||||
break;
|
||||
case METHOD_SET_CURRENT_PAGE:
|
||||
setCurrentPageInternal((Integer) args[0]);
|
||||
break;
|
||||
case METHOD_PAGE_LEFT:
|
||||
pageLeftInternal();
|
||||
break;
|
||||
case METHOD_PAGE_RIGHT:
|
||||
pageRightInternal();
|
||||
break;
|
||||
case METHOD_SET_SCALE_MODE:
|
||||
setScaleModeInternal((Integer) args[0]);
|
||||
break;
|
||||
case METHOD_SET_START_POSITION:
|
||||
setStartPositionInternal((Integer) args[0]);
|
||||
break;
|
||||
case METHOD_ON_ATTACH_TO_ROOT:
|
||||
onAttachToRootInternal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
methodListTemp.clear();
|
||||
argsListTemp.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GLCanvas canvas) {
|
||||
mWillFill = true;
|
||||
int oldCurrentIndex = mCurrentIndex.get();
|
||||
|
||||
// Dispatch method
|
||||
dispatchMethod();
|
||||
|
||||
long time = AnimationTime.get();
|
||||
if (mLayoutManager != null && mLayoutManager.onUpdateAnimation(time)) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
fill();
|
||||
mWillFill = false;
|
||||
|
||||
super.render(canvas);
|
||||
mEdgeView.render(canvas);
|
||||
|
||||
int newCurrentIndex;
|
||||
if (mLayoutManager != null) {
|
||||
newCurrentIndex = mLayoutManager.getCurrentIndex();
|
||||
} else {
|
||||
newCurrentIndex = GalleryPageView.INVALID_INDEX;
|
||||
}
|
||||
mCurrentIndex.lazySet(newCurrentIndex);
|
||||
|
||||
if (oldCurrentIndex != newCurrentIndex) {
|
||||
mListener.onUpdateCurrentIndex(newCurrentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@RenderThread
|
||||
public GalleryPageView findPageByIndex(int id) {
|
||||
if (mLayoutManager != null) {
|
||||
return mLayoutManager.findPageByIndex(id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
GalleryPageView obtainPage() {
|
||||
GalleryPageView page = mGalleryPageViewPool.pop();
|
||||
if (page == null) {
|
||||
page = new GalleryPageView(mContext, mPageTextTexture, mProgressColor, mProgressSize);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
void releasePage(GalleryPageView page) {
|
||||
mGalleryPageViewPool.push(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indeterminate GLProgressView
|
||||
*/
|
||||
GLProgressView obtainProgress() {
|
||||
GLProgressView progress;
|
||||
if (mProgressCache != null) {
|
||||
progress = mProgressCache;
|
||||
mProgressCache = null;
|
||||
} else {
|
||||
progress = new GLProgressView();
|
||||
progress.setColor(mProgressColor);
|
||||
progress.setBgColor(BACKGROUND_COLOR);
|
||||
progress.setIndeterminate(true);
|
||||
progress.setMinimumWidth(mProgressSize);
|
||||
progress.setMinimumHeight(mProgressSize);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param progress Indeterminate GLProgressView
|
||||
*/
|
||||
void releaseProgress(GLProgressView progress) {
|
||||
mProgressCache = progress;
|
||||
}
|
||||
|
||||
GLTextureView obtainErrorView() {
|
||||
GLTextureView errorView;
|
||||
if (mErrorViewCache != null) {
|
||||
errorView = mErrorViewCache;
|
||||
mErrorViewCache = null;
|
||||
} else {
|
||||
errorView = new GLTextureView();
|
||||
}
|
||||
return errorView;
|
||||
}
|
||||
|
||||
void unbindErrorView(GLTextureView errorView) {
|
||||
Texture texture = errorView.getTexture();
|
||||
if (texture != null) {
|
||||
errorView.setTexture(null);
|
||||
if (texture instanceof BasicTexture) {
|
||||
((BasicTexture) texture).recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bindErrorView(GLTextureView errorView, String error) {
|
||||
unbindErrorView(errorView);
|
||||
|
||||
Texture texture = StringTexture.newInstance(error, mErrorSize, mErrorColor);
|
||||
errorView.setTexture(texture);
|
||||
}
|
||||
|
||||
void releaseErrorView(GLTextureView errorView) {
|
||||
unbindErrorView(errorView);
|
||||
mErrorViewCache = errorView;
|
||||
}
|
||||
|
||||
public static abstract class Adapter {
|
||||
|
||||
protected GalleryView mGalleryView;
|
||||
|
||||
private void setGalleryView(@NonNull GalleryView galleryView) {
|
||||
mGalleryView = galleryView;
|
||||
}
|
||||
|
||||
public void bind(GalleryPageView view, int index) {
|
||||
onBind(view, index);
|
||||
view.setIndex(index);
|
||||
}
|
||||
|
||||
public void unbind(GalleryPageView view) {
|
||||
onUnbind(view, view.getIndex());
|
||||
view.setIndex(GalleryPageView.INVALID_INDEX);
|
||||
}
|
||||
|
||||
public abstract void onBind(GalleryPageView view, int index);
|
||||
|
||||
public abstract void onUnbind(GalleryPageView view, int index);
|
||||
|
||||
/**
|
||||
* @return Null for no error
|
||||
*/
|
||||
public abstract String getError();
|
||||
|
||||
public abstract int size();
|
||||
}
|
||||
|
||||
public static abstract class LayoutManager {
|
||||
|
||||
protected GalleryView mGalleryView;
|
||||
|
||||
public LayoutManager(@NonNull GalleryView galleryView) {
|
||||
mGalleryView = galleryView;
|
||||
}
|
||||
|
||||
public abstract void onAttach(Adapter iterator);
|
||||
|
||||
public abstract Adapter onDetach();
|
||||
|
||||
public abstract void onFill();
|
||||
|
||||
public abstract void onDown();
|
||||
|
||||
public abstract void onUp();
|
||||
|
||||
public abstract void onDoubleTapConfirmed(float x, float y);
|
||||
|
||||
public abstract void onLongPress(float x, float y);
|
||||
|
||||
public abstract void onScroll(float dx, float dy, float totalX, float totalY, float x, float y);
|
||||
|
||||
public abstract void onFling(float velocityX, float velocityY);
|
||||
|
||||
public abstract boolean canScale();
|
||||
|
||||
public abstract void onScale(float focusX, float focusY, float scale);
|
||||
|
||||
public abstract boolean onUpdateAnimation(long time);
|
||||
|
||||
public abstract void onDataChanged();
|
||||
|
||||
public abstract void onPageLeft();
|
||||
|
||||
public abstract void onPageRight();
|
||||
|
||||
public abstract boolean isTapOrPressEnable();
|
||||
|
||||
public abstract GalleryPageView findPageByIndex(int index);
|
||||
|
||||
/**
|
||||
* @return {@link GalleryPageView#INVALID_INDEX} for error
|
||||
*/
|
||||
public abstract int getCurrentIndex();
|
||||
|
||||
public abstract void setCurrentIndex(int index);
|
||||
|
||||
public abstract int getIndexUnder(float x, float y);
|
||||
|
||||
abstract int getInternalCurrentIndex();
|
||||
|
||||
protected void placeCenter(GLView view) {
|
||||
int spec = GLView.MeasureSpec.makeMeasureSpec(GLView.LayoutParams.WRAP_CONTENT,
|
||||
GLView.LayoutParams.WRAP_CONTENT);
|
||||
view.measure(spec, spec);
|
||||
int viewWidth = view.getMeasuredWidth();
|
||||
int viewHeight = view.getMeasuredHeight();
|
||||
int viewLeft = mGalleryView.getWidth() / 2 - viewWidth / 2;
|
||||
int viewTop = mGalleryView.getHeight() / 2 - viewHeight / 2;
|
||||
view.layout(viewLeft, viewTop, viewLeft + viewWidth, viewTop + viewHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
@RenderThread
|
||||
void onUpdateCurrentIndex(int index);
|
||||
|
||||
@RenderThread
|
||||
void onTapSliderArea();
|
||||
|
||||
@RenderThread
|
||||
void onTapMenuArea();
|
||||
|
||||
@RenderThread
|
||||
void onLongPressPage(int index);
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.view.GestureDetectorCompat;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
|
||||
// This class aggregates three gesture detectors: GestureDetector,
|
||||
// ScaleGestureDetector, and DownUpDetector.
|
||||
public class GestureRecognizer {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "GestureRecognizer";
|
||||
|
||||
public interface Listener {
|
||||
boolean onSingleTapUp(float x, float y);
|
||||
boolean onSingleTapConfirmed(float x, float y);
|
||||
boolean onDoubleTap(float x, float y);
|
||||
boolean onDoubleTapConfirmed(float x, float y);
|
||||
void onLongPress(float x, float y);
|
||||
boolean onScroll(float dx, float dy, float totalX, float totalY, float x, float y);
|
||||
|
||||
/**
|
||||
* @param velocityX Finger from top to bottom is positive
|
||||
* @param velocityY Finger from left to right is positive
|
||||
*/
|
||||
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
|
||||
boolean onScaleBegin(float focusX, float focusY);
|
||||
boolean onScale(float focusX, float focusY, float scale);
|
||||
void onScaleEnd();
|
||||
void onDown(float x, float y);
|
||||
void onUp();
|
||||
void onPointerDown(float x, float y);
|
||||
void onPointerUp();
|
||||
}
|
||||
|
||||
private final GestureDetectorCompat mGestureDetector;
|
||||
private final ScaleGestureDetector mScaleDetector;
|
||||
private final DownUpDetector mDownUpDetector;
|
||||
private final Listener mListener;
|
||||
|
||||
public GestureRecognizer(Context context, Listener listener) {
|
||||
mListener = listener;
|
||||
MyGestureListener gestureListener = new MyGestureListener();
|
||||
mGestureDetector = new GestureDetectorCompat(context, gestureListener,
|
||||
null /* ignoreMultitouch */);
|
||||
mGestureDetector.setOnDoubleTapListener(gestureListener);
|
||||
mScaleDetector = new ScaleGestureDetector(
|
||||
context, new MyScaleListener());
|
||||
mDownUpDetector = new DownUpDetector(new MyDownUpListener());
|
||||
}
|
||||
|
||||
public void onTouchEvent(MotionEvent event) {
|
||||
mScaleDetector.onTouchEvent(event);
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
mDownUpDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
return mDownUpDetector.isDown();
|
||||
}
|
||||
|
||||
public void cancelScale() {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
MotionEvent cancelEvent = MotionEvent.obtain(
|
||||
now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
||||
mScaleDetector.onTouchEvent(cancelEvent);
|
||||
cancelEvent.recycle();
|
||||
}
|
||||
|
||||
private class MyGestureListener
|
||||
extends GestureDetector.SimpleOnGestureListener {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
return mListener.onSingleTapUp(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
return mListener.onSingleTapConfirmed(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTapEvent(MotionEvent e) {
|
||||
if (e.getAction() == MotionEvent.ACTION_UP) {
|
||||
return mListener.onDoubleTapConfirmed(e.getX(), e.getY());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
return mListener.onDoubleTap(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
mListener.onLongPress(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(
|
||||
MotionEvent e1, MotionEvent e2, float dx, float dy) {
|
||||
return mListener.onScroll(
|
||||
dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY(), e2.getX(), e2.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
|
||||
float velocityY) {
|
||||
return mListener.onFling(e1, e2, velocityX, velocityY);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyScaleListener
|
||||
extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
return mListener.onScaleBegin(
|
||||
detector.getFocusX(), detector.getFocusY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
return mListener.onScale(detector.getFocusX(),
|
||||
detector.getFocusY(), detector.getScaleFactor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
mListener.onScaleEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyDownUpListener implements DownUpDetector.DownUpListener {
|
||||
@Override
|
||||
public void onDown(MotionEvent e) {
|
||||
mListener.onDown(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUp(MotionEvent e) {
|
||||
mListener.onUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerDown(MotionEvent e) {
|
||||
mListener.onPointerDown(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerUp(MotionEvent e) {
|
||||
mListener.onPointerUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,620 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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.gl;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.support.annotation.IntDef;
|
||||
|
||||
import com.hippo.glview.anim.AlphaAnimation;
|
||||
import com.hippo.glview.glrenderer.GLCanvas;
|
||||
import com.hippo.glview.glrenderer.Texture;
|
||||
import com.hippo.glview.image.ImageTexture;
|
||||
import com.hippo.glview.view.GLView;
|
||||
import com.hippo.yorozuya.AnimationUtils;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ImageView extends GLView implements ImageTexture.Callback {
|
||||
|
||||
@IntDef({SCALE_ORIGIN, SCALE_FIT_WIDTH, SCALE_FIT_HEIGHT, SCALE_FIT, SCALE_FIXED})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Scale {}
|
||||
|
||||
@IntDef({START_POSITION_TOP_LEFT, START_POSITION_TOP_RIGHT, START_POSITION_BOTTOM_LEFT,
|
||||
START_POSITION_BOTTOM_RIGHT, START_POSITION_CENTER})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StartPosition {}
|
||||
|
||||
// TODO adjust scale max and min according to image size and screen size
|
||||
private static final float SCALE_MIN = 1 / 10.0f;
|
||||
private static final float SCALE_MAX = 10.0f;
|
||||
|
||||
public static final int SCALE_ORIGIN = 0;
|
||||
public static final int SCALE_FIT_WIDTH = 1;
|
||||
public static final int SCALE_FIT_HEIGHT = 2;
|
||||
public static final int SCALE_FIT = 3;
|
||||
public static final int SCALE_FIXED = 4;
|
||||
|
||||
public static final int START_POSITION_TOP_LEFT = 0;
|
||||
public static final int START_POSITION_TOP_RIGHT = 1;
|
||||
public static final int START_POSITION_BOTTOM_LEFT = 2;
|
||||
public static final int START_POSITION_BOTTOM_RIGHT = 3;
|
||||
public static final int START_POSITION_CENTER = 4;
|
||||
|
||||
private static final long ALPHA_ANIMATION_DURING = 300L;
|
||||
|
||||
private ImageTexture mImageTexture;
|
||||
private int mTextureWidth;
|
||||
private int mTextureHeight;
|
||||
|
||||
private final RectF mDst = new RectF();
|
||||
private final RectF mSrcActual = new RectF();
|
||||
private final RectF mDstActual = new RectF();
|
||||
private final Rect mValidRect = new Rect();
|
||||
|
||||
private int mScaleMode = SCALE_FIT;
|
||||
private int mStartPosition = START_POSITION_TOP_RIGHT;
|
||||
private float mScaleValue = 1.0f;
|
||||
|
||||
private float mScale = 1.0f;
|
||||
|
||||
private boolean mScaleOffsetDirty = true;
|
||||
private boolean mPositionInRootDirty = true;
|
||||
|
||||
private final AlphaAnimation mAlphaAnimation;
|
||||
|
||||
public ImageView() {
|
||||
mAlphaAnimation = new AlphaAnimation(0.0f, 1.0f);
|
||||
mAlphaAnimation.setDuration(ALPHA_ANIMATION_DURING);
|
||||
mAlphaAnimation.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR);
|
||||
}
|
||||
|
||||
@Scale
|
||||
public static int sanitizeScaleMode(int scaleMode) {
|
||||
if (scaleMode != SCALE_ORIGIN &&
|
||||
scaleMode != SCALE_FIT_WIDTH &&
|
||||
scaleMode != SCALE_FIT_HEIGHT &&
|
||||
scaleMode != SCALE_FIT &&
|
||||
scaleMode != SCALE_FIXED) {
|
||||
return SCALE_FIT;
|
||||
} else {
|
||||
return scaleMode;
|
||||
}
|
||||
}
|
||||
|
||||
@StartPosition
|
||||
public static int sanitizeStartPosition(int startPosition) {
|
||||
if (startPosition != START_POSITION_TOP_LEFT &&
|
||||
startPosition != START_POSITION_TOP_RIGHT &&
|
||||
startPosition != START_POSITION_BOTTOM_LEFT &&
|
||||
startPosition != START_POSITION_BOTTOM_RIGHT &&
|
||||
startPosition != START_POSITION_CENTER) {
|
||||
return START_POSITION_TOP_RIGHT;
|
||||
} else {
|
||||
return startPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumWidth() {
|
||||
return Math.max(super.getSuggestedMinimumWidth(),
|
||||
mImageTexture == null ? 0 : mTextureWidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumHeight() {
|
||||
return Math.max(super.getSuggestedMinimumHeight(),
|
||||
mImageTexture == null ? 0 : mTextureHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthSpec, int heightSpec) {
|
||||
if (mImageTexture == null) {
|
||||
super.onMeasure(widthSpec, heightSpec);
|
||||
} else {
|
||||
float ratio = (float) mTextureWidth / mTextureHeight;
|
||||
int widthSize = MeasureSpec.getSize(widthSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightSpec);
|
||||
int measureWidth = -1;
|
||||
int measureHeight = -1;
|
||||
|
||||
if (widthMode == MeasureSpec.EXACTLY) {
|
||||
measureWidth = widthSize;
|
||||
if (heightMode == MeasureSpec.EXACTLY) {
|
||||
measureHeight = heightSize;
|
||||
} else {
|
||||
measureHeight = (int) (widthSize / ratio);
|
||||
if (heightMode == MeasureSpec.AT_MOST) {
|
||||
measureHeight = Math.min(measureHeight, heightSize);
|
||||
}
|
||||
}
|
||||
} else if (heightMode == MeasureSpec.EXACTLY) {
|
||||
measureHeight = heightSize;
|
||||
measureWidth = (int) (heightSize * ratio);
|
||||
if (widthMode == MeasureSpec.AT_MOST) {
|
||||
measureWidth = Math.min(measureWidth, widthSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (measureWidth == -1 || measureHeight == -1) {
|
||||
super.onMeasure(widthSpec, heightSpec);
|
||||
} else {
|
||||
setMeasuredSize(measureWidth, measureHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int newW, int newH, int oldW, int oldH) {
|
||||
mScaleOffsetDirty = true;
|
||||
mPositionInRootDirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPositionInRootChanged(int x, int y, int oldX, int oldY) {
|
||||
mPositionInRootDirty = true;
|
||||
|
||||
if (mImageTexture != null) {
|
||||
getValidRect(mValidRect);
|
||||
if (!mValidRect.isEmpty()) {
|
||||
mImageTexture.start();
|
||||
} else {
|
||||
mImageTexture.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getScaleDefault(float[] scaleDefault) {
|
||||
if (mImageTexture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
scaleDefault[0] = 1.0f;
|
||||
scaleDefault[1] = (float) getWidth() / mTextureWidth;
|
||||
scaleDefault[2] = (float) getHeight() / mTextureHeight;
|
||||
scaleDefault[3] = Math.max(scaleDefault[1], scaleDefault[2]) * 2;
|
||||
|
||||
scaleDefault[0] = MathUtils.clamp(scaleDefault[0], SCALE_MIN, SCALE_MAX);
|
||||
scaleDefault[1] = MathUtils.clamp(scaleDefault[1], SCALE_MIN, SCALE_MAX);
|
||||
scaleDefault[2] = MathUtils.clamp(scaleDefault[2], SCALE_MIN, SCALE_MAX);
|
||||
scaleDefault[3] = MathUtils.clamp(scaleDefault[3], SCALE_MIN, SCALE_MAX);
|
||||
|
||||
Arrays.sort(scaleDefault);
|
||||
}
|
||||
|
||||
public void setImageTexture(ImageTexture imageTexture) {
|
||||
// Remove callback
|
||||
if (mImageTexture != null) {
|
||||
mImageTexture.setCallback(null);
|
||||
mImageTexture.stop();
|
||||
}
|
||||
|
||||
int oldTextureWidth = mTextureWidth;
|
||||
int oldTextureHeight = mTextureHeight;
|
||||
|
||||
mImageTexture = imageTexture;
|
||||
|
||||
if (imageTexture != null) {
|
||||
imageTexture.setCallback(this);
|
||||
mTextureWidth = imageTexture.getWidth();
|
||||
mTextureHeight = imageTexture.getHeight();
|
||||
// Avoid zero and negative
|
||||
if (mTextureWidth <= 0) {
|
||||
mTextureWidth = 1;
|
||||
}
|
||||
if (mTextureHeight <= 0) {
|
||||
mTextureHeight = 1;
|
||||
}
|
||||
|
||||
// Start alpha animation, do not show animation for image has no valid rect
|
||||
getValidRect(mValidRect);
|
||||
if (!mValidRect.isEmpty()) {
|
||||
startAnimation(mAlphaAnimation, true);
|
||||
mImageTexture.start();
|
||||
}
|
||||
} else {
|
||||
mTextureWidth = 1;
|
||||
mTextureHeight = 1;
|
||||
}
|
||||
|
||||
mScaleOffsetDirty = true;
|
||||
mPositionInRootDirty = true;
|
||||
|
||||
if (oldTextureWidth != mTextureWidth || oldTextureHeight != mTextureHeight) {
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public ImageTexture getImageTexture() {
|
||||
return mImageTexture;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return mImageTexture != null;
|
||||
}
|
||||
|
||||
public boolean canFlingVertically() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return mDst.top < 0.0f || mDst.bottom > getHeight();
|
||||
}
|
||||
|
||||
public boolean canFlingHorizontally() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return mDst.left < 0.0f || mDst.right > getWidth();
|
||||
}
|
||||
|
||||
public boolean canFling() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return mDst.left < 0.0f || mDst.top < 0.0f || mDst.right > getWidth() || mDst.bottom > getHeight();
|
||||
}
|
||||
|
||||
public int getMaxDx() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return Math.max(0, -(int) mDst.left);
|
||||
}
|
||||
|
||||
public int getMinDx() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return Math.min(0, getWidth() - (int) mDst.right);
|
||||
}
|
||||
|
||||
public int getMaxDy() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return Math.max(0, -(int) mDst.top);
|
||||
}
|
||||
|
||||
public int getMinDy() {
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
if (mScaleOffsetDirty) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return Math.min(0, getHeight() - (int) mDst.bottom);
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* If target is shorter then screen, make it in screen center. If target is
|
||||
* longer then parent, make sure target fill parent over
|
||||
*/
|
||||
private void adjustPosition() {
|
||||
RectF dst = mDst;
|
||||
int screenWidth = getWidth();
|
||||
int screenHeight = getHeight();
|
||||
float targetWidth = dst.width();
|
||||
float targetHeight = dst.height();
|
||||
|
||||
if (targetWidth > screenWidth) {
|
||||
float fixXOffset = dst.left;
|
||||
if (fixXOffset > 0) {
|
||||
dst.left -= fixXOffset;
|
||||
dst.right -= fixXOffset;
|
||||
} else if ((fixXOffset = screenWidth - dst.right) > 0) {
|
||||
dst.left += fixXOffset;
|
||||
dst.right += fixXOffset;
|
||||
}
|
||||
} else {
|
||||
float left = (screenWidth - targetWidth) / 2;
|
||||
dst.offsetTo(left, dst.top);
|
||||
}
|
||||
if (targetHeight > screenHeight) {
|
||||
float fixYOffset = dst.top;
|
||||
if (fixYOffset > 0) {
|
||||
dst.top -= fixYOffset;
|
||||
dst.bottom -= fixYOffset;
|
||||
} else if ((fixYOffset = screenHeight - dst.bottom) > 0) {
|
||||
dst.top += fixYOffset;
|
||||
dst.bottom += fixYOffset;
|
||||
}
|
||||
} else {
|
||||
float top = (screenHeight - targetHeight) / 2;
|
||||
dst.offsetTo(dst.left, top);
|
||||
}
|
||||
}
|
||||
|
||||
public void setScaleOffset(@Scale int scaleMode, @StartPosition int startPosition, float scaleValue) {
|
||||
mScaleMode = scaleMode;
|
||||
mStartPosition = startPosition;
|
||||
mScaleValue = scaleValue;
|
||||
|
||||
int screenWidth = getWidth();
|
||||
int screenHeight = getHeight();
|
||||
|
||||
if (mImageTexture == null || screenWidth == 0 || screenHeight == 0) {
|
||||
mScaleOffsetDirty = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int textureWidth = mTextureWidth;
|
||||
int textureHeight = mTextureHeight;
|
||||
|
||||
// Set scale
|
||||
float targetWidth;
|
||||
float targetHeight;
|
||||
switch (scaleMode) {
|
||||
case SCALE_ORIGIN:
|
||||
mScale = 1.0f;
|
||||
targetWidth = textureWidth;
|
||||
targetHeight = textureHeight;
|
||||
break;
|
||||
case SCALE_FIT_WIDTH:
|
||||
mScale = (float) screenWidth / textureWidth;
|
||||
targetWidth = screenWidth;
|
||||
targetHeight = textureHeight * mScale;
|
||||
break;
|
||||
case SCALE_FIT_HEIGHT:
|
||||
mScale = (float) screenHeight / textureHeight;
|
||||
targetWidth = textureWidth * mScale;
|
||||
targetHeight = screenHeight;
|
||||
break;
|
||||
case SCALE_FIT:
|
||||
float scaleX = (float) screenWidth / textureWidth;
|
||||
float scaleY = (float) screenHeight / textureHeight;
|
||||
if (scaleX < scaleY) {
|
||||
mScale = scaleX;
|
||||
targetWidth = screenWidth;
|
||||
targetHeight = textureHeight * scaleX;
|
||||
} else {
|
||||
mScale = scaleY;
|
||||
targetWidth = textureWidth * scaleY;
|
||||
targetHeight = screenHeight;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCALE_FIXED:
|
||||
default:
|
||||
mScale = scaleValue;
|
||||
targetWidth = textureWidth * scaleValue;
|
||||
targetHeight = textureHeight * scaleValue;
|
||||
break;
|
||||
}
|
||||
|
||||
// adjust scale, not too big, not too small
|
||||
if (mScale < SCALE_MIN) {
|
||||
mScale = SCALE_MIN;
|
||||
targetWidth = textureWidth * SCALE_MIN;
|
||||
targetHeight = textureHeight * SCALE_MIN;
|
||||
} else if (mScale > SCALE_MAX) {
|
||||
mScale = SCALE_MAX;
|
||||
targetWidth = textureWidth * SCALE_MAX;
|
||||
targetHeight = textureHeight * SCALE_MAX;
|
||||
}
|
||||
|
||||
// Set mDst.left and mDst.right
|
||||
RectF dst = mDst;
|
||||
switch (startPosition) {
|
||||
case START_POSITION_TOP_LEFT:
|
||||
dst.left = 0;
|
||||
dst.top = 0;
|
||||
break;
|
||||
case START_POSITION_TOP_RIGHT:
|
||||
dst.left = screenWidth - targetWidth;
|
||||
dst.top = 0;
|
||||
break;
|
||||
case START_POSITION_BOTTOM_LEFT:
|
||||
dst.left = 0;
|
||||
dst.top = screenHeight - targetHeight;
|
||||
break;
|
||||
case START_POSITION_BOTTOM_RIGHT:
|
||||
dst.left = screenWidth - targetWidth;
|
||||
dst.top = screenHeight - targetHeight;
|
||||
break;
|
||||
case START_POSITION_CENTER:
|
||||
default:
|
||||
dst.left = (screenWidth - targetWidth) / 2;
|
||||
dst.top = (screenHeight - targetHeight) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set mDst.right and mDst.bottom
|
||||
dst.right = dst.left + targetWidth;
|
||||
dst.bottom = dst.top + targetHeight;
|
||||
|
||||
// adjust position
|
||||
adjustPosition();
|
||||
|
||||
mScaleOffsetDirty = false;
|
||||
mPositionInRootDirty = true;
|
||||
}
|
||||
|
||||
public void scroll(int dx, int dy, int[] remain) {
|
||||
// Only work after layout
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
}
|
||||
if (mScaleOffsetDirty) {
|
||||
remain[0] = dx;
|
||||
remain[1] = dy;
|
||||
return;
|
||||
}
|
||||
|
||||
RectF dst = mDst;
|
||||
int screenWidth = getWidth();
|
||||
int screenHeight = getHeight();
|
||||
float targetWidth = dst.width();
|
||||
float targetHeight = dst.height();
|
||||
|
||||
if (targetWidth > screenWidth) {
|
||||
dst.left -= dx;
|
||||
dst.right -= dx;
|
||||
|
||||
float fixXOffset = dst.left;
|
||||
if (fixXOffset > 0) {
|
||||
dst.left -= fixXOffset;
|
||||
dst.right -= fixXOffset;
|
||||
remain[0] = -(int) fixXOffset;
|
||||
} else if ((fixXOffset = screenWidth - dst.right) > 0) {
|
||||
dst.left += fixXOffset;
|
||||
dst.right += fixXOffset;
|
||||
remain[0] = (int) fixXOffset;
|
||||
} else {
|
||||
remain[0] = 0;
|
||||
}
|
||||
} else {
|
||||
remain[0] = dx;
|
||||
}
|
||||
if (targetHeight > screenHeight) {
|
||||
dst.top -= dy;
|
||||
dst.bottom -= dy;
|
||||
|
||||
float fixYOffset = dst.top;
|
||||
if (fixYOffset > 0) {
|
||||
dst.top -= fixYOffset;
|
||||
dst.bottom -= fixYOffset;
|
||||
remain[1] = -(int) fixYOffset;
|
||||
} else if ((fixYOffset = screenHeight - dst.bottom) > 0) {
|
||||
dst.top += fixYOffset;
|
||||
dst.bottom += fixYOffset;
|
||||
remain[1] = (int) fixYOffset;
|
||||
} else {
|
||||
remain[1] = 0;
|
||||
}
|
||||
} else {
|
||||
remain[1] = dy;
|
||||
}
|
||||
|
||||
if (dx != remain[0] || dy != remain[1]) {
|
||||
mPositionInRootDirty = true;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void scale(float focusX, float focusY, float scale) {
|
||||
// Only work after layout
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
}
|
||||
if (mScaleOffsetDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mScale == SCALE_MAX && scale >= 1.0f) || (mScale == SCALE_MIN && scale < 1.0f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float newScale = mScale * scale;
|
||||
newScale = MathUtils.clamp(newScale, SCALE_MIN, SCALE_MAX);
|
||||
mScale = newScale;
|
||||
RectF dst = mDst;
|
||||
float left = (focusX - ((focusX - dst.left) * scale));
|
||||
float top = (focusY - ((focusY - dst.top) * scale));
|
||||
dst.set(left, top,
|
||||
(left + (mImageTexture.getWidth() * newScale)),
|
||||
(top + (mImageTexture.getHeight() * newScale)));
|
||||
|
||||
// adjust position
|
||||
adjustPosition();
|
||||
|
||||
mPositionInRootDirty = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void applyPositionInRoot() {
|
||||
int width = mImageTexture.getWidth();
|
||||
int height = mImageTexture.getHeight();
|
||||
RectF dst = mDst;
|
||||
RectF dstActual = mDstActual;
|
||||
RectF srcActual = mSrcActual;
|
||||
|
||||
dstActual.set(dst);
|
||||
getValidRect(mValidRect);
|
||||
if (dstActual.intersect(mValidRect.left, mValidRect.top, mValidRect.right, mValidRect.bottom)) {
|
||||
srcActual.left = MathUtils.lerp(0, width,
|
||||
MathUtils.delerp(dst.left, dst.right, dstActual.left));
|
||||
srcActual.right = MathUtils.lerp(0, width,
|
||||
MathUtils.delerp(dst.left, dst.right, dstActual.right));
|
||||
srcActual.top = MathUtils.lerp(0, height,
|
||||
MathUtils.delerp(dst.top, dst.bottom, dstActual.top));
|
||||
srcActual.bottom = MathUtils.lerp(0, height,
|
||||
MathUtils.delerp(dst.top, dst.bottom, dstActual.bottom));
|
||||
} else {
|
||||
// Can't be seen, set src and dst empty
|
||||
srcActual.setEmpty();
|
||||
dstActual.setEmpty();
|
||||
}
|
||||
|
||||
mPositionInRootDirty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRender(GLCanvas canvas) {
|
||||
Texture texture = mImageTexture;
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mScaleOffsetDirty) {
|
||||
setScaleOffset(mScaleMode, mStartPosition, mScaleValue);
|
||||
}
|
||||
|
||||
if (mPositionInRootDirty) {
|
||||
applyPositionInRoot();
|
||||
}
|
||||
|
||||
if (!mSrcActual.isEmpty()) {
|
||||
texture.draw(canvas, mSrcActual, mDstActual);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateImageTexture(ImageTexture who) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -27,7 +27,7 @@ import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider2;
|
||||
import com.hippo.io.UniFileInputStreamPipe;
|
||||
import com.hippo.io.UniFileOutputStreamPipe;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
@@ -169,7 +169,7 @@ public final class SpiderDen {
|
||||
|
||||
@Nullable
|
||||
private static UniFile findImageFile(UniFile dir, int index) {
|
||||
for (String extension : GalleryProvider.SUPPORT_IMAGE_EXTENSIONS) {
|
||||
for (String extension : GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS) {
|
||||
String filename = generateImageFilename(index, extension);
|
||||
UniFile file = dir.findFile(filename);
|
||||
if (file != null) {
|
||||
@@ -193,10 +193,10 @@ public final class SpiderDen {
|
||||
* @param extension with dot
|
||||
*/
|
||||
private String fixExtension(String extension) {
|
||||
if (Utilities.contain(GalleryProvider.SUPPORT_IMAGE_EXTENSIONS, extension)) {
|
||||
if (Utilities.contain(GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS, extension)) {
|
||||
return extension;
|
||||
} else {
|
||||
return GalleryProvider.SUPPORT_IMAGE_EXTENSIONS[0];
|
||||
return GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +275,8 @@ public final class SpiderDen {
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
for (int i = 0, n = GalleryProvider.SUPPORT_IMAGE_EXTENSIONS.length; i < n; i++) {
|
||||
String filename = generateImageFilename(index, GalleryProvider.SUPPORT_IMAGE_EXTENSIONS[i]);
|
||||
for (int i = 0, n = GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS.length; i < n; i++) {
|
||||
String filename = generateImageFilename(index, GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS[i]);
|
||||
UniFile file = dir.subFile(filename);
|
||||
if (file != null) {
|
||||
result |= file.delete();
|
||||
|
||||
@@ -45,8 +45,9 @@ import com.hippo.ehviewer.client.exception.ParseException;
|
||||
import com.hippo.ehviewer.client.parser.GalleryDetailParser;
|
||||
import com.hippo.ehviewer.client.parser.GalleryPageParser;
|
||||
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryPageView;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider2;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.glgallery.GalleryProvider;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
import com.hippo.streampipe.OutputStreamPipe;
|
||||
@@ -1092,8 +1093,8 @@ public final class SpiderQueen implements Runnable {
|
||||
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(
|
||||
responseBody.contentType().toString());
|
||||
// Ensure extension
|
||||
if (!Utilities.contain(GalleryProvider.SUPPORT_IMAGE_EXTENSIONS, extension)) {
|
||||
extension = GalleryProvider.SUPPORT_IMAGE_EXTENSIONS[0];
|
||||
if (!Utilities.contain(GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS, extension)) {
|
||||
extension = GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS[0];
|
||||
}
|
||||
|
||||
// Get out put pipe
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -52,16 +53,15 @@ import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.gallery.DirGalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.EhGalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.GalleryProviderListener;
|
||||
import com.hippo.ehviewer.gallery.GalleryProvider2;
|
||||
import com.hippo.ehviewer.gallery.ZipGalleryProvider;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryPageView;
|
||||
import com.hippo.ehviewer.gallery.gl.GalleryView;
|
||||
import com.hippo.ehviewer.gallery.gl.ImageView;
|
||||
import com.hippo.ehviewer.widget.GalleryGuideView;
|
||||
import com.hippo.ehviewer.widget.ReversibleSeekBar;
|
||||
import com.hippo.glview.image.ImageTexture;
|
||||
import com.hippo.glview.image.ImageWrapper;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.glgallery.GalleryProvider;
|
||||
import com.hippo.glgallery.GalleryView;
|
||||
import com.hippo.glgallery.SimpleAdapter;
|
||||
import com.hippo.glgallery.SimpleProviderListener;
|
||||
import com.hippo.glview.view.GLRootView;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.SystemUiHelper;
|
||||
@@ -69,14 +69,14 @@ import com.hippo.widget.ColorView;
|
||||
import com.hippo.yorozuya.AnimationUtils;
|
||||
import com.hippo.yorozuya.ConcurrentPool;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.ResourcesUtils;
|
||||
import com.hippo.yorozuya.SimpleAnimatorListener;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class GalleryActivity extends EhActivity
|
||||
implements GalleryProviderListener, SeekBar.OnSeekBarChangeListener,
|
||||
public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChangeListener,
|
||||
GalleryView.Listener {
|
||||
|
||||
public static final String ACTION_DIR = "dir";
|
||||
@@ -103,11 +103,10 @@ public class GalleryActivity extends EhActivity
|
||||
private GLRootView mGLRootView;
|
||||
@Nullable
|
||||
private GalleryView mGalleryView;
|
||||
|
||||
@Nullable
|
||||
private ImageTexture.Uploader mUploader;
|
||||
private GalleryProvider2 mGalleryProvider;
|
||||
@Nullable
|
||||
private GalleryProvider mGalleryProvider;
|
||||
private ProviderListener mProviderListener;
|
||||
|
||||
@Nullable
|
||||
private SystemUiHelper mSystemUiHelper;
|
||||
@@ -236,6 +235,7 @@ public class GalleryActivity extends EhActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
if (Settings.getReadingFullscreen() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window w = getWindow();
|
||||
@@ -257,14 +257,8 @@ public class GalleryActivity extends EhActivity
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mGalleryProvider.setGalleryProviderListener(this);
|
||||
mGalleryProvider.start();
|
||||
|
||||
setContentView(R.layout.activity_gallery);
|
||||
mGLRootView = (GLRootView) ViewUtils.$$(this, R.id.gl_root_view);
|
||||
mGalleryProvider.setGLRoot(mGLRootView);
|
||||
mUploader = new ImageTexture.Uploader(mGLRootView);
|
||||
|
||||
// Get start page
|
||||
int startPage;
|
||||
if (savedInstanceState == null) {
|
||||
startPage = mPage >= 0 ? mPage : mGalleryProvider.getStartPage();
|
||||
@@ -272,10 +266,39 @@ public class GalleryActivity extends EhActivity
|
||||
startPage = mCurrentIndex;
|
||||
}
|
||||
|
||||
mGalleryView = new GalleryView(this, new GalleryAdapter(), this,
|
||||
Settings.getReadingDirection(), Settings.getPageScaling(),
|
||||
Settings.getStartPosition(), startPage);
|
||||
setContentView(R.layout.activity_gallery);
|
||||
mGLRootView = (GLRootView) ViewUtils.$$(this, R.id.gl_root_view);
|
||||
Resources resources = getResources();
|
||||
int primaryColor = ResourcesUtils.getAttrColor(this, R.attr.colorPrimary);
|
||||
mGalleryView = new GalleryView.Builder(this, new SimpleAdapter(mGalleryProvider))
|
||||
.setListener(this)
|
||||
.setLayoutMode(Settings.getReadingDirection())
|
||||
.setScaleMode(Settings.getPageScaling())
|
||||
.setStartPosition(Settings.getStartPosition())
|
||||
.setStartPage(startPage)
|
||||
.setBackgroundColor(resources.getColor(R.color.gallery_background))
|
||||
.setEdgeColor(primaryColor & 0xffffff | 0x33000000)
|
||||
.setPagerInterval(resources.getDimensionPixelOffset(R.dimen.gallery_pager_interval))
|
||||
.setScrollInterval(resources.getDimensionPixelOffset(R.dimen.gallery_scroll_interval))
|
||||
.setPageMinHeight(resources.getDimensionPixelOffset(R.dimen.gallery_page_min_height))
|
||||
.setPageInfoInterval(resources.getDimensionPixelOffset(R.dimen.gallery_page_info_interval))
|
||||
.setProgressColor(primaryColor)
|
||||
.setProgressSize(resources.getDimensionPixelOffset(R.dimen.gallery_progress_size))
|
||||
.setPageTextColor(resources.getColor(R.color.secondary_text_default_dark))
|
||||
.setPageTextSize(resources.getDimensionPixelOffset(R.dimen.gallery_page_text_size))
|
||||
.setPageTextTypeface(Typeface.DEFAULT)
|
||||
.setErrorTextColor(resources.getColor(R.color.red_500))
|
||||
.setErrorTextSize(resources.getDimensionPixelOffset(R.dimen.gallery_error_text_size))
|
||||
.setDefaultErrorString(resources.getString(R.string.error_unknown))
|
||||
.setEmptyString(resources.getString(R.string.error_empty))
|
||||
.build();
|
||||
|
||||
mProviderListener = new ProviderListener(mGLRootView, mGalleryView, mGalleryProvider);
|
||||
|
||||
mGLRootView.setContentPane(mGalleryView);
|
||||
mGalleryProvider.setListener(mProviderListener);
|
||||
mGalleryProvider.setGLRoot(mGLRootView);
|
||||
mGalleryProvider.start();
|
||||
|
||||
// System UI helper
|
||||
if (Settings.getReadingFullscreen()) {
|
||||
@@ -347,12 +370,12 @@ public class GalleryActivity extends EhActivity
|
||||
super.onDestroy();
|
||||
mGLRootView = null;
|
||||
mGalleryView = null;
|
||||
if (mUploader != null) {
|
||||
mUploader.clear();
|
||||
mUploader = null;
|
||||
if (mProviderListener != null) {
|
||||
mProviderListener.clearUploader();
|
||||
mProviderListener = null;
|
||||
}
|
||||
if (mGalleryProvider != null) {
|
||||
mGalleryProvider.setGalleryProviderListener(null);
|
||||
mGalleryProvider.setListener(null);
|
||||
mGalleryProvider.stop();
|
||||
mGalleryProvider = null;
|
||||
}
|
||||
@@ -409,14 +432,14 @@ public class GalleryActivity extends EhActivity
|
||||
// Check volume
|
||||
if (Settings.getVolumePage()) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
mGalleryView.pageRight();
|
||||
} else {
|
||||
mGalleryView.pageLeft();
|
||||
}
|
||||
return true;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
mGalleryView.pageLeft();
|
||||
} else {
|
||||
mGalleryView.pageRight();
|
||||
@@ -429,7 +452,7 @@ public class GalleryActivity extends EhActivity
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_PAGE_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
mGalleryView.pageRight();
|
||||
} else {
|
||||
mGalleryView.pageLeft();
|
||||
@@ -440,7 +463,7 @@ public class GalleryActivity extends EhActivity
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_PAGE_DOWN:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
mGalleryView.pageLeft();
|
||||
} else {
|
||||
mGalleryView.pageRight();
|
||||
@@ -513,7 +536,7 @@ public class GalleryActivity extends EhActivity
|
||||
|
||||
TextView start;
|
||||
TextView end;
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
start = mRightText;
|
||||
end = mLeftText;
|
||||
mSeekBar.setReverse(true);
|
||||
@@ -528,96 +551,11 @@ public class GalleryActivity extends EhActivity
|
||||
mSeekBar.setProgress(mCurrentIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataChanged() {
|
||||
if (mGalleryView != null) {
|
||||
mGalleryView.onDataChanged();
|
||||
}
|
||||
|
||||
if (mGalleryProvider != null) {
|
||||
int size = mGalleryProvider.size();
|
||||
NotifyTask task = mNotifyTaskPool.pop();
|
||||
if (task == null) {
|
||||
task = new NotifyTask();
|
||||
}
|
||||
task.setData(NotifyTask.KEY_SIZE, size);
|
||||
SimpleHandler.getInstance().post(task);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageWait(int index) {
|
||||
GalleryPageView page = findPageByIndex(index);
|
||||
if (page != null) {
|
||||
page.showInfo();
|
||||
page.setImage(null);
|
||||
page.setPage(index + 1);
|
||||
page.setProgress(GalleryPageView.PROGRESS_INDETERMINATE);
|
||||
page.setError(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPagePercent(int index, float percent) {
|
||||
GalleryPageView page = findPageByIndex(index);
|
||||
if (page != null) {
|
||||
page.showInfo();
|
||||
page.setImage(null);
|
||||
page.setPage(index + 1);
|
||||
page.setProgress(percent);
|
||||
page.setError(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSucceed(int index, ImageWrapper image) {
|
||||
GalleryPageView page = findPageByIndex(index);
|
||||
if (page != null) {
|
||||
if (image.obtain()) {
|
||||
ImageTexture imageTexture = new ImageTexture(image);
|
||||
if (mUploader != null) {
|
||||
mUploader.addTexture(imageTexture);
|
||||
}
|
||||
page.showImage();
|
||||
page.setImage(imageTexture);
|
||||
page.setPage(index + 1);
|
||||
page.setProgress(GalleryPageView.PROGRESS_GONE);
|
||||
page.setError(null, null);
|
||||
} else {
|
||||
// The image is recycled, request again.
|
||||
// TODO request loop ?
|
||||
if (mGalleryProvider != null) {
|
||||
mGalleryProvider.request(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFailed(int index, String error) {
|
||||
GalleryPageView page = findPageByIndex(index);
|
||||
if (page != null && mGalleryView != null) {
|
||||
page.showInfo();
|
||||
page.setImage(null);
|
||||
page.setPage(index + 1);
|
||||
page.setProgress(GalleryPageView.PROGRESS_GONE);
|
||||
page.setError(error, mGalleryView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataChanged(int index) {
|
||||
GalleryPageView page = findPageByIndex(index);
|
||||
if (page != null && mGalleryProvider != null) {
|
||||
mGalleryProvider.request(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
TextView start;
|
||||
if (mLayoutMode == GalleryView.LAYOUT_MODE_RIGHT_TO_LEFT) {
|
||||
if (mLayoutMode == GalleryView.LAYOUT_RIGHT_TO_LEFT) {
|
||||
start = mRightText;
|
||||
} else {
|
||||
start = mLeftText;
|
||||
@@ -816,8 +754,8 @@ public class GalleryActivity extends EhActivity
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int screenRotation = mScreenRotation.getSelectedItemPosition();
|
||||
int layoutMode = GalleryView.sanitizeLayoutMode(mReadingDirection.getSelectedItemPosition());
|
||||
int scaleMode = ImageView.sanitizeScaleMode(mScaleMode.getSelectedItemPosition());
|
||||
int startPosition = ImageView.sanitizeStartPosition(mStartPosition.getSelectedItemPosition());
|
||||
int scaleMode = GalleryView.sanitizeScaleMode(mScaleMode.getSelectedItemPosition());
|
||||
int startPosition = GalleryView.sanitizeStartPosition(mStartPosition.getSelectedItemPosition());
|
||||
boolean keepScreenOn = mKeepScreenOn.isChecked();
|
||||
boolean showClock = mShowClock.isChecked();
|
||||
boolean showProgress = mShowProgress.isChecked();
|
||||
@@ -1039,46 +977,26 @@ public class GalleryActivity extends EhActivity
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryAdapter extends GalleryView.Adapter {
|
||||
private class ProviderListener extends SimpleProviderListener {
|
||||
|
||||
@Override
|
||||
public String getError() {
|
||||
if (mGalleryProvider == null) {
|
||||
return getString(R.string.error_no_provider);
|
||||
} else if (mGalleryProvider.size() <= GalleryProvider.STATE_ERROR) {
|
||||
return mGalleryProvider.getError();
|
||||
}
|
||||
return null;
|
||||
public ProviderListener(@NonNull GLRootView glRootView,
|
||||
@NonNull GalleryView galleryView, @NonNull GalleryProvider provider) {
|
||||
super(glRootView, galleryView, provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (mGalleryProvider == null) {
|
||||
return GalleryProvider.STATE_ERROR;
|
||||
} else {
|
||||
return mGalleryProvider.size();
|
||||
}
|
||||
}
|
||||
public void onDataChanged() {
|
||||
super.onDataChanged();
|
||||
|
||||
@Override
|
||||
public void onBind(GalleryPageView view, int index) {
|
||||
if (mGalleryProvider != null && mGalleryView != null) {
|
||||
mGalleryProvider.request(index);
|
||||
view.showInfo();
|
||||
view.setImage(null);
|
||||
view.setPage(index + 1);
|
||||
view.setProgress(GalleryPageView.PROGRESS_INDETERMINATE);
|
||||
view.setError(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnbind(GalleryPageView view, int index) {
|
||||
if (mGalleryProvider != null) {
|
||||
mGalleryProvider.cancelRequest(index);
|
||||
int size = mGalleryProvider.size();
|
||||
NotifyTask task = mNotifyTaskPool.pop();
|
||||
if (task == null) {
|
||||
task = new NotifyTask();
|
||||
}
|
||||
task.setData(NotifyTask.KEY_SIZE, size);
|
||||
SimpleHandler.getInstance().post(task);
|
||||
}
|
||||
view.setImage(null);
|
||||
view.setError(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user