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.graphics.Outline;
20import android.graphics.Rect;
21import android.view.View;
22import android.view.ViewDebug;
23import android.view.ViewOutlineProvider;
24
25import com.android.systemui.recents.misc.Utilities;
26
27/* An outline provider that has a clip and outline that can be animated. */
28public class AnimateableViewBounds extends ViewOutlineProvider {
29
30    private static final float MIN_ALPHA = 0.1f;
31    private static final float MAX_ALPHA = 0.8f;
32
33    View mSourceView;
34    @ViewDebug.ExportedProperty(category="recents")
35    Rect mClipRect = new Rect();
36    @ViewDebug.ExportedProperty(category="recents")
37    Rect mClipBounds = new Rect();
38    @ViewDebug.ExportedProperty(category="recents")
39    Rect mLastClipBounds = new Rect();
40    @ViewDebug.ExportedProperty(category="recents")
41    int mCornerRadius;
42    @ViewDebug.ExportedProperty(category="recents")
43    float mAlpha = 1f;
44
45    public AnimateableViewBounds(View source, int cornerRadius) {
46        mSourceView = source;
47        mCornerRadius = cornerRadius;
48    }
49
50    /**
51     * Resets the right and bottom clip for this view.
52     */
53    public void reset() {
54        mClipRect.set(-1, -1, -1, -1);
55        updateClipBounds();
56    }
57
58    @Override
59    public void getOutline(View view, Outline outline) {
60        outline.setAlpha(Utilities.mapRange(mAlpha, MIN_ALPHA, MAX_ALPHA));
61        if (mCornerRadius > 0) {
62            outline.setRoundRect(mClipRect.left, mClipRect.top,
63                    mSourceView.getWidth() - mClipRect.right,
64                    mSourceView.getHeight() - mClipRect.bottom,
65                    mCornerRadius);
66        } else {
67            outline.setRect(mClipRect.left, mClipRect.top,
68                    mSourceView.getWidth() - mClipRect.right,
69                    mSourceView.getHeight() - mClipRect.bottom);
70        }
71    }
72
73    /**
74     * Sets the view outline alpha.
75     */
76    void setAlpha(float alpha) {
77        if (Float.compare(alpha, mAlpha) != 0) {
78            mAlpha = alpha;
79            // TODO, If both clip and alpha change in the same frame, only invalidate once
80            mSourceView.invalidateOutline();
81        }
82    }
83
84    /**
85     * @return the outline alpha.
86     */
87    public float getAlpha() {
88        return mAlpha;
89    }
90
91    /** Sets the top clip. */
92    public void setClipTop(int top) {
93        mClipRect.top = top;
94        updateClipBounds();
95    }
96
97    /** Returns the top clip. */
98    public int getClipTop() {
99        return mClipRect.top;
100    }
101
102    /** Sets the bottom clip. */
103    public void setClipBottom(int bottom) {
104        mClipRect.bottom = bottom;
105        updateClipBounds();
106    }
107
108    /** Returns the bottom clip. */
109    public int getClipBottom() {
110        return mClipRect.bottom;
111    }
112
113    private void updateClipBounds() {
114        mClipBounds.set(Math.max(0, mClipRect.left), Math.max(0, mClipRect.top),
115                mSourceView.getWidth() - Math.max(0, mClipRect.right),
116                mSourceView.getHeight() - Math.max(0, mClipRect.bottom));
117        if (!mLastClipBounds.equals(mClipBounds)) {
118            mSourceView.setClipBounds(mClipBounds);
119            // TODO, If both clip and alpha change in the same frame, only invalidate once
120            mSourceView.invalidateOutline();
121            mLastClipBounds.set(mClipBounds);
122        }
123    }
124}
125