/* * Copyright (C) 2015 Haruki Hasegawa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.h6ah4i.android.widget.advrecyclerview.utils; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import com.h6ah4i.android.widget.advrecyclerview.adapter.AdapterPath; import com.h6ah4i.android.widget.advrecyclerview.adapter.AdapterPathSegment; import com.h6ah4i.android.widget.advrecyclerview.adapter.SimpleWrapperAdapter; import com.h6ah4i.android.widget.advrecyclerview.adapter.UnwrapPositionResult; import com.h6ah4i.android.widget.advrecyclerview.adapter.WrapperAdapter; import java.util.ArrayList; import java.util.List; public class WrapperAdapterUtils { private WrapperAdapterUtils() { } public static <T> T findWrappedAdapter(RecyclerView.Adapter adapter, Class<T> clazz) { if (clazz.isInstance(adapter)) { return clazz.cast(adapter); } else if (adapter instanceof SimpleWrapperAdapter) { final RecyclerView.Adapter wrappedAdapter = ((SimpleWrapperAdapter) adapter).getWrappedAdapter(); return findWrappedAdapter(wrappedAdapter, clazz); } else { return null; } } public static <T> T findWrappedAdapter(RecyclerView.Adapter originAdapter, Class<T> clazz, int position) { final AdapterPath path = new AdapterPath(); final int wrappedPosition = unwrapPosition(originAdapter, null, null, position, path); if (wrappedPosition == RecyclerView.NO_POSITION) { return null; } for (AdapterPathSegment segment : path.segments()) { if (clazz.isInstance(segment.adapter)) { return clazz.cast(segment.adapter); } } return null; } public static RecyclerView.Adapter releaseAll(RecyclerView.Adapter adapter) { return releaseCyclically(adapter); } @SuppressWarnings("unchecked") private static RecyclerView.Adapter releaseCyclically(RecyclerView.Adapter adapter) { if (!(adapter instanceof WrapperAdapter)) { return adapter; } final WrapperAdapter wrapperAdapter = (WrapperAdapter) adapter; final List<RecyclerView.Adapter> wrappedAdapters = new ArrayList<>(); wrapperAdapter.getWrappedAdapters(wrappedAdapters); wrapperAdapter.release(); for (int i = wrappedAdapters.size() - 1; i >= 0; i--) { RecyclerView.Adapter wrappedAdapter = wrappedAdapters.get(i); releaseCyclically(wrappedAdapter); } wrappedAdapters.clear(); return adapter; } public static int unwrapPosition(@NonNull RecyclerView.Adapter originAdapter, int position) { return unwrapPosition(originAdapter, null, position); } public static int unwrapPosition(@NonNull RecyclerView.Adapter originAdapter, @Nullable RecyclerView.Adapter targetAdapter, int position) { return unwrapPosition(originAdapter, targetAdapter, null, position, null); } public static int unwrapPosition(@NonNull RecyclerView.Adapter originAdapter, @Nullable RecyclerView.Adapter targetAdapter, Object targetAdapterTag, int position) { return unwrapPosition(originAdapter, targetAdapter, targetAdapterTag, position, null); } public static int unwrapPosition(RecyclerView.Adapter originAdapter, RecyclerView.Adapter targetAdapter, Object targetAdapterTag, int originPosition, @Nullable AdapterPath destPath) { RecyclerView.Adapter wrapper = originAdapter; int wrappedPosition = originPosition; final UnwrapPositionResult tmpResult = new UnwrapPositionResult(); Object wrappedAdapterTag = null; if (destPath != null) { destPath.clear(); } if (wrapper == null) { return RecyclerView.NO_POSITION; } if (destPath != null) { destPath.append(new AdapterPathSegment(originAdapter, null)); } do { if (wrappedPosition == RecyclerView.NO_POSITION) { break; } if (wrapper == targetAdapter) { break; } if (!(wrapper instanceof WrapperAdapter)) { if (targetAdapter != null) { wrappedPosition = RecyclerView.NO_POSITION; } break; } final WrapperAdapter wrapperParentAdapter = (WrapperAdapter) wrapper; tmpResult.clear(); wrapperParentAdapter.unwrapPosition(tmpResult, wrappedPosition); wrappedPosition = tmpResult.position; wrappedAdapterTag = tmpResult.tag; if (tmpResult.isValid()) { if (destPath != null) { destPath.append(tmpResult); } } wrapper = tmpResult.adapter; } while (wrapper != null); if (targetAdapter != null && wrapper != targetAdapter) { wrappedPosition = RecyclerView.NO_POSITION; } if (targetAdapterTag != null && (wrappedAdapterTag != targetAdapterTag)) { wrappedPosition = RecyclerView.NO_POSITION; } if (wrappedPosition == RecyclerView.NO_POSITION && destPath != null) { destPath.clear(); } return wrappedPosition; } public static int wrapPosition(@NonNull AdapterPath path, @Nullable RecyclerView.Adapter originAdapter, @Nullable RecyclerView.Adapter targetAdapter, int position) { final List<AdapterPathSegment> segments = path.segments(); final int nSegments = segments.size(); int originSegmentIndex = (originAdapter == null) ? nSegments - 1 : -1; int targetSegmentIndex = (targetAdapter == null) ? 0 : -1; if (originAdapter != null || targetAdapter != null) { for (int i = 0; i < nSegments; i++) { AdapterPathSegment segment = segments.get(i); if (originAdapter != null && segment.adapter == originAdapter) { originSegmentIndex = i; } if (targetAdapter != null && segment.adapter == targetAdapter) { targetSegmentIndex = i; } } } if (!((originSegmentIndex != -1) && (targetSegmentIndex != -1) && (targetSegmentIndex <= originSegmentIndex))) { return RecyclerView.NO_POSITION; } return wrapPosition(path, originSegmentIndex, targetSegmentIndex, position); } public static int wrapPosition(@NonNull AdapterPath path, int originSegmentIndex, int targetSegmentIndex, int position) { final List<AdapterPathSegment> segments = path.segments(); int wrappedPosition = position; for (int i = originSegmentIndex; i > targetSegmentIndex; i--) { AdapterPathSegment segment = segments.get(i); AdapterPathSegment parentSegment = segments.get(i - 1); final int prevWrappedPosition = wrappedPosition; wrappedPosition = ((WrapperAdapter) parentSegment.adapter).wrapPosition(segment, wrappedPosition); if (wrappedPosition == RecyclerView.NO_POSITION) { break; } } return wrappedPosition; } }