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.statusbar;
18
19import android.content.Context;
20import android.content.res.ColorStateList;
21import android.graphics.Canvas;
22import android.graphics.PorterDuff;
23import android.graphics.drawable.Drawable;
24import android.graphics.drawable.RippleDrawable;
25import android.util.AttributeSet;
26import android.view.View;
27
28/**
29 * A view that can be used for both the dimmed and normal background of an notification.
30 */
31public class NotificationBackgroundView extends View {
32
33    private Drawable mBackground;
34    private int mClipTopAmount;
35    private int mActualHeight;
36    private int mClipBottomAmount;
37
38    public NotificationBackgroundView(Context context, AttributeSet attrs) {
39        super(context, attrs);
40    }
41
42    @Override
43    protected void onDraw(Canvas canvas) {
44        draw(canvas, mBackground);
45    }
46
47    private void draw(Canvas canvas, Drawable drawable) {
48        int bottom = mActualHeight - mClipBottomAmount;
49        if (drawable != null && bottom > mClipTopAmount) {
50            drawable.setBounds(0, mClipTopAmount, getWidth(), bottom);
51            drawable.draw(canvas);
52        }
53    }
54
55    @Override
56    protected boolean verifyDrawable(Drawable who) {
57        return super.verifyDrawable(who) || who == mBackground;
58    }
59
60    @Override
61    protected void drawableStateChanged() {
62        drawableStateChanged(mBackground);
63    }
64
65    private void drawableStateChanged(Drawable d) {
66        if (d != null && d.isStateful()) {
67            d.setState(getDrawableState());
68        }
69    }
70
71    @Override
72    public void drawableHotspotChanged(float x, float y) {
73        if (mBackground != null) {
74            mBackground.setHotspot(x, y);
75        }
76    }
77
78    /**
79     * Sets a background drawable. As we need to change our bounds independently of layout, we need
80     * the notion of a background independently of the regular View background..
81     */
82    public void setCustomBackground(Drawable background) {
83        if (mBackground != null) {
84            mBackground.setCallback(null);
85            unscheduleDrawable(mBackground);
86        }
87        mBackground = background;
88        if (mBackground != null) {
89            mBackground.setCallback(this);
90        }
91        if (mBackground instanceof RippleDrawable) {
92            ((RippleDrawable) mBackground).setForceSoftware(true);
93        }
94        invalidate();
95    }
96
97    public void setCustomBackground(int drawableResId) {
98        final Drawable d = mContext.getDrawable(drawableResId);
99        setCustomBackground(d);
100    }
101
102    public void setTint(int tintColor) {
103        if (tintColor != 0) {
104            mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
105        } else {
106            mBackground.clearColorFilter();
107        }
108        invalidate();
109    }
110
111    public void setActualHeight(int actualHeight) {
112        mActualHeight = actualHeight;
113        invalidate();
114    }
115
116    public int getActualHeight() {
117        return mActualHeight;
118    }
119
120    public void setClipTopAmount(int clipTopAmount) {
121        mClipTopAmount = clipTopAmount;
122        invalidate();
123    }
124
125    public void setClipBottomAmount(int clipBottomAmount) {
126        mClipBottomAmount = clipBottomAmount;
127        invalidate();
128    }
129
130    @Override
131    public boolean hasOverlappingRendering() {
132
133        // Prevents this view from creating a layer when alpha is animating.
134        return false;
135    }
136
137    public void setState(int[] drawableState) {
138        mBackground.setState(drawableState);
139    }
140
141    public void setRippleColor(int color) {
142        if (mBackground instanceof RippleDrawable) {
143            RippleDrawable ripple = (RippleDrawable) mBackground;
144            ripple.setColor(ColorStateList.valueOf(color));
145        }
146    }
147
148    public void setDrawableAlpha(int drawableAlpha) {
149        mBackground.setAlpha(drawableAlpha);
150    }
151}
152