package edu.vanderbilt.vm.guide.ui.adapter; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.location.Location; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import edu.vanderbilt.vm.guide.R; import edu.vanderbilt.vm.guide.db.GuideDBConstants; import edu.vanderbilt.vm.guide.ui.adapter.CursorIndexerFactory.CursorIndexer; import edu.vanderbilt.vm.guide.util.DBUtils; import edu.vanderbilt.vm.guide.util.Geomancer; public class IndexedCursorAdapter extends BaseAdapter { private final Cursor mCursor; private final Context mContext; private final CursorIndexer mIndexer; private int mIdColIx; private int mNameColIx; private int mCatColIx; private int mLatColIx; private int mLngColIx; public static final int SORT_ALPHABETICALLY = 0; public static final int SORT_BY_DISTANCE = 1; public static final int SORT_BY_CATEGORY = 2; /** * Do not call this constructor. * * @throws Exception */ public IndexedCursorAdapter() throws Exception { throw new Exception("Do not call this constructor"); } public IndexedCursorAdapter(Context context, Cursor cursor, int sort) { mContext = context; mCursor = cursor; mIdColIx = mCursor.getColumnIndex(GuideDBConstants.PlaceTable.ID_COL); if (mIdColIx == -1) { throw new SQLiteException("Cursor does not have an id column"); } mNameColIx = mCursor.getColumnIndex(GuideDBConstants.PlaceTable.NAME_COL); if (mNameColIx == -1) { throw new SQLiteException("Cursor does not have a name column"); } mCatColIx = mCursor.getColumnIndex(GuideDBConstants.PlaceTable.CATEGORY_COL); if (mCatColIx == -1) { throw new SQLiteException("Cursor does not have a category column"); } mLatColIx = mCursor.getColumnIndex(GuideDBConstants.PlaceTable.LATITUDE_COL); if (mLatColIx == -1) { throw new SQLiteException("Cursor does not have a latitude column"); } mLngColIx = mCursor.getColumnIndex(GuideDBConstants.PlaceTable.LONGITUDE_COL); if (mLngColIx == -1) { throw new SQLiteException("Cursor does not have a longitude column"); } switch (sort) { case SORT_ALPHABETICALLY: mIndexer = CursorIndexerFactory.getAlphabeticalIndexer(context, cursor, mNameColIx); break; case SORT_BY_CATEGORY: mIndexer = CursorIndexerFactory.getCategoricalIndexer(context, cursor, mCatColIx); break; case SORT_BY_DISTANCE: mIndexer = CursorIndexerFactory.getDistanceIndexer(context, cursor, mLatColIx, mLngColIx); break; default: mIndexer = null; } } public static String[] getExpectedProjection() { return new String[] { GuideDBConstants.PlaceTable.ID_COL, GuideDBConstants.PlaceTable.NAME_COL, GuideDBConstants.PlaceTable.CATEGORY_COL, GuideDBConstants.PlaceTable.LATITUDE_COL, GuideDBConstants.PlaceTable.LONGITUDE_COL }; } @Override public int getCount() { return mIndexer.categoriesCount() + mCursor.getCount(); } @Override public Object getItem(int position) { checkPosition(position); mCursor.moveToPosition(mIndexer.getDBRow(position)); return DBUtils.getPlaceFromCursor(mCursor); } @Override public long getItemId(int position) { checkPosition(position); if (mIndexer.isHeader(position)) { return -1; } mCursor.moveToPosition(mIndexer.getDBRow(position)); return mCursor.getInt(mIdColIx); } private class ViewHolder { LinearLayout headerLayout; LinearLayout itemLayout; TextView headerTitleView; TextView itemTitleView; ImageView thumbnailView; TextView itemDistView; } @Override public View getView(int position, View convertView, ViewGroup parent) { checkPosition(position); LinearLayout layout; if (convertView == null) { layout = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.place_list_item, null); } else { layout = (LinearLayout)convertView; } ViewHolder holder; if (layout.getTag() == null || !(layout.getTag() instanceof ViewHolder)) { holder = new ViewHolder(); holder.headerLayout = (LinearLayout)layout.findViewById(R.id.placelist_item_header); holder.itemLayout = (LinearLayout)layout.findViewById(R.id.placelist_item_item); holder.headerTitleView = (TextView)layout.findViewById(R.id.header_title); holder.itemTitleView = (TextView)layout.findViewById(R.id.placelist_item_title); holder.thumbnailView = (ImageView)layout.findViewById(R.id.placelist_item_thumbnail); holder.itemDistView = (TextView)layout.findViewById(R.id.placelist_item_distance); layout.setTag(holder); } else { holder = (ViewHolder)layout.getTag(); } if (mIndexer.isHeader(position)) { holder.headerLayout.setVisibility(View.VISIBLE); holder.itemLayout.setVisibility(View.GONE); holder.headerTitleView.setText(mIndexer.getHeaderTitle(position)); } else { holder.headerLayout.setVisibility(View.GONE); holder.itemLayout.setVisibility(View.VISIBLE); mCursor.moveToPosition(mIndexer.getDBRow(position)); holder.itemTitleView.setText(mCursor.getString(mNameColIx)); // TODO replace placeholder icon with categorical icon holder.thumbnailView.setImageResource(R.drawable.home); Location tmp = new Location("Temp"); tmp.setLatitude(Double.parseDouble(mCursor.getString(mLatColIx))); tmp.setLongitude(Double.parseDouble(mCursor.getString(mLngColIx))); holder.itemDistView.setText(Geomancer.getDistanceString(tmp)); } return layout; } private void checkPosition(int position) { if (position < 0 || position >= (mCursor.getCount() + mIndexer.categoriesCount())) { throw new IndexOutOfBoundsException("Position " + position + " is invalid for a cursor with " + getCount() + "rows."); } } }