1 /*
2  * Copyright (C) 2024 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.systemui.communal.widgets
18 
19 import android.appwidget.AppWidgetHostView
20 import android.appwidget.AppWidgetProviderInfo
21 import android.content.Context
22 import android.graphics.Outline
23 import android.graphics.Rect
24 import android.view.View
25 import android.view.ViewOutlineProvider
26 import com.android.systemui.animation.LaunchableView
27 import com.android.systemui.animation.LaunchableViewDelegate
28 
29 /** AppWidgetHostView that displays in communal hub with support for rounded corners. */
30 class CommunalAppWidgetHostView(context: Context) : AppWidgetHostView(context), LaunchableView {
31     private val launchableViewDelegate =
32         LaunchableViewDelegate(
33             this,
<lambda>null34             superSetVisibility = { super.setVisibility(it) },
35         )
36 
37     // Mutable corner radius.
38     var enforcedCornerRadius: Float
39 
40     // Mutable `Rect`. The size will be mutated when the widget is reapplied.
41     var enforcedRectangle: Rect
42 
43     init {
44         enforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context)
45         enforcedRectangle = Rect()
46     }
47 
onLayoutnull48     override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
49         super.onLayout(changed, l, t, r, b)
50 
51         enforceRoundedCorners()
52     }
53 
setAppWidgetnull54     override fun setAppWidget(appWidgetId: Int, info: AppWidgetProviderInfo?) {
55         super.setAppWidget(appWidgetId, info)
56         setPadding(0, 0, 0, 0)
57     }
58 
59     private val cornerRadiusEnforcementOutline: ViewOutlineProvider =
60         object : ViewOutlineProvider() {
getOutlinenull61             override fun getOutline(view: View?, outline: Outline) {
62                 if (enforcedRectangle.isEmpty || enforcedCornerRadius <= 0) {
63                     outline.setEmpty()
64                 } else {
65                     outline.setRoundRect(enforcedRectangle, enforcedCornerRadius)
66                 }
67             }
68         }
69 
enforceRoundedCornersnull70     private fun enforceRoundedCorners() {
71         if (enforcedCornerRadius <= 0) {
72             resetRoundedCorners()
73             return
74         }
75         val background: View? = RoundedCornerEnforcement.findBackground(this)
76         if (background == null || RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
77             resetRoundedCorners()
78             return
79         }
80         RoundedCornerEnforcement.computeRoundedRectangle(this, background, enforcedRectangle)
81         outlineProvider = cornerRadiusEnforcementOutline
82         clipToOutline = true
83         invalidateOutline()
84     }
85 
resetRoundedCornersnull86     private fun resetRoundedCorners() {
87         outlineProvider = ViewOutlineProvider.BACKGROUND
88         clipToOutline = false
89     }
90 
setShouldBlockVisibilityChangesnull91     override fun setShouldBlockVisibilityChanges(block: Boolean) =
92         launchableViewDelegate.setShouldBlockVisibilityChanges(block)
93 
94     override fun setVisibility(visibility: Int) = launchableViewDelegate.setVisibility(visibility)
95 }
96