1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.support.v4.util.CircularIntArray;
17
18import java.io.PrintWriter;
19
20/**
21 * A Grid with restriction to single row.
22 */
23class SingleRow extends Grid {
24
25    private final Location mTmpLocation = new Location(0);
26    private Object[] mTmpItem = new Object[1];
27
28    SingleRow() {
29        setNumRows(1);
30    }
31
32    @Override
33    public final Location getLocation(int index) {
34        // all items are on row 0, share the same Location object.
35        return mTmpLocation;
36    }
37
38    @Override
39    public final void debugPrint(PrintWriter pw) {
40        pw.print("SingleRow<");
41        pw.print(mFirstVisibleIndex);
42        pw.print(",");
43        pw.print(mLastVisibleIndex);
44        pw.print(">");
45        pw.println();
46    }
47
48    int getStartIndexForAppend() {
49        if (mLastVisibleIndex >= 0) {
50            return mLastVisibleIndex + 1;
51        } else if (mStartIndex != START_DEFAULT) {
52            return Math.min(mStartIndex, mProvider.getCount() - 1);
53        } else {
54            return 0;
55        }
56    }
57
58    int getStartIndexForPrepend() {
59        if (mFirstVisibleIndex >= 0) {
60            return mFirstVisibleIndex - 1;
61        } else if (mStartIndex != START_DEFAULT) {
62            return Math.min(mStartIndex, mProvider.getCount() - 1);
63        } else {
64            return mProvider.getCount() - 1;
65        }
66    }
67
68    @Override
69    protected final boolean prependVisibleItems(int toLimit, boolean oneColumnMode) {
70        if (mProvider.getCount() == 0) {
71            return false;
72        }
73        if (!oneColumnMode && checkPrependOverLimit(toLimit)) {
74            return false;
75        }
76        boolean filledOne = false;
77        for (int index = getStartIndexForPrepend(); index >= 0; index--) {
78            int size = mProvider.createItem(index, false, mTmpItem);
79            int edge;
80            if (mFirstVisibleIndex < 0 || mLastVisibleIndex < 0) {
81                edge = mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE;
82                mLastVisibleIndex = mFirstVisibleIndex = index;
83            } else {
84                if (mReversedFlow) {
85                    edge = mProvider.getEdge(index + 1) + mMargin + size;
86                } else {
87                    edge = mProvider.getEdge(index + 1) - mMargin - size;
88                }
89                mFirstVisibleIndex = index;
90            }
91            mProvider.addItem(mTmpItem[0], index, size, 0, edge);
92            filledOne = true;
93            if (oneColumnMode || checkPrependOverLimit(toLimit)) {
94                break;
95            }
96        }
97        return filledOne;
98    }
99
100    @Override
101    protected final boolean appendVisibleItems(int toLimit, boolean oneColumnMode) {
102        if (mProvider.getCount() == 0) {
103            return false;
104        }
105        if (!oneColumnMode && checkAppendOverLimit(toLimit)) {
106            // not in one column mode, return immediately if over limit
107            return false;
108        }
109        boolean filledOne = false;
110        for (int index = getStartIndexForAppend(); index < mProvider.getCount(); index++) {
111            int size = mProvider.createItem(index, true, mTmpItem);
112            int edge;
113            if (mFirstVisibleIndex < 0 || mLastVisibleIndex< 0) {
114                edge = mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE;
115                mLastVisibleIndex = mFirstVisibleIndex = index;
116            } else {
117                if (mReversedFlow) {
118                    edge = mProvider.getEdge(index - 1) - mProvider.getSize(index - 1) - mMargin;
119                } else {
120                    edge = mProvider.getEdge(index - 1) + mProvider.getSize(index - 1) + mMargin;
121                }
122                mLastVisibleIndex = index;
123            }
124            mProvider.addItem(mTmpItem[0], index, size, 0, edge);
125            filledOne = true;
126            if (oneColumnMode || checkAppendOverLimit(toLimit)) {
127                break;
128            }
129        }
130        return filledOne;
131    }
132
133    @Override
134    public final CircularIntArray[] getItemPositionsInRows(int startPos, int endPos) {
135        // all items are on the same row:
136        mTmpItemPositionsInRows[0].clear();
137        mTmpItemPositionsInRows[0].addLast(startPos);
138        mTmpItemPositionsInRows[0].addLast(endPos);
139        return mTmpItemPositionsInRows;
140    }
141
142    @Override
143    protected final int findRowMin(boolean findLarge, int indexLimit, int[] indices) {
144        if (indices != null) {
145            indices[0] = 0;
146            indices[1] = indexLimit;
147        }
148        return mReversedFlow ? mProvider.getEdge(indexLimit) - mProvider.getSize(indexLimit)
149                : mProvider.getEdge(indexLimit);
150    }
151
152    @Override
153    protected final int findRowMax(boolean findLarge, int indexLimit, int[] indices) {
154        if (indices != null) {
155            indices[0] = 0;
156            indices[1] = indexLimit;
157        }
158        return mReversedFlow ? mProvider.getEdge(indexLimit)
159                : mProvider.getEdge(indexLimit) + mProvider.getSize(indexLimit);
160    }
161
162}
163