1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 *      http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.statusbar.phone;
16
17import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
18
19import android.animation.ArgbEvaluator;
20import android.content.Context;
21import android.content.res.ColorStateList;
22import android.graphics.Rect;
23import android.util.ArrayMap;
24import android.widget.ImageView;
25
26import com.android.systemui.R;
27import com.android.systemui.statusbar.policy.DarkIconDispatcher;
28
29public class DarkIconDispatcherImpl implements DarkIconDispatcher {
30
31    private final LightBarTransitionsController mTransitionsController;
32    private final Rect mTintArea = new Rect();
33    private final ArrayMap<Object, DarkReceiver> mReceivers = new ArrayMap<>();
34
35    private int mIconTint = DEFAULT_ICON_TINT;
36    private float mDarkIntensity;
37    private int mDarkModeIconColorSingleTone;
38    private int mLightModeIconColorSingleTone;
39
40    public DarkIconDispatcherImpl(Context context) {
41        mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
42        mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
43
44        mTransitionsController = new LightBarTransitionsController(context,
45                this::setIconTintInternal);
46    }
47
48    public LightBarTransitionsController getTransitionsController() {
49        return mTransitionsController;
50    }
51
52    public void addDarkReceiver(DarkReceiver receiver) {
53        mReceivers.put(receiver, receiver);
54        receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
55    }
56
57    public void addDarkReceiver(ImageView imageView) {
58        DarkReceiver receiver = (area, darkIntensity, tint) -> imageView.setImageTintList(
59                ColorStateList.valueOf(getTint(mTintArea, imageView, mIconTint)));
60        mReceivers.put(imageView, receiver);
61        receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
62    }
63
64    public void removeDarkReceiver(DarkReceiver object) {
65        mReceivers.remove(object);
66    }
67
68    public void removeDarkReceiver(ImageView object) {
69        mReceivers.remove(object);
70    }
71
72    public void applyDark(ImageView object) {
73        mReceivers.get(object).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
74    }
75
76    /**
77     * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
78     *
79     * @param darkArea the area in which icons should change it's tint, in logical screen
80     *                 coordinates
81     */
82    public void setIconsDarkArea(Rect darkArea) {
83        if (darkArea == null && mTintArea.isEmpty()) {
84            return;
85        }
86        if (darkArea == null) {
87            mTintArea.setEmpty();
88        } else {
89            mTintArea.set(darkArea);
90        }
91        applyIconTint();
92    }
93
94    private void setIconTintInternal(float darkIntensity) {
95        mDarkIntensity = darkIntensity;
96        mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
97                mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
98        applyIconTint();
99    }
100
101    private void applyIconTint() {
102        for (int i = 0; i < mReceivers.size(); i++) {
103            mReceivers.valueAt(i).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
104        }
105    }
106}
107