chromium/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.findinpage;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import org.chromium.chrome.R;
import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.interpolators.Interpolators;

/** A tablet specific version of the {@link FindToolbar}. */
public class FindToolbarTablet extends FindToolbar {
    private static final int ENTER_EXIT_ANIMATION_DURATION_MS = 200;
    private static final int MAKE_ROOM_ANIMATION_DURATION_MS = 200;

    private static final float Y_INSET_DP = 8.f;

    private ObjectAnimator mCurrentAnimation;

    private ObjectAnimator mAnimationEnter;
    private ObjectAnimator mAnimationLeave;

    private final int mYInsetPx;

    /**
     * Creates an instance of a {@link FindToolbarTablet}.
     * @param context The Context to create the {@link FindToolbarTablet} under.
     * @param attrs The AttributeSet used to create the {@link FindToolbarTablet}.
     */
    public FindToolbarTablet(Context context, AttributeSet attrs) {
        super(context, attrs);

        mYInsetPx = (int) (context.getResources().getDisplayMetrics().density * Y_INSET_DP);
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();

        setVisibility(View.GONE);

        Resources resources = getContext().getResources();
        int width = resources.getDimensionPixelSize(R.dimen.find_in_page_popup_width);
        int endMargin = resources.getDimensionPixelOffset(R.dimen.find_in_page_popup_margin_end);
        int translateWidth = width + endMargin;

        mAnimationEnter = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, translateWidth, 0);
        mAnimationEnter.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS);
        mAnimationEnter.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR);
        mAnimationEnter.addListener(
                new CancelAwareAnimatorListener() {
                    @Override
                    public void onStart(Animator animation) {
                        setVisibility(View.VISIBLE);
                        postInvalidateOnAnimation();
                        FindToolbarTablet.super.handleActivate();
                    }

                    @Override
                    public void onEnd(Animator animation) {
                        mCurrentAnimation = null;
                    }
                });

        mAnimationLeave = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, 0, translateWidth);
        mAnimationLeave.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS);
        mAnimationLeave.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR);
        mAnimationLeave.addListener(
                new CancelAwareAnimatorListener() {
                    @Override
                    public void onStart(Animator animator) {
                        setVisibility(View.VISIBLE);
                        postInvalidateOnAnimation();
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        setVisibility(View.GONE);
                        mCurrentAnimation = null;
                    }
                });
    }

    @Override
    protected void handleActivate() {
        if (mCurrentAnimation == mAnimationEnter) return;
        assert isWebContentAvailable();
        setShowState(true);
    }

    @Override
    protected void handleDeactivation(boolean clearSelection) {
        if (mCurrentAnimation != mAnimationLeave) setShowState(false);
        super.handleDeactivation(clearSelection);
    }

    @Override
    public boolean isAnimating() {
        return mCurrentAnimation != null;
    }

    @Override
    public void findResultSelected(Rect rect) {
        super.findResultSelected(rect);

        boolean makeRoom = false;
        float density = getContext().getResources().getDisplayMetrics().density;

        if (rect != null
                && rect.intersects(
                        (int) (getLeft() / density),
                        0,
                        (int) (getRight() / density),
                        (int) (getHeight() / density))) {
            makeRoom = true;
        }

        setMakeRoomForResults(makeRoom);
    }

    @Override
    protected void clearResults() {
        super.clearResults();
        setMakeRoomForResults(false);
    }

    private void setMakeRoomForResults(boolean makeRoom) {
        float translationY = makeRoom ? -(getHeight() - mYInsetPx) : 0.f;

        if (translationY == getTranslationY()) return;

        if (mCurrentAnimation != null) {
            if (mCurrentAnimation == mAnimationEnter || mCurrentAnimation == mAnimationLeave) {
                mCurrentAnimation.end();
            } else {
                mCurrentAnimation.cancel();
            }
        }

        mCurrentAnimation = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, translationY);
        mCurrentAnimation.setDuration(MAKE_ROOM_ANIMATION_DURATION_MS);
        mCurrentAnimation.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR);
        mCurrentAnimation.addListener(
                new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        postInvalidateOnAnimation();
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mCurrentAnimation = null;
                    }
                });
        startAnimationOverContent(mCurrentAnimation);
    }

    private void setShowState(boolean show) {
        ObjectAnimator nextAnimator = null;

        if (show && getVisibility() != View.VISIBLE && mCurrentAnimation != mAnimationEnter) {
            View anchorView = getRootView().findViewById(R.id.toolbar);
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
            lp.topMargin = anchorView.getBottom() - mYInsetPx;
            setLayoutParams(lp);
            nextAnimator = mAnimationEnter;
        } else if (!show && getVisibility() != View.GONE && mCurrentAnimation != mAnimationLeave) {
            nextAnimator = mAnimationLeave;
            onHideAnimationStart();
        }

        if (nextAnimator != null) {
            if (mCurrentAnimation != null) mCurrentAnimation.cancel();

            mCurrentAnimation = nextAnimator;
            startAnimationOverContent(nextAnimator);
            postInvalidateOnAnimation();
        }
    }
}