2010-06-02 00:55:31 +00:00
|
|
|
/*
|
|
|
|
* 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.Email;
|
2010-11-22 21:47:11 +00:00
|
|
|
import com.android.email.ResourceHelper;
|
2010-08-11 22:28:31 +00:00
|
|
|
import com.android.email.data.ThrottlingCursorLoader;
|
2011-02-11 23:05:17 +00:00
|
|
|
import com.android.emailcommon.Logging;
|
2011-02-10 18:26:56 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent;
|
|
|
|
import com.android.emailcommon.provider.EmailContent.Message;
|
|
|
|
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
2011-03-31 20:29:23 +00:00
|
|
|
import com.android.emailcommon.utility.TextUtilities;
|
2011-02-11 23:05:17 +00:00
|
|
|
import com.android.emailcommon.utility.Utility;
|
2010-06-02 00:55:31 +00:00
|
|
|
|
|
|
|
import android.content.Context;
|
2010-08-11 22:28:31 +00:00
|
|
|
import android.content.Loader;
|
2010-06-02 00:55:31 +00:00
|
|
|
import android.database.Cursor;
|
2010-08-11 22:28:31 +00:00
|
|
|
import android.os.Bundle;
|
2010-06-02 00:55:31 +00:00
|
|
|
import android.util.Log;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.CursorAdapter;
|
|
|
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class implements the adapter for displaying messages based on cursors.
|
|
|
|
*/
|
2010-06-09 21:43:43 +00:00
|
|
|
/* package */ class MessagesAdapter extends CursorAdapter {
|
2010-08-11 22:28:31 +00:00
|
|
|
private static final String STATE_CHECKED_ITEMS =
|
|
|
|
"com.android.email.activity.MessagesAdapter.checkedItems";
|
|
|
|
|
|
|
|
/* package */ static final String[] MESSAGE_PROJECTION = new String[] {
|
|
|
|
EmailContent.RECORD_ID, MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
|
|
|
|
MessageColumns.DISPLAY_NAME, MessageColumns.SUBJECT, MessageColumns.TIMESTAMP,
|
|
|
|
MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE, MessageColumns.FLAG_ATTACHMENT,
|
2010-09-02 02:06:15 +00:00
|
|
|
MessageColumns.FLAGS, MessageColumns.SNIPPET
|
2010-08-11 22:28:31 +00:00
|
|
|
};
|
2010-06-02 00:55:31 +00:00
|
|
|
|
|
|
|
public static final int COLUMN_ID = 0;
|
|
|
|
public static final int COLUMN_MAILBOX_KEY = 1;
|
|
|
|
public static final int COLUMN_ACCOUNT_KEY = 2;
|
|
|
|
public static final int COLUMN_DISPLAY_NAME = 3;
|
|
|
|
public static final int COLUMN_SUBJECT = 4;
|
|
|
|
public static final int COLUMN_DATE = 5;
|
|
|
|
public static final int COLUMN_READ = 6;
|
|
|
|
public static final int COLUMN_FAVORITE = 7;
|
|
|
|
public static final int COLUMN_ATTACHMENTS = 8;
|
|
|
|
public static final int COLUMN_FLAGS = 9;
|
2010-09-02 02:06:15 +00:00
|
|
|
public static final int COLUMN_SNIPPET = 10;
|
2010-06-02 00:55:31 +00:00
|
|
|
|
2010-11-22 21:47:11 +00:00
|
|
|
private final ResourceHelper mResourceHelper;
|
|
|
|
|
|
|
|
/** If true, show color chips. */
|
|
|
|
private boolean mShowColorChips;
|
|
|
|
|
2011-03-31 20:29:23 +00:00
|
|
|
/** If not null, the query represented by this group of messages */
|
|
|
|
private String mQuery;
|
|
|
|
|
2010-08-27 20:00:48 +00:00
|
|
|
/**
|
2010-10-06 22:55:04 +00:00
|
|
|
* Set of seleced message IDs.
|
2010-08-27 20:00:48 +00:00
|
|
|
*/
|
|
|
|
private final HashSet<Long> mSelectedSet = new HashSet<Long>();
|
2010-06-02 00:55:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback from MessageListAdapter. All methods are called on the UI thread.
|
|
|
|
*/
|
|
|
|
public interface Callback {
|
|
|
|
/** Called when the use starts/unstars a message */
|
|
|
|
void onAdapterFavoriteChanged(MessageListItem itemView, boolean newFavorite);
|
|
|
|
/** Called when the user selects/unselects a message */
|
|
|
|
void onAdapterSelectedChanged(MessageListItem itemView, boolean newSelected,
|
|
|
|
int mSelectedCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
private final Callback mCallback;
|
|
|
|
|
2010-08-27 20:00:48 +00:00
|
|
|
public MessagesAdapter(Context context, Callback callback) {
|
2010-08-11 22:28:31 +00:00
|
|
|
super(context.getApplicationContext(), null, 0 /* no auto requery */);
|
2010-11-22 21:47:11 +00:00
|
|
|
mResourceHelper = ResourceHelper.getInstance(context);
|
2010-06-02 00:55:31 +00:00
|
|
|
mCallback = callback;
|
|
|
|
}
|
|
|
|
|
2010-08-11 22:28:31 +00:00
|
|
|
public void onSaveInstanceState(Bundle outState) {
|
|
|
|
Set<Long> checkedset = getSelectedSet();
|
|
|
|
long[] checkedarray = new long[checkedset.size()];
|
|
|
|
int i = 0;
|
|
|
|
for (Long l : checkedset) {
|
|
|
|
checkedarray[i] = l;
|
|
|
|
i++;
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
2010-08-11 22:28:31 +00:00
|
|
|
outState.putLongArray(STATE_CHECKED_ITEMS, checkedarray);
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
|
|
|
|
2010-08-11 22:28:31 +00:00
|
|
|
public void loadState(Bundle savedInstanceState) {
|
|
|
|
Set<Long> checkedset = getSelectedSet();
|
|
|
|
for (long l: savedInstanceState.getLongArray(STATE_CHECKED_ITEMS)) {
|
|
|
|
checkedset.add(l);
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-22 21:47:11 +00:00
|
|
|
/**
|
|
|
|
* Set true for combined mailboxes.
|
|
|
|
*/
|
|
|
|
public void setShowColorChips(boolean show) {
|
|
|
|
mShowColorChips = show;
|
|
|
|
}
|
|
|
|
|
2011-03-31 20:29:23 +00:00
|
|
|
public void setQuery(String query) {
|
|
|
|
mQuery = query;
|
|
|
|
}
|
|
|
|
|
2010-06-02 00:55:31 +00:00
|
|
|
public Set<Long> getSelectedSet() {
|
2010-08-27 20:00:48 +00:00
|
|
|
return mSelectedSet;
|
2010-06-23 00:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isSelected(MessageListItem itemView) {
|
2010-08-27 20:00:48 +00:00
|
|
|
return mSelectedSet.contains(itemView.mMessageId);
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void bindView(View view, Context context, Cursor cursor) {
|
|
|
|
// Reset the view (in case it was recycled) and prepare for binding
|
|
|
|
MessageListItem itemView = (MessageListItem) view;
|
2010-06-23 00:19:58 +00:00
|
|
|
itemView.bindViewInit(this);
|
2010-06-02 00:55:31 +00:00
|
|
|
|
|
|
|
// Load the public fields in the view (for later use)
|
|
|
|
itemView.mMessageId = cursor.getLong(COLUMN_ID);
|
|
|
|
itemView.mMailboxId = cursor.getLong(COLUMN_MAILBOX_KEY);
|
2010-11-22 21:47:11 +00:00
|
|
|
final long accountId = cursor.getLong(COLUMN_ACCOUNT_KEY);
|
|
|
|
itemView.mAccountId = accountId;
|
2010-06-02 00:55:31 +00:00
|
|
|
itemView.mRead = cursor.getInt(COLUMN_READ) != 0;
|
2010-11-10 20:14:55 +00:00
|
|
|
itemView.mIsFavorite = cursor.getInt(COLUMN_FAVORITE) != 0;
|
|
|
|
itemView.mHasInvite =
|
|
|
|
(cursor.getInt(COLUMN_FLAGS) & Message.FLAG_INCOMING_MEETING_INVITE) != 0;
|
|
|
|
itemView.mHasAttachment = cursor.getInt(COLUMN_ATTACHMENTS) != 0;
|
|
|
|
itemView.mTimestamp = cursor.getLong(COLUMN_DATE);
|
|
|
|
itemView.mSender = cursor.getString(COLUMN_DISPLAY_NAME);
|
|
|
|
itemView.mSnippet = cursor.getString(COLUMN_SNIPPET);
|
2010-12-04 07:12:48 +00:00
|
|
|
itemView.mSubject = cursor.getString(COLUMN_SUBJECT);
|
2010-11-10 20:14:55 +00:00
|
|
|
itemView.mSnippetLineCount = MessageListItem.NEEDS_LAYOUT;
|
2010-11-22 21:47:11 +00:00
|
|
|
itemView.mColorChipPaint =
|
2010-12-04 07:12:48 +00:00
|
|
|
mShowColorChips ? mResourceHelper.getAccountColorPaint(accountId) : null;
|
2011-03-31 20:29:23 +00:00
|
|
|
|
|
|
|
if (mQuery != null && itemView.mSnippet != null) {
|
|
|
|
itemView.mSnippet =
|
|
|
|
TextUtilities.highlightTermsInText(cursor.getString(COLUMN_SNIPPET), mQuery);
|
|
|
|
}
|
2010-10-06 22:55:04 +00:00
|
|
|
}
|
|
|
|
|
2010-06-02 00:55:31 +00:00
|
|
|
@Override
|
|
|
|
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
2010-11-10 20:14:55 +00:00
|
|
|
//return mInflater.inflate(R.layout.message_list_item, parent, false);
|
|
|
|
MessageListItem item = new MessageListItem(context);
|
|
|
|
item.setVisibility(View.VISIBLE);
|
|
|
|
return item;
|
2010-08-27 20:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void toggleSelected(MessageListItem itemView) {
|
|
|
|
updateSelected(itemView, !isSelected(itemView));
|
|
|
|
}
|
|
|
|
|
2010-06-02 00:55:31 +00:00
|
|
|
/**
|
|
|
|
* This is used as a callback from the list items, to set the selected state
|
|
|
|
*
|
|
|
|
* <p>Must be called on the UI thread.
|
|
|
|
*
|
|
|
|
* @param itemView the item being changed
|
|
|
|
* @param newSelected the new value of the selected flag (checkbox state)
|
|
|
|
*/
|
2010-08-27 20:00:48 +00:00
|
|
|
private void updateSelected(MessageListItem itemView, boolean newSelected) {
|
2010-06-02 00:55:31 +00:00
|
|
|
if (newSelected) {
|
2010-08-27 20:00:48 +00:00
|
|
|
mSelectedSet.add(itemView.mMessageId);
|
2010-06-02 00:55:31 +00:00
|
|
|
} else {
|
2010-08-27 20:00:48 +00:00
|
|
|
mSelectedSet.remove(itemView.mMessageId);
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
|
|
|
if (mCallback != null) {
|
2010-08-27 20:00:48 +00:00
|
|
|
mCallback.onAdapterSelectedChanged(itemView, newSelected, mSelectedSet.size());
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is used as a callback from the list items, to set the favorite state
|
|
|
|
*
|
|
|
|
* <p>Must be called on the UI thread.
|
|
|
|
*
|
|
|
|
* @param itemView the item being changed
|
|
|
|
* @param newFavorite the new value of the favorite flag (star state)
|
|
|
|
*/
|
|
|
|
public void updateFavorite(MessageListItem itemView, boolean newFavorite) {
|
2010-10-06 22:55:04 +00:00
|
|
|
changeFavoriteIcon(itemView, newFavorite);
|
2010-06-02 00:55:31 +00:00
|
|
|
if (mCallback != null) {
|
|
|
|
mCallback.onAdapterFavoriteChanged(itemView, newFavorite);
|
|
|
|
}
|
|
|
|
}
|
2010-06-23 00:19:58 +00:00
|
|
|
|
2010-10-06 22:55:04 +00:00
|
|
|
private void changeFavoriteIcon(MessageListItem view, boolean isFavorite) {
|
2010-11-10 20:14:55 +00:00
|
|
|
view.invalidate();
|
2010-06-23 00:19:58 +00:00
|
|
|
}
|
2010-08-11 22:28:31 +00:00
|
|
|
|
|
|
|
public static Loader<Cursor> createLoader(Context context, long mailboxId) {
|
|
|
|
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
2011-02-11 23:05:17 +00:00
|
|
|
Log.d(Logging.LOG_TAG, "MessagesAdapter createLoader mailboxId=" + mailboxId);
|
2010-08-11 22:28:31 +00:00
|
|
|
}
|
2010-11-22 21:47:11 +00:00
|
|
|
return new MessagesCursorLoader(context, mailboxId);
|
2010-08-11 22:28:31 +00:00
|
|
|
|
|
|
|
}
|
2010-09-09 00:38:34 +00:00
|
|
|
|
2011-03-31 20:29:23 +00:00
|
|
|
static private class MessagesCursorLoader extends ThrottlingCursorLoader {
|
2010-09-09 00:38:34 +00:00
|
|
|
private final Context mContext;
|
|
|
|
private final long mMailboxId;
|
|
|
|
|
2010-11-22 21:47:11 +00:00
|
|
|
public MessagesCursorLoader(Context context, long mailboxId) {
|
2010-09-09 00:38:34 +00:00
|
|
|
// Initialize with no where clause. We'll set it later.
|
|
|
|
super(context, EmailContent.Message.CONTENT_URI,
|
|
|
|
MESSAGE_PROJECTION, null, null,
|
2010-09-22 02:02:21 +00:00
|
|
|
EmailContent.MessageColumns.TIMESTAMP + " DESC");
|
2010-09-09 00:38:34 +00:00
|
|
|
mContext = context;
|
|
|
|
mMailboxId = mailboxId;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Cursor loadInBackground() {
|
|
|
|
// Determine the where clause. (Can't do this on the UI thread.)
|
|
|
|
setSelection(Utility.buildMailboxIdSelection(mContext, mMailboxId));
|
|
|
|
|
|
|
|
// Then do a query.
|
2010-12-23 22:37:25 +00:00
|
|
|
return Utility.CloseTraceCursorWrapper.get(super.loadInBackground());
|
|
|
|
}
|
|
|
|
}
|
2010-06-02 00:55:31 +00:00
|
|
|
}
|