16e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu/* 26e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Copyright (C) 2014 The Android Open Source Project 36e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 46e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 56e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in compliance with the License. You may obtain a copy of the License at 66e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 76e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * http://www.apache.org/licenses/LICENSE-2.0 86e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 96e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License 106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * or implied. See the License for the specific language governing permissions and limitations under 126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the License. 136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gupackage android.support.v17.leanback.widget; 156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guimport android.support.v4.util.CircularIntArray; 176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guimport android.util.Log; 186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guimport java.io.PrintWriter; 206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu/** 22f923d595ace34894c49d1609d3c629336b175b89Dake Gu * A grid is representation of single or multiple rows layout data structure and algorithm. 23f923d595ace34894c49d1609d3c629336b175b89Dake Gu * Grid is the base class for single row, non-staggered grid and staggered grid. 246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * To use the Grid, user must implement a Provider to create or remove visible item. 266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Grid maintains a list of visible items. Visible items are created when 276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * user calls appendVisibleItems() or prependVisibleItems() with certain limitation 286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (e.g. a max edge that append up to). Visible items are deleted when user calls 296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * removeInvisibleItemsAtEnd() or removeInvisibleItemsAtFront(). Grid's algorithm 306e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * uses size of visible item returned from Provider.createItem() to decide which row 316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * to add a new visible item and may cache the algorithm results. User must call 326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * invalidateItemsAfter() when it detects item size changed to ask Grid to remove cached 336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * results. 346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Guabstract class Grid { 366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * A constant representing a default starting index, indicating that the 396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * developer did not provide a start index. 406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static final int START_DEFAULT = -1; 426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * When user uses Grid, he should provide count of items and 456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the method to create item and remove item. 466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static interface Provider { 486e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return how many items (are in the adapter). 516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract int getCount(); 536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Create visible item and where the provider should measure it. 566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * The call is always followed by addItem(). 576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 586e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param append True if new item is after last visible item, false if new item is 596e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * before first visible item. 606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param item item[0] returns created item that will be passed in addItem() call. 616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return length of the item. 626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract int createItem(int index, boolean append, Object[] item); 646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * add item to given row and given edge. The call is always after createItem(). 676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param item The object returned by createItem() 686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param length The size of the object 706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param rowIndex Row index to put the item 716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param edge min_edge if not reversed or max_edge if reversed. 726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract void addItem(Object item, int index, int length, int rowIndex, int edge); 746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Remove visible item at index. 776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract void removeItem(int index); 806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Get edge of an existing visible item. edge will be the min_edge 836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if not reversed or the max_edge if reversed. 846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract int getEdge(int index); 876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Get size of an existing visible item. 906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param index 0-based index of the item in provider 916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract int getSize(int index); 936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Cached representation of an item in Grid. May be subclassed. 976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public static class Location { 996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * The index of the row for this Location. 1016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public int row; 1036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public Location(int row) { 1056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu this.row = row; 1066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected Provider mProvider; 1106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected boolean mReversedFlow; 1116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mMargin; 1126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mNumRows; 1136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mFirstVisibleIndex = -1; 1146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mLastVisibleIndex = -1; 1156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected CircularIntArray[] mTmpItemPositionsInRows; 1176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu // the first index that grid will layout 1196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected int mStartIndex = START_DEFAULT; 1206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 122f923d595ace34894c49d1609d3c629336b175b89Dake Gu * Creates a single or multiple rows (can be staggered or not staggered) grid 1236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 124f923d595ace34894c49d1609d3c629336b175b89Dake Gu public static Grid createGrid(int rows) { 125f923d595ace34894c49d1609d3c629336b175b89Dake Gu Grid grid; 126f923d595ace34894c49d1609d3c629336b175b89Dake Gu if (rows == 1) { 127f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid = new SingleRow(); 128f923d595ace34894c49d1609d3c629336b175b89Dake Gu } else { 129f923d595ace34894c49d1609d3c629336b175b89Dake Gu // TODO support non staggered multiple rows grid 130f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid = new StaggeredGridDefault(); 131f923d595ace34894c49d1609d3c629336b175b89Dake Gu grid.setNumRows(rows); 132f923d595ace34894c49d1609d3c629336b175b89Dake Gu } 1336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return grid; 1346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets the margin between items in a row 1386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void setMargin(int margin) { 1406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mMargin = margin; 1416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets if reversed flow (rtl) 1456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void setReversedFlow(boolean reversedFlow) { 1476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mReversedFlow = reversedFlow; 1486e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if reversed flow (rtl) 1526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public boolean isReversedFlow() { 1546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mReversedFlow; 1556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1586e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets the {@link Provider} for this grid. 1596e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 1606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param provider The provider for this grid. 1616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void setProvider(Provider provider) { 1636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider = provider; 1646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets the first item index to create when there are no items. 1686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 1696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param startIndex the index of the first item 1706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void setStart(int startIndex) { 1726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mStartIndex = startIndex; 1736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns the number of rows in the grid. 1776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public int getNumRows() { 1796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mNumRows; 1806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 1826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 1836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Sets number of rows to fill into. For views that represent a 1846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * horizontal list, this will be the rows of the view. For views that 1856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * represent a vertical list, this will be the columns. 1866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * 1876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param numRows numberOfRows 1886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 1896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu void setNumRows(int numRows) { 1906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (numRows <= 0) { 1916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu throw new IllegalArgumentException(); 1926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mNumRows == numRows) { 1946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 1956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 1966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mNumRows = numRows; 1976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mTmpItemPositionsInRows = new CircularIntArray[mNumRows]; 1986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu for (int i = 0; i < mNumRows; i++) { 1996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mTmpItemPositionsInRows[i] = new CircularIntArray(); 2006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns index of first visible item in the staggered grid. Returns negative value 2056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if no visible item. 2066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getFirstVisibleIndex() { 2086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mFirstVisibleIndex; 2096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns index of last visible item in the staggered grid. Returns negative value 2136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * if no visible item. 2146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getLastVisibleIndex() { 2166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return mLastVisibleIndex; 2176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Reset visible indices and keep cache (if exists) 2216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void resetVisibleIndex() { 2236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mFirstVisibleIndex = mLastVisibleIndex = -1; 2246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Invalidate items after or equal to index. This will remove visible items 2286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * after that and invalidate cache of layout results after that. 2296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2306e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void invalidateItemsAfter(int index) { 2316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (index < 0) { 2326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 2336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mLastVisibleIndex < 0) { 2356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return; 2366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu while (mLastVisibleIndex >= index) { 2386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider.removeItem(mLastVisibleIndex); 2396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mLastVisibleIndex--; 2406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu resetVisbileIndexIfEmpty(); 2426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (getFirstVisibleIndex() < 0) { 2436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu setStart(index); 2446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2486e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Gets the row index of item at given index. 2496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int getRowIndex(int index) { 2516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return getLocation(index).row; 2526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Gets {@link Location} of item. The return object is read only and temporarily. 2566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract Location getLocation(int index); 2586e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2596e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row min edge of visible items, 2616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the row index is returned in indices[0], the item index is returned in indices[1]. 2626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int findRowMin(boolean findLarge, int[] indices) { 2646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return findRowMin(findLarge, mReversedFlow ? mLastVisibleIndex : mFirstVisibleIndex, 2656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu indices); 2666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row min edge of visible items, starts searching from 2706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * indexLimit, the row index is returned in indices[0], the item index is returned in indices[1]. 2716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract int findRowMin(boolean findLarge, int indexLimit, int[] rowIndex); 2736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Finds the largest or smallest row max edge of visible items, the row index is returned in 2766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * indices[0], the item index is returned in indices[1]. 2776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final int findRowMax(boolean findLarge, int[] indices) { 2796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return findRowMax(findLarge, mReversedFlow ? mFirstVisibleIndex : mLastVisibleIndex, 2806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu indices); 2816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Find largest or smallest row max edge of visible items, starts searching from indexLimit, 2856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * the row index is returned in indices[0], the item index is returned in indices[1]. 2866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract int findRowMax(boolean findLarge, int indexLimit, int[] indices); 2886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 2896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 2906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if appending item has reached "toLimit" 2916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 2926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected final boolean checkAppendOverLimit(int toLimit) { 29385df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu if (mLastVisibleIndex < 0) { 29485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return false; 29585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu } 29685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return mReversedFlow ? findRowMin(true, null) <= toLimit + mMargin : 29785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu findRowMax(false, null) >= toLimit - mMargin; 2986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 2996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returns true if prepending item has reached "toLimit" 3026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected final boolean checkPrependOverLimit(int toLimit) { 30485df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu if (mLastVisibleIndex < 0) { 30585df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return false; 30685df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu } 30785df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu return mReversedFlow ? findRowMax(false, null) >= toLimit + mMargin : 30885df3117f0fcd0aa10d7bd45194dab97e22112f2Dake Gu findRowMin(true, null) <= toLimit - mMargin; 3096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return array of int array for all rows, each int array contains visible item positions 3136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in pair on that row between startPos(included) and endPositions(included). 3146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returned value is read only, do not change it. 3156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 3166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * E.g. First row has 3,7,8, second row has 4,5,6. 3176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * getItemPositionsInRows(3, 8) returns { {3,3,7,8}, {4,6} } 3186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract CircularIntArray[] getItemPositionsInRows(int startPos, int endPos); 3206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Return array of int array for all rows, each int array contains visible item positions 3236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * in pair on that row. 3246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Returned value is read only, do not change it. 3256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * <p> 3266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * E.g. First row has 3,7,8, second row has 4,5,6 { {3,3,7,8}, {4,6} } 3276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3286e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final CircularIntArray[] getItemPositionsInRows() { 3296e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return getItemPositionsInRows(getFirstVisibleIndex(), getLastVisibleIndex()); 3306e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3316e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3326e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3336e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items and stops after one column is filled. 3346e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (i.e. filled items from row 0 to row mNumRows - 1) 3356e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3366e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3376e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final boolean prependOneColumnVisibleItems() { 3386e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return prependVisibleItems(mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE, true); 3396e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3406e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3416e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3426e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items until first item or reaches toLimit (min edge when not reversed or 3436e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * max edge when reversed) 3446e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3456e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void prependVisibleItems(int toLimit) { 3466e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu prependVisibleItems(toLimit, false); 3476e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3486e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3496e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3506e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Prepends items until first item or reaches toLimit (min edge when not reversed or 3516e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * max edge when reversed). 3526e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param oneColumnMode true when fills one column and stops, false 3536e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * when checks if condition matches before filling first column. 3546e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3556e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3566e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract boolean prependVisibleItems(int toLimit, boolean oneColumnMode); 3576e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3586e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3596e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Appends items and stops after one column is filled. 3606e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * (i.e. filled items from row 0 to row mNumRows - 1) 3616e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if at least one item is filled. 3626e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3636e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public boolean appendOneColumnVisibleItems() { 3646e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu return appendVisibleItems(mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE, true); 3656e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3666e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3676e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3686e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Append items until last item or reaches toLimit (max edge when not 3696e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * reversed or min edge when reversed) 3706e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3716e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public final void appendVisibleItems(int toLimit) { 3726e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu appendVisibleItems(toLimit, false); 3736e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3746e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3756e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3766e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Appends items until last or reaches toLimit (high edge when not 3776e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * reversed or low edge when reversed). 3786e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @param oneColumnMode True when fills one column and stops, false 3796e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * when checks if condition matches before filling first column. 3806e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * @return true if filled at least one item 3816e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3826e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu protected abstract boolean appendVisibleItems(int toLimit, boolean oneColumnMode); 3836e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 3846e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 3856e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Removes invisible items from end until reaches item at aboveIndex or toLimit. 3866e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 3876e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void removeInvisibleItemsAtEnd(int aboveIndex, int toLimit) { 3886e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu while(mLastVisibleIndex >= mFirstVisibleIndex && mLastVisibleIndex > aboveIndex) { 3896e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu boolean offEnd = !mReversedFlow ? mProvider.getEdge(mLastVisibleIndex) >= toLimit 3906e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu : mProvider.getEdge(mLastVisibleIndex) <= toLimit; 3916e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (offEnd) { 3926e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider.removeItem(mLastVisibleIndex); 3936e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mLastVisibleIndex--; 3946e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } else { 3956e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu break; 3966e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3976e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 3986e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu resetVisbileIndexIfEmpty(); 3996e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4006e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 4016e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu /** 4026e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu * Removes invisible items from front until reaches item at belowIndex or toLimit. 4036e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu */ 4046e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public void removeInvisibleItemsAtFront(int belowIndex, int toLimit) { 4056e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu while(mLastVisibleIndex >= mFirstVisibleIndex && mFirstVisibleIndex < belowIndex) { 4066e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu boolean offFront = !mReversedFlow ? mProvider.getEdge(mFirstVisibleIndex) 4076e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu + mProvider.getSize(mFirstVisibleIndex) <= toLimit 4086e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu : mProvider.getEdge(mFirstVisibleIndex) 4096e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu - mProvider.getSize(mFirstVisibleIndex) >= toLimit; 4106e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (offFront) { 4116e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mProvider.removeItem(mFirstVisibleIndex); 4126e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu mFirstVisibleIndex++; 4136e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } else { 4146e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu break; 4156e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4166e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4176e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu resetVisbileIndexIfEmpty(); 4186e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4196e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 4206e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu private void resetVisbileIndexIfEmpty() { 4216e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu if (mLastVisibleIndex < mFirstVisibleIndex) { 4226e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu resetVisibleIndex(); 4236e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4246e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu } 4256e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu 4266e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu public abstract void debugPrint(PrintWriter pw); 4276e96b9d46e7af6bedf6213ecc2ba0ad7b8050778Dake Gu} 428