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 */ 51 fun changeFavoriteStatus(controlId: String, favorite: Boolean) {} 52 53 /** 54 * Move an item (in elements) from one position to another. 55 */ 56 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 */ 63 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 */ 73 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 123 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