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 /**
77 * Interface to facilitate moving controls from an [AccessibilityDelegate].
78 *
79 * All positions should be 0 based.
80 */
81 interface MoveHelper {
82
83 /**
84 * Whether the control in `position` can be moved to the position before it.
85 */
86 fun canMoveBefore(position: Int): Boolean
87
88 /**
89 * Whether the control in `position` can be moved to the position after it.
90 */
91 fun canMoveAfter(position: Int): Boolean
92
93 /**
94 * Move the control in `position` to the position before it.
95 */
96 fun moveBefore(position: Int)
97
98 /**
99 * Move the control in `position` to the position after it.
100 */
101 fun moveAfter(position: Int)
102 }
103 }
104
105 /**
106 * Wrapper classes for the different types of elements shown in the [RecyclerView]s in
107 * [ControlAdapter].
108 */
109 sealed class ElementWrapper
110
111 data class ZoneNameWrapper(val zoneName: CharSequence) : ElementWrapper()
112
113 data class ControlStatusWrapper(
114 val controlStatus: ControlStatus
115 ) : ElementWrapper(), ControlInterface by controlStatus
116
117 @Suppress("UNUSED_PARAMETER") // Use function instead of lambda for compile time alloc
nullIconGetternull118 private fun nullIconGetter(_a: ComponentName, _b: String): Icon? = null
119
120 data class ControlInfoWrapper(
121 override val component: ComponentName,
122 val controlInfo: ControlInfo,
123 override var favorite: Boolean
124 ) : ElementWrapper(), ControlInterface {
125
126 var customIconGetter: (ComponentName, String) -> Icon? = ::nullIconGetter
127 private set
128
129 // Separate constructor so the getter is not used in auto-generated methods
130 constructor(
131 component: ComponentName,
132 controlInfo: ControlInfo,
133 favorite: Boolean,
134 customIconGetter: (ComponentName, String) -> Icon?
135 ): this(component, controlInfo, favorite) {
136 this.customIconGetter = customIconGetter
137 }
138
139 override val controlId: String
140 get() = controlInfo.controlId
141 override val title: CharSequence
142 get() = controlInfo.controlTitle
143 override val subtitle: CharSequence
144 get() = controlInfo.controlSubtitle
145 override val deviceType: Int
146 get() = controlInfo.deviceType
147 override val customIcon: Icon?
148 get() = customIconGetter(component, controlId)
149 }
150
151 data class DividerWrapper(
152 var showNone: Boolean = false,
153 var showDivider: Boolean = false
154 ) : ElementWrapper()
155