blob: c876c3228eb87487b5f019a88c65a9d0ec44caaa [file] [log] [blame]
Jason Monk07473ce2016-01-05 14:59:19 -05001/*
2 * Copyright (C) 2015 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
17package com.android.systemui.statusbar.phone;
18
Gus Prevasab336792018-11-14 13:52:20 -050019import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
20
Evan Lairde1d13c92018-03-20 16:58:01 -040021import android.annotation.NonNull;
22import android.annotation.Nullable;
Gus Prevasab336792018-11-14 13:52:20 -050023
Evan Lairde1d13c92018-03-20 16:58:01 -040024import com.android.internal.annotations.VisibleForTesting;
Gus Prevasab336792018-11-14 13:52:20 -050025
Jason Monk07473ce2016-01-05 14:59:19 -050026import java.io.PrintWriter;
27import java.util.ArrayList;
Evan Lairde1d13c92018-03-20 16:58:01 -040028import java.util.List;
29
Jason Monk07473ce2016-01-05 14:59:19 -050030public class StatusBarIconList {
Evan Lairde1d13c92018-03-20 16:58:01 -040031 private ArrayList<Slot> mSlots = new ArrayList<>();
Jason Monk07473ce2016-01-05 14:59:19 -050032
Jason Monkc6fe61c2016-07-26 13:04:50 -040033 public StatusBarIconList(String[] slots) {
Jason Monk07473ce2016-01-05 14:59:19 -050034 final int N = slots.length;
35 for (int i=0; i < N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -040036 mSlots.add(new Slot(slots[i], null));
Jason Monk07473ce2016-01-05 14:59:19 -050037 }
38 }
39
40 public int getSlotIndex(String slot) {
41 final int N = mSlots.size();
42 for (int i=0; i<N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -040043 Slot item = mSlots.get(i);
44 if (item.getName().equals(slot)) {
Jason Monk07473ce2016-01-05 14:59:19 -050045 return i;
46 }
47 }
48 // Auto insert new items at the beginning.
Evan Lairde1d13c92018-03-20 16:58:01 -040049 mSlots.add(0, new Slot(slot, null));
Jason Monk07473ce2016-01-05 14:59:19 -050050 return 0;
51 }
52
Evan Lairde1d13c92018-03-20 16:58:01 -040053 protected ArrayList<Slot> getSlots() {
54 return new ArrayList<>(mSlots);
55 }
56
57 protected Slot getSlot(String name) {
58 return mSlots.get(getSlotIndex(name));
59 }
60
Jason Monk07473ce2016-01-05 14:59:19 -050061 public int size() {
62 return mSlots.size();
63 }
64
Evan Lairde1d13c92018-03-20 16:58:01 -040065 public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
66 mSlots.get(index).addHolder(holder);
Jason Monk07473ce2016-01-05 14:59:19 -050067 }
68
Evan Lairde1d13c92018-03-20 16:58:01 -040069 public void removeIcon(int index, int tag) {
70 mSlots.get(index).removeForTag(tag);
Jason Monk07473ce2016-01-05 14:59:19 -050071 }
72
Evan Lairde1d13c92018-03-20 16:58:01 -040073 public String getSlotName(int index) {
74 return mSlots.get(index).getName();
Jason Monk07473ce2016-01-05 14:59:19 -050075 }
76
Evan Lairde1d13c92018-03-20 16:58:01 -040077 public StatusBarIconHolder getIcon(int index, int tag) {
78 return mSlots.get(index).getHolderForTag(tag);
Jason Monk07473ce2016-01-05 14:59:19 -050079 }
80
Evan Lairde1d13c92018-03-20 16:58:01 -040081 public int getViewIndex(int slotIndex, int tag) {
Jason Monk07473ce2016-01-05 14:59:19 -050082 int count = 0;
Evan Lairde1d13c92018-03-20 16:58:01 -040083 for (int i = 0; i < slotIndex; i++) {
84 Slot item = mSlots.get(i);
85 if (item.hasIconsInSlot()) {
86 count += item.numberOfIcons();
Jason Monk07473ce2016-01-05 14:59:19 -050087 }
88 }
Evan Lairde1d13c92018-03-20 16:58:01 -040089
90 Slot viewItem = mSlots.get(slotIndex);
91 return count + viewItem.viewIndexOffsetForTag(tag);
Jason Monk07473ce2016-01-05 14:59:19 -050092 }
93
94 public void dump(PrintWriter pw) {
Evan Laird937d9fa2018-02-08 10:12:16 -080095 pw.println("StatusBarIconList state:");
Jason Monk07473ce2016-01-05 14:59:19 -050096 final int N = mSlots.size();
Dan Sandlerf3a1f2c2016-06-26 15:59:13 -040097 pw.println(" icon slots: " + N);
Jason Monk07473ce2016-01-05 14:59:19 -050098 for (int i=0; i<N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -040099 pw.printf(" %2d:%s\n", i, mSlots.get(i).toString());
100 }
101 }
102
103 public static class Slot {
104 private final String mName;
105 private StatusBarIconHolder mHolder;
106 /**
107 * Only used if multiple icons are added to the same slot.
108 *
109 * If there are mSubSlots, then these are structured like:
110 * [ First item | (the rest) ]
111 *
112 * The tricky thing to keep in mind here is that the list [mHolder, mSubSlots] is ordered
113 * ascending, but for view logic we should go backwards through the list. I.e., the first
114 * element (mHolder) should be the highest index, because higher priority items go to the
115 * right of lower priority items
116 */
117 private ArrayList<StatusBarIconHolder> mSubSlots;
118
119 public Slot(String name, StatusBarIconHolder iconHolder) {
120 mName = name;
121 mHolder = iconHolder;
122 }
123
124 public String getName() {
125 return mName;
126 }
127
128 @Nullable
129 public StatusBarIconHolder getHolderForTag(int tag) {
130 if (tag == TAG_PRIMARY) {
131 return mHolder;
132 }
133
134 if (mSubSlots != null) {
135 for (StatusBarIconHolder holder : mSubSlots) {
136 if (holder.getTag() == tag) {
137 return holder;
138 }
139 }
140 }
141
142 return null;
143 }
144
145 public void addHolder(StatusBarIconHolder holder) {
146 int tag = holder.getTag();
147 if (tag == TAG_PRIMARY) {
148 mHolder = holder;
149 } else {
150 setSubSlot(holder, tag);
151 }
152 }
153
154 public void removeForTag(int tag) {
155 if (tag == TAG_PRIMARY) {
156 mHolder = null;
157 } else {
158 int index = getIndexForTag(tag);
159 if (index != -1) {
160 mSubSlots.remove(index);
161 }
162 }
163 }
164
165 @VisibleForTesting
166 public void clear() {
167 mHolder = null;
168 if (mSubSlots != null) {
169 mSubSlots = null;
170 }
171 }
172
173 private void setSubSlot(StatusBarIconHolder holder, int tag) {
174 if (mSubSlots == null) {
175 mSubSlots = new ArrayList<>();
176 mSubSlots.add(holder);
177 return;
178 }
179
180 if (getIndexForTag(tag) != -1) {
181 // Holder exists for tag; no-op
182 return;
183 }
184
185 // These holders get added to the end. Confused yet?
186 mSubSlots.add(holder);
187 }
188
189 private int getIndexForTag(int tag) {
190 for (int i = 0; i < mSubSlots.size(); i++) {
191 StatusBarIconHolder h = mSubSlots.get(i);
192 if (h.getTag() == tag) {
193 return i;
194 }
195 }
196
197 return -1;
198 }
199
200 public boolean hasIconsInSlot() {
201 if (mHolder != null) return true;
202 if (mSubSlots == null) return false;
203
204 return mSubSlots.size() > 0;
205 }
206
207 public int numberOfIcons() {
208 int num = mHolder == null ? 0 : 1;
209 if (mSubSlots == null) return num;
210
211 return num + mSubSlots.size();
212 }
213
214 /**
Evan Lairdeae911d2018-04-26 16:05:46 -0400215 * View index is inverted from regular index, because they are laid out back-to-front
Evan Lairde1d13c92018-03-20 16:58:01 -0400216 * @param tag the tag of the holder being viewed
217 * @return (1 + mSubSlots.size() - indexOfTag)
218 */
219 public int viewIndexOffsetForTag(int tag) {
220 if (mSubSlots == null) {
221 return 0;
222 }
223
224 int subSlots = mSubSlots.size();
225 if (tag == TAG_PRIMARY) {
226 return subSlots;
227 }
228
229 return subSlots - getIndexForTag(tag) - 1;
230 }
231
Evan Lairdeae911d2018-04-26 16:05:46 -0400232 /**
233 * Build a list of the {@link StatusBarIconHolder}s in the same order they appear in their
234 * view group. This provides a safe list that can be iterated and inserted into its group.
235 *
236 * @return all holders contained here, in view order
237 */
238 public List<StatusBarIconHolder> getHolderListInViewOrder() {
Evan Lairde1d13c92018-03-20 16:58:01 -0400239 ArrayList<StatusBarIconHolder> holders = new ArrayList<>();
Evan Lairdeae911d2018-04-26 16:05:46 -0400240 if (mSubSlots != null) {
241 for (int i = mSubSlots.size() - 1; i >= 0; i--) {
242 holders.add(mSubSlots.get(i));
243 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400244 }
245
Evan Lairdeae911d2018-04-26 16:05:46 -0400246 if (mHolder != null) {
247 holders.add(mHolder);
Evan Lairde1d13c92018-03-20 16:58:01 -0400248 }
249
250 return holders;
251 }
252
Yong Shi4a50a8e2018-05-21 15:53:02 +0800253 /**
254 * Build a list of the {@link StatusBarIconHolder}s in the same order.
255 * This provides a safe list that can be iterated and inserted into its group.
256 *
257 * @return all holders contained here
258 */
259 public List<StatusBarIconHolder> getHolderList() {
260 ArrayList<StatusBarIconHolder> holders = new ArrayList<>();
261 if (mHolder != null) {
262 holders.add(mHolder);
263 }
264
265 if (mSubSlots != null) {
266 holders.addAll(mSubSlots);
267 }
268
269 return holders;
270 }
271
Evan Lairde1d13c92018-03-20 16:58:01 -0400272 @Override
273 public String toString() {
274 return String.format("(%s) %s", mName, subSlotsString());
275 }
276
277 private String subSlotsString() {
278 if (mSubSlots == null) {
279 return "";
280 }
281
282 return "" + mSubSlots.size() + " subSlots";
Jason Monk07473ce2016-01-05 14:59:19 -0500283 }
284 }
285}