1 /*
2  * Copyright (C) 2018 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 
17 package com.android.systemui.statusbar.stack;
18 
19 import android.view.View;
20 
21 import com.android.systemui.statusbar.ActivatableNotificationView;
22 import com.android.systemui.statusbar.ExpandableNotificationRow;
23 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
24 
25 import java.util.HashSet;
26 
27 /**
28  * A class that manages the roundness for notification views
29  */
30 class NotificationRoundnessManager implements OnHeadsUpChangedListener {
31 
32     private boolean mExpanded;
33     private ActivatableNotificationView mFirst;
34     private ActivatableNotificationView mLast;
35     private HashSet<View> mAnimatedChildren;
36     private Runnable mRoundingChangedCallback;
37     private ExpandableNotificationRow mTrackedHeadsUp;
38     private float mAppearFraction;
39 
40     @Override
onHeadsUpPinned(ExpandableNotificationRow headsUp)41     public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
42         updateRounding(headsUp, false /* animate */);
43     }
44 
45     @Override
onHeadsUpUnPinned(ExpandableNotificationRow headsUp)46     public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
47         updateRounding(headsUp, true /* animate */);
48     }
49 
onHeadsupAnimatingAwayChanged(ExpandableNotificationRow row, boolean isAnimatingAway)50     public void onHeadsupAnimatingAwayChanged(ExpandableNotificationRow row,
51             boolean isAnimatingAway) {
52         updateRounding(row, false /* animate */);
53     }
54 
updateRounding(ActivatableNotificationView view, boolean animate)55     private void updateRounding(ActivatableNotificationView view, boolean animate) {
56         float topRoundness = getRoundness(view, true /* top */);
57         float bottomRoundness = getRoundness(view, false /* top */);
58         boolean firstChanged = view.setTopRoundness(topRoundness, animate);
59         boolean secondChanged = view.setBottomRoundness(bottomRoundness, animate);
60         if ((view == mFirst || view == mLast) && (firstChanged || secondChanged)) {
61             mRoundingChangedCallback.run();
62         }
63     }
64 
getRoundness(ActivatableNotificationView view, boolean top)65     private float getRoundness(ActivatableNotificationView view, boolean top) {
66         if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
67             return 1.0f;
68         }
69         if (view == mFirst && top) {
70             return 1.0f;
71         }
72         if (view == mLast && !top) {
73             return 1.0f;
74         }
75         if (view == mTrackedHeadsUp && mAppearFraction <= 0.0f) {
76             // If we're pushing up on a headsup the appear fraction is < 0 and it needs to still be
77             // rounded.
78             return 1.0f;
79         }
80         return 0.0f;
81     }
82 
setExpanded(float expandedHeight, float appearFraction)83     public void setExpanded(float expandedHeight, float appearFraction) {
84         mExpanded = expandedHeight != 0.0f;
85         mAppearFraction = appearFraction;
86         if (mTrackedHeadsUp != null) {
87             updateRounding(mTrackedHeadsUp, true);
88         }
89     }
90 
setFirstAndLastBackgroundChild(ActivatableNotificationView first, ActivatableNotificationView last)91     public void setFirstAndLastBackgroundChild(ActivatableNotificationView first,
92             ActivatableNotificationView last) {
93         boolean firstChanged = mFirst != first;
94         boolean lastChanged = mLast != last;
95         if (!firstChanged && !lastChanged) {
96             return;
97         }
98         ActivatableNotificationView oldFirst = mFirst;
99         ActivatableNotificationView oldLast = mLast;
100         mFirst = first;
101         mLast = last;
102         if (firstChanged && oldFirst != null && !oldFirst.isRemoved()) {
103             updateRounding(oldFirst, oldFirst.isShown());
104         }
105         if (lastChanged && oldLast != null && !oldLast.isRemoved()) {
106             updateRounding(oldLast, oldLast.isShown());
107         }
108         if (mFirst != null) {
109             updateRounding(mFirst, mFirst.isShown() && !mAnimatedChildren.contains(mFirst));
110         }
111         if (mLast != null) {
112             updateRounding(mLast, mLast.isShown() && !mAnimatedChildren.contains(mLast));
113         }
114         mRoundingChangedCallback.run();
115     }
116 
setAnimatedChildren(HashSet<View> animatedChildren)117     public void setAnimatedChildren(HashSet<View> animatedChildren) {
118         mAnimatedChildren = animatedChildren;
119     }
120 
setOnRoundingChangedCallback(Runnable roundingChangedCallback)121     public void setOnRoundingChangedCallback(Runnable roundingChangedCallback) {
122         mRoundingChangedCallback = roundingChangedCallback;
123     }
124 
setTrackingHeadsUp(ExpandableNotificationRow row)125     public void setTrackingHeadsUp(ExpandableNotificationRow row) {
126         mTrackedHeadsUp = row;
127     }
128 }
129