@ActionMethod(ids = R.id.mainmenu_thumbnail)
 public void setCurrentPageAsThumbnail(final ActionEx action) {
   final Page page = documentModel.getCurrentPageObject();
   if (page != null) {
     documentModel.createBookThumbnail(bookSettings, page, true, false);
   }
 }
 @ActionMethod(ids = R.id.actions_addBookmark)
 public void addBookmark(final ActionEx action) {
   final Editable value = action.getParameter("input");
   final String name = value.toString();
   final Page page = documentModel.getCurrentPageObject();
   if (page != null) {
     final ViewState state = ViewState.get(getDocumentController());
     final PointF pos = state.getPositionOnPage(page);
     bookSettings.bookmarks.add(new Bookmark(name, documentModel.getCurrentIndex(), pos.x, pos.y));
     Collections.sort(bookSettings.bookmarks);
     SettingsManager.storeBookSettings(bookSettings);
     IUIManager.instance.invalidateOptionsMenu(getManagedComponent());
     state.release();
   }
 }
  @Override
  public ViewState process() {
    if (model == null) {
      return null;
    }

    final int pageCount = model.getPageCount();
    if (viewIndex < 0 && viewIndex >= pageCount) {
      if (LCTX.isDebugEnabled()) {
        LCTX.d("Bad page index: " + viewIndex + ", page count: " + pageCount);
      }
      return viewState;
    }

    final Page page = model.getPageObject(viewIndex);
    if (page == null) {
      if (LCTX.isDebugEnabled()) {
        LCTX.d("No page found for index: " + viewIndex);
      }
      return viewState;
    }

    model.setCurrentPageIndex(page.index);

    final IView view = ctrl.getView();

    final int scrollX = view.getScrollX();
    final int scrollY = view.getScrollY();

    final PointF p = calculateScroll(page, scrollX, scrollY);
    final int left = Math.round(p.x);
    final int top = Math.round(p.y);

    if (isScrollRequired(left, top, scrollX, scrollY)) {
      view.forceFinishScroll();
      view.scrollTo(left, top);
      viewState.update();
      return viewState;
    }
    viewState.release();

    return EventPool.newEventScrollTo(ctrl, viewIndex).process();
  }
    @Override
    protected void onPostExecute(Throwable result) {
      LCTX.d("BookLoadTask.onPostExecute(): start");
      try {
        if (result == null) {
          try {
            getDocumentController().show();

            final DocumentModel dm = getDocumentModel();
            currentPageChanged(PageIndex.NULL, dm.getCurrentIndex());

          } catch (final Throwable th) {
            result = th;
          }
        }

        super.onPostExecute(result);

        if (result instanceof MuPdfPasswordException) {
          final MuPdfPasswordException pex = (MuPdfPasswordException) result;
          final int promptId =
              pex.isWrongPasswordEntered()
                  ? R.string.msg_wrong_password
                  : R.string.msg_password_required;

          askPassword(m_fileName, promptId);

        } else if (result != null) {
          final String msg = result.getMessage();
          LogManager.onUnexpectedError(result);
          showErrorDlg(R.string.msg_unexpected_error, msg);
        } else {
          if (codecType != null && codecType.useCustomFonts) {
            EBookDroidApp.checkInstalledFonts(getManagedComponent());
          }
        }
      } catch (final Throwable th) {
        LCTX.e("BookLoadTask.onPostExecute(): Unexpected error", th);
        LogManager.onUnexpectedError(result);
      } finally {
        LCTX.d("BookLoadTask.onPostExecute(): finish");
      }
    }
 @ActionMethod(ids = R.id.actions_doClose)
 public void doClose(final ActionEx action) {
   if (documentModel != null) {
     documentModel.recycle();
   }
   if (scheme != null && scheme.temporary) {
     CacheManager.clear(m_fileName);
   }
   SettingsManager.releaseBookSettings(id, bookSettings);
   getManagedComponent().finish();
 }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.ebookdroid.common.settings.listeners.IBookSettingsChangeListener#onBookSettingsChanged(org.ebookdroid.common.settings.books.BookSettings,
   *     org.ebookdroid.common.settings.books.BookSettings,
   *     org.ebookdroid.common.settings.books.BookSettings.Diff)
   */
  @Override
  public void onBookSettingsChanged(
      final BookSettings oldSettings,
      final BookSettings newSettings,
      final BookSettings.Diff diff) {
    if (newSettings == null) {
      return;
    }

    boolean redrawn = false;
    if (diff.isViewModeChanged() || diff.isSplitPagesChanged() || diff.isCropPagesChanged()) {
      redrawn = true;
      final IViewController newDc = switchDocumentController(newSettings);
      if (!diff.isFirstTime() && newDc != null) {
        newDc.init(null);
        newDc.show();
      }
    }

    if (diff.isRotationChanged()) {
      getManagedComponent()
          .setRequestedOrientation(newSettings.getOrientation(AppSettings.current()));
    }

    if (diff.isFirstTime()) {
      getZoomModel().initZoom(newSettings.getZoom());
    }

    final IViewController dc = getDocumentController();

    if (!redrawn && (diff.isEffectsChanged())) {
      redrawn = true;
      dc.toggleRenderingEffects();
    }

    if (!redrawn && diff.isPageAlignChanged()) {
      dc.setAlign(newSettings.pageAlign);
    }

    if (diff.isAnimationTypeChanged()) {
      dc.updateAnimationType();
    }

    currentPageChanged(PageIndex.NULL, documentModel.getCurrentIndex());

    IUIManager.instance.invalidateOptionsMenu(getManagedComponent());
  }
  @ActionMethod(ids = R.id.mainmenu_bookmark)
  public void showBookmarkDialog(final ActionEx action) {
    final int page = documentModel.getCurrentViewPageIndex();

    final String message = getManagedComponent().getString(R.string.add_bookmark_name);

    final BookSettings bs = getBookSettings();
    final int offset = bs != null ? bs.firstPageOffset : 1;

    final EditText input =
        (EditText) LayoutInflater.from(getManagedComponent()).inflate(R.layout.bookmark_edit, null);
    input.setText(getManagedComponent().getString(R.string.text_page) + " " + (page + offset));
    input.selectAll();

    final ActionDialogBuilder builder = new ActionDialogBuilder(getManagedComponent(), this);
    builder.setTitle(R.string.menu_add_bookmark).setMessage(message).setView(input);
    builder.setPositiveButton(R.id.actions_addBookmark, new EditableValue("input", input));
    builder.setNegativeButton().show();
  }
  /**
   * {@inheritDoc}
   *
   * @see org.emdev.ui.AbstractActivityController#onDestroy(boolean)
   */
  @Override
  public void onDestroy(final boolean finishing) {
    if (finishing) {
      if (BackupSettings.current().backupOnBookClose) {
        BackupManager.backup();
      }
      if (documentModel != null) {
        documentModel.recycle();
      }
      if (scheme != null && scheme.temporary) {
        CacheManager.clear(scheme.key);
      }
      SettingsManager.removeListener(this);
      BitmapManager.clear("on finish");
      ByteBufferManager.clear("on finish");

      EBookDroidApp.onActivityClose(finishing);
    }
  }
  /**
   * {@inheritDoc}
   *
   * @see org.emdev.ui.AbstractActivityController#afterCreate(android.app.Activity, boolean)
   */
  @Override
  public void afterCreate(final ViewerActivity activity, final boolean recreated) {

    final AppSettings appSettings = AppSettings.current();

    IUIManager.instance.setFullScreenMode(
        activity, getManagedComponent().view.getView(), appSettings.fullScreen);

    createAction(R.id.mainmenu_crop)
        .putValue("view", activity.getManualCropControls())
        .putValue("mode", DocumentViewMode.SINGLE_PAGE);
    createAction(R.id.mainmenu_zoom).putValue("view", activity.getZoomControls());
    createAction(R.id.mainmenu_search).putValue("view", activity.getSearchControls());
    createAction(R.id.actions_toggleTouchManagerView).putValue("view", activity.getTouchView());
    createAction(R.id.mainmenu_force_portrait).putValue("mode", BookRotationType.PORTRAIT);
    createAction(R.id.mainmenu_force_landscape).putValue("mode", BookRotationType.LANDSCAPE);

    if (recreated) {
      return;
    }

    documentModel = ActivityControllerStub.DM_STUB;
    searchModel = new SearchModel(this);

    if (intent == null) {
      showErrorDlg(R.string.msg_bad_intent, intent);
      return;
    }

    final Uri data = intent.getData();
    if (data == null) {
      showErrorDlg(R.string.msg_no_intent_data, intent);
      return;
    }

    scheme = ContentScheme.getScheme(intent);
    if (scheme == ContentScheme.UNKNOWN) {
      showErrorDlg(R.string.msg_bad_intent, intent);
      return;
    }

    bookTitle = scheme.getResourceName(activity.getContentResolver(), data);
    codecType = CodecType.getByUri(bookTitle);

    if (codecType == null) {
      bookTitle = ContentScheme.getDefaultResourceName(data, "");
      codecType = CodecType.getByUri(bookTitle);
    }

    if (codecType == null) {
      final String type = intent.getType();
      LCTX.i("Book mime type: " + type);
      if (LengthUtils.isNotEmpty(type)) {
        codecType = CodecType.getByMimeType(type);
      }
    }

    LCTX.i("Book codec type: " + codecType);
    LCTX.i("Book title: " + bookTitle);
    if (codecType == null) {
      showErrorDlg(R.string.msg_unknown_intent_data_type, data);
      return;
    }

    documentModel = new DocumentModel(codecType);
    documentModel.addListener(ViewerActivityController.this);
    progressModel = new DecodingProgressModel();
    progressModel.addListener(ViewerActivityController.this);

    final Uri uri = data;
    if (scheme.temporary) {
      m_fileName = scheme.key;
      CacheManager.clear(scheme.key);
    } else {
      m_fileName = PathFromUri.retrieve(activity.getContentResolver(), uri);
    }

    bookSettings = SettingsManager.create(id, m_fileName, scheme.temporary, intent);
    SettingsManager.applyBookSettingsChanges(null, bookSettings);
  }