@Override
  public void onLongPress(MotionEvent e) {
    CharSequence word = bookView.getWordAt(e.getX(), e.getY());

    if (word != null) {
      bookViewListener.onWordLongPressed(word);
    }
  }
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

    float scrollUnitSize = SCROLL_FACTOR * metrics.density;

    final int TAP_RANGE_H = bookView.getWidth() / 5;
    float delta = (e1.getY() - e2.getY()) / scrollUnitSize;
    int level = (int) delta;

    if (e1.getX() < TAP_RANGE_H) {
      return this.bookViewListener.onLeftEdgeSlide(level);
    } else if (e1.getX() > bookView.getWidth() - TAP_RANGE_H) {

      return this.bookViewListener.onRightEdgeSlide(level);
    }

    return super.onScroll(e1, e2, distanceX, distanceY);
  }
  @Override
  public boolean onSingleTapUp(MotionEvent e) {

    // Links get preference
    if (bookView.hasLinkAt(e.getX(), e.getY())) {
      return false;
    }

    final int TAP_RANGE_H = bookView.getWidth() / 5;
    final int TAP_RANGE_V = bookView.getHeight() / 5;

    if (e.getX() < TAP_RANGE_H) {
      return bookViewListener.onTapLeftEdge();
    } else if (e.getX() > bookView.getWidth() - TAP_RANGE_H) {
      return bookViewListener.onTapRightEdge();
    }

    int yBase = bookView.getScrollY();

    if (e.getY() < TAP_RANGE_V + yBase) {
      return bookViewListener.onTapTopEdge();
    } else if (e.getY() > (yBase + bookView.getHeight()) - TAP_RANGE_V) {
      return bookViewListener.onTopBottomEdge();
    }

    this.bookViewListener.onScreenTap();
    return false;
  }