16fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins/* 26fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Copyright (C) 2010 The Android Open Source Project 36fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * 46fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Licensed under the Apache License, Version 2.0 (the "License"); 56fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * you may not use this file except in compliance with the License. 66fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * You may obtain a copy of the License at 76fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * 86fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * http://www.apache.org/licenses/LICENSE-2.0 96fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * 106fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Unless required by applicable law or agreed to in writing, software 116fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * distributed under the License is distributed on an "AS IS" BASIS, 126fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * See the License for the specific language governing permissions and 146fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * limitations under the License. 156fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 166fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 176fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginspackage com.android.browser; 186fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 196fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.content.Context; 206fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.database.Cursor; 216fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.database.DataSetObserver; 222483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scrogginsimport android.view.LayoutInflater; 236fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.view.View; 246fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.view.ViewGroup; 256fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scrogginsimport android.webkit.DateSorter; 268ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonimport android.widget.BaseExpandableListAdapter; 272483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scrogginsimport android.widget.ExpandableListView; 282483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scrogginsimport android.widget.TextView; 296fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 306fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins/** 316fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * ExpandableListAdapter which separates data into categories based on date. 326fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Used for History and Downloads. 336fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 348ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamiltonpublic class DateSortedExpandableListAdapter extends BaseExpandableListAdapter { 356fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // Array for each of our bins. Each entry represents how many items are 366fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // in that bin. 376fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private int mItemMap[]; 386fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // This is our GroupCount. We will have at most DateSorter.DAY_COUNT 396fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // bins, less if the user has no items in one or more bins. 406fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private int mNumberOfBins; 416fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private Cursor mCursor; 426fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private DateSorter mDateSorter; 436fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private int mDateIndex; 442483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins private int mIdIndex; 452483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins private Context mContext; 466fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 478ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton boolean mDataValid; 486fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 498ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton DataSetObserver mDataSetObserver = new DataSetObserver() { 506fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins @Override 518ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public void onChanged() { 528ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mDataValid = true; 538ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton notifyDataSetChanged(); 546fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 556fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 566fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins @Override 578ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public void onInvalidated() { 588ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mDataValid = false; 598ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton notifyDataSetInvalidated(); 606fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 618ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton }; 628ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 638ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public DateSortedExpandableListAdapter(Context context, int dateIndex) { 642483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins mContext = context; 656fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mDateSorter = new DateSorter(context); 666fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mDateIndex = dateIndex; 678ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mDataValid = false; 688ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mIdIndex = -1; 696fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 706fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 716fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 726fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Set up the bins for determining which items belong to which groups. 736fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 746fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private void buildMap() { 756fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // The cursor is sorted by date 766fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // The ItemMap will store the number of items in each bin. 776fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int array[] = new int[DateSorter.DAY_COUNT]; 786fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // Zero out the array. 796fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins for (int j = 0; j < DateSorter.DAY_COUNT; j++) { 806fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins array[j] = 0; 816fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 826fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mNumberOfBins = 0; 836fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int dateIndex = -1; 846fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (mCursor.moveToFirst() && mCursor.getCount() > 0) { 856fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins while (!mCursor.isAfterLast()) { 862483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins long date = getLong(mDateIndex); 876fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int index = mDateSorter.getIndex(date); 886fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (index > dateIndex) { 896fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mNumberOfBins++; 906fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (index == DateSorter.DAY_COUNT - 1) { 916fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // We are already in the last bin, so it will 926fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // include all the remaining items 936fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins array[index] = mCursor.getCount() 946fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins - mCursor.getPosition(); 956fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins break; 966fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 976fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins dateIndex = index; 986fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 996fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins array[dateIndex]++; 1006fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mCursor.moveToNext(); 1016fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1026fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1036fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins mItemMap = array; 1046fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1056fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 1066fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 1076fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Get the byte array at cursorIndex from the Cursor. Assumes the Cursor 1086fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * has already been moved to the correct position. Along with 1096fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * {@link #getInt} and {@link #getString}, these are provided so the client 1106fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * does not need to access the Cursor directly 1116fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param cursorIndex Index to query the Cursor. 1126fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @return corresponding byte array from the Cursor. 1136fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 1146fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /* package */ byte[] getBlob(int cursorIndex) { 1158ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return null; 1166fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return mCursor.getBlob(cursorIndex); 1176fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1186fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 1192483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins /* package */ Context getContext() { 1202483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return mContext; 1212483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 1222483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins 1236fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 1246fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Get the integer at cursorIndex from the Cursor. Assumes the Cursor has 1256fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * already been moved to the correct position. Along with 1266fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * {@link #getBlob} and {@link #getString}, these are provided so the client 1276fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * does not need to access the Cursor directly 1286fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param cursorIndex Index to query the Cursor. 1296fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @return corresponding integer from the Cursor. 1306fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 1316fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /* package */ int getInt(int cursorIndex) { 1328ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 1336fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return mCursor.getInt(cursorIndex); 1346fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1356fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 1366fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 1372483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * Get the long at cursorIndex from the Cursor. Assumes the Cursor has 1382483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * already been moved to the correct position. 1396fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 1402483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins /* package */ long getLong(int cursorIndex) { 1418ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 1422483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return mCursor.getLong(cursorIndex); 1436fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1446fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 1456fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 1466fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Get the String at cursorIndex from the Cursor. Assumes the Cursor has 1476fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * already been moved to the correct position. Along with 1486fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * {@link #getInt} and {@link #getInt}, these are provided so the client 1496fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * does not need to access the Cursor directly 1506fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param cursorIndex Index to query the Cursor. 1516fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @return corresponding String from the Cursor. 1526fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 1536fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /* package */ String getString(int cursorIndex) { 1548ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return null; 1556fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return mCursor.getString(cursorIndex); 1566fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1576fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 1586fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 1592483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * Determine which group an item belongs to. 1602483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * @param childId ID of the child view in question. 1612483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * @return int Group position of the containing group. 1622483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins /* package */ int groupFromChildId(long childId) { 1638ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return -1; 1642483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins int group = -1; 1652483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins for (mCursor.moveToFirst(); !mCursor.isAfterLast(); 1662483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins mCursor.moveToNext()) { 1672483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins if (getLong(mIdIndex) == childId) { 1682483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins int bin = mDateSorter.getIndex(getLong(mDateIndex)); 1692483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins // bin is the same as the group if the number of bins is the 1702483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins // same as DateSorter 1718ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (DateSorter.DAY_COUNT == mNumberOfBins) { 1728ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton return bin; 1738ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 1742483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins // There are some empty bins. Find the corresponding group. 1752483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins group = 0; 1762483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins for (int i = 0; i < bin; i++) { 1778ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (mItemMap[i] != 0) { 1788ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton group++; 1798ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 1802483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 1812483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins break; 1822483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 1832483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 1842483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return group; 1852483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 1862483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins 1872483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins /** 1886fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Translates from a group position in the ExpandableList to a bin. This is 1896fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * necessary because some groups have no history items, so we do not include 1906fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * those in the ExpandableList. 1916fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param groupPosition Position in the ExpandableList's set of groups 1926fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @return The corresponding bin that holds that group. 1936fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 1946fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins private int groupPositionToBin(int groupPosition) { 1958ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return -1; 1966fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (groupPosition < 0 || groupPosition >= DateSorter.DAY_COUNT) { 1976fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins throw new AssertionError("group position out of range"); 1986fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 1996fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (DateSorter.DAY_COUNT == mNumberOfBins || 0 == mNumberOfBins) { 2006fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // In the first case, we have exactly the same number of bins 2016fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // as our maximum possible, so there is no need to do a 2026fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // conversion 2036fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // The second statement is in case this method gets called when 2046fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // the array is empty, in which case the provided groupPosition 2056fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins // will do fine. 2066fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return groupPosition; 2076fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2086fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int arrayPosition = -1; 2096fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins while (groupPosition > -1) { 2106fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins arrayPosition++; 2116fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins if (mItemMap[arrayPosition] != 0) { 2126fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins groupPosition--; 2136fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2146fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2156fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return arrayPosition; 2166fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2176fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 2186fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /** 2192483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * Move the cursor to the position indicated. 2202483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * @param packedPosition Position in packed position representation. 2212483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins * @return True on success, false otherwise. 2222483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins */ 2232483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins boolean moveCursorToPackedChildPosition(long packedPosition) { 2242483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins if (ExpandableListView.getPackedPositionType(packedPosition) != 2252483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins ExpandableListView.PACKED_POSITION_TYPE_CHILD) { 2262483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return false; 2272483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 2282483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins int groupPosition = ExpandableListView.getPackedPositionGroup( 2292483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins packedPosition); 2302483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins int childPosition = ExpandableListView.getPackedPositionChild( 2312483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins packedPosition); 2322483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return moveCursorToChildPosition(groupPosition, childPosition); 2332483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 2342483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins 2352483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins /** 2366fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * Move the cursor the the position indicated. 2376fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param groupPosition Index of the group containing the desired item. 2386fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @param childPosition Index of the item within the specified group. 2396fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * @return boolean False if the cursor is closed, so the Cursor was not 2406fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins * moved. True on success. 2416fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins */ 2426fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins /* package */ boolean moveCursorToChildPosition(int groupPosition, 2436fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int childPosition) { 2448ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid || mCursor.isClosed()) { 2458ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton return false; 2468ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 2476fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins groupPosition = groupPositionToBin(groupPosition); 2486fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins int index = childPosition; 2496fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins for (int i = 0; i < groupPosition; i++) { 2506fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins index += mItemMap[i]; 2516fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2522483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return mCursor.moveToPosition(index); 2536fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2546fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 2558ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton public void changeCursor(Cursor cursor) { 2568ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (cursor == mCursor) { 2576fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return; 2586fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2598ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (mCursor != null) { 2608ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mCursor.unregisterDataSetObserver(mDataSetObserver); 2618ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mCursor.close(); 2628ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } 2638ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mCursor = cursor; 2648ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (cursor != null) { 2658ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton cursor.registerDataSetObserver(mDataSetObserver); 2668ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mIdIndex = cursor.getColumnIndexOrThrow("_id"); 2678ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mDataValid = true; 2688ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton buildMap(); 2698ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton // notify the observers about the new cursor 2708ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton notifyDataSetChanged(); 2718ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton } else { 2728ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mIdIndex = -1; 2738ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mDataValid = false; 2748ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton // notify the observers about the lack of a data set 2758ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton notifyDataSetInvalidated(); 2766fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2776fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2786fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 2798ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 2806fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public View getGroupView(int groupPosition, boolean isExpanded, 2816fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins View convertView, ViewGroup parent) { 2828ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) throw new IllegalStateException("Data is not valid"); 2832483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins TextView item; 2842483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins if (null == convertView || !(convertView instanceof TextView)) { 2852483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins LayoutInflater factory = LayoutInflater.from(mContext); 2862483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins item = (TextView) factory.inflate(R.layout.history_header, null); 2872483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } else { 2882483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins item = (TextView) convertView; 2892483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 2902483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins String label = mDateSorter.getLabel(groupPositionToBin(groupPosition)); 2912483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins item.setText(label); 2922483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return item; 2936fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 2946fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 2958ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 2966fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public View getChildView(int groupPosition, int childPosition, 2976fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins boolean isLastChild, View convertView, ViewGroup parent) { 2988ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) throw new IllegalStateException("Data is not valid"); 2996fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return null; 3006fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3016fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3028ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3036fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public boolean areAllItemsEnabled() { 3046fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return true; 3056fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3066fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3078ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3086fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public boolean isChildSelectable(int groupPosition, int childPosition) { 3096fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return true; 3106fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3116fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3128ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3136fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public int getGroupCount() { 3148ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3156fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return mNumberOfBins; 3166fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3176fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3188ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3196fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public int getChildrenCount(int groupPosition) { 3208ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3216fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return mItemMap[groupPositionToBin(groupPosition)]; 3226fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3236fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3248ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3256fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public Object getGroup(int groupPosition) { 3266fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return null; 3276fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3286fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3298ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3306fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public Object getChild(int groupPosition, int childPosition) { 3316fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return null; 3326fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3336fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3348ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3356fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public long getGroupId(int groupPosition) { 3368ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3376fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return groupPosition; 3386fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3396fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3408ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3416fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public long getChildId(int groupPosition, int childPosition) { 3428ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3432483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins if (moveCursorToChildPosition(groupPosition, childPosition)) { 3442483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return getLong(mIdIndex); 3452483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins } 3462483745674f95f60b8c3b8c9e817f2df1776a0b5Leon Scroggins return 0; 3476fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3486fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3498ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3506fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public boolean hasStableIds() { 3516fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return true; 3526fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3536fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3548ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3556fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public void onGroupExpanded(int groupPosition) { 3566fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3576fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3588ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3596fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public void onGroupCollapsed(int groupPosition) { 3606fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3616fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3628ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3636fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public long getCombinedChildId(long groupId, long childId) { 3648ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3656fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return childId; 3666fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3676fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3688ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3696fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public long getCombinedGroupId(long groupId) { 3708ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton if (!mDataValid) return 0; 3716fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins return groupId; 3726fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3736fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins 3748ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton @Override 3756fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins public boolean isEmpty() { 3768ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton return !mDataValid || mCursor == null || mCursor.isClosed() || mCursor.getCount() == 0; 3776fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins } 3786fd2ed751dc2efcdaed50631bd0f78f9eb0308fbLeon Scroggins} 379