/**
   * Prepare effect panel.
   *
   * @param effect the effect
   * @param entry the entry
   */
  private void prepareEffectPanel(final AbstractEffectPanel effect, final EffectEntry entry) {
    View option_child = null;
    View drawing_child = null;

    if (effect instanceof OptionPanel) {
      option_child =
          ((OptionPanel) effect)
              .getOptionView(UIUtils.getLayoutInflater(), mContext.getOptionsPanelContainer());
      mContext.getOptionsPanelContainer().addView(option_child);
    }

    if (effect instanceof ContentPanel) {
      drawing_child = ((ContentPanel) effect).getContentView(UIUtils.getLayoutInflater());
      drawing_child.setLayoutParams(
          new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
      mContext.getDrawingImageContainer().addView(drawing_child);
    }

    effect.onCreate(mBitmap);
  }
  /**
   * This is the entry point of every feather tools. The main activity catches the tool onClick
   * listener and notify the filtermanager.
   *
   * @param tag the tag
   */
  public void activateEffect(final EffectEntry tag) {
    if (!getEnabled() || !isClosed() || mBitmap == null) return;

    if (mCurrentEffect != null)
      throw new IllegalStateException("There is already an active effect. Cannot activate new");
    if (mEffectLoader == null)
      mEffectLoader = (EffectLoaderService) getService(EffectLoaderService.class);

    final AbstractEffectPanel effect = mEffectLoader.load(tag);

    if (effect != null) {
      mCurrentEffect = effect;
      mCurrentEntry = tag;

      setCurrentState(STATE.OPENING);
      prepareEffectPanel(effect, tag);

      Tracker.recordTag(mCurrentEntry.name.name().toLowerCase(Locale.US) + ": opened");
      mContext
          .getBottomBar()
          .setOnPanelOpenListener(
              new OnPanelOpenListener() {

                @Override
                public void onOpened() {
                  setCurrentState(STATE.OPENED);
                  mContext.getBottomBar().setOnPanelOpenListener(null);
                }

                @Override
                public void onOpening() {
                  mCurrentEffect.onOpening();
                }
              });

      mContext.getBottomBar().open();
    }
  }
  /**
   * On close.
   *
   * @param isConfirmed the is confirmed
   */
  private void onClose(final boolean isConfirmed) {

    logger.info("onClose");

    setCurrentState(STATE.CLOSING);

    mContext
        .getBottomBar()
        .setOnPanelCloseListener(
            new OnPanelCloseListener() {

              @Override
              public void onClosed() {
                setCurrentState(isConfirmed ? STATE.CLOSED_CONFIRMED : STATE.CLOSED_CANCEL);
                mContext.getBottomBar().setOnPanelCloseListener(null);
              }

              @Override
              public void onClosing() {
                mCurrentEffect.onClosing();
              }
            });
    mContext.getBottomBar().close();
  }
  /**
   * Sets the current state.
   *
   * @param newState the new current state
   */
  private void setCurrentState(final STATE newState) {
    if (newState != mCurrentState) {
      final STATE previousState = mCurrentState;
      mCurrentState = newState;

      switch (newState) {
        case OPENING:
          mCurrentEffect.setOnPreviewListener(this);
          mCurrentEffect.setOnApplyResultListener(this);
          mCurrentEffect.setOnErrorListener(this);
          mCurrentEffect.setOnProgressListener(this);

          if (mCurrentEffect instanceof ContentPanel)
            ((ContentPanel) mCurrentEffect).setOnReadyListener(this);

          mHandler.sendEmptyMessage(FilterManager.STATE_OPENING);
          break;

        case OPENED:
          mCurrentEffect.onActivate();
          mHandler.sendEmptyMessage(FilterManager.STATE_OPENED);

          if (!(mCurrentEffect instanceof ContentPanel)) {
            mHandler.sendEmptyMessage(STATE_READY);
          }

          break;

        case CLOSING:
          mHandler.sendEmptyMessage(FilterManager.STATE_CLOSING);

          mCurrentEffect.onDeactivate();
          if (mCurrentEffect instanceof ContentPanel) {
            ((ContentPanel) mCurrentEffect).setOnReadyListener(null);
          }

          mHandler.postDelayed(
              new Runnable() {

                @Override
                public void run() {
                  if (null != mBitmapChangeListener) mBitmapChangeListener.onClearColorFilter();
                  mContext.getDrawingImageContainer().removeAllViews();
                  mContext.deactivatePopupContainer();
                }
              },
              100);
          break;

        case CLOSED_CANCEL:
        case CLOSED_CONFIRMED:
          mContext.getOptionsPanelContainer().removeAllViews();

          if (previousState != STATE.DISABLED) {
            mCurrentEffect.onDestroy();
            mCurrentEffect.setOnPreviewListener(null);
            mCurrentEffect.setOnApplyResultListener(null);
            mCurrentEffect.setOnErrorListener(null);
            mCurrentEffect.setOnProgressListener(null);
            mCurrentEffect = null;
            mCurrentEntry = null;
          }

          mHandler.sendEmptyMessage(FilterManager.STATE_CLOSED);

          if ((newState == STATE.CLOSED_CONFIRMED) && (previousState != STATE.DISABLED))
            if (mToolListener != null) mToolListener.onToolCompleted();
          System.gc();
          break;

        case DISABLED:
          mHandler.sendEmptyMessage(FilterManager.STATE_DISABLED);
          break;
      }
    }
  }
 /**
  * Return the current image transformation matrix. this is useful for those tools which implement
  * ContentPanel and want to display the preview bitmap with the same zoom level of the main image
  *
  * @return the current image view matrix
  * @see ContentPanel
  */
 @Override
 public Matrix getCurrentImageViewMatrix() {
   return mContext.getMainImage().getDisplayMatrix();
 }
 @Override
 public void setPanelApplyStatusEnabled(boolean enabled) {
   mContext.getToolbar().setApplyVisibility(enabled);
 }
 @Override
 public void restoreToolbarTitle() {
   if (mCurrentEntry != null) mContext.getToolbar().setTitle(mCurrentEntry.labelResourceId);
 }
 @Override
 public void setToolbarTitle(CharSequence value) {
   mContext.getToolbar().setTitle(value);
 }
 @Override
 public void onProgressModalEnd() {
   mContext.hideModalProgress();
 }
 @Override
 public void onProgressModalStart() {
   mContext.showModalProgress();
 }
 @Override
 public void onProgressEnd() {
   mContext.hideToolProgress();
 }
 @Override
 public void onProgressStart() {
   mContext.showToolProgress();
 }