/* * Copyright (C) 2016 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.settings.dashboard; import android.annotation.IntDef; import android.support.annotation.Nullable; import android.support.v7.util.DiffUtil; import android.text.TextUtils; import com.android.settings.R; import com.android.settings.dashboard.conditional.Condition; import com.android.settingslib.drawer.DashboardCategory; import com.android.settingslib.drawer.Tile; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** * Description about data list used in the DashboardAdapter. In the data list each item can be * Condition, suggestion or category tile. *
* ItemsData has inner class Item, which represents the Item in data list.
*/
public class DashboardData {
public static final int SUGGESTION_MODE_DEFAULT = 0;
public static final int SUGGESTION_MODE_COLLAPSED = 1;
public static final int SUGGESTION_MODE_EXPANDED = 2;
public static final int POSITION_NOT_FOUND = -1;
public static final int DEFAULT_SUGGESTION_COUNT = 2;
// id namespace for different type of items.
private static final int NS_SPACER = 0;
private static final int NS_ITEMS = 2000;
private static final int NS_CONDITION = 3000;
private final List
* First, try to find the exact identical instance of the tile object, if not found,
* then try to find a tile has the same title.
*
* @param tile tile that need to be found
* @return position of the object, return INDEX_NOT_FOUND if object isn't in the list
*/
public int getPositionByTile(Tile tile) {
final int size = mItems.size();
for (int i = 0; i < size; i++) {
final Object entity = mItems.get(i).entity;
if (entity == tile) {
return i;
} else if (entity instanceof Tile && tile.title.equals(((Tile) entity).title)) {
return i;
}
}
return POSITION_NOT_FOUND;
}
/**
* Get the count of suggestions to display
*
* The displayable count mainly depends on the {@link #mSuggestionMode}
* and the size of suggestions list.
*
* When in default mode, displayable count couldn't larger than
* {@link #DEFAULT_SUGGESTION_COUNT}.
*
* When in expanded mode, display all the suggestions.
*
* @return the count of suggestions to display
*/
public int getDisplayableSuggestionCount() {
final int suggestionSize = mSuggestions.size();
return mSuggestionMode == SUGGESTION_MODE_DEFAULT
? Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize)
: mSuggestionMode == SUGGESTION_MODE_EXPANDED
? suggestionSize : 0;
}
public boolean hasMoreSuggestions() {
return mSuggestionMode == SUGGESTION_MODE_COLLAPSED
|| (mSuggestionMode == SUGGESTION_MODE_DEFAULT
&& mSuggestions.size() > DEFAULT_SUGGESTION_COUNT);
}
private void resetCount() {
mId = 0;
}
/**
* Count the item and add it into list when {@paramref add} is true.
*
* Note that {@link #mId} will increment automatically and the real
* id stored in {@link Item} is shifted by {@paramref nameSpace}. This is a
* simple way to keep the id stable.
*
* @param object maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
* @param type type of the item, and value is the layout id
* @param add flag about whether to add item into list
* @param nameSpace namespace based on the type
*/
private void countItem(Object object, int type, boolean add, int nameSpace) {
if (add) {
mItems.add(new Item(object, type, mId + nameSpace, object == mExpandedCondition));
}
mId++;
}
/**
* A special count item method for just suggestions. Id is calculated using suggestion hash
* instead of the position of suggestion in list. This is a more stable id than countItem.
*/
private void countSuggestion(Tile tile, boolean add) {
if (add) {
mItems.add(new Item(tile, R.layout.suggestion_tile, Objects.hash(tile.title), false));
}
mId++;
}
/**
* Build the mItems list using mConditions, mSuggestions, mCategories data
* and mIsShowingAll, mSuggestionMode flag.
*/
private void buildItemsData() {
boolean hasConditions = false;
for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
boolean shouldShow = mConditions.get(i).shouldShow();
hasConditions |= shouldShow;
countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
}
resetCount();
final boolean hasSuggestions = mSuggestions != null && mSuggestions.size() != 0;
countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
countItem(buildSuggestionHeaderData(), R.layout.suggestion_header, hasSuggestions,
NS_SPACER);
resetCount();
if (mSuggestions != null) {
int maxSuggestions = getDisplayableSuggestionCount();
for (int i = 0; i < mSuggestions.size(); i++) {
countSuggestion(mSuggestions.get(i), i < maxSuggestions);
}
}
resetCount();
for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
DashboardCategory category = mCategories.get(i);
countItem(category, R.layout.dashboard_category,
!TextUtils.isEmpty(category.title), NS_ITEMS);
for (int j = 0; j < category.tiles.size(); j++) {
Tile tile = category.tiles.get(j);
countItem(tile, R.layout.dashboard_tile, true, NS_ITEMS);
}
}
}
private SuggestionHeaderData buildSuggestionHeaderData() {
SuggestionHeaderData data;
if (mSuggestions == null) {
data = new SuggestionHeaderData();
} else {
final boolean hasMoreSuggestions = hasMoreSuggestions();
final int suggestionSize = mSuggestions.size();
final int undisplayedSuggestionCount = suggestionSize - getDisplayableSuggestionCount();
data = new SuggestionHeaderData(hasMoreSuggestions, suggestionSize,
undisplayedSuggestionCount);
}
return data;
}
/**
* Builder used to build the ItemsData
*
* {@link #mExpandedCondition} and {@link #mSuggestionMode} have default value
* while others are not.
*/
public static class Builder {
private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;
private Condition mExpandedCondition = null;
private List