use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method removeRange.
/**
* Removes a list of consecutive items and notify the change.
* <p>If the item, resulting from the provided position:</p>
* - is <u>not expandable</u> with <u>no</u> parent, it is removed as usual.<br/>
* - is <u>not expandable</u> with a parent, it is removed only if the parent is expanded.<br/>
* - is <u>expandable</u> implementing {@link IExpandable}, it is removed as usual, but
* it will be collapsed if expanded.<br/>
* - has a {@link IHeader} item, the header will be automatically linked to the first item
* after the range or can remain orphan.
* <p>Optionally you can pass any payload to notify the <u>parent</u> or the <u>header</u>
* about the change and optimize the view binding.</p>
*
* @param positionStart the start position of the first item
* @param itemCount how many items should be removed
* @param payload any non-null user object to notify the parent (the payload will be
* therefore passed to the bind method of the parent ViewHolder),
* pass null to <u>not</u> notify the parent
* @see #clear()
* @see #clearAllBut(Integer...)
* @see #removeItem(int, Object)
* @see #removeItems(List, Object)
* @see #removeRange(int, int)
* @see #removeAllSelectedItems(Object)
* @see #setPermanentDelete(boolean)
* @see #setRestoreSelectionOnUndo(boolean)
* @see #getDeletedItems()
* @see #getDeletedChildren(IExpandable)
* @see #restoreDeletedItems()
* @see #startUndoTimer(long, OnDeleteCompleteListener)
* @see #emptyBin()
* @since 5.0.0-b1
*/
//FIXME: Fix payload message if customized
public void removeRange(@IntRange(from = 0) int positionStart, @IntRange(from = 0) int itemCount, @Nullable Object payload) {
int initialCount = getItemCount();
if (DEBUG)
Log.d(TAG, "removeRange positionStart=" + positionStart + " itemCount=" + itemCount);
if (positionStart < 0 || (positionStart + itemCount) > initialCount) {
Log.e(TAG, "Cannot removeRange with positionStart out of OutOfBounds!");
return;
}
// Update content of the header linked to first item of the range
T item = getItem(positionStart);
IHeader header = getHeaderOf(item);
int headerPosition = getGlobalPositionOf(header);
if (header != null && headerPosition >= 0) {
// The header does not represents a group anymore, add it to the Orphan list
addToOrphanListIfNeeded(header, positionStart, itemCount);
notifyItemChanged(headerPosition, payload);
}
int parentPosition = -1;
IExpandable parent = null;
for (int position = positionStart; position < positionStart + itemCount; position++) {
item = getItem(positionStart);
if (!permanentDelete) {
//When removing a range of children, parent is always the same :-)
if (parent == null)
parent = getExpandableOf(item);
//Differentiate: (Expandable & NonExpandable with No parent) from (NonExpandable with a parent)
if (parent == null) {
createRestoreItemInfo(positionStart, item, Payload.UNDO);
} else {
parentPosition = createRestoreSubItemInfo(parent, item, Payload.UNDO);
}
}
// Change to hidden status for section headers
if (isHeader(item)) {
header = (IHeader) item;
header.setHidden(true);
// If item is a Header, remove linkage from ALL Sectionable items if exist
if (unlinkOnRemoveHeader) {
List<ISectionable> sectionableList = getSectionItems(header);
for (ISectionable sectionable : sectionableList) {
sectionable.setHeader(null);
if (payload != null)
notifyItemChanged(getGlobalPositionOf(sectionable), Payload.UNLINK);
}
}
}
// Remove item from internal list
mItems.remove(positionStart);
removeSelection(position);
}
// Notify range removal
notifyItemRangeRemoved(positionStart, itemCount);
// Notify the Parent about the change if requested
if (parentPosition >= 0 && payload != null) {
notifyItemChanged(parentPosition, payload);
}
// Remove orphan headers
if (removeOrphanHeaders) {
for (IHeader orphanHeader : mOrphanHeaders) {
headerPosition = getGlobalPositionOf(orphanHeader);
if (headerPosition >= 0) {
if (DEBUG)
Log.v(TAG, "Removing orphan header " + orphanHeader);
if (!permanentDelete)
createRestoreItemInfo(headerPosition, (T) orphanHeader, Payload.UNDO);
mItems.remove(headerPosition);
notifyItemRemoved(headerPosition);
}
}
mOrphanHeaders.clear();
}
// Update empty view
if (mUpdateListener != null && !multiRange && initialCount > 0 && getItemCount() == 0)
mUpdateListener.onUpdateEmptyView(getMainItemCount());
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method addFilteredSubItems.
/**
* Adds to the final list also the filtered subItems.
*/
private int addFilteredSubItems(List<T> values, T item) {
if (isExpandable(item)) {
IExpandable expandable = (IExpandable) item;
if (hasSubItems(expandable)) {
// Add subItems if not hidden by filterObject()
List<T> filteredSubItems = new ArrayList<>();
List<T> subItems = expandable.getSubItems();
for (T subItem : subItems) {
if (!subItem.isHidden())
filteredSubItems.add(subItem);
}
values.addAll(filteredSubItems);
return filteredSubItems.size();
}
}
return 0;
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method expandAll.
/**
* Expands all IExpandable items with at least the specified level.
* <p>Parent will be notified.</p>
*
* @param level the minimum level to expand the sub expandable items
* @return the number of parent successfully expanded
* @see #expandAll()
* @see #setMinCollapsibleLevel(int)
* @since 5.0.0-b6
*/
public int expandAll(int level) {
int expanded = 0;
// More efficient if we expand from First expandable position
int startPosition = Math.max(0, mScrollableHeaders.size() - 1);
for (int i = startPosition; i < (getItemCount() - mScrollableFooters.size()); i++) {
T item = getItem(i);
if (isExpandable(item)) {
IExpandable expandable = (IExpandable) item;
if (expandable.getExpansionLevel() <= level && expand(i, true, false, true) > 0) {
i += expandable.getSubItems().size();
expanded++;
}
}
}
return expanded;
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method collapse.
/**
* Collapses an {@code IExpandable} item that is already expanded, if no subItem is selected.
* <p>Multilevel behaviour: all {@code IExpandable} subItem, that are expanded, are recursively
* collapsed.</p>
*
* @param position the position of the item to collapse
* @param notifyParent notify the parent with {@link Payload#COLLAPSED}
* @return the number of subItems collapsed
* @see #collapseAll()
* @since 5.0.0-b1
*/
public int collapse(@IntRange(from = 0) int position, boolean notifyParent) {
T item = getItem(position);
if (!isExpandable(item))
return 0;
IExpandable expandable = (IExpandable) item;
// Take the current subList (will improve the performance when collapseAll)
List<T> subItems = getExpandableList(expandable);
int subItemsCount = subItems.size(), recursiveCount = 0;
if (DEBUG && mHashItems == null) {
Log.v(TAG, "Request to Collapse on position=" + position + " expanded=" + expandable.isExpanded() + " hasSubItemsSelected=" + hasSubItemsSelected(position, subItems));
}
if (expandable.isExpanded() && subItemsCount > 0 && (!hasSubItemsSelected(position, subItems) || getPendingRemovedItem(item) != null)) {
// Recursive collapse of all sub expandable
recursiveCount = recursiveCollapse(position + 1, subItems, expandable.getExpansionLevel());
mItems.removeAll(subItems);
subItemsCount = subItems.size();
// Save expanded state
expandable.setExpanded(false);
// Collapse!
if (notifyParent)
notifyItemChanged(position, Payload.COLLAPSED);
notifyItemRangeRemoved(position + 1, subItemsCount);
// Hide also the headers of the subItems
if (headersShown && !isHeader(item)) {
for (T subItem : subItems) {
hideHeaderOf(subItem);
}
}
// Expandable as a Scrollable Header/Footer
if (!collapseSHF(mScrollableHeaders, expandable))
collapseSHF(mScrollableFooters, expandable);
if (DEBUG)
Log.v(TAG, "Collapsed " + subItemsCount + " subItems on position " + position);
}
return subItemsCount + recursiveCount;
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method resetFilterFlags.
/**
* Clears flags after searchText is cleared out for Expandable items and sub items.
*/
private void resetFilterFlags(List<T> items) {
// Reset flags for all items!
for (int i = 0; i < items.size(); i++) {
T item = items.get(i);
item.setHidden(false);
if (isExpandable(item)) {
IExpandable expandable = (IExpandable) item;
// Reset expanded flag
if (mExpandedFilterFlags != null)
expandable.setExpanded(mExpandedFilterFlags.contains(expandable));
if (hasSubItems(expandable)) {
List<T> subItems = expandable.getSubItems();
for (T subItem : subItems) {
// Reset subItem hidden flag
subItem.setHidden(false);
// Show subItems for expanded items
if (expandable.isExpanded()) {
i++;
if (i < items.size())
items.add(i, subItem);
else
items.add(subItem);
}
}
}
}
}
mExpandedFilterFlags = null;
}
Aggregations