package com.wigwamlabs.spotify; import java.util.ArrayList; public abstract class NativeItemCollection<T extends NativeItem> extends NativeItem { private ArrayList<T> mItems; NativeItemCollection(int handle) { super(handle); } @Override public void destroy() { if (mItems != null) { for (T item : mItems) { if (item != null) { item.destroy(); } } mItems = null; } super.destroy(); } void initList() { if (mItems == null) { final int count = nativeGetCount(); mItems = new ArrayList<T>(count); for (int i = 0; i < count; i++) { mItems.add(null); } } } abstract int nativeGetCount(); public int getCount() { initList(); return mItems.size(); } public T getItem(int index) { initList(); // check cache T item = mItems.get(index); if (item != null) { return item; } // create new and cache item = createNewItem(index); mItems.set(index, item); return item; } abstract T createNewItem(int index); void onItemsMoved(int oldPosition, int newPosition) { if (oldPosition == newPosition) { return; } if (mItems != null) { final T oldItem; if (oldPosition >= 0) { // move or remove oldItem = mItems.remove(oldPosition); } else { // new oldItem = null; } if (newPosition >= 0) { // move or add int pos = newPosition; if (newPosition > oldPosition && oldPosition >= 0) { // moving downwards pos--; // the index is reported as too big } mItems.add(pos, oldItem); } else { // remove if (oldItem != null) { oldItem.destroy(); } } } } void onItemsMoved(int[] oldPositions, int newPosition) { if (mItems != null) { final int count = oldPositions.length; for (int i = 0; i < count; i++) { final int oldPosition = oldPositions[i]; onItemsMoved(oldPosition, newPosition); final boolean added = (oldPosition < 0); final boolean moved = (oldPosition >= 0 && newPosition >= 0); final boolean movedLeft = (moved && newPosition < oldPosition); final boolean movedNowhere = (moved && newPosition == oldPosition); final boolean removed = (newPosition < 0); // adjust future source positions if (moved || removed) { for (int j = i + 1; j < count; j++) { final int futureOldPosition = oldPositions[j]; if (oldPosition < futureOldPosition && // item to the left (removed || (newPosition > futureOldPosition))) { //removed or moved to right of future oldPositions[j] = futureOldPosition - 1; } else if (moved && (oldPosition > futureOldPosition && // item to the right of future (newPosition <= futureOldPosition))) {// moved to the left of future oldPositions[j] = futureOldPosition + 1; } } } // adjust target position if (added || movedLeft || movedNowhere) { newPosition++; } } } } }