/*
|
* 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 static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
|
|
import android.annotation.NonNull;
|
import android.annotation.Nullable;
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
import java.io.PrintWriter;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
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 inverted from regular index, because they are laid out back-to-front
|
* @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;
|
}
|
|
/**
|
* Build a list of the {@link StatusBarIconHolder}s in the same order they appear in their
|
* view group. This provides a safe list that can be iterated and inserted into its group.
|
*
|
* @return all holders contained here, in view order
|
*/
|
public List<StatusBarIconHolder> getHolderListInViewOrder() {
|
ArrayList<StatusBarIconHolder> holders = new ArrayList<>();
|
if (mSubSlots != null) {
|
for (int i = mSubSlots.size() - 1; i >= 0; i--) {
|
holders.add(mSubSlots.get(i));
|
}
|
}
|
|
if (mHolder != null) {
|
holders.add(mHolder);
|
}
|
|
return holders;
|
}
|
|
/**
|
* Build a list of the {@link StatusBarIconHolder}s in the same order.
|
* This provides a safe list that can be iterated and inserted into its group.
|
*
|
* @return all holders contained here
|
*/
|
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";
|
}
|
}
|
}
|