Collapse MailboxAdapter & MailboxFragmentAdapter
MFA was the only subclass of MA and the abstraction no longer made sense. Collapse the two into a single adapter class. Change-Id: I32c6f027bc37f3da08626f743c3f494e5f48c3f0
This commit is contained in:
parent
96e44859cf
commit
1b404f4fff
@ -16,9 +16,12 @@
|
||||
|
||||
package com.android.email.activity;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import com.android.email.Email;
|
||||
import com.android.email.FolderProperties;
|
||||
import com.android.email.R;
|
||||
import com.android.email.ResourceHelper;
|
||||
import com.android.email.data.ClosingMatrixCursor;
|
||||
import com.android.email.data.ThrottlingCursorLoader;
|
||||
import com.android.emailcommon.Logging;
|
||||
@ -38,8 +41,11 @@ import android.database.MatrixCursor;
|
||||
import android.database.MatrixCursor.RowBuilder;
|
||||
import android.database.MergeCursor;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -57,15 +63,284 @@ import android.widget.TextView;
|
||||
* TODO Determine if we actually need a separate adapter / view / loader for nested folder
|
||||
* navigation. It's a little convoluted at the moment, but, still manageable.
|
||||
*/
|
||||
/*package*/ class MailboxFragmentAdapter extends MailboxesAdapter {
|
||||
class MailboxFragmentAdapter extends CursorAdapter {
|
||||
/**
|
||||
* Callback interface used to report clicks other than the basic list item click or long press.
|
||||
*/
|
||||
interface Callback {
|
||||
/** Callback for setting background of mailbox list items during a drag */
|
||||
public void onBind(MailboxListItem listItem);
|
||||
}
|
||||
|
||||
/** Do-nothing callback to avoid null tests for <code>mCallback</code>. */
|
||||
private static final class EmptyCallback implements Callback {
|
||||
public static final Callback INSTANCE = new EmptyCallback();
|
||||
@Override public void onBind(MailboxListItem listItem) { }
|
||||
}
|
||||
|
||||
/*
|
||||
* The type of the row to present to the user. There are 4 defined rows that each
|
||||
* have a slightly different look. These are typically used in the constant column
|
||||
* {@link #ROW_TYPE} specified in {@link #PROJECTION} and {@link #SUBMAILBOX_PROJECTION}.
|
||||
*/
|
||||
/** Both regular and combined mailboxes */
|
||||
private static final int ROW_TYPE_MAILBOX = 0;
|
||||
/** Account "mailboxes" in the combined view */
|
||||
private static final int ROW_TYPE_ACCOUNT = 1;
|
||||
// STOPSHIP Need to determine if these types are sufficient for nested folders
|
||||
// The following types are used when drilling into a mailbox
|
||||
/** The current mailbox */
|
||||
private static final int ROW_TYPE_CURMAILBOX = 2;
|
||||
/** Sub mailboxes */
|
||||
private static final int ROW_TYPE_SUBMAILBOX = 3;
|
||||
/** Header */
|
||||
private static final int ROW_TYPE_HEADER = 4;
|
||||
|
||||
/** The type of count to use. Different mailboxes have different counts. */
|
||||
private static final int COUNT_TYPE_UNREAD = 0;
|
||||
private static final int COUNT_TYPE_TOTAL = 1;
|
||||
private static final int COUNT_TYPE_NO_COUNT = 2;
|
||||
|
||||
/** The type of data contained in the cursor row. */
|
||||
private static final String ROW_TYPE = "rowType";
|
||||
/** The original ID of the cursor row. May be negative. */
|
||||
private static final String ORIGINAL_ID = "orgMailboxId";
|
||||
/**
|
||||
* Projection for a typical mailbox or account row.
|
||||
* <p><em>NOTE</em> This projection contains two ID columns. The first, named "_id", is used
|
||||
* by the framework ListView implementation. Since ListView does not handle negative IDs in
|
||||
* this column, we define a "mailbox_id" column that contains the real mailbox ID; which
|
||||
* may be negative for special mailboxes.
|
||||
*/
|
||||
private static final String[] PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_MAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
// STOPSHIP May need to adjust sub-folder projection depending upon final UX
|
||||
/**
|
||||
* Projection used to retrieve immediate children for a mailbox. The columns need to
|
||||
* be identical to those in {@link #PROJECTION}. We are only changing the constant
|
||||
* column {@link #ROW_TYPE}.
|
||||
*/
|
||||
private static final String[] SUBMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_SUBMAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
private static final String[] CURMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_CURMAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
/** Project to use for matrix cursors; rows MUST be identical to {@link #PROJECTION} */
|
||||
private static final String[] MATRIX_PROJECTION = new String[] {
|
||||
MailboxColumns.ID, ORIGINAL_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
|
||||
MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT, ROW_TYPE, MailboxColumns.FLAGS,
|
||||
MailboxColumns.ACCOUNT_KEY };
|
||||
|
||||
/** All mailboxes for the account */
|
||||
private static final String ALL_MAILBOX_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?" +
|
||||
" AND " + Mailbox.USER_VISIBLE_MAILBOX_SELECTION;
|
||||
/** All mailboxes with the given parent */
|
||||
private static final String MAILBOX_SELECTION_WITH_PARENT = ALL_MAILBOX_SELECTION +
|
||||
" AND " + MailboxColumns.PARENT_KEY + "=?";
|
||||
/** Selection for a specific mailbox */
|
||||
private static final String MAILBOX_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?" +
|
||||
" AND " + MailboxColumns.ID + "=?";
|
||||
|
||||
private static final String MAILBOX_ORDER_BY = "CASE " + MailboxColumns.TYPE +
|
||||
" WHEN " + Mailbox.TYPE_INBOX + " THEN 0" +
|
||||
" WHEN " + Mailbox.TYPE_DRAFTS + " THEN 1" +
|
||||
" WHEN " + Mailbox.TYPE_OUTBOX + " THEN 2" +
|
||||
" WHEN " + Mailbox.TYPE_SENT + " THEN 3" +
|
||||
" WHEN " + Mailbox.TYPE_TRASH + " THEN 4" +
|
||||
" WHEN " + Mailbox.TYPE_JUNK + " THEN 5" +
|
||||
// Other mailboxes (i.e. of Mailbox.TYPE_MAIL) are shown in alphabetical order.
|
||||
" ELSE 10 END" +
|
||||
" ," + MailboxColumns.DISPLAY_NAME;
|
||||
|
||||
/** View is of a "normal" row */
|
||||
private static final int ITEM_VIEW_TYPE_NORMAL = 0;
|
||||
/** View is of a separator row */
|
||||
private static final int ITEM_VIEW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
|
||||
|
||||
private static boolean sEnableUpdate = true;
|
||||
private final LayoutInflater mInflater;
|
||||
private final ResourceHelper mResourceHelper;
|
||||
private final Callback mCallback;
|
||||
|
||||
public MailboxFragmentAdapter(Context context, Callback callback) {
|
||||
super(context, null, 0 /* flags; no content observer */);
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
|
||||
mResourceHelper = ResourceHelper.getInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return isHeader(position) ? ITEM_VIEW_TYPE_HEADER : ITEM_VIEW_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return !isHeader(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
if (view instanceof MailboxListItem) {
|
||||
bindListItem(view, context, cursor);
|
||||
} else {
|
||||
bindListHeader(view, context, cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
if (cursor.getInt(cursor.getColumnIndex(ROW_TYPE)) == ROW_TYPE_HEADER) {
|
||||
return mInflater.inflate(R.layout.mailbox_list_header, parent, false);
|
||||
}
|
||||
return mInflater.inflate(R.layout.mailbox_list_item, parent, false);
|
||||
}
|
||||
|
||||
private boolean isHeader(int position) {
|
||||
Cursor c = getCursor();
|
||||
c.moveToPosition(position);
|
||||
int rowType = c.getInt(c.getColumnIndex(ROW_TYPE));
|
||||
return rowType == ROW_TYPE_HEADER;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the specified row is of an account in the combined view. */
|
||||
boolean isAccountRow(int position) {
|
||||
return isAccountRow((Cursor) getItem(position));
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the current row is of an account in the combined view. */
|
||||
private static boolean isAccountRow(Cursor cursor) {
|
||||
return getRowType(cursor) == ROW_TYPE_ACCOUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of count to use for the given row.
|
||||
*/
|
||||
private int getCountType(Cursor cursor) {
|
||||
if (isAccountRow(cursor)) {
|
||||
return COUNT_TYPE_UNREAD;
|
||||
}
|
||||
// otherwise, look at mailbox type to determine the count
|
||||
switch (cursor.getInt(cursor.getColumnIndex(MailboxColumns.TYPE))) {
|
||||
case Mailbox.TYPE_DRAFTS:
|
||||
case Mailbox.TYPE_OUTBOX:
|
||||
return COUNT_TYPE_TOTAL;
|
||||
case Mailbox.TYPE_SENT:
|
||||
case Mailbox.TYPE_TRASH:
|
||||
return COUNT_TYPE_NO_COUNT;
|
||||
}
|
||||
return COUNT_TYPE_UNREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unread count for the given row if the count type is {@link #COUNT_TYPE_UNREAD}.
|
||||
* Otherwise, {@code 0}.
|
||||
*/
|
||||
int getUnreadCount(int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
if (getCountType(c) != COUNT_TYPE_UNREAD) {
|
||||
return 0; // Don't have a unread count.
|
||||
}
|
||||
return c.getInt(c.getColumnIndex(MailboxColumns.UNREAD_COUNT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name for the given row.
|
||||
*/
|
||||
String getDisplayName(Context context, int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return getDisplayName(context, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the given row. It may be a mailbox or account ID depending upon the
|
||||
* result of {@link #isAccountRow}.
|
||||
*/
|
||||
long getId(int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return getId(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the account ID of the mailbox owner for the given row. If the given row is a
|
||||
* combined mailbox, {@link Account#ACCOUNT_ID_COMBINED_VIEW} is returned. If the given
|
||||
* row is an account, returns the account's ID [the same as {@link #ORIGINAL_ID}].
|
||||
*/
|
||||
long getAccountId(int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return getAccountId(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on and off list updates; during a drag operation, we do NOT want to the list of
|
||||
* mailboxes to update, as this would be visually jarring
|
||||
* @param state whether or not the MailboxList can be updated
|
||||
*/
|
||||
static void enableUpdates(boolean state) {
|
||||
sEnableUpdate = state;
|
||||
}
|
||||
|
||||
private static String getDisplayName(Context context, Cursor cursor) {
|
||||
String name = null;
|
||||
if (getRowType(cursor) == ROW_TYPE_MAILBOX) {
|
||||
// If it's a mailbox (as opposed to account row in combined view), and of certain types,
|
||||
// we use the predefined names.
|
||||
final int type = getType(cursor);
|
||||
final long mailboxId = getId(cursor);
|
||||
name = FolderProperties.getInstance(context).getDisplayName(type, mailboxId);
|
||||
}
|
||||
if (name == null) {
|
||||
name = cursor.getString(cursor.getColumnIndex(MailboxColumns.DISPLAY_NAME));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static long getId(Cursor cursor) {
|
||||
return cursor.getLong(cursor.getColumnIndex(ORIGINAL_ID));
|
||||
}
|
||||
|
||||
static int getType(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(MailboxColumns.TYPE));
|
||||
}
|
||||
|
||||
static int getMessageCount(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(MailboxColumns.MESSAGE_COUNT));
|
||||
}
|
||||
|
||||
static int getUnreadCount(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(MailboxColumns.UNREAD_COUNT));
|
||||
}
|
||||
|
||||
static long getAccountId(Cursor cursor) {
|
||||
return cursor.getLong(cursor.getColumnIndex(MailboxColumns.ACCOUNT_KEY));
|
||||
}
|
||||
|
||||
private static int getRowType(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(ROW_TYPE));
|
||||
}
|
||||
|
||||
private static int getFlags(Cursor cursor) {
|
||||
return cursor.getInt(cursor.getColumnIndex(MailboxColumns.FLAGS));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Cursor} with extra information which is returned by the loader created by
|
||||
* {@link MailboxFragmentAdapter#createMailboxesLoader}.
|
||||
*/
|
||||
public static class CursorWithExtras extends CursorWrapper {
|
||||
static class CursorWithExtras extends CursorWrapper {
|
||||
/**
|
||||
* The number of mailboxes in the cursor if the cursor contains top-level mailboxes.
|
||||
* Otherwise, the number of *child* mailboxes.
|
||||
@ -78,29 +353,18 @@ import android.widget.TextView;
|
||||
}
|
||||
}
|
||||
|
||||
public MailboxFragmentAdapter(Context context, Callback callback) {
|
||||
super(context, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
if (view instanceof MailboxListItem) {
|
||||
bindListItem(view, context, cursor);
|
||||
} else {
|
||||
bindListHeader(view, context, cursor);
|
||||
}
|
||||
}
|
||||
private void bindListHeader(View view, Context context, Cursor cursor) {
|
||||
final TextView nameView = (TextView) view.findViewById(R.id.display_name);
|
||||
nameView.setText(getDisplayName(context, cursor));
|
||||
}
|
||||
|
||||
private void bindListItem(View view, Context context, Cursor cursor) {
|
||||
final boolean isAccount = isAccountRow(cursor);
|
||||
final int type = cursor.getInt(COLUMN_TYPE);
|
||||
final long id = cursor.getLong(COLUMN_ID);
|
||||
final long accountId = cursor.getLong(COLUMN_ACCOUNT_ID);
|
||||
final int flags = cursor.getInt(COLUMN_FLAGS);
|
||||
final int rowType = cursor.getInt(COLUMN_ROW_TYPE);
|
||||
final int type = getType(cursor);
|
||||
final long id = getId(cursor);
|
||||
final long accountId = getAccountId(cursor);
|
||||
final int flags = getFlags(cursor);
|
||||
final int rowType = getRowType(cursor);
|
||||
final boolean hasVisibleChildren = (flags & Mailbox.FLAG_HAS_CHILDREN) != 0
|
||||
&& (flags & Mailbox.FLAG_CHILDREN_VISIBLE) != 0;
|
||||
|
||||
@ -123,12 +387,12 @@ import android.widget.TextView;
|
||||
nameView.setText(getDisplayName(context, cursor));
|
||||
// Set count
|
||||
final int count;
|
||||
switch (getCountTypeForMailboxType(cursor)) {
|
||||
switch (getCountType(cursor)) {
|
||||
case COUNT_TYPE_UNREAD:
|
||||
count = cursor.getInt(COLUMN_UNREAD_COUNT);
|
||||
count = getUnreadCount(cursor);
|
||||
break;
|
||||
case COUNT_TYPE_TOTAL:
|
||||
count = cursor.getInt(COLUMN_MESSAGE_COUNT);
|
||||
count = getMessageCount(cursor);
|
||||
break;
|
||||
default: // no count
|
||||
count = 0;
|
||||
@ -191,15 +455,6 @@ import android.widget.TextView;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
if (cursor.getInt(cursor.getColumnIndex(ROW_TYPE)) == ROW_TYPE_HEADER) {
|
||||
return mInflater.inflate(R.layout.mailbox_list_header, parent, false);
|
||||
}
|
||||
return mInflater.inflate(R.layout.mailbox_list_item, parent, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a cursor loader for the mailboxes of the given account. If <code>parentKey</code>
|
||||
* refers to a valid mailbox ID [e.g. non-zero], restrict the loader to only those mailboxes
|
||||
@ -207,7 +462,7 @@ import android.widget.TextView;
|
||||
*
|
||||
* Note the returned loader always returns a {@link CursorWithExtras}.
|
||||
*/
|
||||
public static Loader<Cursor> createMailboxesLoader(Context context, long accountId,
|
||||
static Loader<Cursor> createMailboxesLoader(Context context, long accountId,
|
||||
long parentMailboxId) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MailboxFragmentAdapter#CursorWithExtras accountId=" + accountId
|
||||
@ -222,7 +477,7 @@ import android.widget.TextView;
|
||||
/**
|
||||
* Returns a cursor loader for the combined view.
|
||||
*/
|
||||
public static Loader<Cursor> createCombinedViewLoader(Context context) {
|
||||
static Loader<Cursor> createCombinedViewLoader(Context context) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MailboxFragmentAdapter#createCombinedViewLoader");
|
||||
}
|
||||
@ -329,7 +584,8 @@ import android.widget.TextView;
|
||||
/**
|
||||
* Loader for mailboxes in "Combined view".
|
||||
*/
|
||||
/*package*/ static class CombinedMailboxLoader extends ThrottlingCursorLoader {
|
||||
@VisibleForTesting
|
||||
static class CombinedMailboxLoader extends ThrottlingCursorLoader {
|
||||
private static final String[] ACCOUNT_PROJECTION = new String[] {
|
||||
EmailContent.RECORD_ID, AccountColumns.DISPLAY_NAME,
|
||||
};
|
||||
@ -338,7 +594,7 @@ import android.widget.TextView;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public CombinedMailboxLoader(Context context) {
|
||||
private CombinedMailboxLoader(Context context) {
|
||||
super(context, Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null, null);
|
||||
mContext = context;
|
||||
}
|
||||
@ -364,9 +620,9 @@ import android.widget.TextView;
|
||||
return Utility.CloseTraceCursorWrapper.get(returnCursor);
|
||||
}
|
||||
|
||||
/*package*/ static MatrixCursor buildCombinedMailboxes(Context context,
|
||||
Cursor innerCursor) {
|
||||
MatrixCursor cursor = new ClosingMatrixCursor(PROJECTION, innerCursor);
|
||||
@VisibleForTesting
|
||||
static MatrixCursor buildCombinedMailboxes(Context context, Cursor innerCursor) {
|
||||
MatrixCursor cursor = new ClosingMatrixCursor(MATRIX_PROJECTION, innerCursor);
|
||||
// Combined inbox -- show unread count
|
||||
addCombinedMailboxRow(cursor, Mailbox.QUERY_ALL_INBOXES, Mailbox.TYPE_INBOX,
|
||||
Mailbox.getUnreadCountByMailboxType(context, Mailbox.TYPE_INBOX), true);
|
||||
|
@ -191,7 +191,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
||||
|
||||
// UI Support
|
||||
private Activity mActivity;
|
||||
private MailboxesAdapter mListAdapter;
|
||||
private MailboxFragmentAdapter mListAdapter;
|
||||
private Callback mCallback = EmptyCallback.INSTANCE;
|
||||
|
||||
// See the class javadoc
|
||||
@ -220,8 +220,8 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
||||
|
||||
private Parcelable mSavedListState;
|
||||
|
||||
private final MailboxesAdapter.Callback mMailboxesAdapterCallback =
|
||||
new MailboxesAdapter.Callback() {
|
||||
private final MailboxFragmentAdapter.Callback mMailboxesAdapterCallback =
|
||||
new MailboxFragmentAdapter.Callback() {
|
||||
@Override
|
||||
public void onBind(MailboxListItem listItem) {
|
||||
listItem.setDropTargetBackground(mDragInProgress, mDragItemMailboxId);
|
||||
@ -870,7 +870,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
||||
* <p>
|
||||
* @param doNotUse <em>IMPORTANT</em>: Do not use this parameter. The ID in the list widget
|
||||
* must be a positive value. However, we rely on negative IDs for special mailboxes. Instead,
|
||||
* we use the ID returned by {@link MailboxesAdapter#getId(int)}.
|
||||
* we use the ID returned by {@link MailboxFragmentAdapter#getId(int)}.
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long doNotUse) {
|
||||
@ -1127,7 +1127,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
||||
if (mDragInProgress) {
|
||||
mDragInProgress = false;
|
||||
// Reenable updates to the view and redraw (in case it changed)
|
||||
MailboxesAdapter.enableUpdates(true);
|
||||
MailboxFragmentAdapter.enableUpdates(true);
|
||||
mListAdapter.notifyDataSetChanged();
|
||||
// Stop highlighting targets
|
||||
updateChildViews();
|
||||
@ -1160,7 +1160,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
||||
}
|
||||
mDragInProgress = true;
|
||||
// Stop the list from updating
|
||||
MailboxesAdapter.enableUpdates(false);
|
||||
MailboxFragmentAdapter.enableUpdates(false);
|
||||
// Update the backgrounds of our child views to highlight drop targets
|
||||
updateChildViews();
|
||||
return true;
|
||||
|
@ -50,7 +50,7 @@ public class MailboxListItem extends RelativeLayout {
|
||||
public boolean mIsValidDropTarget;
|
||||
/** If {@code true} this item can be navigated to. Otherwise, it can just be selected. */
|
||||
public boolean mIsNavigable;
|
||||
public MailboxesAdapter mAdapter;
|
||||
public MailboxFragmentAdapter mAdapter;
|
||||
|
||||
private Drawable mBackground;
|
||||
private TextView mLabelName;
|
||||
|
@ -38,7 +38,7 @@ import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Cursor adapter for the "move to mailbox" dialog.
|
||||
* TODO We've detached this class from {@link MailboxesAdapter} and {@link MailboxFragmentAdapter}.
|
||||
* TODO We've detached this class from {@link MailboxFragmentAdapter} and {@link MailboxFragmentAdapter}.
|
||||
* Depending upon the UX for the dialog and nested folders, we may want to bring these three
|
||||
* adapter classes back into alignment.
|
||||
*/
|
||||
|
@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 com.android.email.activity;
|
||||
|
||||
import com.android.email.FolderProperties;
|
||||
import com.android.email.ResourceHelper;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.CursorAdapter;
|
||||
|
||||
/**
|
||||
* Super class adapter for displaying a mailbox list.
|
||||
* NOTE: Do not use {@link #getItemId(int)}; it's only for ListView. Instead, use {@link #getId}.
|
||||
*
|
||||
* TODO Show "Starred" per account
|
||||
* TODO Unit test, when UI is settled.
|
||||
*/
|
||||
/*package*/ abstract class MailboxesAdapter extends CursorAdapter {
|
||||
/**
|
||||
* Return value from {@link #getCountType}.
|
||||
*/
|
||||
/*package*/ static final int COUNT_TYPE_UNREAD = 0;
|
||||
/*package*/ static final int COUNT_TYPE_TOTAL = 1;
|
||||
/*package*/ static final int COUNT_TYPE_NO_COUNT = 2;
|
||||
|
||||
/**
|
||||
* Callback interface used to report clicks other than the basic list item click or long press.
|
||||
*/
|
||||
public interface Callback {
|
||||
/** Callback for setting background of mailbox list items during a drag */
|
||||
public void onBind(MailboxListItem listItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the row to present to the user. There are 4 defined rows that each
|
||||
* have a slightly different look. These are typically used in the constant column
|
||||
* {@link #ROW_TYPE} specified in {@link #PROJECTION} and {@link #SUBMAILBOX_PROJECTION}.
|
||||
*/
|
||||
/** Both regular and combined mailboxes */
|
||||
static final int ROW_TYPE_MAILBOX = 0;
|
||||
/** Account "mailboxes" in the combined view */
|
||||
static final int ROW_TYPE_ACCOUNT = 1;
|
||||
// STOPSHIP Need to determine if these types are sufficient for nested folders
|
||||
// The following types are used when drilling into a mailbox
|
||||
/** The current mailbox */
|
||||
static final int ROW_TYPE_CURMAILBOX = 2;
|
||||
/** Sub mailboxes */
|
||||
static final int ROW_TYPE_SUBMAILBOX = 3;
|
||||
/** Header */
|
||||
static final int ROW_TYPE_HEADER = 4;
|
||||
|
||||
/**
|
||||
* Projection for a typical mailbox or account row.
|
||||
* <p><em>NOTE</em> This projection contains two ID columns. The first, named "_id", is used
|
||||
* by the framework ListView implementation. Since ListView does not handle negative IDs in
|
||||
* this column, we define a "mailbox_id" column that contains the real mailbox ID; which
|
||||
* may be negative for special mailboxes.
|
||||
*/
|
||||
final static String ROW_TYPE = "rowType";
|
||||
final static String ORIGINAL_ID = "orgMailboxId";
|
||||
static final String[] PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_MAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
// STOPSHIP May need to adjust sub-folder projection depending upon final UX
|
||||
/**
|
||||
* Projection used to retrieve immediate children for a mailbox. The columns need to
|
||||
* be identical to those in {@link #PROJECTION}. We are only changing the constant
|
||||
* column {@link #ROW_TYPE}.
|
||||
*/
|
||||
static final String[] SUBMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_SUBMAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
static final String[] CURMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
|
||||
MailboxColumns.ID + " AS " + ORIGINAL_ID,
|
||||
MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
|
||||
MailboxColumns.MESSAGE_COUNT, ROW_TYPE_CURMAILBOX + " AS " + ROW_TYPE,
|
||||
MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
|
||||
/** Project to use for matrix cursors; rows MUST be identical to {@link #PROJECTION} */
|
||||
static final String[] MATRIX_PROJECTION = new String[] {
|
||||
MailboxColumns.ID, ORIGINAL_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
|
||||
MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT, ROW_TYPE, MailboxColumns.FLAGS,
|
||||
MailboxColumns.ACCOUNT_KEY };
|
||||
|
||||
// Column 0 is only for ListView; we don't use it in our code.
|
||||
/**
|
||||
* ID for the current row. Normally it's the ID for the current mailbox, but if it's an account
|
||||
* row on the combined view, it's the ID for the account.
|
||||
*/
|
||||
/*package*/ static final int COLUMN_ID = 1;
|
||||
/*package*/ static final int COLUMN_DISPLAY_NAME = 2;
|
||||
/*package*/ static final int COLUMN_TYPE = 3;
|
||||
/*package*/ static final int COLUMN_UNREAD_COUNT = 4;
|
||||
/*package*/ static final int COLUMN_MESSAGE_COUNT = 5;
|
||||
/*package*/ static final int COLUMN_ROW_TYPE = 6;
|
||||
/*package*/ static final int COLUMN_FLAGS = 7;
|
||||
/**
|
||||
* ID for the owner account of the mailbox. If it's a combined mailbox, it's
|
||||
* {@link Account#ACCOUNT_ID_COMBINED_VIEW}. If it's an account row on the combined view,
|
||||
* it's the ID for the account.
|
||||
*/
|
||||
/*package*/ static final int COLUMN_ACCOUNT_ID = 8;
|
||||
|
||||
/** All mailboxes for the account */
|
||||
/*package*/ static final String ALL_MAILBOX_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?" +
|
||||
" AND " + Mailbox.USER_VISIBLE_MAILBOX_SELECTION;
|
||||
/** All mailboxes with the given parent */
|
||||
/*package*/ static final String MAILBOX_SELECTION_WITH_PARENT = ALL_MAILBOX_SELECTION +
|
||||
" AND " + MailboxColumns.PARENT_KEY + "=?";
|
||||
|
||||
/*package*/ static final String MAILBOX_ORDER_BY = "CASE " + MailboxColumns.TYPE +
|
||||
" WHEN " + Mailbox.TYPE_INBOX + " THEN 0" +
|
||||
" WHEN " + Mailbox.TYPE_DRAFTS + " THEN 1" +
|
||||
" WHEN " + Mailbox.TYPE_OUTBOX + " THEN 2" +
|
||||
" WHEN " + Mailbox.TYPE_SENT + " THEN 3" +
|
||||
" WHEN " + Mailbox.TYPE_TRASH + " THEN 4" +
|
||||
" WHEN " + Mailbox.TYPE_JUNK + " THEN 5" +
|
||||
// Other mailboxes (i.e. of Mailbox.TYPE_MAIL) are shown in alphabetical order.
|
||||
" ELSE 10 END" +
|
||||
" ," + MailboxColumns.DISPLAY_NAME;
|
||||
|
||||
/** Do-nothing callback to avoid null tests for <code>mCallback</code>. */
|
||||
private static final class EmptyCallback implements Callback {
|
||||
public static final Callback INSTANCE = new EmptyCallback();
|
||||
@Override
|
||||
public void onBind(MailboxListItem listItem) {
|
||||
}
|
||||
}
|
||||
private final static int ITEM_VIEW_TYPE_NORMAL = 0;
|
||||
private final static int ITEM_VIEW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
|
||||
|
||||
/*package*/ static boolean sEnableUpdate = true;
|
||||
/*package*/ final LayoutInflater mInflater;
|
||||
/*package*/ final ResourceHelper mResourceHelper;
|
||||
/*package*/ final Callback mCallback;
|
||||
|
||||
/*package*/ MailboxesAdapter(Context context, Callback callback) {
|
||||
super(context, null, 0 /* flags; no content observer */);
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
|
||||
mResourceHelper = ResourceHelper.getInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void bindView(View view, Context context, Cursor cursor);
|
||||
|
||||
@Override
|
||||
public abstract View newView(Context context, Cursor cursor, ViewGroup parent);
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return isHeader(position) ? ITEM_VIEW_TYPE_HEADER : ITEM_VIEW_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return !isHeader(position);
|
||||
}
|
||||
|
||||
private boolean isHeader(int position) {
|
||||
Cursor c = getCursor();
|
||||
c.moveToPosition(position);
|
||||
int rowType = c.getInt(c.getColumnIndex(ROW_TYPE));
|
||||
return rowType == ROW_TYPE_HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the current row is of an account in the combined view.
|
||||
*/
|
||||
/*package*/ static boolean isAccountRow(Cursor c) {
|
||||
return c.getInt(COLUMN_ROW_TYPE) == ROW_TYPE_ACCOUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the specified row is of an account in the combined view.
|
||||
*/
|
||||
public boolean isAccountRow(int position) {
|
||||
return isAccountRow((Cursor) getItem(position));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return which type of count should be used for the current row.
|
||||
* Possible return values are COUNT_TYPE_*.
|
||||
*/
|
||||
/*package*/ static int getCountTypeForMailboxType(Cursor c) {
|
||||
if (isAccountRow(c)) {
|
||||
return COUNT_TYPE_UNREAD; // Use the unread count for account rows.
|
||||
}
|
||||
switch (c.getInt(COLUMN_TYPE)) {
|
||||
case Mailbox.TYPE_DRAFTS:
|
||||
case Mailbox.TYPE_OUTBOX:
|
||||
return COUNT_TYPE_TOTAL;
|
||||
case Mailbox.TYPE_SENT:
|
||||
case Mailbox.TYPE_TRASH:
|
||||
return COUNT_TYPE_NO_COUNT;
|
||||
}
|
||||
return COUNT_TYPE_UNREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count type for the specified row. See {@link #getCountTypeForMailboxType}
|
||||
*/
|
||||
private int getCountType(int position) {
|
||||
if (isAccountRow(position)) {
|
||||
return COUNT_TYPE_UNREAD;
|
||||
}
|
||||
return getCountTypeForMailboxType((Cursor) getItem(position));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count type for the specified row.
|
||||
*/
|
||||
public int getUnreadCount(int position) {
|
||||
if (getCountType(position) != COUNT_TYPE_UNREAD) {
|
||||
return 0; // Don't have a unread count.
|
||||
}
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return c.getInt(COLUMN_UNREAD_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return display name for the specified row.
|
||||
*/
|
||||
public String getDisplayName(Context context, int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return getDisplayName(context, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the mailbox (or account, if {@link #isAccountRow} is {@code true})
|
||||
* of the given row.
|
||||
*/
|
||||
public long getId(int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return c.getLong(COLUMN_ID);
|
||||
}
|
||||
|
||||
/** @see #COLUMN_ACCOUNT_ID */
|
||||
public long getAccountId(int position) {
|
||||
Cursor c = (Cursor) getItem(position);
|
||||
return c.getLong(COLUMN_ACCOUNT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on and off list updates; during a drag operation, we do NOT want to the list of
|
||||
* mailboxes to update, as this would be visually jarring
|
||||
* @param state whether or not the MailboxList can be updated
|
||||
*/
|
||||
public static void enableUpdates(boolean state) {
|
||||
sEnableUpdate = state;
|
||||
}
|
||||
|
||||
/*package*/ static String getDisplayName(Context context, Cursor cursor) {
|
||||
String name = null;
|
||||
if (cursor.getInt(COLUMN_ROW_TYPE) == ROW_TYPE_MAILBOX) {
|
||||
// If it's a mailbox (as opposed to account row in combined view), and of certain types,
|
||||
// we use the predefined names.
|
||||
final int type = cursor.getInt(COLUMN_TYPE);
|
||||
final long mailboxId = cursor.getLong(COLUMN_ID);
|
||||
name = FolderProperties.getInstance(context).getDisplayName(type, mailboxId);
|
||||
}
|
||||
if (name == null) {
|
||||
name = cursor.getString(COLUMN_DISPLAY_NAME);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*package*/ static long getIdForTest(Cursor cursor) {
|
||||
return cursor.getLong(COLUMN_ID);
|
||||
}
|
||||
|
||||
/*package*/ static int getTypeForTest(Cursor cursor) {
|
||||
return cursor.getInt(COLUMN_TYPE);
|
||||
}
|
||||
|
||||
/*package*/ static int getMessageCountForTest(Cursor cursor) {
|
||||
return cursor.getInt(COLUMN_MESSAGE_COUNT);
|
||||
}
|
||||
|
||||
/*package*/ static int getUnreadCountForTest(Cursor cursor) {
|
||||
return cursor.getInt(COLUMN_UNREAD_COUNT);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static long getAccountId(Cursor cursor) {
|
||||
return cursor.getLong(COLUMN_ACCOUNT_ID);
|
||||
}
|
||||
}
|
@ -115,11 +115,11 @@ public class MailboxFragmentAdapterTest extends ProviderTestCase2<EmailProvider>
|
||||
int count) {
|
||||
// _id must always be >= 0; otherwise ListView gets confused.
|
||||
Assert.assertTrue(cursor.getLong(cursor.getColumnIndex("_id")) >= 0);
|
||||
Assert.assertEquals(id, MailboxesAdapter.getIdForTest(cursor));
|
||||
Assert.assertEquals(type, MailboxesAdapter.getTypeForTest(cursor));
|
||||
Assert.assertEquals(count, MailboxesAdapter.getMessageCountForTest(cursor));
|
||||
Assert.assertEquals(count, MailboxesAdapter.getUnreadCountForTest(cursor));
|
||||
Assert.assertEquals(id, MailboxFragmentAdapter.getId(cursor));
|
||||
Assert.assertEquals(type, MailboxFragmentAdapter.getType(cursor));
|
||||
Assert.assertEquals(count, MailboxFragmentAdapter.getMessageCount(cursor));
|
||||
Assert.assertEquals(count, MailboxFragmentAdapter.getUnreadCount(cursor));
|
||||
Assert.assertEquals(Account.ACCOUNT_ID_COMBINED_VIEW,
|
||||
MailboxesAdapter.getAccountId(cursor));
|
||||
MailboxFragmentAdapter.getAccountId(cursor));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user