| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.statusbar.phone; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.internal.statusbar.StatusBarIcon; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY; |
| |
| public class StatusBarIconList { |
| private ArrayList<Slot> mSlots = new ArrayList<>(); |
| |
| public StatusBarIconList(String[] slots) { |
| final int N = slots.length; |
| for (int i=0; i < N; i++) { |
| mSlots.add(new Slot(slots[i], null)); |
| } |
| } |
| |
| public int getSlotIndex(String slot) { |
| final int N = mSlots.size(); |
| for (int i=0; i<N; i++) { |
| Slot item = mSlots.get(i); |
| if (item.getName().equals(slot)) { |
| return i; |
| } |
| } |
| // Auto insert new items at the beginning. |
| mSlots.add(0, new Slot(slot, null)); |
| return 0; |
| } |
| |
| protected ArrayList<Slot> getSlots() { |
| return new ArrayList<>(mSlots); |
| } |
| |
| protected Slot getSlot(String name) { |
| return mSlots.get(getSlotIndex(name)); |
| } |
| |
| public int size() { |
| return mSlots.size(); |
| } |
| |
| public void setIcon(int index, @NonNull StatusBarIconHolder holder) { |
| mSlots.get(index).addHolder(holder); |
| } |
| |
| public void removeIcon(int index, int tag) { |
| mSlots.get(index).removeForTag(tag); |
| } |
| |
| public String getSlotName(int index) { |
| return mSlots.get(index).getName(); |
| } |
| |
| public StatusBarIconHolder getIcon(int index, int tag) { |
| return mSlots.get(index).getHolderForTag(tag); |
| } |
| |
| public int getViewIndex(int slotIndex, int tag) { |
| int count = 0; |
| for (int i = 0; i < slotIndex; i++) { |
| Slot item = mSlots.get(i); |
| if (item.hasIconsInSlot()) { |
| count += item.numberOfIcons(); |
| } |
| } |
| |
| Slot viewItem = mSlots.get(slotIndex); |
| return count + viewItem.viewIndexOffsetForTag(tag); |
| } |
| |
| public void dump(PrintWriter pw) { |
| pw.println("StatusBarIconList state:"); |
| final int N = mSlots.size(); |
| pw.println(" icon slots: " + N); |
| for (int i=0; i<N; i++) { |
| pw.printf(" %2d:%s\n", i, mSlots.get(i).toString()); |
| } |
| } |
| |
| public static class Slot { |
| private final String mName; |
| private StatusBarIconHolder mHolder; |
| /** |
| * Only used if multiple icons are added to the same slot. |
| * |
| * If there are mSubSlots, then these are structured like: |
| * [ First item | (the rest) ] |
| * |
| * The tricky thing to keep in mind here is that the list [mHolder, mSubSlots] is ordered |
| * ascending, but for view logic we should go backwards through the list. I.e., the first |
| * element (mHolder) should be the highest index, because higher priority items go to the |
| * right of lower priority items |
| */ |
| private ArrayList<StatusBarIconHolder> mSubSlots; |
| |
| public Slot(String name, StatusBarIconHolder iconHolder) { |
| mName = name; |
| mHolder = iconHolder; |
| } |
| |
| public String getName() { |
| return mName; |
| } |
| |
| @Nullable |
| public StatusBarIconHolder getHolderForTag(int tag) { |
| if (tag == TAG_PRIMARY) { |
| return mHolder; |
| } |
| |
| if (mSubSlots != null) { |
| for (StatusBarIconHolder holder : mSubSlots) { |
| if (holder.getTag() == tag) { |
| return holder; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| public void addHolder(StatusBarIconHolder holder) { |
| int tag = holder.getTag(); |
| if (tag == TAG_PRIMARY) { |
| mHolder = holder; |
| } else { |
| setSubSlot(holder, tag); |
| } |
| } |
| |
| public void removeForTag(int tag) { |
| if (tag == TAG_PRIMARY) { |
| mHolder = null; |
| } else { |
| int index = getIndexForTag(tag); |
| if (index != -1) { |
| mSubSlots.remove(index); |
| } |
| } |
| } |
| |
| @VisibleForTesting |
| public void clear() { |
| mHolder = null; |
| if (mSubSlots != null) { |
| mSubSlots = null; |
| } |
| } |
| |
| private void setSubSlot(StatusBarIconHolder holder, int tag) { |
| if (mSubSlots == null) { |
| mSubSlots = new ArrayList<>(); |
| mSubSlots.add(holder); |
| return; |
| } |
| |
| if (getIndexForTag(tag) != -1) { |
| // Holder exists for tag; no-op |
| return; |
| } |
| |
| // These holders get added to the end. Confused yet? |
| mSubSlots.add(holder); |
| } |
| |
| private int getIndexForTag(int tag) { |
| for (int i = 0; i < mSubSlots.size(); i++) { |
| StatusBarIconHolder h = mSubSlots.get(i); |
| if (h.getTag() == tag) { |
| return i; |
| } |
| } |
| |
| return -1; |
| } |
| |
| public boolean hasIconsInSlot() { |
| if (mHolder != null) return true; |
| if (mSubSlots == null) return false; |
| |
| return mSubSlots.size() > 0; |
| } |
| |
| public int numberOfIcons() { |
| int num = mHolder == null ? 0 : 1; |
| if (mSubSlots == null) return num; |
| |
| return num + mSubSlots.size(); |
| } |
| |
| /** |
| * View index is backwards from regular index |
| * @param tag the tag of the holder being viewed |
| * @return (1 + mSubSlots.size() - indexOfTag) |
| */ |
| public int viewIndexOffsetForTag(int tag) { |
| if (mSubSlots == null) { |
| return 0; |
| } |
| |
| int subSlots = mSubSlots.size(); |
| if (tag == TAG_PRIMARY) { |
| return subSlots; |
| } |
| |
| return subSlots - getIndexForTag(tag) - 1; |
| } |
| |
| public List<StatusBarIconHolder> getHolderList() { |
| ArrayList<StatusBarIconHolder> holders = new ArrayList<>(); |
| if (mHolder != null) { |
| holders.add(mHolder); |
| } |
| |
| if (mSubSlots != null) { |
| holders.addAll(mSubSlots); |
| } |
| |
| return holders; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("(%s) %s", mName, subSlotsString()); |
| } |
| |
| private String subSlotsString() { |
| if (mSubSlots == null) { |
| return ""; |
| } |
| |
| return "" + mSubSlots.size() + " subSlots"; |
| } |
| } |
| } |