package com.mikepenz.fastadapter.utils; import android.support.v4.util.ArraySet; import android.util.SparseIntArray; import com.mikepenz.fastadapter.FastAdapter; import com.mikepenz.fastadapter.IExpandable; import com.mikepenz.fastadapter.IItem; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * Created by mikepenz on 31.12.15. */ public class AdapterUtil { /** * internal method which correctly set the selected state and expandable state on the newly added items * * @param fastAdapter the fastAdapter which manages everything * @param startPosition the position of the first item to handle * @param endPosition the position of the last item to handle */ public static <Item extends IItem> void handleStates(FastAdapter<Item> fastAdapter, int startPosition, int endPosition) { for (int i = endPosition; i >= startPosition; i--) { Item updateItem = fastAdapter.getItem(i); if (updateItem != null) { if (updateItem.isSelected()) { fastAdapter.getSelections().add(i); } else if (fastAdapter.getSelections().contains(i)) { fastAdapter.getSelections().remove(i); } if (updateItem instanceof IExpandable) { if (((IExpandable) updateItem).isExpanded() && fastAdapter.getExpanded().indexOfKey(i) < 0) { fastAdapter.expand(i); } } } } } /** * internal method to handle the selections if items are added / removed * * @param positions the positions map which should be adjusted * @param startPosition the global index of the first element modified * @param endPosition the global index up to which the modification changed the indices (should be MAX_INT if we check til the end) * @param adjustBy the value by which the data was shifted * @return the adjusted set */ public static Set<Integer> adjustPosition(Set<Integer> positions, int startPosition, int endPosition, int adjustBy) { Set<Integer> newPositions = new ArraySet<>(); for (Integer entry : positions) { int position = entry; //if our current position is not within the bounds to check for we can add it if (position < startPosition || position > endPosition) { newPositions.add(position); } else if (adjustBy > 0) { //if we added items and we are within the bounds we can simply add the adjustBy to our entry newPositions.add(position + adjustBy); } else if (adjustBy < 0) { //if we removed items and we are within the bounds we have to check if the item was removed //adjustBy is negative in this case if (position > startPosition + adjustBy && position <= startPosition) { ;//we are within the removed items range we don't add this item anymore } else { //otherwise we adjust our position newPositions.add(position + adjustBy); } } } return newPositions; } /** * internal method to handle the selections if items are added / removed * * @param positions the positions map which should be adjusted * @param startPosition the global index of the first element modified * @param endPosition the global index up to which the modification changed the indices (should be MAX_INT if we check til the end) * @param adjustBy the value by which the data was shifted * @return the adjusted map */ public static SparseIntArray adjustPosition(SparseIntArray positions, int startPosition, int endPosition, int adjustBy) { SparseIntArray newPositions = new SparseIntArray(); for (int i = 0, size = positions.size(); i < size; i++) { int position = positions.keyAt(i); //if our current position is not within the bounds to check for we can add it if (position < startPosition || position > endPosition) { newPositions.put(position, positions.valueAt(i)); } else if (adjustBy > 0) { //if we added items and we are within the bounds we can simply add the adjustBy to our entry newPositions.put(position + adjustBy, positions.valueAt(i)); } else if (adjustBy < 0) { //if we removed items and we are within the bounds we have to check if the item was removed //adjustBy is negative in this case if (position > startPosition + adjustBy && position <= startPosition) { ;//we are within the removed items range we don't add this item anymore } else { //otherwise we adjust our position newPositions.put(position + adjustBy, positions.valueAt(i)); } } } return newPositions; } /** * internal method to restore the selection state of subItems * * @param item the parent item * @param selectedItems the list of selectedItems from the savedInstanceState */ public static <Item extends IItem> void restoreSubItemSelectionStatesForAlternativeStateManagement(Item item, List<String> selectedItems) { if (item instanceof IExpandable && !((IExpandable) item).isExpanded() && ((IExpandable) item).getSubItems() != null) { List<Item> subItems = (List<Item>) ((IExpandable<Item, ?>) item).getSubItems(); Item subItem; String id; for (int i = 0, size = subItems.size(); i < size; i++) { subItem = subItems.get(i); id = String.valueOf(subItem.getIdentifier()); if (selectedItems != null && selectedItems.contains(id)) { subItem.withSetSelected(true); } restoreSubItemSelectionStatesForAlternativeStateManagement(subItem, selectedItems); } } } /** * internal method to find all selections from subItems and sub sub items so we can save those inside our savedInstanceState * * @param item the parent item * @param selections the ArrayList which will be stored in the savedInstanceState */ public static <Item extends IItem> void findSubItemSelections(Item item, List<String> selections) { if (item instanceof IExpandable && !((IExpandable) item).isExpanded() && ((IExpandable) item).getSubItems() != null) { List<Item> subItems = (List<Item>) ((IExpandable<Item, ?>) item).getSubItems(); Item subItem; String id; for (int i = 0, size = subItems.size(); i < size; i++) { subItem = subItems.get(i); id = String.valueOf(subItem.getIdentifier()); if (subItem.isSelected()) { selections.add(id); } findSubItemSelections(subItem, selections); } } } /** * Gets all items (including sub items) from the FastAdapter * * @param fastAdapter the FastAdapter * @return a list of all items including the whole subItem hirachy */ public static <Item extends IItem> List<Item> getAllItems(FastAdapter<Item> fastAdapter) { int size = fastAdapter.getItemCount(); List<Item> items = new ArrayList<>(size); for (int i = 0; i < size; i++) { Item item = fastAdapter.getItem(i); items.add(item); addAllSubItems(item, items); } return items; } /** * Gets all subItems from a given parent item * * @param item the parent from which we add all items * @param items the list in which we add the subItems */ public static <Item extends IItem> void addAllSubItems(Item item, List<Item> items) { if (item instanceof IExpandable && !((IExpandable) item).isExpanded() && ((IExpandable) item).getSubItems() != null) { List<Item> subItems = (List<Item>) ((IExpandable<Item, ?>) item).getSubItems(); Item subItem; for (int i = 0, size = subItems.size(); i < size; i++) { subItem = subItems.get(i); items.add(subItem); addAllSubItems(subItem, items); } } } }