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);
}
}