diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
| commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/widget/AlphabetIndexer.java | |
| parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/widget/AlphabetIndexer.java')
| -rw-r--r-- | core/java/android/widget/AlphabetIndexer.java | 283 |
1 files changed, 0 insertions, 283 deletions
diff --git a/core/java/android/widget/AlphabetIndexer.java b/core/java/android/widget/AlphabetIndexer.java deleted file mode 100644 index bbabaaaf74ac..000000000000 --- a/core/java/android/widget/AlphabetIndexer.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * 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 android.widget; - -import android.database.Cursor; -import android.database.DataSetObserver; -import android.util.SparseIntArray; - -/** - * A helper class for adapters that implement the SectionIndexer interface. - * If the items in the adapter are sorted by simple alphabet-based sorting, then - * this class provides a way to do fast indexing of large lists using binary search. - * It caches the indices that have been determined through the binary search and also - * invalidates the cache if changes occur in the cursor. - * <p/> - * Your adapter is responsible for updating the cursor by calling {@link #setCursor} if the - * cursor changes. {@link #getPositionForSection} method does the binary search for the starting - * index of a given section (alphabet). - * @hide pending API council approval - */ -public class AlphabetIndexer extends DataSetObserver implements SectionIndexer { - - /** - * Cursor that is used by the adapter of the list view. - */ - protected Cursor mDataCursor; - - /** - * The index of the cursor column that this list is sorted on. - */ - protected int mColumnIndex; - - /** - * The string of characters that make up the indexing sections. - */ - protected CharSequence mAlphabet; - - /** - * Cached length of the alphabet array. - */ - private int mAlphabetLength; - - /** - * This contains a cache of the computed indices so far. It will get reset whenever - * the dataset changes or the cursor changes. - */ - private SparseIntArray mAlphaMap; - - /** - * Use a collator to compare strings in a localized manner. - */ - private java.text.Collator mCollator; - - /** - * The section array converted from the alphabet string. - */ - private String[] mAlphabetArray; - - /** - * Constructs the indexer. - * @param cursor the cursor containing the data set - * @param sortedColumnIndex the column number in the cursor that is sorted - * alphabetically - * @param alphabet string containing the alphabet, with space as the first character. - * For example, use the string " ABCDEFGHIJKLMNOPQRSTUVWXYZ" for English indexing. - * The characters must be uppercase and be sorted in ascii/unicode order. Basically - * characters in the alphabet will show up as preview letters. - */ - public AlphabetIndexer(Cursor cursor, int sortedColumnIndex, CharSequence alphabet) { - mDataCursor = cursor; - mColumnIndex = sortedColumnIndex; - mAlphabet = alphabet; - mAlphabetLength = alphabet.length(); - mAlphabetArray = new String[mAlphabetLength]; - for (int i = 0; i < mAlphabetLength; i++) { - mAlphabetArray[i] = Character.toString(mAlphabet.charAt(i)); - } - mAlphaMap = new SparseIntArray(mAlphabetLength); - if (cursor != null) { - cursor.registerDataSetObserver(this); - } - // Get a Collator for the current locale for string comparisons. - mCollator = java.text.Collator.getInstance(); - mCollator.setStrength(java.text.Collator.PRIMARY); - } - - /** - * Returns the section array constructed from the alphabet provided in the constructor. - * @return the section array - */ - public Object[] getSections() { - return mAlphabetArray; - } - - /** - * Sets a new cursor as the data set and resets the cache of indices. - * @param cursor the new cursor to use as the data set - */ - public void setCursor(Cursor cursor) { - if (mDataCursor != null) { - mDataCursor.unregisterDataSetObserver(this); - } - mDataCursor = cursor; - if (cursor != null) { - mDataCursor.registerDataSetObserver(this); - } - mAlphaMap.clear(); - } - - /** - * Default implementation compares the first character of word with letter. - */ - protected int compare(String word, String letter) { - return mCollator.compare(word.substring(0, 1), letter); - } - - /** - * Performs a binary search or cache lookup to find the first row that - * matches a given section's starting letter. - * @param sectionIndex the section to search for - * @return the row index of the first occurrence, or the nearest next letter. - * For instance, if searching for "T" and no "T" is found, then the first - * row starting with "U" or any higher letter is returned. If there is no - * data following "T" at all, then the list size is returned. - */ - public int getPositionForSection(int sectionIndex) { - final SparseIntArray alphaMap = mAlphaMap; - final Cursor cursor = mDataCursor; - - if (cursor == null || mAlphabet == null) { - return 0; - } - - // Check bounds - if (sectionIndex <= 0) { - return 0; - } - if (sectionIndex >= mAlphabetLength) { - sectionIndex = mAlphabetLength - 1; - } - - int savedCursorPos = cursor.getPosition(); - - int count = cursor.getCount(); - int start = 0; - int end = count; - int pos; - - char letter = mAlphabet.charAt(sectionIndex); - String targetLetter = Character.toString(letter); - int key = letter; - // Check map - if (Integer.MIN_VALUE != (pos = alphaMap.get(key, Integer.MIN_VALUE))) { - // Is it approximate? Using negative value to indicate that it's - // an approximation and positive value when it is the accurate - // position. - if (pos < 0) { - pos = -pos; - end = pos; - } else { - // Not approximate, this is the confirmed start of section, return it - return pos; - } - } - - // Do we have the position of the previous section? - if (sectionIndex > 0) { - int prevLetter = - mAlphabet.charAt(sectionIndex - 1); - int prevLetterPos = alphaMap.get(prevLetter, Integer.MIN_VALUE); - if (prevLetterPos != Integer.MIN_VALUE) { - start = Math.abs(prevLetterPos); - } - } - - // Now that we have a possibly optimized start and end, let's binary search - - pos = (end + start) / 2; - - while (pos < end) { - // Get letter at pos - cursor.moveToPosition(pos); - String curName = cursor.getString(mColumnIndex); - if (curName == null) { - if (pos == 0) { - break; - } else { - pos--; - continue; - } - } - int diff = compare(curName, targetLetter); - if (diff != 0) { - // Commenting out approximation code because it doesn't work for certain - // lists with custom comparators - // Enter approximation in hash if a better solution doesn't exist - // String startingLetter = Character.toString(getFirstLetter(curName)); - // int startingLetterKey = startingLetter.charAt(0); - // int curPos = alphaMap.get(startingLetterKey, Integer.MIN_VALUE); - // if (curPos == Integer.MIN_VALUE || Math.abs(curPos) > pos) { - // Negative pos indicates that it is an approximation - // alphaMap.put(startingLetterKey, -pos); - // } - // if (mCollator.compare(startingLetter, targetLetter) < 0) { - if (diff < 0) { - start = pos + 1; - if (start >= count) { - pos = count; - break; - } - } else { - end = pos; - } - } else { - // They're the same, but that doesn't mean it's the start - if (start == pos) { - // This is it - break; - } else { - // Need to go further lower to find the starting row - end = pos; - } - } - pos = (start + end) / 2; - } - alphaMap.put(key, pos); - cursor.moveToPosition(savedCursorPos); - return pos; - } - - /** - * Returns the section index for a given position in the list by querying the item - * and comparing it with all items in the section array. - */ - public int getSectionForPosition(int position) { - int savedCursorPos = mDataCursor.getPosition(); - mDataCursor.moveToPosition(position); - mDataCursor.moveToPosition(savedCursorPos); - String curName = mDataCursor.getString(mColumnIndex); - // Linear search, as there are only a few items in the section index - // Could speed this up later if it actually gets used. - for (int i = 0; i < mAlphabetLength; i++) { - char letter = mAlphabet.charAt(i); - String targetLetter = Character.toString(letter); - if (compare(curName, targetLetter) == 0) { - return i; - } - } - return 0; // Don't recognize the letter - falls under zero'th section - } - - /* - * @hide - */ - @Override - public void onChanged() { - super.onChanged(); - mAlphaMap.clear(); - } - - /* - * @hide - */ - @Override - public void onInvalidated() { - super.onInvalidated(); - mAlphaMap.clear(); - } -} |
