package androidx.recyclerview.widget; import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class ChildHelper { private static final boolean DEBUG = false; private static final String TAG = "ChildrenHelper"; public final Bucket mBucket = new Bucket(); public final Callback mCallback; public final List mHiddenViews = new ArrayList(); public static class Bucket { public static final int BITS_PER_WORD = 64; public static final long LAST_BIT = Long.MIN_VALUE; public long mData = 0; public Bucket mNext; private void ensureNext() { if (this.mNext == null) { this.mNext = new Bucket(); } } public void clear(int i) { if (i >= 64) { Bucket bucket = this.mNext; if (bucket != null) { bucket.clear(i - 64); return; } return; } this.mData &= ~(1 << i); } public int countOnesBefore(int i) { Bucket bucket = this.mNext; if (bucket == null) { return i >= 64 ? Long.bitCount(this.mData) : Long.bitCount(this.mData & ((1 << i) - 1)); } if (i < 64) { return Long.bitCount(this.mData & ((1 << i) - 1)); } return Long.bitCount(this.mData) + bucket.countOnesBefore(i - 64); } public boolean get(int i) { if (i < 64) { return (this.mData & (1 << i)) != 0; } ensureNext(); return this.mNext.get(i - 64); } public void insert(int i, boolean z2) { if (i >= 64) { ensureNext(); this.mNext.insert(i - 64, z2); return; } long j = this.mData; boolean z3 = (Long.MIN_VALUE & j) != 0; long j2 = (1 << i) - 1; this.mData = ((j & (~j2)) << 1) | (j & j2); if (z2) { set(i); } else { clear(i); } if (z3 || this.mNext != null) { ensureNext(); this.mNext.insert(0, z3); } } public boolean remove(int i) { if (i >= 64) { ensureNext(); return this.mNext.remove(i - 64); } long j = 1 << i; long j2 = this.mData; boolean z2 = (j2 & j) != 0; long j3 = j2 & (~j); this.mData = j3; long j4 = j - 1; this.mData = (j3 & j4) | Long.rotateRight((~j4) & j3, 1); Bucket bucket = this.mNext; if (bucket != null) { if (bucket.get(0)) { set(63); } this.mNext.remove(0); } return z2; } public void reset() { this.mData = 0; Bucket bucket = this.mNext; if (bucket != null) { bucket.reset(); } } public void set(int i) { if (i >= 64) { ensureNext(); this.mNext.set(i - 64); return; } this.mData |= 1 << i; } public String toString() { if (this.mNext == null) { return Long.toBinaryString(this.mData); } return this.mNext.toString() + "xx" + Long.toBinaryString(this.mData); } } public interface Callback { void addView(View view, int i); void attachViewToParent(View view, int i, ViewGroup.LayoutParams layoutParams); void detachViewFromParent(int i); View getChildAt(int i); int getChildCount(); RecyclerView.ViewHolder getChildViewHolder(View view); int indexOfChild(View view); void onEnteredHiddenState(View view); void onLeftHiddenState(View view); void removeAllViews(); void removeViewAt(int i); } public ChildHelper(Callback callback) { this.mCallback = callback; } private int getOffset(int i) { if (i < 0) { return -1; } int childCount = this.mCallback.getChildCount(); int i2 = i; while (i2 < childCount) { int countOnesBefore = i - (i2 - this.mBucket.countOnesBefore(i2)); if (countOnesBefore == 0) { while (this.mBucket.get(i2)) { i2++; } return i2; } i2 += countOnesBefore; } return -1; } private void hideViewInternal(View view) { this.mHiddenViews.add(view); this.mCallback.onEnteredHiddenState(view); } private boolean unhideViewInternal(View view) { if (!this.mHiddenViews.remove(view)) { return false; } this.mCallback.onLeftHiddenState(view); return true; } public void addView(View view, int i, boolean z2) { int childCount = i < 0 ? this.mCallback.getChildCount() : getOffset(i); this.mBucket.insert(childCount, z2); if (z2) { hideViewInternal(view); } this.mCallback.addView(view, childCount); } public void addView(View view, boolean z2) { addView(view, -1, z2); } public void attachViewToParent(View view, int i, ViewGroup.LayoutParams layoutParams, boolean z2) { int childCount = i < 0 ? this.mCallback.getChildCount() : getOffset(i); this.mBucket.insert(childCount, z2); if (z2) { hideViewInternal(view); } this.mCallback.attachViewToParent(view, childCount, layoutParams); } public void detachViewFromParent(int i) { int offset = getOffset(i); this.mBucket.remove(offset); this.mCallback.detachViewFromParent(offset); } public View findHiddenNonRemovedView(int i) { int size = this.mHiddenViews.size(); for (int i2 = 0; i2 < size; i2++) { View view = this.mHiddenViews.get(i2); RecyclerView.ViewHolder childViewHolder = this.mCallback.getChildViewHolder(view); if (!(childViewHolder.getLayoutPosition() != i || childViewHolder.isInvalid() || childViewHolder.isRemoved())) { return view; } } return null; } public View getChildAt(int i) { return this.mCallback.getChildAt(getOffset(i)); } public int getChildCount() { return this.mCallback.getChildCount() - this.mHiddenViews.size(); } public View getUnfilteredChildAt(int i) { return this.mCallback.getChildAt(i); } public int getUnfilteredChildCount() { return this.mCallback.getChildCount(); } public void hide(View view) { int indexOfChild = this.mCallback.indexOfChild(view); if (indexOfChild >= 0) { this.mBucket.set(indexOfChild); hideViewInternal(view); return; } throw new IllegalArgumentException("view is not a child, cannot hide " + view); } public int indexOfChild(View view) { int indexOfChild = this.mCallback.indexOfChild(view); if (indexOfChild != -1 && !this.mBucket.get(indexOfChild)) { return indexOfChild - this.mBucket.countOnesBefore(indexOfChild); } return -1; } public boolean isHidden(View view) { return this.mHiddenViews.contains(view); } public void removeAllViewsUnfiltered() { this.mBucket.reset(); for (int size = this.mHiddenViews.size() - 1; size >= 0; size--) { this.mCallback.onLeftHiddenState(this.mHiddenViews.get(size)); this.mHiddenViews.remove(size); } this.mCallback.removeAllViews(); } public void removeView(View view) { int indexOfChild = this.mCallback.indexOfChild(view); if (indexOfChild >= 0) { if (this.mBucket.remove(indexOfChild)) { unhideViewInternal(view); } this.mCallback.removeViewAt(indexOfChild); } } public void removeViewAt(int i) { int offset = getOffset(i); View childAt = this.mCallback.getChildAt(offset); if (childAt != null) { if (this.mBucket.remove(offset)) { unhideViewInternal(childAt); } this.mCallback.removeViewAt(offset); } } public boolean removeViewIfHidden(View view) { int indexOfChild = this.mCallback.indexOfChild(view); if (indexOfChild == -1) { unhideViewInternal(view); return true; } else if (!this.mBucket.get(indexOfChild)) { return false; } else { this.mBucket.remove(indexOfChild); unhideViewInternal(view); this.mCallback.removeViewAt(indexOfChild); return true; } } public String toString() { return this.mBucket.toString() + ", hidden list:" + this.mHiddenViews.size(); } public void unhide(View view) { int indexOfChild = this.mCallback.indexOfChild(view); if (indexOfChild < 0) { throw new IllegalArgumentException("view is not a child, cannot hide " + view); } else if (this.mBucket.get(indexOfChild)) { this.mBucket.clear(indexOfChild); unhideViewInternal(view); } else { throw new RuntimeException("trying to unhide a view that was not hidden" + view); } } }