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