1a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev/*
2a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Copyright (C) 2015 The Android Open Source Project
3a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
4a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Licensed under the Apache License, Version 2.0 (the "License");
5a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * you may not use this file except in compliance with the License.
6a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * You may obtain a copy of the License at
7a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
8a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *      http://www.apache.org/licenses/LICENSE-2.0
9a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev *
10a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * Unless required by applicable law or agreed to in writing, software
11a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * distributed under the License is distributed on an "AS IS" BASIS,
12a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * See the License for the specific language governing permissions and
14a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * limitations under the License.
15a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev */
16a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
17a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevpackage android.support.v7.util;
18a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
19a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport android.util.SparseArray;
20a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
21a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevimport java.lang.reflect.Array;
22a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
23a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev/**
24a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev * A sparse collection of tiles sorted for efficient access.
25a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev */
26a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheevclass TileList<T> {
27a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
28a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    final int mTileSize;
29a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
30a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    // Keyed by start position.
31a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    private final SparseArray<Tile<T>> mTiles = new SparseArray<Tile<T>>(10);
32a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
33a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    Tile<T> mLastAccessedTile;
34a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
35a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public TileList(int tileSize) {
36a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mTileSize = tileSize;
37a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
38a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
39a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public T getItemAt(int pos) {
40a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        if (mLastAccessedTile == null || !mLastAccessedTile.containsPosition(pos)) {
41a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            final int startPosition = pos - (pos % mTileSize);
42a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            final int index = mTiles.indexOfKey(startPosition);
43a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            if (index < 0) {
44a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev                return null;
45a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            }
46a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLastAccessedTile = mTiles.valueAt(index);
47a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
48a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return mLastAccessedTile.getByPosition(pos);
49a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
50a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
51a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public int size() {
52a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return mTiles.size();
53a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
54a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
55a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public void clear() {
56a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mTiles.clear();
57a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
58a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
59a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public Tile<T> getAtIndex(int index) {
60a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return mTiles.valueAt(index);
61a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
62a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
63a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public Tile<T> addOrReplace(Tile<T> newTile) {
64a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        final int index = mTiles.indexOfKey(newTile.mStartPosition);
65a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        if (index < 0) {
66a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mTiles.put(newTile.mStartPosition, newTile);
67a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            return null;
68a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
69a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Tile<T> oldTile = mTiles.valueAt(index);
70a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mTiles.setValueAt(index, newTile);
71a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        if (mLastAccessedTile == oldTile) {
72a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLastAccessedTile = newTile;
73a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
74a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return oldTile;
75a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
76a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
77a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public Tile<T> removeAtPos(int startPosition) {
78a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Tile<T> tile = mTiles.get(startPosition);
79a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        if (mLastAccessedTile == tile) {
80a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mLastAccessedTile = null;
81a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
82a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        mTiles.delete(startPosition);
83a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        return tile;
84a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
85a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
86a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    public static class Tile<T> {
87a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public final T[] mItems;
88a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public int mStartPosition;
89a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public int mItemCount;
90a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        Tile<T> mNext;  // Used only for pooling recycled tiles.
91a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
92a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        public Tile(Class<T> klass, int size) {
93a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            //noinspection unchecked
94a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            mItems = (T[]) Array.newInstance(klass, size);
95a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
96a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
97a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        boolean containsPosition(int pos) {
98a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            return mStartPosition <= pos && pos < mStartPosition + mItemCount;
99a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
100a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev
101a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        T getByPosition(int pos) {
102a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev            return mItems[pos - mStartPosition];
103a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev        }
104a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev    }
105a1470623b0f7c52c9e3985012bf9daeb692d7bccVladislav Kaznacheev}
106