summaryrefslogtreecommitdiffstats
path: root/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java
blob: fdeb0c1705552a213768b60c2d248cd3cfe3b4c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.quickstep;

import android.graphics.Rect;

import com.android.launcher3.Utilities;

/**
 * Helper class to interpolate the animation between a task view representation and an actual
 * window.
 */
public class RecentsAnimationInterpolator {

    public static class TaskWindowBounds {
        public float taskScale = 1f;
        public float taskX = 0f;
        public float taskY = 0f;

        public float winScale = 1f;
        public float winX = 0f;
        public float winY = 0f;
        public Rect winCrop = new Rect();

        @Override
        public String toString() {
            return "taskScale=" + taskScale + " taskX=" + taskX + " taskY=" + taskY
                    + " winScale=" + winScale + " winX=" + winX + " winY=" + winY
                    + " winCrop=" + winCrop;
        }
    }

    private TaskWindowBounds mTmpTaskWindowBounds = new TaskWindowBounds();
    private Rect mTmpInsets = new Rect();

    private Rect mWindow;
    private Rect mInsetWindow;
    private Rect mInsets;
    private Rect mTask;
    private Rect mTaskInsets;
    private Rect mThumbnail;

    private float mInitialTaskScale;
    private float mInitialTaskTranslationX;
    private float mFinalTaskScale;
    private Rect mScaledTask;
    private Rect mTargetTask;
    private Rect mSrcWindow;

    public RecentsAnimationInterpolator(Rect window, Rect insets, Rect task, Rect taskInsets,
            float taskScale, float taskTranslationX) {
        mWindow = window;
        mInsets = insets;
        mTask = task;
        mTaskInsets = taskInsets;
        mInsetWindow = new Rect(window);
        Utilities.insetRect(mInsetWindow, insets);

        mThumbnail = new Rect(task);
        Utilities.insetRect(mThumbnail, taskInsets);
        mInitialTaskScale = taskScale;
        mInitialTaskTranslationX = taskTranslationX;
        mFinalTaskScale = (float) mInsetWindow.width() / mThumbnail.width();
        mScaledTask = new Rect(task);
        Utilities.scaleRectAboutCenter(mScaledTask, mFinalTaskScale);
        Rect finalScaledTaskInsets = new Rect(taskInsets);
        Utilities.scaleRect(finalScaledTaskInsets, mFinalTaskScale);
        mTargetTask = new Rect(mInsetWindow);
        mTargetTask.offsetTo(window.left + insets.left - finalScaledTaskInsets.left,
                window.top + insets.top - finalScaledTaskInsets.top);

        float initialWinScale = 1f / mFinalTaskScale;
        Rect scaledWindow = new Rect(mInsetWindow);
        Utilities.scaleRectAboutCenter(scaledWindow, initialWinScale);
        Rect scaledInsets = new Rect(insets);
        Utilities.scaleRect(scaledInsets, initialWinScale);
        mSrcWindow = new Rect(scaledWindow);
        mSrcWindow.offsetTo(mThumbnail.left - scaledInsets.left,
                mThumbnail.top - scaledInsets.top);
    }

    public TaskWindowBounds interpolate(float t) {
        mTmpTaskWindowBounds.taskScale = Utilities.mapRange(t,
                mInitialTaskScale, mFinalTaskScale);
        mTmpTaskWindowBounds.taskX = Utilities.mapRange(t,
                mInitialTaskTranslationX, mTargetTask.left - mScaledTask.left);
        mTmpTaskWindowBounds.taskY = Utilities.mapRange(t,
                0, mTargetTask.top - mScaledTask.top);

        float taskScale = Utilities.mapRange(t, 1, mFinalTaskScale);
        mTmpTaskWindowBounds.winScale = taskScale / mFinalTaskScale;
        mTmpTaskWindowBounds.winX = Utilities.mapRange(t,
                mSrcWindow.left, 0);
        mTmpTaskWindowBounds.winY = Utilities.mapRange(t,
                mSrcWindow.top, 0);

        mTmpInsets.set(mInsets);
        Utilities.scaleRect(mTmpInsets, (1f - t));
        mTmpTaskWindowBounds.winCrop.set(mWindow);
        Utilities.insetRect(mTmpTaskWindowBounds.winCrop, mTmpInsets);

        return mTmpTaskWindowBounds;
    }
}