1 /*
2  * Copyright (C) 2023 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 package com.android.systemui.contrast
17 
18 import android.app.UiModeManager
19 import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH
20 import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM
21 import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD
22 import android.app.UiModeManager.ContrastUtils.fromContrastLevel
23 import android.app.UiModeManager.ContrastUtils.toContrastLevel
24 import android.content.Context
25 import android.os.Bundle
26 import android.provider.Settings
27 import android.view.LayoutInflater
28 import android.view.View
29 import android.widget.FrameLayout
30 import com.android.internal.annotations.VisibleForTesting
31 import com.android.systemui.R
32 import com.android.systemui.dagger.qualifiers.Main
33 import com.android.systemui.settings.UserTracker
34 import com.android.systemui.statusbar.phone.SystemUIDialog
35 import com.android.systemui.util.settings.SecureSettings
36 import java.util.concurrent.Executor
37 
38 /** Dialog to select contrast options */
39 class ContrastDialog(
40     context: Context?,
41     @Main private val mainExecutor: Executor,
42     private val uiModeManager: UiModeManager,
43     private val userTracker: UserTracker,
44     private val secureSettings: SecureSettings,
45 ) : SystemUIDialog(context), UiModeManager.ContrastChangeListener {
46 
47     @VisibleForTesting lateinit var contrastButtons: Map<Int, FrameLayout>
48     lateinit var dialogView: View
49     @VisibleForTesting var initialContrast: Float = fromContrastLevel(CONTRAST_LEVEL_STANDARD)
50 
51     public override fun onCreate(savedInstanceState: Bundle?) {
52         dialogView = LayoutInflater.from(context).inflate(R.layout.contrast_dialog, null)
53         setView(dialogView)
54 
55         setTitle(R.string.quick_settings_contrast_label)
56         setNeutralButton(R.string.cancel) { _, _ ->
57             secureSettings.putFloatForUser(
58                 Settings.Secure.CONTRAST_LEVEL,
59                 initialContrast,
60                 userTracker.userId
61             )
62             dismiss()
63         }
64         setPositiveButton(R.string.done) { _, _ -> dismiss() }
65         super.onCreate(savedInstanceState)
66 
67         contrastButtons =
68             mapOf(
69                 CONTRAST_LEVEL_STANDARD to requireViewById(R.id.contrast_button_standard),
70                 CONTRAST_LEVEL_MEDIUM to requireViewById(R.id.contrast_button_medium),
71                 CONTRAST_LEVEL_HIGH to requireViewById(R.id.contrast_button_high)
72             )
73 
74         contrastButtons.forEach { (contrastLevel, contrastButton) ->
75             contrastButton.setOnClickListener {
76                 val contrastValue = fromContrastLevel(contrastLevel)
77                 secureSettings.putFloatForUser(
78                     Settings.Secure.CONTRAST_LEVEL,
79                     contrastValue,
80                     userTracker.userId
81                 )
82             }
83         }
84 
85         initialContrast = uiModeManager.contrast
86         highlightContrast(toContrastLevel(initialContrast))
87     }
88 
89     override fun start() {
90         uiModeManager.addContrastChangeListener(mainExecutor, this)
91     }
92 
93     override fun stop() {
94         uiModeManager.removeContrastChangeListener(this)
95     }
96 
97     override fun onContrastChanged(contrast: Float) {
98         highlightContrast(toContrastLevel(contrast))
99     }
100 
101     private fun highlightContrast(contrast: Int) {
102         contrastButtons.forEach { (level, button) -> button.isSelected = level == contrast }
103     }
104 }
105