Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for fully recursive lists (expansion, collapsing, and update) #397

Merged
merged 4 commits into from
Jun 30, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,37 @@ public List<Integer> getExpandedPositions() {
return expandedPositions;
}

/**
* Convenience method to determine the total number of items up to the subposition of expandable
* subitems
*
* @return item count, including recursive expansions, to the first level subposition item
*/
private int getRecursiveSubItemCount( @NonNull IExpandable parent) {
return getRecursiveSubItemCount(parent, parent.getSubItems().size());
}

/**
* Recursively determine the total number of items between a range of expandable subitems
*
* @return item count, including recursive expansions, to the first level subposition item
*/
private int getRecursiveSubItemCount( @NonNull IExpandable parent, int subPosition) {
int count = 0;
// Get the subItems
List<T> subItems = parent.getSubItems();
// Iterate through subItems
for(int index = 0; index < subPosition; index++) {
T tempSubItem = subItems.get(index);
// Check whether item is also expandable, and expanded
if(this.isExpandable(tempSubItem) && ((IExpandable) tempSubItem).isExpanded()) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When isExpanded() is called isExpandable() is checked internally too.

count += getRecursiveSubItemCount((IExpandable) tempSubItem);
}
count++;
}
return count;
}

/**
* Expands an item that is {@code IExpandable} type, not yet expanded and if has subItems.
* <p>If configured, automatic smooth scroll will be performed when necessary.</p>
Expand Down Expand Up @@ -2647,7 +2678,7 @@ private int expand(int position, boolean expandAll, boolean init, boolean notify

// Every time an expansion is requested, subItems must be taken from the
// original Object and without the subItems marked hidden (removed)
List<T> subItems = getExpandableList(expandable);
List<T> subItems = getExpandableList(expandable, true);
mItems.addAll(position + 1, subItems);
subItemsCount = subItems.size();
// Save expanded state
Expand Down Expand Up @@ -2763,8 +2794,8 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) {

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;
List<T> subItems = getExpandableList(expandable, true);
int subItemsCount = subItems.size();

Log.v("Request to Collapse on position=%s expanded=%s hasSubItemsSelected=%s",
position, expandable.isExpanded(), hasSubItemsSelected(position, subItems));
Expand All @@ -2773,7 +2804,7 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) {
(!hasSubItemsSelected(position, subItems) || getPendingRemovedItem(item) != null)) {

// Recursive collapse of all sub expandable
recursiveCount = recursiveCollapse(position + 1, subItems, expandable.getExpansionLevel());
recursiveCollapse(position + 1, subItems, expandable.getExpansionLevel());
mItems.removeAll(subItems);
subItemsCount = subItems.size();
// Save expanded state
Expand All @@ -2796,7 +2827,7 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) {

Log.v("Collapsed %s subItems on position %s", subItemsCount, position);
}
return subItemsCount + recursiveCount;
return subItemsCount;
}

private boolean collapseSHF(List<T> scrollables, IExpandable expandable) {
Expand Down Expand Up @@ -3162,7 +3193,7 @@ private boolean addSubItems(@IntRange(from = 0) int parentPosition,
// Notify the adapter of the new addition to display it and animate it.
// If parent is collapsed there's no need to add sub items.
if (parent.isExpanded()) {
added = addItems(parentPosition + 1 + Math.max(0, subPosition), subItems);
added = addItems(parentPosition + 1 + getRecursiveSubItemCount(parent, subPosition), subItems);
}
// Notify the parent about the change if requested
if (payload != null) notifyItemChanged(parentPosition, payload);
Expand Down Expand Up @@ -4945,7 +4976,7 @@ private RestoreInfo getPendingRemovedItem(T item) {
* @since 5.0.0-b1
*/
private void createRestoreSubItemInfo(IExpandable expandable, T item) {
List<T> siblings = getExpandableList(expandable);
List<T> siblings = getExpandableList(expandable, true);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this call should return only direct siblings, so the parameter should be false.
Because when restoring deleted items in restoreDeletedItems(), the position is relative to the parent when addSubItem() is called there.

int childPosition = siblings.indexOf(item);
mRestoreList.add(new RestoreInfo((T) expandable, item, childPosition));
Log.v("Recycled SubItem %s with Parent position=%s",
Expand All @@ -4972,19 +5003,40 @@ private void createRestoreItemInfo(int position, T item) {
Log.v("Recycled Item %s on position=%s", mRestoreList.get(mRestoreList.size() - 1), position);
}


/**
* @param expandable the parent item
* @return the list of the subItems not hidden
* @return the list of the subItems not hidden, non-recursively
* @since 5.0.0-b1
*/
@NonNull
private List<T> getExpandableList(IExpandable expandable) {
return getExpandableList(expandable, false);
}

/**
* @param expandable the parent item
* @return the list of the subItems not hidden
* @since 5.0.0-b1
*/
@NonNull
private List<T> getExpandableList(IExpandable expandable, boolean isRecursive) {
List<T> subItems = new ArrayList<>();
if (expandable != null && hasSubItems(expandable)) {
List<T> allSubItems = expandable.getSubItems();
for (T subItem : allSubItems) {
// Pick up only no hidden items (doesn't get into account the filtered items)
if (!subItem.isHidden()) subItems.add(subItem);
if (!subItem.isHidden()) {
// Add the current subitem
subItems.add(subItem);
// If expandable, expanded, and of non-zero size, recursively add sub-subItems
if(this.isExpandable(subItem) &&
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, isExpandable() can be removed.

isRecursive &&
((IExpandable) subItem).isExpanded() &&
((IExpandable) subItem).getSubItems().size() > 0) {
subItems.addAll(getExpandableList((IExpandable) subItem, true));
}
}
}
}
return subItems;
Expand All @@ -4996,6 +5048,7 @@ private List<T> getExpandableList(IExpandable expandable) {
* @param startPosition helps to improve performance, so we can avoid a new search for position
* @param subItems the list of sub items to check
* @return true if at least 1 subItem is currently selected, false if no subItems are selected
* search is non-recursive
* @since 5.0.0-b1
*/
private boolean hasSubItemsSelected(int startPosition, List<T> subItems) {
Expand Down Expand Up @@ -5420,7 +5473,7 @@ public int getRestorePosition(boolean isChild) {
// Assert the expandable children are collapsed
recursiveCollapse(refPosition, getCurrentChildren((IExpandable) item), 0);
} else if (isExpanded(item) && !isChild) {
refPosition += getExpandableList((IExpandable) item).size() + 1;
refPosition += getExpandableList((IExpandable) item, true).size() + 1;
} else {
refPosition++;
}
Expand Down Expand Up @@ -5548,14 +5601,12 @@ private void prepareItemsForUpdate(List<T> newItems) {
if (isExpanded(item)) {
IExpandable expandable = (IExpandable) item;
expandable.setExpanded(true);
List<T> subItems = getExpandableList(expandable);
List<T> subItems = getExpandableList(expandable, false);
int itemCount = newItems.size();
if (position < itemCount) {
newItems.addAll(position + 1, subItems);
position += subItems.size();
} else {
newItems.addAll(subItems);
position = itemCount;
}
}
// Display headers too
Expand Down