package com.noshufou.android.su.widget; import android.content.Context; import android.database.Cursor; import android.graphics.Color; import android.support.v4.widget.CursorAdapter; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.SectionIndexer; import android.widget.TextView; import android.widget.AbsListView.OnScrollListener; import com.noshufou.android.su.R; import com.noshufou.android.su.provider.PermissionsProvider.Logs; import com.noshufou.android.su.util.Util; import com.noshufou.android.su.widget.PinnedHeaderListView.PinnedHeaderCache; public class LogAdapter extends CursorAdapter implements OnScrollListener, SectionIndexer, PinnedHeaderListView.PinnedHeaderAdapter { private SectionIndexer mIndexer; private boolean mDisplaySectionHeaders = true; private boolean mShowName = true; private Cursor mCursor; private Context mContext; public static final String[] PROJECTION = new String[] { Logs._ID, Logs.NAME, Logs.DATE, Logs.TYPE }; private static final int LOG_COLUMN_NAME = 1; private static final int LOG_COLUMN_DATE = 2; private static final int LOG_COLUMN_TYPE = 3; public LogAdapter(Cursor cursor, Context context) { super(context, cursor, false); mCursor = cursor; mContext = context; } public LogAdapter(Cursor cursor, Context context, boolean showName) { this(cursor, context); mShowName = showName; } @Override public Cursor swapCursor(Cursor newCursor) { mCursor = newCursor; updateIndexer(newCursor); return super.swapCursor(newCursor); } private void updateIndexer(Cursor cursor) { if (cursor == null || cursor.getCount() == 0) { mIndexer = null; return; } mIndexer = new DateIndexer(mContext, cursor, LOG_COLUMN_DATE); } public boolean getDisplaySectionHeadersEnabled() { return mDisplaySectionHeaders; } @Override public boolean hasStableIds() { return true; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = super.getView(position, convertView, parent); bindSectionHeader(v, position, true); return v; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final LogListItem view = new LogListItem(context, null); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { LogListItem item = (LogListItem) view; item.setTimeText(Util.formatTime(context, cursor.getLong(LOG_COLUMN_DATE))); if (mShowName) { item.setNameText(cursor.getString(LOG_COLUMN_NAME)); } int logType = R.string.unknown; switch (cursor.getInt(LOG_COLUMN_TYPE)) { case Logs.LogType.ALLOW: logType = R.string.allowed; break; case Logs.LogType.DENY: logType = R.string.denied; break; case Logs.LogType.CREATE: logType = R.string.created; break; case Logs.LogType.TOGGLE: logType = R.string.toggled; break; } item.setTypeText(mContext.getString(logType)); } private void bindSectionHeader(View itemView, int position, boolean displaySectionHeaders) { final LogListItem view = (LogListItem) itemView; if (!displaySectionHeaders) { view.setSectionHeader(null); view.setDividerVisible(true); } else { final int section = getSectionForPosition(position); if (getPositionForSection(section) == position) { String title = (String)mIndexer.getSections()[section]; view.setSectionHeader(title); } else { view.setDividerVisible(false); view.setSectionHeader(null); } // move the divider for the last item in a section if (getPositionForSection(section + 1) - 1 == position) { view.setDividerVisible(false); } else { view.setDividerVisible(true); } } } @Override public Object[] getSections() { if (mIndexer == null) { return new String[] { " " } ; } else { return mIndexer.getSections(); } } @Override public int getPositionForSection(int section) { if (mIndexer == null) { return -1; } else { return mIndexer.getPositionForSection(section); } } @Override public int getSectionForPosition(int position) { if (mIndexer == null) { return -1; } else { return mIndexer.getSectionForPosition(position); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view instanceof PinnedHeaderListView) { ((PinnedHeaderListView)view).configureHeaderView(firstVisibleItem); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // Don't need to do anything here, but we must override it anyway } @Override public int getPinnedHeaderState(int position) { if (mIndexer == null || mCursor == null || mCursor.getCount() == 0 || mCursor.isClosed()) { return PINNED_HEADER_GONE; } if (position < 0) { return PINNED_HEADER_GONE; } int section = getSectionForPosition(position); int nextSectionPosition = getPositionForSection(section + 1); if (nextSectionPosition != -1 && position == nextSectionPosition - 1) { return PINNED_HEADER_PUSHED_UP; } return PINNED_HEADER_VISIBLE; } @Override public void configurePinnedHeader(View header, int position, int alpha) { PinnedHeaderCache cache = (PinnedHeaderCache)header.getTag(); if (cache == null) { cache = new PinnedHeaderCache(); cache.titleView = (TextView)header.findViewById(R.id.header_text); cache.textColor = cache.titleView.getTextColors(); cache.background = header.getBackground(); header.setTag(cache); } int section = getSectionForPosition(position); String title = (String)mIndexer.getSections()[section]; cache.titleView.setText(title); if (alpha == 255) { // Opaque, use the default background and original text color header.setBackgroundDrawable(cache.background); cache.titleView.setTextColor(cache.textColor); } else { // Faded, use a solid color approximation of the background and // a translucent text color header.setBackgroundColor(0x00ffffff); int textColor = cache.textColor.getDefaultColor(); cache.titleView.setTextColor(Color.argb(alpha, Color.red(textColor), Color.green(textColor), Color.blue(textColor))); } } }