@Override
 public Footer getFooterArea() {
   switch (myViewOptions.ScrollbarType.getValue()) {
     case SCROLLBAR_SHOW_AS_FOOTER:
       if (!(myFooter instanceof FooterNewStyle)) {
         if (myFooter != null) {
           myReader.removeTimerTask(myFooter.UpdateTask);
         }
         myFooter = new FooterNewStyle();
         myReader.addTimerTask(myFooter.UpdateTask, 15000);
       }
       break;
     case SCROLLBAR_SHOW_AS_FOOTER_OLD_STYLE:
       if (!(myFooter instanceof FooterOldStyle)) {
         if (myFooter != null) {
           myReader.removeTimerTask(myFooter.UpdateTask);
         }
         myFooter = new FooterOldStyle();
         myReader.addTimerTask(myFooter.UpdateTask, 15000);
       }
       break;
     default:
       if (myFooter != null) {
         myReader.removeTimerTask(myFooter.UpdateTask);
         myFooter = null;
       }
       break;
   }
   return myFooter;
 }
  @Override
  public void onFingerMove(int x, int y) {
    final SelectionCursor.Which cursor = getSelectionCursorInMovement();
    if (cursor != null) {
      moveSelectionCursorTo(cursor, x, y);
      return;
    }

    synchronized (this) {
      if (myIsBrightnessAdjustmentInProgress) {
        if (x >= getContextWidth() / 5) {
          myIsBrightnessAdjustmentInProgress = false;
          startManualScrolling(x, y);
        } else {
          final int delta = (myStartBrightness + 30) * (myStartY - y) / getContextHeight();
          myReader.getViewWidget().setScreenBrightness(myStartBrightness + delta);
          return;
        }
      }

      if (isFlickScrollingEnabled()) {
        myReader.getViewWidget().scrollManuallyTo(x, y);
      }
    }
  }
  @Override
  public void onFingerDoubleTap(int x, int y) {
    myReader.runAction(ActionCode.HIDE_TOAST);

    myReader.runAction(
        getZoneMap()
            .getActionByCoordinates(
                x, y, getContextWidth(), getContextHeight(), TapZoneMap.Tap.doubleTap),
        x,
        y);
  }
 @Override
 protected void releaseSelectionCursor() {
   super.releaseSelectionCursor();
   if (getCountOfSelectedWords() > 0) {
     myReader.runAction(ActionCode.SELECTION_SHOW_PANEL);
   }
 }
  @Override
  public void onFingerReleaseAfterLongPress(int x, int y) {
    final SelectionCursor.Which cursor = getSelectionCursorInMovement();
    if (cursor != null) {
      releaseSelectionCursor();
      return;
    }

    final ZLTextRegion region = getOutlinedRegion();
    if (region != null) {
      final ZLTextRegion.Soul soul = region.getSoul();

      boolean doRunAction = false;
      if (soul instanceof ZLTextWordRegionSoul) {
        doRunAction =
            myReader.MiscOptions.WordTappingAction.getValue()
                == MiscOptions.WordTappingActionEnum.openDictionary;
      } else if (soul instanceof ZLTextImageRegionSoul) {
        doRunAction =
            myReader.ImageOptions.TapAction.getValue() == ImageOptions.TapActionEnum.openImageView;
      }

      if (doRunAction) {
        myReader.runAction(ActionCode.PROCESS_HYPERLINK);
      }
    }
  }
  @Override
  public void onFingerMoveAfterLongPress(int x, int y) {
    final SelectionCursor.Which cursor = getSelectionCursorInMovement();
    if (cursor != null) {
      moveSelectionCursorTo(cursor, x, y);
      return;
    }

    ZLTextRegion region = getOutlinedRegion();
    if (region != null) {
      ZLTextRegion.Soul soul = region.getSoul();
      if (soul instanceof ZLTextHyperlinkRegionSoul || soul instanceof ZLTextWordRegionSoul) {
        if (myReader.MiscOptions.WordTappingAction.getValue()
            != MiscOptions.WordTappingActionEnum.doNothing) {
          region = findRegion(x, y, maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
          if (region != null) {
            soul = region.getSoul();
            if (soul instanceof ZLTextHyperlinkRegionSoul || soul instanceof ZLTextWordRegionSoul) {
              outlineRegion(region);
              myReader.getViewWidget().reset();
              myReader.getViewWidget().repaint();
            }
          }
        }
      }
    }
  }
  private void startManualScrolling(int x, int y) {
    if (!isFlickScrollingEnabled()) {
      return;
    }

    final boolean horizontal = myReader.PageTurningOptions.Horizontal.getValue();
    final Direction direction = horizontal ? Direction.rightToLeft : Direction.up;
    myReader.getViewWidget().startManualScrolling(x, y, direction);
  }
  @Override
  public boolean onFingerLongPress(int x, int y) {
    myReader.runAction(ActionCode.HIDE_TOAST);

    final ZLTextRegion region =
        findRegion(x, y, maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
    if (region != null) {
      final ZLTextRegion.Soul soul = region.getSoul();
      boolean doSelectRegion = false;
      if (soul instanceof ZLTextWordRegionSoul) {
        switch (myReader.MiscOptions.WordTappingAction.getValue()) {
          case startSelecting:
            myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
            initSelection(x, y);
            final SelectionCursor.Which cursor = findSelectionCursor(x, y);
            if (cursor != null) {
              moveSelectionCursorTo(cursor, x, y);
            }
            return true;
          case selectSingleWord:
          case openDictionary:
            doSelectRegion = true;
            break;
        }
      } else if (soul instanceof ZLTextImageRegionSoul) {
        doSelectRegion =
            myReader.ImageOptions.TapAction.getValue() != ImageOptions.TapActionEnum.doNothing;
      } else if (soul instanceof ZLTextHyperlinkRegionSoul) {
        doSelectRegion = true;
      }

      if (doSelectRegion) {
        outlineRegion(region);
        myReader.getViewWidget().reset();
        myReader.getViewWidget().repaint();
        return true;
      }
    }
    return false;
  }
 @Override
 public void onFingerRelease(int x, int y) {
   final SelectionCursor.Which cursor = getSelectionCursorInMovement();
   if (cursor != null) {
     releaseSelectionCursor();
   } else if (myIsBrightnessAdjustmentInProgress) {
     myIsBrightnessAdjustmentInProgress = false;
   } else if (isFlickScrollingEnabled()) {
     myReader
         .getViewWidget()
         .startAnimatedScrolling(x, y, myReader.PageTurningOptions.AnimationSpeed.getValue());
   }
 }
  @Override
  public void onFingerPress(int x, int y) {
    myReader.runAction(ActionCode.HIDE_TOAST);

    final float maxDist = ZLibrary.Instance().getDisplayDPI() / 4;
    final SelectionCursor.Which cursor = findSelectionCursor(x, y, maxDist * maxDist);
    if (cursor != null) {
      myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
      moveSelectionCursorTo(cursor, x, y);
      return;
    }

    if (myReader.MiscOptions.AllowScreenBrightnessAdjustment.getValue()
        && x < getContextWidth() / 10) {
      myIsBrightnessAdjustmentInProgress = true;
      myStartY = y;
      myStartBrightness = myReader.getViewWidget().getScreenBrightness();
      return;
    }

    startManualScrolling(x, y);
  }
 private void onFingerSingleTapLastResort(int x, int y) {
   myReader.runAction(
       getZoneMap()
           .getActionByCoordinates(
               x,
               y,
               getContextWidth(),
               getContextHeight(),
               isDoubleTapSupported()
                   ? TapZoneMap.Tap.singleNotDoubleTap
                   : TapZoneMap.Tap.singleTap),
       x,
       y);
 }
 @Override
 public ZLColor getTextColor(ZLTextHyperlink hyperlink) {
   final ColorProfile profile = myViewOptions.getColorProfile();
   switch (hyperlink.Type) {
     default:
     case FBHyperlinkType.NONE:
       return profile.RegularTextOption.getValue();
     case FBHyperlinkType.INTERNAL:
     case FBHyperlinkType.FOOTNOTE:
       return myReader.Collection.isHyperlinkVisited(myReader.getCurrentBook(), hyperlink.Id)
           ? profile.VisitedHyperlinkTextOption.getValue()
           : profile.HyperlinkTextOption.getValue();
     case FBHyperlinkType.EXTERNAL:
       return profile.HyperlinkTextOption.getValue();
   }
 }
  @Override
  public void onFingerSingleTap(int x, int y) {
    final ZLTextRegion hyperlinkRegion =
        findRegion(x, y, maxSelectionDistance(), ZLTextRegion.HyperlinkFilter);
    if (hyperlinkRegion != null) {
      outlineRegion(hyperlinkRegion);
      myReader.getViewWidget().reset();
      myReader.getViewWidget().repaint();
      myReader.runAction(ActionCode.PROCESS_HYPERLINK);
      return;
    }

    final ZLTextRegion bookRegion = findRegion(x, y, 0, ZLTextRegion.ExtensionFilter);
    if (bookRegion != null) {
      myReader.runAction(ActionCode.DISPLAY_BOOK_POPUP, bookRegion);
      return;
    }

    final ZLTextRegion videoRegion = findRegion(x, y, 0, ZLTextRegion.VideoFilter);
    if (videoRegion != null) {
      outlineRegion(videoRegion);
      myReader.getViewWidget().reset();
      myReader.getViewWidget().repaint();
      myReader.runAction(ActionCode.OPEN_VIDEO, (ZLTextVideoRegionSoul) videoRegion.getSoul());
      return;
    }

    final ZLTextHighlighting highlighting = findHighlighting(x, y, maxSelectionDistance());
    if (highlighting instanceof BookmarkHighlighting) {
      myReader.runAction(
          ActionCode.SELECTION_BOOKMARK, ((BookmarkHighlighting) highlighting).Bookmark);
      return;
    }

    if (myReader.isActionEnabled(ActionCode.HIDE_TOAST)) {
      myReader.runAction(ActionCode.HIDE_TOAST);
      return;
    }

    onFingerSingleTapLastResort(x, y);
  }
 @Override
 public synchronized void onScrollingFinished(PageIndex pageIndex) {
   super.onScrollingFinished(pageIndex);
   myReader.storePosition();
 }