package org.ebookdroid.core; import org.ebookdroid.common.settings.AppSettings; import org.ebookdroid.common.settings.books.BookSettings; import org.ebookdroid.common.settings.types.DocumentViewMode; import org.ebookdroid.common.settings.types.PageAlign; import org.ebookdroid.common.touch.DefaultGestureDetector; import org.ebookdroid.common.touch.IGestureDetector; import org.ebookdroid.common.touch.MultiTouchGestureDetector; import org.ebookdroid.core.curl.PageAnimationType; import org.ebookdroid.core.curl.PageAnimator; import org.ebookdroid.core.curl.PageAnimatorProxy; import org.ebookdroid.core.curl.SinglePageView; import org.ebookdroid.ui.viewer.IActivityController; import android.graphics.Rect; import android.graphics.RectF; import java.util.List; import org.emdev.utils.LengthUtils; /** * The Class SinglePageController. * * Used in single page view mode */ public class SinglePageController extends AbstractViewController { /** The curler. */ private final PageAnimatorProxy curler = new PageAnimatorProxy(new SinglePageView(this)); /** * Instantiates a new single page document view. * * @param baseActivity * the base activity */ public SinglePageController(final IActivityController baseActivity) { super(baseActivity, DocumentViewMode.SINGLE_PAGE); updateAnimationType(); } /** * {@inheritDoc} * * @see org.ebookdroid.core.AbstractViewController#goToPageImpl(int) */ @Override public final void goToPage(final int toPage) { if (toPage >= 0 && toPage < model.getPageCount()) { final Page page = model.getPageObject(toPage); model.setCurrentPageIndex(page.index); curler.setViewDrawn(false); curler.resetPageIndexes(page.index.viewIndex); final ViewState viewState = EventPool.newEventScrollTo(this, page.index.viewIndex).process(); getView().redrawView(viewState); viewState.release(); } } /** * {@inheritDoc} * * @see org.ebookdroid.core.AbstractViewController#goToPageImpl(int, float, float) */ @Override public void goToPage(final int toPage, final float offsetX, final float offsetY) { if (toPage >= 0 && toPage < model.getPageCount()) { final Page page = model.getPageObject(toPage); model.setCurrentPageIndex(page.index); curler.setViewDrawn(false); curler.resetPageIndexes(page.index.viewIndex); final RectF bounds = page.getBounds(getBase().getZoomModel().getZoom()); final float left = bounds.left + offsetX * bounds.width(); final float top = bounds.top + offsetY * bounds.height(); getView().scrollTo((int) left, (int) top); final ViewState viewState = EventPool.newEventScrollTo(this, page.index.viewIndex).process(); pageUpdated(viewState, page); getView().redrawView(viewState); viewState.release(); } } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#onScrollChanged(int, int) */ @Override public void onScrollChanged(final int dX, final int dY) { // bounds could be not updated if (inZoom.get()) { return; } EventPool.newEventScroll(this, dX).process().release(); } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#calculateCurrentPage(org.ebookdroid.core.ViewState) */ @Override public final int calculateCurrentPage(final ViewState viewState, final int firstVisible, final int lastVisible) { return viewState.model.getCurrentViewPageIndex(); } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#verticalConfigScroll(int) */ @Override public final void verticalConfigScroll(final int direction) { if (curler.enabled()) { curler.animate(direction); } else { final BookSettings bs = base.getBookSettings(); final float offsetX = bs != null ? bs.offsetX : 0; final Page page = model.getCurrentPageObject(); final RectF viewRect = base.getView().getViewRect(); final RectF bounds = page.getBounds(getBase().getZoomModel().getZoom()); if (Math.abs(viewRect.top - bounds.top) < 5 && direction < 0) { goToPage(page.index.viewIndex - 1, offsetX, 1); return; } if (Math.abs(viewRect.bottom - bounds.bottom) < 5 && direction > 0) { goToPage(page.index.viewIndex + 1, offsetX, 0); return; } final float pageHeight = bounds.height(); final float viewHeight = viewRect.height(); final float diff = direction * viewHeight * AppSettings.current().scrollHeight / 100.0f; final float oldTop = getScrollY(); final float newTop = oldTop + diff; goToPage(model.getCurrentViewPageIndex(), offsetX, newTop / pageHeight); } } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#getScrollLimits() */ @Override public final Rect getScrollLimits() { final int width = getWidth(); final int height = getHeight(); final float zoom = getBase().getZoomModel().getZoom(); final Page page = model.getCurrentPageObject(); if (page != null) { final RectF bounds = page.getBounds(zoom); final int top = ((int) bounds.top > 0) ? 0 : (int) bounds.top; final int left = ((int) bounds.left > 0) ? 0 : (int) bounds.left; final int bottom = ((int) bounds.bottom < height) ? 0 : (int) bounds.bottom - height; final int right = ((int) bounds.right < width) ? 0 : (int) bounds.right - width; return new Rect(left, top, right, bottom); } return new Rect(0, 0, 0, 0); } /** * {@inheritDoc} * * @see org.ebookdroid.core.AbstractViewController#initGestureDetectors(java.util.List) */ @Override protected List<IGestureDetector> initGestureDetectors(final List<IGestureDetector> list) { final GestureListener listener = new GestureListener(); list.add(new MultiTouchGestureDetector(listener)); list.add(curler); list.add(new DefaultGestureDetector(base.getContext(), listener)); return list; } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#drawView(org.ebookdroid.core.EventGLDraw) */ @Override public void drawView(final EventGLDraw eventDraw) { curler.draw(eventDraw); getView().continueScroll(); } public final ViewState invalidatePages(final ViewState oldState, final Page... pages) { if (LengthUtils.isNotEmpty(pages) && pages[0] != null) { return EventPool.newEventScrollTo(this, pages[0].index.viewIndex).process(); } return oldState; } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#invalidatePageSizes(org.ebookdroid.ui.viewer.IViewController.InvalidateSizeReason, * org.ebookdroid.core.Page) */ @Override public final void invalidatePageSizes(final InvalidateSizeReason reason, final Page changedPage) { if (!isShown()) { return; } final int width = getWidth(); final int height = getHeight(); final BookSettings bookSettings = base.getBookSettings(); final PageAlign pageAlign = DocumentViewMode.getPageAlign(bookSettings); if (changedPage == null) { for (final Page page : model.getPages()) { invalidatePageSize(pageAlign, page, width, height); } } else { invalidatePageSize(pageAlign, changedPage, width, height); } curler.setViewDrawn(false); } private void invalidatePageSize(final PageAlign pageAlign, final Page page, final int width, final int height) { final RectF pageBounds = calcPageBounds(pageAlign, page.getAspectRatio(), width, height); // if the screen is larger than the page, center the page within the screen final float pageWidth = pageBounds.width(); if (width > pageWidth) { final float widthDelta = (width - pageWidth) / 2; pageBounds.offset(widthDelta, 0); } final float pageHeight= pageBounds.height(); if (height > pageHeight) { final float heightDelta = (height - pageHeight) / 2; pageBounds.offset(0, heightDelta); } page.setBounds(pageBounds); } @Override public RectF calcPageBounds(final PageAlign pageAlign, final float pageAspectRatio, final int width, final int height) { PageAlign effective = pageAlign; if (effective == PageAlign.AUTO) { final float pageHeight = width / pageAspectRatio; effective = pageHeight > height ? PageAlign.HEIGHT : PageAlign.WIDTH; } if (effective == PageAlign.WIDTH) { final float pageHeight = width / pageAspectRatio; return new RectF(0, 0, width, pageHeight); } else { final float pageWidth = height * pageAspectRatio; return new RectF(0, 0, pageWidth, height); } } /** * {@inheritDoc} * * @see org.ebookdroid.core.AbstractViewController#isPageVisible(org.ebookdroid.core.Page, * org.ebookdroid.core.ViewState) */ @Override public final boolean isPageVisible(final Page page, final ViewState viewState, final RectF outBounds) { viewState.getBounds(page, outBounds); return curler.isPageVisible(page, viewState); } /** * {@inheritDoc} * * @see org.ebookdroid.ui.viewer.IViewController#updateAnimationType() */ @Override public final void updateAnimationType() { final PageAnimationType animationType = base.getBookSettings().animationType; final PageAnimator newCurler = PageAnimationType.create(animationType, this); newCurler.init(); curler.switchCurler(newCurler); } /** * {@inheritDoc} * * @see org.ebookdroid.core.AbstractViewController#pageUpdated(org.ebookdroid.core.ViewState, * org.ebookdroid.core.Page) */ @Override public void pageUpdated(final ViewState viewState, final Page page) { curler.pageUpdated(viewState, page); } }