• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 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.customization.picker.settings.ui.binder
18 
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.util.Log
23 import android.view.View
24 import android.widget.ImageView
25 import android.widget.TextView
26 import androidx.core.view.isVisible
27 import androidx.lifecycle.LifecycleOwner
28 import com.android.themepicker.R
29 import com.android.wallpaper.picker.common.text.ui.viewbinder.TextViewBinder
30 import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
31 import com.android.wallpaper.picker.customization.ui.binder.ColorUpdateBinder
32 import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel
33 
34 object ColorContrastSectionViewBinder2 {
35 
36     private const val TAG = "ColorContrastSectionViewBinder2"
37 
38     interface Binding {
39         /** Destroys the binding in spite of lifecycle state. */
40         fun destroy()
41     }
42 
43     fun bind(
44         view: View,
45         contrast: Int,
46         colorUpdateViewModel: ColorUpdateViewModel,
47         shouldAnimateColor: () -> Boolean,
48         lifecycleOwner: LifecycleOwner,
49     ): Binding {
50 
51         val descriptionView: TextView = view.requireViewById(R.id.option_entry_description)
52         val iconInner: ImageView = view.requireViewById(R.id.option_entry_icon_inner_part)
53         val iconOuter: ImageView = view.requireViewById(R.id.option_entry_icon_outer_part)
54 
55         // Bind outer and inner parts of the contrast icon separately. Use the same material color
56         // tokens despite contrast level because the tokens adjust according to contrast thanks to
57         // dynamic color magic.
58         val bindingOuter: ColorUpdateBinder.Binding =
59             ColorUpdateBinder.bind(
60                 setColor = { color -> iconOuter.setColorFilter(color) },
61                 color = colorUpdateViewModel.colorPrimaryContainer,
62                 shouldAnimate = shouldAnimateColor,
63                 lifecycleOwner = lifecycleOwner,
64             )
65         val bindingInner: ColorUpdateBinder.Binding =
66             ColorUpdateBinder.bind(
67                 setColor = { color -> iconInner.setColorFilter(color) },
68                 color = colorUpdateViewModel.colorPrimary,
69                 shouldAnimate = shouldAnimateColor,
70                 lifecycleOwner = lifecycleOwner,
71             )
72 
73         TextViewBinder.bind(
74             view = descriptionView,
75             viewModel =
76                 when (contrast) {
77                     CONTRAST_LEVEL_STANDARD -> Text.Resource(R.string.color_contrast_default_title)
78                     CONTRAST_LEVEL_MEDIUM -> Text.Resource(R.string.color_contrast_medium_title)
79                     CONTRAST_LEVEL_HIGH -> Text.Resource(R.string.color_contrast_high_title)
80                     else -> {
81                         iconInner.isVisible = false
82                         iconOuter.isVisible = false
83                         Log.e(TAG, "Invalid contrast value: $contrast")
84                         throw IllegalArgumentException("Invalid contrast value: $contrast")
85                     }
86                 },
87         )
88 
89         return object : Binding {
90             override fun destroy() {
91                 bindingInner.destroy()
92                 bindingOuter.destroy()
93             }
94         }
95     }
96 }
97