1 /*
2  * Copyright (C) 2019 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.controls.management
18 
19 import android.content.ComponentName
20 import android.graphics.drawable.Icon
21 import androidx.recyclerview.widget.RecyclerView
22 import com.android.systemui.controls.ControlInterface
23 import com.android.systemui.controls.ControlStatus
24 import com.android.systemui.controls.controller.ControlInfo
25 
26 /**
27  * Model for using with [ControlAdapter].
28  *
29  * Implementations of this interface provide different views of the controls to show.
30  */
31 interface ControlsModel {
32 
33     /**
34      * List of favorites in order.
35      *
36      * This should be obtained prior to storing the favorites using
37      * [ControlsController.replaceFavoritesForComponent].
38      */
39     val favorites: List<ControlInfo>
40 
41     /**
42      * List of all the elements to display by the corresponding [RecyclerView].
43      */
44     val elements: List<ElementWrapper>
45 
46     val moveHelper: MoveHelper?
47 
48     /**
49      * Change the favorite status of a particular control.
50      */
changeFavoriteStatusnull51     fun changeFavoriteStatus(controlId: String, favorite: Boolean) {}
52 
53     /**
54      * Move an item (in elements) from one position to another.
55      */
onMoveItemnull56     fun onMoveItem(from: Int, to: Int) {}
57 
58     /**
59      * Attach an adapter to the model.
60      *
61      * This can be used to notify the adapter of changes in the model.
62      */
attachAdapternull63     fun attachAdapter(adapter: RecyclerView.Adapter<*>) {}
64 
65     /**
66      * Callback to notify elements (other than the adapter) of relevant changes in the model.
67      */
68     interface ControlsModelCallback {
69 
70         /**
71          * Use to notify that the model has changed for the first time
72          */
onFirstChangenull73         fun onFirstChange()
74 
75         /**
76          * Use to notify that the model has changed
77          */
78         fun onChange()
79     }
80 
81     /**
82      * Interface to facilitate moving controls from an [AccessibilityDelegate].
83      *
84      * All positions should be 0 based.
85      */
86     interface MoveHelper {
87 
88         /**
89          * Whether the control in `position` can be moved to the position before it.
90          */
91         fun canMoveBefore(position: Int): Boolean
92 
93         /**
94          * Whether the control in `position` can be moved to the position after it.
95          */
96         fun canMoveAfter(position: Int): Boolean
97 
98         /**
99          * Move the control in `position` to the position before it.
100          */
101         fun moveBefore(position: Int)
102 
103         /**
104          * Move the control in `position` to the position after it.
105          */
106         fun moveAfter(position: Int)
107     }
108 }
109 
110 /**
111  * Wrapper classes for the different types of elements shown in the [RecyclerView]s in
112  * [ControlAdapter].
113  */
114 sealed class ElementWrapper
115 
116 data class ZoneNameWrapper(val zoneName: CharSequence) : ElementWrapper()
117 
118 data class ControlStatusWrapper(
119     val controlStatus: ControlStatus
120 ) : ElementWrapper(), ControlInterface by controlStatus
121 
122 @Suppress("UNUSED_PARAMETER") // Use function instead of lambda for compile time alloc
nullIconGetternull123 private fun nullIconGetter(_a: ComponentName, _b: String): Icon? = null
124 
125 data class ControlInfoWrapper(
126     override val component: ComponentName,
127     val controlInfo: ControlInfo,
128     override var favorite: Boolean
129 ) : ElementWrapper(), ControlInterface {
130 
131     var customIconGetter: (ComponentName, String) -> Icon? = ::nullIconGetter
132         private set
133 
134     // Separate constructor so the getter is not used in auto-generated methods
135     constructor(
136         component: ComponentName,
137         controlInfo: ControlInfo,
138         favorite: Boolean,
139         customIconGetter: (ComponentName, String) -> Icon?
140     ) : this(component, controlInfo, favorite) {
141         this.customIconGetter = customIconGetter
142     }
143 
144     override val controlId: String
145         get() = controlInfo.controlId
146     override val title: CharSequence
147         get() = controlInfo.controlTitle
148     override val subtitle: CharSequence
149         get() = controlInfo.controlSubtitle
150     override val deviceType: Int
151         get() = controlInfo.deviceType
152     override val customIcon: Icon?
153         get() = customIconGetter(component, controlId)
154 }
155 
156 data class DividerWrapper(
157     var showNone: Boolean = false,
158     var showDivider: Boolean = false
159 ) : ElementWrapper()
160