1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.recents.views;
18
19import android.animation.Animator;
20import android.animation.ObjectAnimator;
21import android.animation.PropertyValuesHolder;
22import android.graphics.Rect;
23import android.graphics.RectF;
24import android.util.IntProperty;
25import android.util.Property;
26import android.view.View;
27
28import com.android.systemui.recents.misc.Utilities;
29
30import java.util.ArrayList;
31
32/**
33 * The visual properties for a {@link TaskView}.
34 */
35public class TaskViewTransform {
36
37    public static final Property<View, Rect> LTRB =
38            new Property<View, Rect>(Rect.class, "leftTopRightBottom") {
39
40                private Rect mTmpRect = new Rect();
41
42                @Override
43                public void set(View v, Rect ltrb) {
44                    v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom);
45                }
46
47                @Override
48                public Rect get(View v) {
49                    mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
50                    return mTmpRect;
51                }
52            };
53
54    public float translationZ = 0;
55    public float scale = 1f;
56    public float alpha = 1f;
57    public float dimAlpha = 0f;
58    public float viewOutlineAlpha = 0f;
59
60    public boolean visible = false;
61
62    // This is a window-space rect used for positioning the task in the stack and freeform workspace
63    public RectF rect = new RectF();
64
65    /**
66     * Fills int this transform from the state of the given TaskView.
67     */
68    public void fillIn(TaskView tv) {
69        translationZ = tv.getTranslationZ();
70        scale = tv.getScaleX();
71        alpha = tv.getAlpha();
72        visible = true;
73        dimAlpha = tv.getDimAlpha();
74        viewOutlineAlpha = tv.getViewBounds().getAlpha();
75        rect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
76    }
77
78    /**
79     * Copies the transform state from another {@link TaskViewTransform}.
80     */
81    public void copyFrom(TaskViewTransform other) {
82        translationZ = other.translationZ;
83        scale = other.scale;
84        alpha = other.alpha;
85        visible = other.visible;
86        dimAlpha = other.dimAlpha;
87        viewOutlineAlpha = other.viewOutlineAlpha;
88        rect.set(other.rect);
89    }
90
91    /**
92     * @return whether {@param other} is the same transform as this
93     */
94    public boolean isSame(TaskViewTransform other) {
95        return translationZ == other.translationZ
96                && scale == other.scale
97                && other.alpha == alpha
98                && dimAlpha == other.dimAlpha
99                && visible == other.visible
100                && rect.equals(other.rect);
101    }
102
103    /**
104     * Resets the current transform.
105     */
106    public void reset() {
107        translationZ = 0;
108        scale = 1f;
109        alpha = 1f;
110        dimAlpha = 0f;
111        viewOutlineAlpha = 0f;
112        visible = false;
113        rect.setEmpty();
114    }
115
116    /** Convenience functions to compare against current property values */
117    public boolean hasAlphaChangedFrom(float v) {
118        return (Float.compare(alpha, v) != 0);
119    }
120
121    public boolean hasScaleChangedFrom(float v) {
122        return (Float.compare(scale, v) != 0);
123    }
124
125    public boolean hasTranslationZChangedFrom(float v) {
126        return (Float.compare(translationZ, v) != 0);
127    }
128
129    public boolean hasRectChangedFrom(View v) {
130        return ((int) rect.left != v.getLeft()) || ((int) rect.right != v.getRight()) ||
131                ((int) rect.top != v.getTop()) || ((int) rect.bottom != v.getBottom());
132    }
133
134    /**
135     * Applies this transform to a view.
136     */
137    public void applyToTaskView(TaskView v, ArrayList<Animator> animators,
138            AnimationProps animation, boolean allowShadows) {
139        // Return early if not visible
140        if (!visible) {
141            return;
142        }
143
144        if (animation.isImmediate()) {
145            if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
146                v.setTranslationZ(translationZ);
147            }
148            if (hasScaleChangedFrom(v.getScaleX())) {
149                v.setScaleX(scale);
150                v.setScaleY(scale);
151            }
152            if (hasAlphaChangedFrom(v.getAlpha())) {
153                v.setAlpha(alpha);
154            }
155            if (hasRectChangedFrom(v)) {
156                v.setLeftTopRightBottom((int) rect.left, (int) rect.top, (int) rect.right,
157                        (int) rect.bottom);
158            }
159        } else {
160            if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
161                ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.TRANSLATION_Z,
162                        v.getTranslationZ(), translationZ);
163                animators.add(animation.apply(AnimationProps.TRANSLATION_Z, anim));
164            }
165            if (hasScaleChangedFrom(v.getScaleX())) {
166                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
167                        PropertyValuesHolder.ofFloat(View.SCALE_X, v.getScaleX(), scale),
168                        PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale));
169                animators.add(animation.apply(AnimationProps.SCALE, anim));
170            }
171            if (hasAlphaChangedFrom(v.getAlpha())) {
172                ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha);
173                animators.add(animation.apply(AnimationProps.ALPHA, anim));
174            }
175            if (hasRectChangedFrom(v)) {
176                Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
177                Rect toViewRect = new Rect();
178                rect.round(toViewRect);
179                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
180                        PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR,
181                                fromViewRect, toViewRect));
182                animators.add(animation.apply(AnimationProps.BOUNDS, anim));
183            }
184        }
185    }
186
187    /** Reset the transform on a view. */
188    public static void reset(TaskView v) {
189        v.setTranslationX(0f);
190        v.setTranslationY(0f);
191        v.setTranslationZ(0f);
192        v.setScaleX(1f);
193        v.setScaleY(1f);
194        v.setAlpha(1f);
195        v.getViewBounds().setClipBottom(0);
196        v.setLeftTopRightBottom(0, 0, 0, 0);
197    }
198
199    @Override
200    public String toString() {
201        return "R: " + rect + " V: " + visible;
202    }
203}
204