1 /*
<lambda>null2 * 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 */
17
18 package com.android.systemui.keyguard.ui.view.layout.sections
19
20 import android.content.Context
21 import android.view.View
22 import androidx.constraintlayout.widget.Barrier
23 import androidx.constraintlayout.widget.ConstraintLayout
24 import androidx.constraintlayout.widget.ConstraintSet
25 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
26 import androidx.constraintlayout.widget.ConstraintSet.END
27 import androidx.constraintlayout.widget.ConstraintSet.GONE
28 import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
29 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
30 import androidx.constraintlayout.widget.ConstraintSet.START
31 import androidx.constraintlayout.widget.ConstraintSet.TOP
32 import androidx.constraintlayout.widget.ConstraintSet.VISIBLE
33 import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
34 import com.android.systemui.customization.R as custR
35 import com.android.systemui.dagger.SysUISingleton
36 import com.android.systemui.keyguard.MigrateClocksToBlueprint
37 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
38 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
39 import com.android.systemui.keyguard.shared.model.KeyguardSection
40 import com.android.systemui.keyguard.ui.binder.KeyguardClockViewBinder
41 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
42 import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
43 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
44 import com.android.systemui.plugins.clocks.ClockController
45 import com.android.systemui.plugins.clocks.ClockFaceLayout
46 import com.android.systemui.res.R
47 import com.android.systemui.shared.R as sharedR
48 import dagger.Lazy
49 import javax.inject.Inject
50
51 internal fun ConstraintSet.setVisibility(
52 views: Iterable<View>,
53 visibility: Int,
54 ) = views.forEach { view -> this.setVisibility(view.id, visibility) }
55
setAlphanull56 internal fun ConstraintSet.setAlpha(
57 views: Iterable<View>,
58 alpha: Float,
59 ) = views.forEach { view -> this.setAlpha(view.id, alpha) }
60
61 @SysUISingleton
62 class ClockSection
63 @Inject
64 constructor(
65 private val clockInteractor: KeyguardClockInteractor,
66 protected val keyguardClockViewModel: KeyguardClockViewModel,
67 private val context: Context,
68 val smartspaceViewModel: KeyguardSmartspaceViewModel,
69 val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
70 private val rootViewModel: KeyguardRootViewModel,
71 ) : KeyguardSection() {
addViewsnull72 override fun addViews(constraintLayout: ConstraintLayout) {}
bindDatanull73 override fun bindData(constraintLayout: ConstraintLayout) {
74 if (!MigrateClocksToBlueprint.isEnabled) {
75 return
76 }
77
78 KeyguardClockViewBinder.bind(
79 this,
80 constraintLayout,
81 keyguardClockViewModel,
82 clockInteractor,
83 blueprintInteractor.get(),
84 rootViewModel,
85 )
86 }
87
applyConstraintsnull88 override fun applyConstraints(constraintSet: ConstraintSet) {
89 if (!MigrateClocksToBlueprint.isEnabled) {
90 return
91 }
92
93 keyguardClockViewModel.currentClock.value?.let { clock ->
94 constraintSet.applyDeltaFrom(buildConstraints(clock, constraintSet))
95 }
96 }
97
removeViewsnull98 override fun removeViews(constraintLayout: ConstraintLayout) {}
99
buildConstraintsnull100 private fun buildConstraints(
101 clock: ClockController,
102 constraintSet: ConstraintSet
103 ): ConstraintSet {
104 // Add constraint between rootView and clockContainer
105 applyDefaultConstraints(constraintSet)
106 getNonTargetClockFace(clock).applyConstraints(constraintSet)
107 getTargetClockFace(clock).applyConstraints(constraintSet)
108
109 // Add constraint between elements in clock and clock container
110 return constraintSet.apply {
111 setVisibility(getTargetClockFace(clock).views, VISIBLE)
112 setVisibility(getNonTargetClockFace(clock).views, GONE)
113 setAlpha(getTargetClockFace(clock).views, 1F)
114 setAlpha(getNonTargetClockFace(clock).views, 0F)
115 if (!keyguardClockViewModel.isLargeClockVisible.value) {
116 connect(sharedR.id.bc_smartspace_view, TOP, sharedR.id.date_smartspace_view, BOTTOM)
117 }
118 }
119 }
120
getTargetClockFacenull121 private fun getTargetClockFace(clock: ClockController): ClockFaceLayout =
122 if (keyguardClockViewModel.isLargeClockVisible.value) clock.largeClock.layout
123 else clock.smallClock.layout
124 private fun getNonTargetClockFace(clock: ClockController): ClockFaceLayout =
125 if (keyguardClockViewModel.isLargeClockVisible.value) clock.smallClock.layout
126 else clock.largeClock.layout
127
128 fun constrainWeatherClockDateIconsBarrier(constraints: ConstraintSet) {
129 constraints.apply {
130 if (keyguardClockViewModel.isAodIconsVisible.value) {
131 createBarrier(
132 R.id.weather_clock_date_and_icons_barrier_bottom,
133 Barrier.BOTTOM,
134 0,
135 *intArrayOf(sharedR.id.bc_smartspace_view, R.id.aod_notification_icon_container)
136 )
137 } else {
138 if (smartspaceViewModel.bcSmartspaceVisibility.value == VISIBLE) {
139 createBarrier(
140 R.id.weather_clock_date_and_icons_barrier_bottom,
141 Barrier.BOTTOM,
142 0,
143 (sharedR.id.bc_smartspace_view)
144 )
145 } else {
146 createBarrier(
147 R.id.weather_clock_date_and_icons_barrier_bottom,
148 Barrier.BOTTOM,
149 getDimen(ENHANCED_SMARTSPACE_HEIGHT),
150 (R.id.lockscreen_clock_view)
151 )
152 }
153 }
154 }
155 }
156
applyDefaultConstraintsnull157 open fun applyDefaultConstraints(constraints: ConstraintSet) {
158 val guideline =
159 if (keyguardClockViewModel.clockShouldBeCentered.value) PARENT_ID
160 else R.id.split_shade_guideline
161 constraints.apply {
162 connect(R.id.lockscreen_clock_view_large, START, PARENT_ID, START)
163 connect(R.id.lockscreen_clock_view_large, END, guideline, END)
164 connect(R.id.lockscreen_clock_view_large, BOTTOM, R.id.device_entry_icon_view, TOP)
165 val largeClockTopMargin =
166 keyguardClockViewModel.getLargeClockTopMargin() +
167 getDimen(DATE_WEATHER_VIEW_HEIGHT) +
168 getDimen(ENHANCED_SMARTSPACE_HEIGHT)
169 connect(R.id.lockscreen_clock_view_large, TOP, PARENT_ID, TOP, largeClockTopMargin)
170 constrainWidth(R.id.lockscreen_clock_view_large, WRAP_CONTENT)
171 constrainHeight(R.id.lockscreen_clock_view_large, MATCH_CONSTRAINT)
172 constrainWidth(R.id.lockscreen_clock_view, WRAP_CONTENT)
173 constrainHeight(
174 R.id.lockscreen_clock_view,
175 context.resources.getDimensionPixelSize(custR.dimen.small_clock_height)
176 )
177 connect(
178 R.id.lockscreen_clock_view,
179 START,
180 PARENT_ID,
181 START,
182 context.resources.getDimensionPixelSize(custR.dimen.clock_padding_start) +
183 context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal)
184 )
185 val smallClockTopMargin = keyguardClockViewModel.getSmallClockTopMargin()
186 create(R.id.small_clock_guideline_top, ConstraintSet.HORIZONTAL_GUIDELINE)
187 setGuidelineBegin(R.id.small_clock_guideline_top, smallClockTopMargin)
188 connect(R.id.lockscreen_clock_view, TOP, R.id.small_clock_guideline_top, BOTTOM)
189 }
190
191 constrainWeatherClockDateIconsBarrier(constraints)
192 }
193
getDimennull194 private fun getDimen(name: String): Int {
195 return getDimen(context, name)
196 }
197
198 companion object {
199 private const val DATE_WEATHER_VIEW_HEIGHT = "date_weather_view_height"
200 private const val ENHANCED_SMARTSPACE_HEIGHT = "enhanced_smartspace_height"
getDimennull201 fun getDimen(context: Context, name: String): Int {
202 val res = context.packageManager.getResourcesForApplication(context.packageName)
203 val id = res.getIdentifier(name, "dimen", context.packageName)
204 return if (id == 0) 0 else res.getDimensionPixelSize(id)
205 }
206 }
207 }
208