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.policy;
18
19import android.annotation.NonNull;
20import android.content.res.Resources;
21import android.util.ArraySet;
22import android.view.ContextThemeWrapper;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.widget.FrameLayout;
26
27import com.android.internal.util.Preconditions;
28import com.android.systemui.R;
29import com.android.systemui.statusbar.phone.NotificationPanelView;
30import com.android.systemui.statusbar.phone.StatusBarWindowView;
31
32import java.util.function.Consumer;
33
34/**
35 * Controls showing and hiding of the brightness mirror.
36 */
37public class BrightnessMirrorController
38        implements CallbackController<BrightnessMirrorController.BrightnessMirrorListener> {
39
40    private final StatusBarWindowView mStatusBarWindow;
41    private final Consumer<Boolean> mVisibilityCallback;
42    private final NotificationPanelView mNotificationPanel;
43    private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
44    private final int[] mInt2Cache = new int[2];
45    private View mBrightnessMirror;
46
47    public BrightnessMirrorController(StatusBarWindowView statusBarWindow,
48            @NonNull Consumer<Boolean> visibilityCallback) {
49        mStatusBarWindow = statusBarWindow;
50        mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
51        mNotificationPanel = statusBarWindow.findViewById(R.id.notification_panel);
52        mNotificationPanel.setPanelAlphaEndAction(() -> {
53            mBrightnessMirror.setVisibility(View.INVISIBLE);
54        });
55        mVisibilityCallback = visibilityCallback;
56    }
57
58    public void showMirror() {
59        mBrightnessMirror.setVisibility(View.VISIBLE);
60        mVisibilityCallback.accept(true);
61        mNotificationPanel.setPanelAlpha(0, true /* animate */);
62    }
63
64    public void hideMirror() {
65        mVisibilityCallback.accept(false);
66        mNotificationPanel.setPanelAlpha(255, true /* animate */);
67    }
68
69    public void setLocation(View original) {
70        original.getLocationInWindow(mInt2Cache);
71
72        // Original is slightly larger than the mirror, so make sure to use the center for the
73        // positioning.
74        int originalX = mInt2Cache[0] + original.getWidth() / 2;
75        int originalY = mInt2Cache[1] + original.getHeight() / 2;
76        mBrightnessMirror.setTranslationX(0);
77        mBrightnessMirror.setTranslationY(0);
78        mBrightnessMirror.getLocationInWindow(mInt2Cache);
79        int mirrorX = mInt2Cache[0] + mBrightnessMirror.getWidth() / 2;
80        int mirrorY = mInt2Cache[1] + mBrightnessMirror.getHeight() / 2;
81        mBrightnessMirror.setTranslationX(originalX - mirrorX);
82        mBrightnessMirror.setTranslationY(originalY - mirrorY);
83    }
84
85    public View getMirror() {
86        return mBrightnessMirror;
87    }
88
89    public void updateResources() {
90        FrameLayout.LayoutParams lp =
91                (FrameLayout.LayoutParams) mBrightnessMirror.getLayoutParams();
92        Resources r = mBrightnessMirror.getResources();
93        lp.width = r.getDimensionPixelSize(R.dimen.qs_panel_width);
94        lp.height = r.getDimensionPixelSize(R.dimen.brightness_mirror_height);
95        lp.gravity = r.getInteger(R.integer.notification_panel_layout_gravity);
96        mBrightnessMirror.setLayoutParams(lp);
97    }
98
99    public void onOverlayChanged() {
100        reinflate();
101    }
102
103    public void onDensityOrFontScaleChanged() {
104        reinflate();
105    }
106
107    private void reinflate() {
108        ContextThemeWrapper qsThemeContext =
109                new ContextThemeWrapper(mBrightnessMirror.getContext(), R.style.qs_theme);
110        int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
111        mStatusBarWindow.removeView(mBrightnessMirror);
112        mBrightnessMirror = LayoutInflater.from(qsThemeContext).inflate(
113                R.layout.brightness_mirror, mStatusBarWindow, false);
114        mStatusBarWindow.addView(mBrightnessMirror, index);
115
116        for (int i = 0; i < mBrightnessMirrorListeners.size(); i++) {
117            mBrightnessMirrorListeners.valueAt(i).onBrightnessMirrorReinflated(mBrightnessMirror);
118        }
119    }
120
121    @Override
122    public void addCallback(BrightnessMirrorListener listener) {
123        Preconditions.checkNotNull(listener);
124        mBrightnessMirrorListeners.add(listener);
125    }
126
127    @Override
128    public void removeCallback(BrightnessMirrorListener listener) {
129        mBrightnessMirrorListeners.remove(listener);
130    }
131
132    public interface BrightnessMirrorListener {
133        void onBrightnessMirrorReinflated(View brightnessMirror);
134    }
135}
136