diff --git a/app/build.gradle b/app/build.gradle index cc4248213..b4fbdf6a7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,7 @@ dependencies { compile 'com.github.seven332:conaco:0.1.5-eh' compile 'com.github.seven332:drawerlayout:0.1.0' compile 'com.github.seven332:easyrecyclerview:0.1.0' + compile 'com.github.seven332:glgallery:0.1.1' compile 'com.github.seven332:glview:0.1.0' compile 'com.github.seven332:glview-image:0.1.0' compile 'com.github.seven332:hotspot:0.1.0' diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java index e6edaf61e..303aa958c 100644 --- a/app/src/main/java/com/hippo/ehviewer/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/Settings.java @@ -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) { diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/DirGalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/DirGalleryProvider.java index 11ee83068..7ef64fd90 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/DirGalleryProvider.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/DirGalleryProvider.java @@ -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(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/EhGalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/EhGalleryProvider.java index 49cf20cce..19d2f1d43 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/EhGalleryProvider.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/EhGalleryProvider.java @@ -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; diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider.java deleted file mode 100644 index 9d3886159..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider.java +++ /dev/null @@ -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 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 mPool; - - @Type - private int mType; - private int mIndex; - private float mPercent; - private ImageWrapper mImage; - private String mError; - - public NotifyTask(GalleryProviderListener galleryProviderListener, ConcurrentPool 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 { - - 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(); - } - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider2.java b/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider2.java new file mode 100644 index 000000000..434cda239 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProvider2.java @@ -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); +} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProviderListener.java b/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProviderListener.java deleted file mode 100644 index 72cf98732..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/GalleryProviderListener.java +++ /dev/null @@ -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); -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ZipGalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/ZipGalleryProvider.java index 1b462d610..92765e256 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ZipGalleryProvider.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ZipGalleryProvider.java @@ -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(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/DownUpDetector.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/DownUpDetector.java deleted file mode 100644 index e82b073bb..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/DownUpDetector.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/Fling.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/Fling.java deleted file mode 100644 index 6549b0dae..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/Fling.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java deleted file mode 100644 index d1bf9bf78..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java deleted file mode 100644 index 5f22140a8..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java +++ /dev/null @@ -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 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 mMethodList = new ArrayList<>(5); - private final List mArgsList = new ArrayList<>(5); - private final List mMethodListTemp = new ArrayList<>(5); - private final List 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 methodListTemp = mMethodListTemp; - List 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); - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GestureRecognizer.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GestureRecognizer.java deleted file mode 100644 index 54ab193b7..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GestureRecognizer.java +++ /dev/null @@ -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(); - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/ImageView.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/ImageView.java deleted file mode 100644 index a00569d61..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/ImageView.java +++ /dev/null @@ -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(); - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/PagerLayoutManager.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/PagerLayoutManager.java deleted file mode 100644 index 68b4cd5fc..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/PagerLayoutManager.java +++ /dev/null @@ -1,1051 +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.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.util.Log; -import android.view.animation.Interpolator; - -import com.hippo.ehviewer.gallery.GalleryProvider; -import com.hippo.glview.anim.Animation; -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.AnimationUtils; -import com.hippo.yorozuya.AssertUtils; -import com.hippo.yorozuya.LayoutUtils; -import com.hippo.yorozuya.MathUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -public class PagerLayoutManager extends GalleryView.LayoutManager { - - private static final String TAG = PagerLayoutManager.class.getSimpleName(); - - @IntDef({MODE_LEFT_TO_RIGHT, MODE_RIGHT_TO_LEFT}) - @Retention(RetentionPolicy.SOURCE) - private @interface Mode {} - - public static final int MODE_LEFT_TO_RIGHT = 0; - public static final int MODE_RIGHT_TO_LEFT = 1; - - private static final int INTERVAL = 48; - - private static final Interpolator SMOOTH_SCROLLER_INTERPOLATOR = new Interpolator() { - @Override - public float getInterpolation(float t) { - t -= 1.0f; - return t * t * t * t * t + 1.0f; - } - }; - - private GalleryView.Adapter mAdapter; - - private GLProgressView mProgress; - private String mErrorStr; - private GLTextureView mErrorView; - private GalleryPageView mPrevious; - private GalleryPageView mCurrent; - private GalleryPageView mNext; - - @Mode - private int mMode = MODE_RIGHT_TO_LEFT; - @ImageView.Scale - private int mScaleMode; - @ImageView.StartPosition - private int mStartPosition; - private float mScaleValue; - - private int mOffset; - private int mDeltaX; - private int mDeltaY; - private boolean mCanScrollBetweenPages = false; - private boolean mStopAnimationFinger; - - private final int mInterval; - - private final int[] mScrollRemain = new int[2]; - private final float[] mScaleDefault = new float[4]; - - private final PageFling mPageFling; - private final SmoothScroller mSmoothScroller; - private final SmoothScaler mSmoothScaler; - - // Current index - private int mIndex; - - private final Rect mTempRect = new Rect(); - - public PagerLayoutManager(Context context, @NonNull GalleryView galleryView, - @ImageView.Scale int scaleMode, @ImageView.StartPosition int startPoint, float scaleValue) { - super(galleryView); - - mScaleMode = scaleMode; - mStartPosition = startPoint; - mScaleValue = scaleValue; - - mInterval = LayoutUtils.dp2pix(context, INTERVAL); - mPageFling = new PageFling(context); - mSmoothScroller = new SmoothScroller(); - mSmoothScaler = new SmoothScaler(); - } - - private void resetParameters() { - mOffset = 0; - mDeltaX = 0; - mDeltaY = 0; - mCanScrollBetweenPages = false; - mStopAnimationFinger = false; - } - - private boolean cancelAllAnimations() { - boolean running = mSmoothScroller.isRunning(); - running |= mPageFling.isRunning(); - running |= mSmoothScroller.isRunning(); - mSmoothScroller.cancel(); - mPageFling.cancel(); - mSmoothScaler.cancel(); - return running; - } - - public void setMode(@Mode int mode) { - if (mMode == mode) { - return; - } - - mMode = mode; - if (mAdapter != null) { - // It is attached, refill - // Cancel all animations - cancelAllAnimations(); - // Remove all view - removeProgress(); - removeErrorView(); - removeAllPages(); - // Reset parameters - resetParameters(); - // Request fill - mGalleryView.requestFill(); - } - } - - public void setScaleMode(@ImageView.Scale int scaleMode) { - if (mScaleMode == scaleMode) { - return; - } - mScaleMode = scaleMode; - - if (mCurrent != null) { - mCurrent.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - if (mPrevious != null) { - mPrevious.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - if (mNext != null) { - mNext.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - } - - public void setStartPosition(@ImageView.StartPosition int startPosition) { - if (mStartPosition == startPosition) { - return; - } - mStartPosition = startPosition; - - if (mCurrent != null) { - mCurrent.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - if (mPrevious != null) { - mPrevious.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - if (mNext != null) { - mNext.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - } - - @Override - public void onAttach(GalleryView.Adapter adapter) { - AssertUtils.assertNull("The PagerLayoutManager is attached", mAdapter); - AssertUtils.assertNotNull("The adapter is null", adapter); - mAdapter = adapter; - // Reset parameters - resetParameters(); - } - - private void removeProgress() { - if (mProgress != null) { - mGalleryView.removeComponent(mProgress); - mGalleryView.releaseProgress(mProgress); - mProgress = null; - } - } - - private void removeErrorView() { - if (mErrorView != null) { - mGalleryView.removeComponent(mErrorView); - mGalleryView.releaseErrorView(mErrorView); - mErrorView = null; - mErrorStr = null; - } - } - - private void removePage(@NonNull GalleryPageView page) { - mGalleryView.removeComponent(page); - mAdapter.unbind(page); - mGalleryView.releasePage(page); - } - - private void removeAllPages() { - // Remove gallery view - if (mPrevious != null) { - removePage(mPrevious); - mPrevious = null; - } - if (mCurrent != null) { - removePage(mCurrent); - mCurrent = null; - } - if (mNext != null) { - removePage(mNext); - mNext = null; - } - } - - @Override - public GalleryView.Adapter onDetach() { - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", mAdapter); - - // Cancel all animations - cancelAllAnimations(); - - // Remove all view - removeProgress(); - removeErrorView(); - removeAllPages(); - - // Clear iterator - GalleryView.Adapter adapter = mAdapter; - mAdapter = null; - - return adapter; - } - - private GalleryPageView getLeftPage() { - switch (mMode) { - case MODE_LEFT_TO_RIGHT: - return mPrevious; - default: - case MODE_RIGHT_TO_LEFT: - return mNext; - } - } - - private GalleryPageView getRightPage() { - switch (mMode) { - case MODE_LEFT_TO_RIGHT: - return mNext; - default: - case MODE_RIGHT_TO_LEFT: - return mPrevious; - } - } - - private GalleryPageView obtainPage() { - GalleryPageView page = mGalleryView.obtainPage(); - page.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - return page; - } - - private void layoutPage(GalleryPageView page, int widthSpec, int heightSpec, - int left, int top, int right, int bottom) { - Rect rect = mTempRect; - page.getValidRect(rect); - boolean oldValid = !rect.isEmpty(); - page.measure(widthSpec, heightSpec); - page.layout(left, top, right, bottom); - page.getValidRect(rect); - boolean newValid = !rect.isEmpty(); - if (!oldValid && newValid) { - page.getImageView().setScaleOffset(mScaleMode, mStartPosition, mScaleValue); - } - } - - @Override - public void onFill() { - GalleryView.Adapter adapter = mAdapter; - GalleryView galleryView = mGalleryView; - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", adapter); - - int width = galleryView.getWidth(); - int height = galleryView.getHeight(); - int size = adapter.size(); - String errorStr = adapter.getError(); - - if (size == GalleryProvider.STATE_WAIT) { // Wait here, show progress bar - // Remove error view and all pages - removeErrorView(); - removeAllPages(); - - // Ensure progress - if (mProgress == null) { - mProgress = galleryView.obtainProgress(); - galleryView.addComponent(mProgress); - } - - // Place progress center - placeCenter(mProgress); - } else if (size <= GalleryProvider.STATE_ERROR || size == 0) { // Get error or empty, show error text - // Ensure error is not null - if (0 == size) { - errorStr = galleryView.getEmptyStr(); - } else if (null == errorStr) { - errorStr = galleryView.getDefaultErrorStr(); - } - - // Remove progress and all pages - removeProgress(); - removeAllPages(); - - // Ensure error view - if (mErrorView == null) { - mErrorView = galleryView.obtainErrorView(); - galleryView.addComponent(mErrorView); - } - - // Update error string - if (!errorStr.equals(mErrorStr)) { - mErrorStr = errorStr; - galleryView.bindErrorView(mErrorView, errorStr); - } - - // Place error view center - placeCenter(mErrorView); - } else { - // Remove progress and error view - removeProgress(); - removeErrorView(); - - // Ensure index in range - int index = mIndex; - if (index < 0) { - index = 0; - mIndex = index; - removeAllPages(); - Log.e(TAG, "index < 0, index = " + index); - } else if (index >= size) { - index = size - 1; - mIndex = index; - removeAllPages(); - Log.e(TAG, "index >= size, index = " + index + ", size = " + size); - } - - // Ensure pages - if (mCurrent == null) { - mCurrent = obtainPage(); - galleryView.addComponent(mCurrent); - adapter.bind(mCurrent, index); - } - if (mPrevious == null && index > 0) { - mPrevious = obtainPage(); - galleryView.addComponent(mPrevious); - adapter.bind(mPrevious, index - 1); - } else if (mPrevious != null && index == 0) { - removePage(mPrevious); - } - if (mNext == null && index < size - 1) { - mNext = obtainPage(); - galleryView.addComponent(mNext); - adapter.bind(mNext, index + 1); - } else if (mNext != null && index == size - 1) { - removePage(mNext); - } - - GalleryPageView leftPage = getLeftPage(); - GalleryPageView rightPage = getRightPage(); - - // Fix offset - final int min = rightPage == null ? 0 : -width - mInterval + 1; - final int max = leftPage == null ? 0 : width + mInterval - 1; - mOffset = MathUtils.clamp(mOffset, min, max); - - // Measure and layout pages - final int offset = mOffset; - final int widthSpec = GLView.MeasureSpec.makeMeasureSpec(width, GLView.MeasureSpec.EXACTLY); - final int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.EXACTLY); - if (mCurrent != null) { - layoutPage(mCurrent, widthSpec, heightSpec, - offset, 0, width + offset, height); - } - if (leftPage != null) { - layoutPage(leftPage, widthSpec, heightSpec, - -mInterval - width + offset, 0, -mInterval + offset, height); - } - if (rightPage != null) { - layoutPage(rightPage, widthSpec, heightSpec, - width + mInterval + offset, 0, width + mInterval + width + offset, height); - } - } - } - - @Override - public void onDown() { - mDeltaX = 0; - mDeltaY = 0; - mStopAnimationFinger = cancelAllAnimations(); - } - - @Override - public void onUp() { - mGalleryView.getEdgeView().onRelease(); - - if (mCurrent == null) { - return; - } - - // Scroll - if (mOffset != 0) { - int width = mGalleryView.getWidth(); - int dx; - if (mOffset >= mInterval && getLeftPage() != null) { - dx = mOffset - width - mInterval; - } else if (mOffset <= -mInterval && getRightPage() != null) { - dx = mOffset + width + mInterval; - } else { - dx = mOffset; - } - final float pageDelta = 7 * (float) Math.abs(mOffset) / (width + mInterval); - int duration = (int) ((pageDelta + 1) * 100); - mSmoothScroller.startSmoothScroll(dx, 0, duration); - } - } - - @Override - public void onDoubleTapConfirmed(float x, float y) { - if (mCurrent == null || !mCurrent.getImageView().isLoaded()) { - return; - } - - float[] scales = mScaleDefault; - ImageView image = mCurrent.getImageView(); - image.getScaleDefault(scales); - float scale = image.getScale(); - float endScale = scales[0]; - for (float value: scales) { - if (scale < value - 0.01f) { - endScale = value; - break; - } - } - - mSmoothScaler.startSmoothScaler(x, y, scale, endScale, 300); - } - - @Override - public void onLongPress(float x, float y) { - - } - - private void pagePrevious() { - if (mIndex <= 0) { - return; - } - mIndex--; - - if (mNext != null) { - removePage(mNext); - } - mNext = mCurrent; - mCurrent = mPrevious; - mPrevious = null; - - if (mIndex > 0) { - mPrevious = obtainPage(); - mGalleryView.addComponent(mPrevious); - mAdapter.bind(mPrevious, mIndex - 1); - } - } - - private void pageNext() { - GalleryView.Adapter adapter = mAdapter; - int size = adapter.size(); - if (mIndex >= size - 1) { - return; - } - mIndex++; - - if (mPrevious != null) { - removePage(mPrevious); - } - mPrevious = mCurrent; - mCurrent = mNext; - mNext = null; - - if (mIndex < size - 1) { - mNext = obtainPage(); - mGalleryView.addComponent(mNext); - adapter.bind(mNext, mIndex + 1); - } - } - - private void pageLeft() { - switch (mMode) { - case MODE_LEFT_TO_RIGHT: - pagePrevious(); - break; - default: - case MODE_RIGHT_TO_LEFT: - pageNext(); - break; - } - } - - private void pageRight() { - switch (mMode) { - case MODE_LEFT_TO_RIGHT: - pageNext(); - break; - default: - case MODE_RIGHT_TO_LEFT: - pagePrevious(); - break; - } - } - - private int scrollBetweenPages(int dx) { - GalleryPageView leftPage = getLeftPage(); - GalleryPageView rightPage = getRightPage(); - int width = mGalleryView.getWidth(); - - int remain; - if (dx < 0) { // Try to show left - int limit; - if (leftPage == null) { - limit = 0; - } else { - limit = width + mInterval; - } - - if (dx > mOffset - limit) { - remain = 0; - mOffset -= dx; - } else { - // Go to left page if left page not null - if (leftPage != null) { - pageLeft(); - } - remain = dx + limit - mOffset; - mOffset = 0; - } - } else { // Try to show right - int limit; - if (rightPage == null) { - limit = 0; - } else { - limit = - width - mInterval; - } - - if (dx < mOffset - limit) { - remain = 0; - mOffset -= dx; - } else { - // Go to right page if right page not null - if (rightPage != null) { - pageRight(); - } - remain = dx + limit - mOffset; - mOffset = 0; - } - } - - return remain; - } - - public void overScrollEdge(int dx, int dy, float x, float y) { - GLEdgeView edgeView = mGalleryView.getEdgeView(); - - mDeltaX += dx; - mDeltaY += dy; - - if (mDeltaX < 0) { - edgeView.onPull(-mDeltaX, y, GLEdgeView.LEFT); - if (!edgeView.isFinished(GLEdgeView.RIGHT)) { - edgeView.onRelease(GLEdgeView.RIGHT); - } - } else if (mDeltaX > 0) { - edgeView.onPull(mDeltaX, y, GLEdgeView.RIGHT); - if (!edgeView.isFinished(GLEdgeView.LEFT)) { - edgeView.onRelease(GLEdgeView.LEFT); - } - } - - if (mCurrent.getImageView().canFlingVertically()) { - if (mDeltaY < 0) { - edgeView.onPull(-mDeltaY, x, GLEdgeView.TOP); - if (!edgeView.isFinished(GLEdgeView.BOTTOM)) { - edgeView.onRelease(GLEdgeView.BOTTOM); - } - } else if (mDeltaY > 0) { - edgeView.onPull(mDeltaY, x, GLEdgeView.BOTTOM); - if (!edgeView.isFinished(GLEdgeView.TOP)) { - edgeView.onRelease(GLEdgeView.TOP); - } - } - } - } - - public void scrollInternal(float dx, float dy, float x, float y) { - if (mCurrent == null) { - return; - } - - boolean needFill = false; - boolean canImageScroll = true; - int remainX = (int) dx; - int remainY = (int) dy; - - if (mGalleryView.isFirstScroll()) { - mCanScrollBetweenPages = Math.abs(dx) > Math.abs(dy) * 1.5; - } - - while (remainX != 0 || remainY != 0) { - if (mOffset == 0 && canImageScroll) { - ImageView image = mCurrent.getImageView(); - image.scroll(remainX, remainY, mScrollRemain); - remainX = mScrollRemain[0]; - remainY = mScrollRemain[1]; - canImageScroll = false; - mDeltaX = 0; - mDeltaY = 0; - } else if (remainX == 0 || - (getLeftPage() == null && mOffset == 0 && remainX < 0) || - (getRightPage() == null && mOffset == 0 && remainX > 0)) { - // On edge - overScrollEdge(remainX, remainY, x, y); - remainX = 0; - remainY = 0; - } else if (mCanScrollBetweenPages) { - remainX = scrollBetweenPages(remainX); - canImageScroll = true; - needFill = true; - mDeltaX = 0; - mDeltaY = 0; - } else { - remainX = 0; - remainY = 0; - mDeltaX = 0; - mDeltaY = 0; - } - } - - if (needFill) { - mGalleryView.requestFill(); - } - } - - @Override - public void onScroll(float dx, float dy, float totalX, float totalY, float x, float y) { - scrollInternal(dx, dy, x, y); - } - - @Override - public void onFling(float velocityX, float velocityY) { - if (mCurrent == null || mOffset != 0 || !mCurrent.getImageView().isLoaded() || - !mCurrent.getImageView().canFling()) { - return; - } - - ImageView image = mCurrent.getImageView(); - mPageFling.startFling((int) velocityX, image.getMinDx(), image.getMaxDx(), - (int) velocityY, image.getMinDy(), image.getMaxDy()); - } - - @Override - public boolean canScale() { - return mCurrent != null && mOffset == 0 && mCurrent.getImageView().isLoaded(); - } - - @Override - public void onScale(float focusX, float focusY, float scale) { - if (mCurrent == null || !mCurrent.getImageView().isLoaded()) { - return; - } - - mCurrent.getImageView().scale(focusX, focusY, scale); - mScaleValue = mCurrent.getImageView().getScale(); - } - - @Override - public boolean onUpdateAnimation(long time) { - boolean invalidate = mSmoothScroller.calculate(time); - invalidate |= mPageFling.calculate(time); - invalidate |= mSmoothScaler.calculate(time); - return invalidate; - } - - @Override - public void onDataChanged() { - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", mAdapter); - - // Cancel all animations - cancelAllAnimations(); - // Remove all views - removeProgress(); - removeErrorView(); - removeAllPages(); - // Reset parameters - resetParameters(); - mGalleryView.requestFill(); - } - - @Override - public void onPageLeft() { - int size = mAdapter.size(); - if (size <= 0 || mCurrent == null) { - return; - } - - if (mMode == MODE_LEFT_TO_RIGHT) { - if (mIndex == 0) { - GalleryView galleryView = mGalleryView; - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getWidth(), - galleryView.getHeight() / 2, GLEdgeView.LEFT); - edgeView.onRelease(GLEdgeView.LEFT); - } else { - setCurrentIndex(mIndex - 1); - } - } else { - if (mIndex >= size - 1) { - GalleryView galleryView = mGalleryView; - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getWidth(), - galleryView.getHeight() / 2, GLEdgeView.LEFT); - edgeView.onRelease(GLEdgeView.LEFT); - } else { - setCurrentIndex(mIndex + 1); - } - } - } - - @Override - public void onPageRight() { - int size = mAdapter.size(); - if (size <= 0 || mCurrent == null) { - return; - } - - if (mMode == MODE_LEFT_TO_RIGHT) { - if (mIndex >= size - 1) { - GalleryView galleryView = mGalleryView; - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getWidth(), - galleryView.getHeight() / 2, GLEdgeView.RIGHT); - edgeView.onRelease(GLEdgeView.RIGHT); - } else { - setCurrentIndex(mIndex + 1); - } - } else { - if (mIndex == 0) { - GalleryView galleryView = mGalleryView; - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getWidth(), - galleryView.getHeight() / 2, GLEdgeView.RIGHT); - edgeView.onRelease(GLEdgeView.RIGHT); - } else { - setCurrentIndex(mIndex - 1); - } - } - } - - @Override - public boolean isTapOrPressEnable() { - return !mStopAnimationFinger; - } - - @Override - public GalleryPageView findPageByIndex(int index) { - if (mCurrent != null && mCurrent.getIndex() == index) { - return mCurrent; - } - if (mPrevious != null && mPrevious.getIndex() == index) { - return mPrevious; - } - if (mNext != null && mNext.getIndex() == index) { - return mNext; - } - return null; - } - - @Override - public int getCurrentIndex() { - if (mCurrent != null) { - return mCurrent.getIndex(); - } else { - return GalleryPageView.INVALID_INDEX; - } - } - - @Override - public void setCurrentIndex(int index) { - int size = mAdapter.size(); - if (size <= 0) { - // Can't get size now, assume size is MAX - size = Integer.MAX_VALUE; - } - if (index == mIndex || index < 0 || index >= size) { - return; - } - if (mCurrent == null) { - mIndex = index; - } else if (index == mIndex - 1) { - // Cancel all animations - cancelAllAnimations(); - // Reset parameters - resetParameters(); - // Go to previous - pagePrevious(); - // Request fill - mGalleryView.requestFill(); - } else if (index == mIndex + 1) { - // Cancel all animations - cancelAllAnimations(); - // Reset parameters - resetParameters(); - // Go to next - pageNext(); - // Request fill - mGalleryView.requestFill(); - } else { - mIndex = index; - // It is attached, refill - // Cancel all animations - cancelAllAnimations(); - // Remove all view - removeProgress(); - removeErrorView(); - removeAllPages(); - // Reset parameters - resetParameters(); - // Request fill - mGalleryView.requestFill(); - } - } - - @Override - public int getIndexUnder(float x, float y) { - if (mCurrent == null) { - return GalleryPageView.INVALID_INDEX; - } else { - int intX = (int) x; - int intY = (int) y; - if (mCurrent.bounds().contains(intX, intY)) { - return mCurrent.getIndex(); - } else if (mPrevious != null && mPrevious.bounds().contains(intX, intY)) { - return mPrevious.getIndex(); - } else if (mNext != null && mNext.bounds().contains(intX, intY)) { - return mNext.getIndex(); - } else { - return GalleryPageView.INVALID_INDEX; - } - } - } - - @Override - int getInternalCurrentIndex() { - int currentIndex = getCurrentIndex(); - if (currentIndex == GalleryPageView.INVALID_INDEX) { - currentIndex = mIndex; - } - return currentIndex; - } - - class SmoothScroller extends Animation { - - private int mDx; - private int mDy; - private int mLastX; - private int mLastY; - - public SmoothScroller() { - setInterpolator(SMOOTH_SCROLLER_INTERPOLATOR); - } - - public void startSmoothScroll(int dx, int dy, int duration) { - mDx = dx; - mDy = dy; - mLastX = 0; - mLastY = 0; - setDuration(duration); - start(); - mGalleryView.invalidate(); - } - - @Override - protected void onCalculate(float progress) { - int x = (int) (mDx * progress); - int y = (int) (mDy * progress); - int offsetX = x - mLastX; - while (offsetX != 0) { - int oldOffsetX = offsetX; - offsetX = scrollBetweenPages(offsetX); - // Avoid loop infinitely - if (offsetX == oldOffsetX) { - break; - } else { - mGalleryView.requestFill(); - } - } - mLastX = x; - mLastY = y; - } - } - - class PageFling extends Fling { - - private int mVelocityX; - private int mVelocityY; - private int mDx; - private int mDy; - private int mLastX; - private int mLastY; - private final int[] mTemp = new int[2]; - - public PageFling(Context context) { - super(context); - } - - public void startFling(int velocityX, int minX, int maxX, - int velocityY, int minY, int maxY) { - mVelocityX = velocityX; - mVelocityY = velocityY; - mDx = (int) (getSplineFlingDistance(velocityX) * Math.signum(velocityX)); - mDy = (int) (getSplineFlingDistance(velocityY) * Math.signum(velocityY)); - mLastX = 0; - mLastY = 0; - int durationX = getSplineFlingDuration(velocityX); - int durationY = getSplineFlingDuration(velocityY); - - if (mDx < minX) { - durationX = adjustDuration(0, mDx, minX, durationX); - mDx = minX; - } - if (mDx > maxX) { - durationX = adjustDuration(0, mDx, maxX, durationX); - mDx = maxX; - } - if (mDy < minY) { - durationY = adjustDuration(0, mDy, minY, durationY); - mDy = minY; - } - if (mDy > maxY) { - durationY = adjustDuration(0, mDy, maxY, durationY); - mDy = maxY; - } - - if (mDx == 0 && mDy == 0) { - return; - } - - setDuration(Math.max(durationX, durationY)); - start(); - mGalleryView.invalidate(); - } - - @Override - protected void onCalculate(float progress) { - int x = (int) (mDx * progress); - int y = (int) (mDy * progress); - int offsetX = x - mLastX; - int offsetY = y - mLastY; - if (mCurrent != null && (offsetX != 0 || offsetY != 0)) { - mCurrent.getImageView().scroll(-offsetX, -offsetY, mTemp); - } - mLastX = x; - mLastY = y; - } - - @Override - protected void onFinish() { - if (mCurrent == null) { - return; - } - - GLEdgeView edgeView = mGalleryView.getEdgeView(); - ImageView imageView = mCurrent.getImageView(); - if (imageView.canFlingHorizontally()) { - if (mVelocityX > 0 && getLeftPage() == null && imageView.getMaxDx() == 0 && - edgeView.isFinished(GLEdgeView.LEFT)) { - edgeView.onAbsorb(mVelocityX, GLEdgeView.LEFT); - } else if (mVelocityX < 0 && getRightPage() == null && imageView.getMinDx() == 0 && - edgeView.isFinished(GLEdgeView.RIGHT)) { - edgeView.onAbsorb(-mVelocityX, GLEdgeView.RIGHT); - } - } - if (imageView.canFlingVertically()) { - if (mVelocityY > 0 && imageView.getMaxDy() == 0 && - edgeView.isFinished(GLEdgeView.TOP)) { - edgeView.onAbsorb(mVelocityY, GLEdgeView.TOP); - } else if (mVelocityY < 0 && imageView.getMinDy() == 0 && - edgeView.isFinished(GLEdgeView.BOTTOM)) { - edgeView.onAbsorb(-mVelocityY, GLEdgeView.BOTTOM); - } - } - } - } - - class SmoothScaler extends Animation { - - private float mFocusX; - private float mFocusY; - private float mStartScale; - private float mEndScale; - private float mLastScale; - - public SmoothScaler() { - setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - } - - public void startSmoothScaler(float focusX, float focusY, - float startScale, float endScale, int duration) { - mFocusX = focusX; - mFocusY = focusY; - mStartScale = startScale; - mEndScale = endScale; - mLastScale = startScale; - setDuration(duration); - start(); - mGalleryView.invalidate(); - } - - @Override - protected void onCalculate(float progress) { - if (mCurrent == null) { - return; - } - - float scale = MathUtils.lerp(mStartScale, mEndScale, progress); - mCurrent.getImageView().scale(mFocusX, mFocusY, scale / mLastScale); - mLastScale = scale; - mScaleValue = scale; - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/ScrollLayoutManager.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/ScrollLayoutManager.java deleted file mode 100644 index 345f4fe27..000000000 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/ScrollLayoutManager.java +++ /dev/null @@ -1,1183 +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.support.annotation.NonNull; -import android.util.Log; - -import com.hippo.ehviewer.gallery.GalleryProvider; -import com.hippo.glview.anim.Animation; -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.AnimationUtils; -import com.hippo.yorozuya.AssertUtils; -import com.hippo.yorozuya.LayoutUtils; -import com.hippo.yorozuya.MathUtils; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -public class ScrollLayoutManager extends GalleryView.LayoutManager { - - private static final String TAG = ScrollLayoutManager.class.getSimpleName(); - - private static final int INTERVAL = 24; - - private static final float RESERVATION = 1f; - - private static final float MAX_SCALE = 2.0f; - private static final float MIN_SCALE = 1.0f; - private static final float SCALE_ERROR = 0.01f; - - private static final int INVALID_TOP = Integer.MAX_VALUE; - - private GalleryView.Adapter mAdapter; - - private GLProgressView mProgress; - private String mErrorStr; - private GLTextureView mErrorView; - private final LinkedList mPages = new LinkedList<>(); - private final LinkedList mTempPages = new LinkedList<>(); - - private float mScale = 0.5f; - private int mOffsetX; - private int mOffsetY; - private int mDeltaX; - private int mDeltaY; - private int mKeepTopPageIndex = GalleryPageView.INVALID_INDEX; - private int mKeepTop = INVALID_TOP; - private int mFirstShownPageIndex = GalleryPageView.INVALID_INDEX; - private boolean mScrollUp; - private boolean mFlingUp; - private boolean mStopAnimationFinger; - - private final int mInterval; - - private final PageFling mPageFling; - private final SmoothScaler mSmoothScaler; - - // Current index - private int mIndex; - - private int mBottomStateBottom; - private boolean mBottomStateHasNext; - - public ScrollLayoutManager(Context context, @NonNull GalleryView galleryView) { - super(galleryView); - - mInterval = LayoutUtils.dp2pix(context, INTERVAL); - mPageFling = new PageFling(context); - mSmoothScaler = new SmoothScaler(); - } - - private void resetParameters() { - mScale = 1.0f; - mOffsetX = 0; - mOffsetY = 0; - mDeltaX = 0; - mDeltaY = 0; - mKeepTopPageIndex = GalleryPageView.INVALID_INDEX; - mKeepTop = INVALID_TOP; - mFirstShownPageIndex = GalleryPageView.INVALID_INDEX; - mScrollUp = false; - mFlingUp = false; - mStopAnimationFinger = false; - } - - // Return true for animations are running - private boolean cancelAllAnimations() { - boolean running = mPageFling.isRunning(); - mPageFling.cancel(); - return running; - } - - @Override - public void onAttach(GalleryView.Adapter adapter) { - AssertUtils.assertNull("The ScrollLayoutManager is attached", mAdapter); - AssertUtils.assertNotNull("The iterator is null", adapter); - mAdapter = adapter; - // Reset parameters - resetParameters(); - } - - private void removeProgress() { - if (mProgress != null) { - mGalleryView.removeComponent(mProgress); - mGalleryView.releaseProgress(mProgress); - mProgress = null; - } - } - - private void removeErrorView() { - if (mErrorView != null) { - mGalleryView.removeComponent(mErrorView); - mGalleryView.releaseErrorView(mErrorView); - mErrorView = null; - mErrorStr = null; - } - } - - private void removePage(@NonNull GalleryPageView page) { - mGalleryView.removeComponent(page); - mAdapter.unbind(page); - mGalleryView.releasePage(page); - } - - private void removeAllPages() { - for (GalleryPageView page : mPages) { - removePage(page); - } - mPages.clear(); - } - - @Override - public GalleryView.Adapter onDetach() { - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", mAdapter); - - // Cancel all animations - cancelAllAnimations(); - - // Remove all view - removeProgress(); - removeErrorView(); - removeAllPages(); - - // Clear iterator - GalleryView.Adapter iterator = mAdapter; - mAdapter = null; - - return iterator; - } - - private GalleryPageView obtainPage() { - GalleryPageView page = mGalleryView.obtainPage(); - page.getImageView().setScaleOffset(ImageView.SCALE_FIT, ImageView.START_POSITION_TOP_RIGHT, 1.0f); - return page; - } - - private GalleryPageView getPageForIndex(List pages, int index, boolean remove) { - for (Iterator iterator = pages.iterator(); iterator.hasNext();) { - GalleryPageView page = iterator.next(); - if (index == page.getIndex()) { - if (remove) { - iterator.remove(); - } - return page; - } - } - return null; - } - - private boolean isInScreen(GalleryPageView page) { - int height = mGalleryView.getHeight(); - Rect bound = page.bounds(); - int pageTop = bound.top; - int pageBottom = bound.bottom; - return (pageTop >= 0 && pageTop < height) || (pageBottom > 0 && pageBottom <= height) || - (pageTop < 0 && pageBottom > height); - } - - private float getReservation() { - return Math.max(RESERVATION, (((1 + 2 * RESERVATION) * mScale) - 1) / 2); - } - - private void fillPages(int startIndex, int startOffset) { - final GalleryView.Adapter adapter = mAdapter; - final GalleryView galleryView = mGalleryView; - final LinkedList pages = mPages; - final LinkedList tempPages = mTempPages; - final int width = galleryView.getWidth(); - final int height = galleryView.getHeight(); - final int pageWidth = (int) (width * mScale); - final int size = adapter.size(); - final int interval = mInterval; - final float reservation = getReservation(); - final int minY = (int) (-height * reservation); - final int maxY = (int) (height * (1 + reservation)); - final int widthSpec = GLView.MeasureSpec.makeMeasureSpec(pageWidth, GLView.MeasureSpec.EXACTLY); - final int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.UNSPECIFIED); - - // Fix start index and start offset - if (startIndex < 0) { - startIndex = 0; - startOffset = 0; - } else if (startIndex >= size) { - startIndex = size - 1; - startOffset = 0; - } else if (startOffset < minY) { - while (true) { - GalleryPageView page = getPageForIndex(pages, startIndex, false); - if (null == page) { - startOffset = minY; - break; - } else { - page.measure(widthSpec, heightSpec); - if (startOffset + page.getHeight() > minY) { - break; - } else if (size - 1 == startIndex) { - startOffset = 0; - break; - } else { - ++startIndex; - startOffset += page.getHeight() + interval; - if (startOffset >= minY) { - break; - } - } - } - } - } else if (startOffset >= maxY) { - if (0 == startIndex) { - startOffset = 0; - } else { - --startIndex; - int startBottomOffset = startOffset - interval; - while (true) { - GalleryPageView page = getPageForIndex(pages, startIndex, false); - if (null == page) { - startOffset = maxY - 1; - break; - } else { - page.measure(widthSpec, heightSpec); - startOffset = startBottomOffset - page.getHeight(); - if (startOffset < maxY) { - break; - } else if (0 == startIndex) { - startOffset = 0; - break; - } else { - --startIndex; - startBottomOffset = startOffset - interval; - } - } - } - } - } - - // Put page to temp list - tempPages.addAll(pages); - pages.clear(); - - // Sanitize offsetX - int margin = pageWidth - width; - if (margin >= 0) { - mOffsetX = MathUtils.clamp(mOffsetX, -margin, 0); - } else { - mOffsetX = -margin / 2; - } - - // Layout start page - GalleryPageView page = getPageForIndex(tempPages, startIndex, true); - if (null == page) { - page = obtainPage(); - galleryView.addComponent(page); - adapter.bind(page, startIndex); - } - pages.add(page); - page.measure(widthSpec, heightSpec); - page.layout(mOffsetX, startOffset, mOffsetX + pageWidth, startOffset + page.getMeasuredHeight()); - - // Prepare for check up and down - int bottomOffset = startOffset - interval; - int topOffset = startOffset + page.getMeasuredHeight() + interval; - - // Check up - int index = startIndex - 1; - while (bottomOffset > minY && index >= 0) { - page = getPageForIndex(tempPages, index, true); - if (null == page) { - page = obtainPage(); - galleryView.addComponent(page); - adapter.bind(page, index); - } - pages.addFirst(page); - page.measure(widthSpec, heightSpec); - page.layout(mOffsetX, bottomOffset - page.getMeasuredHeight(), mOffsetX + pageWidth, bottomOffset); - // Update - bottomOffset -= page.getMeasuredHeight() + interval; - index--; - } - - // Avoid space in top - page = pages.getFirst(); - if (0 == page.getIndex() && page.bounds().top > 0) { - int offset = -page.bounds().top; - for (GalleryPageView p: pages) { - p.offsetTopAndBottom(offset); - } - topOffset += offset; - } - - // Check down - index = startIndex + 1; - while (topOffset < maxY && index < size) { - page = getPageForIndex(tempPages, index, true); - if (null == page) { - page = obtainPage(); - galleryView.addComponent(page); - adapter.bind(page, index); - } - pages.addLast(page); - page.measure(widthSpec, heightSpec); - page.layout(mOffsetX, topOffset, mOffsetX + pageWidth, topOffset + page.getMeasuredHeight()); - // Update - topOffset += page.getMeasuredHeight() + interval; - index++; - } - - // Avoid space in bottom - if (size - 1 == pages.getLast().getIndex()) { - while (true) { - page = pages.getLast(); - int pagesBottom = page.bounds().bottom; - if (pagesBottom >= height) { - break; - } - page = pages.getFirst(); - index = page.getIndex(); - if (0 == index) { - break; - } - --index; - int pagesTop = page.bounds().top; - - page = getPageForIndex(tempPages, index, true); - if (null == page) { - page = obtainPage(); - galleryView.addComponent(page); - adapter.bind(page, index); - } - pages.addFirst(page); - page.measure(widthSpec, heightSpec); - - int offset = Math.min(height - pagesBottom, page.getMeasuredHeight()); - for (GalleryPageView p: pages) { - p.offsetTopAndBottom(offset); - } - int bottom = pagesTop - interval + offset; - page.layout(mOffsetX, bottom - page.getMeasuredHeight(), mOffsetX + pageWidth, bottom); - } - } - - // Remove remain page - for (GalleryPageView p : tempPages) { - removePage(p); - } - tempPages.clear(); - - // Update state - if (!pages.isEmpty()) { - page = pages.getFirst(); - mIndex = page.getIndex(); - mOffsetY = page.bounds().top; - } - } - - @Override - public void onFill() { - GalleryView.Adapter adapter = mAdapter; - GalleryView galleryView = mGalleryView; - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", adapter); - - int size = adapter.size(); - String errorStr = adapter.getError(); - - if (size == GalleryProvider.STATE_WAIT) { // Wait here, show progress bar - // Remove error view and all pages - removeErrorView(); - removeAllPages(); - - // Ensure progress - if (mProgress == null) { - mProgress = galleryView.obtainProgress(); - galleryView.addComponent(mProgress); - } - - // Place progress center - placeCenter(mProgress); - } else if (size <= GalleryProvider.STATE_ERROR || size == 0) { // Get error or empty, show error text - // Ensure error is not null - if (0 == size) { - errorStr = galleryView.getEmptyStr(); - } else if (null == errorStr) { - errorStr = galleryView.getDefaultErrorStr(); - } - - // Remove progress and all pages - removeProgress(); - removeAllPages(); - - // Ensure error view - if (mErrorView == null) { - mErrorView = galleryView.obtainErrorView(); - galleryView.addComponent(mErrorView); - } - - // Update error string - if (!errorStr.equals(mErrorStr)) { - mErrorStr = errorStr; - galleryView.bindErrorView(mErrorView, errorStr); - } - - // Place error view center - placeCenter(mErrorView); - } else { - LinkedList pages = mPages; - - // Remove progress and error view - removeProgress(); - removeErrorView(); - - // Ensure index in range - int index = mIndex; - if (index < 0) { - Log.e(TAG, "index < 0, index = " + index); - index = 0; - mIndex = index; - removeAllPages(); - } else if (index >= size) { - Log.e(TAG, "index >= size, index = " + index + ", size = " + size); - index = size - 1; - mIndex = index; - removeAllPages(); - } - - // Find keep index and keep top - int keepTop = INVALID_TOP; - int keepTopIndex; - if (GalleryPageView.INVALID_INDEX != mKeepTopPageIndex) { - keepTopIndex = mKeepTopPageIndex; - keepTop = mKeepTop; - } else if (GalleryPageView.INVALID_INDEX != mFirstShownPageIndex) { - keepTopIndex = mFirstShownPageIndex; - } else { - keepTopIndex = GalleryPageView.INVALID_INDEX; - } - if (GalleryPageView.INVALID_INDEX != keepTopIndex && INVALID_TOP == keepTop) { - keepTop = mOffsetY; - for (GalleryPageView page : pages) { - // Check keep page - if (keepTopIndex == page.getIndex()) { - break; - } - keepTop += page.getHeight() + mInterval; - } - } - - int startIndex; - int startOffset; - if (GalleryPageView.INVALID_INDEX != keepTopIndex) { - startIndex = keepTopIndex; - startOffset = keepTop; - } else { - startIndex = mIndex; - startOffset = mOffsetY; - } - fillPages(startIndex, startOffset); - - // Get first shown image - mFirstShownPageIndex = GalleryPageView.INVALID_INDEX; - for (GalleryPageView page : mPages) { - // Check first shown loaded page - if ((mScrollUp || mFlingUp) && !page.isLoaded()) { - continue; - } - - if (isInScreen(page)) { - mFirstShownPageIndex = page.getIndex(); - break; - } - } - } - } - - @Override - public void onDown() { - mDeltaX = 0; - mDeltaY = 0; - mScrollUp = false; - mStopAnimationFinger = cancelAllAnimations(); - } - - @Override - public void onUp() { - mScrollUp = false; - mGalleryView.getEdgeView().onRelease(); - } - - @Override - public void onDoubleTapConfirmed(float x, float y) { - if (mPages.size() <= 0) { - return; - } - - float startScale = mScale; - float endScale; - if (startScale < MAX_SCALE - SCALE_ERROR) { - endScale = MAX_SCALE; - } else { - endScale = MIN_SCALE; - } - - mSmoothScaler.startSmoothScaler(x, y, startScale, endScale, 300); - } - - @Override - public void onLongPress(float x, float y) { - - } - - public void overScrollEdge(int dx, int dy, float x, float y) { - GLEdgeView edgeView = mGalleryView.getEdgeView(); - - mDeltaX += dx; - mDeltaY += dy; - - if (mDeltaX < 0) { - edgeView.onPull(-mDeltaX, y, GLEdgeView.LEFT); - if (!edgeView.isFinished(GLEdgeView.RIGHT)) { - edgeView.onRelease(GLEdgeView.RIGHT); - } - } else if (mDeltaX > 0) { - edgeView.onPull(mDeltaX, y, GLEdgeView.RIGHT); - if (!edgeView.isFinished(GLEdgeView.LEFT)) { - edgeView.onRelease(GLEdgeView.LEFT); - } - } - - if (mDeltaY < 0) { - edgeView.onPull(-mDeltaY, x, GLEdgeView.TOP); - if (!edgeView.isFinished(GLEdgeView.BOTTOM)) { - edgeView.onRelease(GLEdgeView.BOTTOM); - } - } else if (mDeltaY > 0) { - edgeView.onPull(mDeltaY, x, GLEdgeView.BOTTOM); - if (!edgeView.isFinished(GLEdgeView.TOP)) { - edgeView.onRelease(GLEdgeView.TOP); - } - } - } - - private void getBottomState() { - List pages = mPages; - int bottom = mOffsetY; - int i = 0; - for (GalleryPageView page : pages) { - if (i != 0) { - bottom += mInterval; - } - bottom += page.getHeight(); - i++; - } - boolean hasNext = mIndex + pages.size() < mAdapter.size(); - - mBottomStateBottom = bottom; - mBottomStateHasNext = hasNext; - } - - // True for get top or bottom - private boolean scrollInternal(float dx, float dy, boolean fling, float x, float y) { - if (mPages.size() <= 0) { - return false; - } - - GalleryView galleryView = mGalleryView; - int width = galleryView.getWidth(); - int height = galleryView.getHeight(); - int pageWidth = (int) (width * mScale); - final float reservation = getReservation(); - boolean requestFill = false; - boolean result = false; - - int margin = pageWidth - width; - int dxInt = (int) dx; - if (margin > 0 && 0 != dxInt) { - int oldOffsetX = mOffsetX; - int exceptOffsetX = oldOffsetX - dxInt; - mOffsetX = MathUtils.clamp(exceptOffsetX, -margin, 0); - if (mOffsetX != oldOffsetX) { - requestFill = true; - } - // Do not show over scroll effect for left and right - /* - int extraOffsetX = mOffsetX - exceptOffsetX; - if (0 != extraOffsetX) { - overScrollEdge(extraOffsetX, 0, x, y); - } - */ - } - - int remainY = (int) dy; - while (remainY != 0) { - if (remainY < 0) { // Try to show top - int limit; - if (mIndex > 0) { - limit = (int) (-height * reservation) + mInterval; - } else { - limit = 0; - } - - if (mOffsetY - remainY <= limit) { - mOffsetY -= remainY; - remainY = 0; - requestFill = true; - mDeltaX = 0; - mDeltaY = 0; - } else { - if (mIndex > 0) { - mOffsetY = limit; - remainY = remainY + limit - mOffsetY; - // Offset one pixel to avoid infinite loop - ++mOffsetY; - ++remainY; - galleryView.forceFill(); - requestFill = false; - mDeltaX = 0; - mDeltaY = 0; - } else { - if (mOffsetY != limit) { - mOffsetY = limit; - requestFill = true; - } - if (!fling) { - overScrollEdge(0, remainY + limit - mOffsetY, x, y); - } - remainY = 0; - result = true; - } - } - } else { // Try to show bottom - getBottomState(); - int bottom = mBottomStateBottom; - boolean hasNext = mBottomStateHasNext; - - int limit; - if (hasNext) { - limit = (int) (height * (1 + reservation)) - mInterval; - } else { - limit = height; - } - // Fix limit for page not fill screen - limit = Math.min(bottom, limit); - - if (bottom - remainY >= limit) { - mOffsetY -= remainY; - remainY = 0; - requestFill = true; - mDeltaX = 0; - mDeltaY = 0; - } else { - if (hasNext) { - mOffsetY -= bottom - limit; - remainY = remainY + limit - bottom; - // Offset one pixel to avoid infinite loop - --mOffsetY; - --remainY; - galleryView.forceFill(); - requestFill = false; - mDeltaX = 0; - mDeltaY = 0; - } else { - if (mOffsetY != limit) { - mOffsetY -= bottom - limit; - requestFill = true; - } - if (!fling) { - overScrollEdge(0, remainY + limit - bottom, x, y); - } - remainY = 0; - result = true; - } - } - } - } - - if (requestFill) { - mGalleryView.requestFill(); - } - - return result; - } - - @Override - public void onScroll(float dx, float dy, float totalX, float totalY, float x, float y) { - mKeepTopPageIndex = GalleryPageView.INVALID_INDEX; - mKeepTop = INVALID_TOP; - mScrollUp = dy < 0; - scrollInternal(dx, dy, false, x, y); - } - - @Override - public void onFling(float velocityX, float velocityY) { - if (mPages.size() <= 0) { - return; - } - - mKeepTopPageIndex = GalleryPageView.INVALID_INDEX; - mKeepTop = INVALID_TOP; - mFlingUp = velocityY > 0; - - int maxX; - int minX; - int width = mGalleryView.getWidth(); - int pageWidth = (int) (width * mScale); - int margin = pageWidth - width; - if (margin > 0) { - maxX = -mOffsetX; - minX = -margin + mOffsetX; - } else { - maxX = 0; - minX = 0; - } - - int maxY; - if (mIndex > 0) { - maxY = Integer.MAX_VALUE; - } else { - maxY = -mOffsetY; - } - - getBottomState(); - int bottom = mBottomStateBottom; - boolean hasNext = mBottomStateHasNext; - int minY; - if (hasNext) { - minY = Integer.MIN_VALUE; - } else { - minY = mGalleryView.getHeight() - bottom; - } - - mPageFling.startFling((int) velocityX, minX, maxX, - (int) velocityY, minY, maxY); - } - - @Override - public boolean canScale() { - return mPages.size() > 0; - } - - @Override - public void onScale(float focusX, float focusY, float scale) { - if (mPages.isEmpty()) { - return; - } - - float oldScale = mScale; - mScale = MathUtils.clamp(oldScale * scale, MIN_SCALE, MAX_SCALE); - scale = mScale / oldScale; - - if (oldScale != mScale) { - GalleryPageView page = null; - // Keep scale page origin position - for (GalleryPageView p : mPages) { - if (p.bounds().top < focusY) { - page = p; - } else { - break; - } - } - - if (null != page) { - mKeepTopPageIndex = page.getIndex(); - mKeepTop = page.bounds().top; - - mGalleryView.forceFill(); - int oldKeepTop = mKeepTop; - mKeepTop = INVALID_TOP; - - // Apply scroll - int newOffsetX = (int) (focusX - ((focusX - mOffsetX) * scale)); - int newKeepTop; - if (page.isLoaded()) { - newKeepTop = (int) (focusY - ((focusY - oldKeepTop) * scale)); - } else { - newKeepTop = oldKeepTop; - } - scrollInternal(mOffsetX - newOffsetX, oldKeepTop - newKeepTop, false, focusX, focusY); - } else { - Log.e(TAG, "Can't find target page"); - mKeepTopPageIndex = GalleryPageView.INVALID_INDEX; - mKeepTop = INVALID_TOP; - mGalleryView.forceFill(); - } - } - } - - @Override - public boolean onUpdateAnimation(long time) { - boolean invalidate = mPageFling.calculate(time); - invalidate |= mSmoothScaler.calculate(time); - return invalidate; - } - - @Override - public void onDataChanged() { - AssertUtils.assertNotNull("The PagerLayoutManager is not attached", mAdapter); - - // Cancel all animations - cancelAllAnimations(); - // Remove all views - removeProgress(); - removeErrorView(); - removeAllPages(); - // Reset parameters - resetParameters(); - mGalleryView.requestFill(); - } - - @Override - public void onPageLeft() { - int size = mAdapter.size(); - if (size <= 0 || mPages.isEmpty()) { - return; - } - - /////// - // UP - /////// - GalleryView galleryView = mGalleryView; - if (mIndex == 0 && mOffsetY >= 0) { - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getHeight(), - galleryView.getWidth() / 2, GLEdgeView.TOP); - edgeView.onRelease(GLEdgeView.TOP); - } else { - // Cancel all animations - cancelAllAnimations(); - - // Get first shown page - GalleryPageView previousPage = null; - GalleryPageView firstShownPage = null; - for (GalleryPageView p: mPages) { - if (isInScreen(p)) { - firstShownPage = p; - break; - } - previousPage = p; - } - - int height = galleryView.getHeight(); - int maxOffset = height - mInterval; - if (null == firstShownPage) { - Log.e(TAG, "Can't find first shown page when paging left"); - mOffsetY += height / 2; - } else { - int firstShownTop = firstShownPage.bounds().top; - if (firstShownTop >= 0) { - if (null == previousPage) { - Log.e(TAG, "Can't find previous page when paging left and offsetY == 0"); - mOffsetY += height / 2; - } else { - mOffsetY += Math.min(maxOffset, -previousPage.bounds().top); - } - } else { - mOffsetY += Math.min(maxOffset, -firstShownTop); - } - } - - // Request fill - mGalleryView.requestFill(); - } - } - - @Override - public void onPageRight() { - int size = mAdapter.size(); - if (size <= 0 || mPages.isEmpty()) { - return; - } - - ///////// - // DOWN - ///////// - GalleryView galleryView = mGalleryView; - getBottomState(); - int bottom = mBottomStateBottom; - boolean hasNext = mBottomStateHasNext; - if (!hasNext && bottom <= galleryView.getHeight()) { - GLEdgeView edgeView = galleryView.getEdgeView(); - edgeView.onPull(galleryView.getHeight(), - galleryView.getWidth() / 2, GLEdgeView.BOTTOM); - edgeView.onRelease(GLEdgeView.BOTTOM); - } else { - // Cancel all animations - cancelAllAnimations(); - - // Get first shown page - GalleryPageView lastShownPage = null; - GalleryPageView nextPage = null; - for (GalleryPageView p: mPages) { - if (isInScreen(p)) { - lastShownPage = p; - } else if (null != lastShownPage) { - nextPage = p; - break; - } - } - - int height = galleryView.getHeight(); - int maxOffset = height - mInterval; - if (null == lastShownPage) { - Log.e(TAG, "Can't find last shown page when paging left"); - mOffsetY -= height / 2; - } else { - int lastShownBottom = lastShownPage.bounds().bottom; - if (lastShownBottom <= height) { - if (null == nextPage) { - Log.e(TAG, "Can't find previous page when paging left and offsetY == 0"); - mOffsetY -= height / 2; - } else { - mOffsetY -= Math.min(maxOffset, nextPage.bounds().bottom - height); - } - } else { - mOffsetY -= Math.min(maxOffset, lastShownBottom - height); - } - } - - // Request fill - mGalleryView.requestFill(); - } - } - - @Override - public boolean isTapOrPressEnable() { - return !mStopAnimationFinger; - } - - @Override - public GalleryPageView findPageByIndex(int index) { - for (GalleryPageView page : mPages) { - if (page.getIndex() == index) { - return page; - } - } - return null; - } - - @Override - public int getCurrentIndex() { - for (GalleryPageView page : mPages) { - if (isInScreen(page)) { - return page.getIndex(); - } - } - return GalleryPageView.INVALID_INDEX; - } - - @Override - public void setCurrentIndex(int index) { - int size = mAdapter.size(); - if (size <= 0) { - // Can't get size now, assume size is MAX - size = Integer.MAX_VALUE; - } - if (index < 0 || index >= size) { - return; - } - - mKeepTopPageIndex = index; - mKeepTop = INVALID_TOP; - - if (mPages.isEmpty()) { - mIndex = index; - } else { - // Fix the index page - GalleryPageView targetPage = null; - for (GalleryPageView page : mPages) { - if (page.getIndex() == index) { - targetPage =page; - break; - } - } - - if (targetPage != null) { - // Cancel all animations - cancelAllAnimations(); - mOffsetY -= targetPage.bounds().top; - // Request fill - mGalleryView.requestFill(); - } else { - mIndex = index; - mOffsetY = 0; - // Cancel all animations - cancelAllAnimations(); - // Remove all view - removeProgress(); - removeErrorView(); - removeAllPages(); - // Request fill - mGalleryView.requestFill(); - } - } - } - - @Override - public int getIndexUnder(float x, float y) { - if (mPages.isEmpty()) { - return GalleryPageView.INVALID_INDEX; - } else { - int intX = (int) x; - int intY = (int) y; - for (GalleryPageView page : mPages) { - if (page.bounds().contains(intX, intY)) { - return page.getIndex(); - } - } - return GalleryPageView.INVALID_INDEX; - } - } - - @Override - int getInternalCurrentIndex() { - int currentIndex = getCurrentIndex(); - if (currentIndex == GalleryPageView.INVALID_INDEX) { - currentIndex = mIndex; - } - return currentIndex; - } - - private class PageFling extends Fling { - - private int mVelocityX; - private int mVelocityY; - private int mDx; - private int mDy; - private int mLastX; - private int mLastY; - - public PageFling(Context context) { - super(context); - } - - public void startFling(int velocityX, int minX, int maxX, - int velocityY, int minY, int maxY) { - mVelocityX = velocityX; - mVelocityY = velocityY; - mDx = (int) (getSplineFlingDistance(velocityX) * Math.signum(velocityX)); - mDy = (int) (getSplineFlingDistance(velocityY) * Math.signum(velocityY)); - mLastX = 0; - mLastY = 0; - int durationX = getSplineFlingDuration(velocityX); - int durationY = getSplineFlingDuration(velocityY); - - if (mDx < minX) { - durationX = adjustDuration(0, mDx, minX, durationX); - mDx = minX; - } - if (mDx > maxX) { - durationX = adjustDuration(0, mDx, maxX, durationX); - mDx = maxX; - } - if (mDy < minY) { - durationY = adjustDuration(0, mDy, minY, durationY); - mDy = minY; - } - if (mDy > maxY) { - durationY = adjustDuration(0, mDy, maxY, durationY); - mDy = maxY; - } - - if (mDx == 0 && mDy == 0) { - return; - } - - setDuration(Math.max(durationX, durationY)); - start(); - mGalleryView.invalidate(); - } - - @Override - protected void onCalculate(float progress) { - int x = (int) (mDx * progress); - int y = (int) (mDy * progress); - int offsetX = x - mLastX; - int offsetY = y - mLastY; - if (scrollInternal(-offsetX, -offsetY, true, 0, 0)) { - cancel(); - onFinish(); - } - mLastX = x; - mLastY = y; - } - - @Override - protected void onFinish() { - mFlingUp = false; - - int index = mIndex; - - boolean topEdge = index <= 0 && mOffsetY >= 0; - - getBottomState(); - int bottom = mBottomStateBottom; - boolean hasNext = mBottomStateHasNext; - boolean bottomEdge = !hasNext && bottom <= mGalleryView.getHeight(); - - if (topEdge && bottomEdge) { - return; - } - - GLEdgeView edgeView = mGalleryView.getEdgeView(); - if (topEdge && edgeView.isFinished(GLEdgeView.TOP)) { - edgeView.onAbsorb(mVelocityY, GLEdgeView.TOP); - } else if (bottomEdge && edgeView.isFinished(GLEdgeView.BOTTOM)) { - edgeView.onAbsorb(-mVelocityY, GLEdgeView.BOTTOM); - } - } - } - - private class SmoothScaler extends Animation { - - private float mFocusX; - private float mFocusY; - private float mStartScale; - private float mEndScale; - private float mLastScale; - - public SmoothScaler() { - setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - } - - public void startSmoothScaler(float focusX, float focusY, - float startScale, float endScale, int duration) { - mFocusX = focusX; - mFocusY = focusY; - mStartScale = startScale; - mEndScale = endScale; - mLastScale = startScale; - setDuration(duration); - start(); - mGalleryView.invalidate(); - } - - @Override - protected void onCalculate(float progress) { - if (mPages.size() <= 0) { - return; - } - - float scale = MathUtils.lerp(mStartScale, mEndScale, progress); - onScale(mFocusX, mFocusY, scale / mLastScale); - mLastScale = scale; - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.java b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.java index deee17a71..fce40aa0e 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.java +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.java @@ -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(); diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java index e4c452a31..2a5fc84c5 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java @@ -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 diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java index bf9d3b271..8e56bc11d 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java @@ -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); } } } diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 91d754dcd..d0051c0b5 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -134,4 +134,13 @@ 8dip 8dip + + 48dp + 28dp + 256dp + 24dp + 56dp + 56sp + 24sp +