AccountSelectorAdapter.java revision dc78a769fce18d259eccc602c4623fa74cdf5319
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.activity; 18 19import com.android.email.R; 20import com.android.email.UiUtilities; 21import com.android.email.data.ClosingMatrixCursor; 22import com.android.email.data.ThrottlingCursorLoader; 23import com.android.emailcommon.provider.EmailContent; 24import com.android.emailcommon.provider.EmailContent.Account; 25import com.android.emailcommon.provider.EmailContent.Mailbox; 26import com.android.emailcommon.utility.Utility; 27 28import android.content.Context; 29import android.content.Loader; 30import android.database.Cursor; 31import android.database.MatrixCursor; 32import android.database.MatrixCursor.RowBuilder; 33import android.view.LayoutInflater; 34import android.view.View; 35import android.view.ViewGroup; 36import android.widget.CursorAdapter; 37import android.widget.TextView; 38 39/** 40 * Adapter for the account selector on {@link MessageListXL}. 41 * 42 * TODO Test it! 43 * TODO Use layout? Or use the standard resources that ActionBarDemo uses? 44 * TODO Revisit the sort order when we get more detailed UI spec. (current sort order makes things 45 * simpler for now.) Maybe we can just use SimpleCursorAdapter. 46 */ 47public class AccountSelectorAdapter extends CursorAdapter { 48 /** Projection used to query from Account */ 49 private static final String[] ACCOUNT_PROJECTION = new String[] { 50 EmailContent.RECORD_ID, 51 EmailContent.Account.DISPLAY_NAME, 52 EmailContent.Account.EMAIL_ADDRESS, 53 }; 54 55 /** 56 * Projection for the resulting MatrixCursor -- must be {@link #ACCOUNT_PROJECTION} 57 * with "UNREAD_COUNT". 58 */ 59 private static final String[] RESULT_PROJECTION = new String[] { 60 EmailContent.RECORD_ID, 61 EmailContent.Account.DISPLAY_NAME, 62 EmailContent.Account.EMAIL_ADDRESS, 63 "UNREAD_COUNT" 64 }; 65 66 private static final int ID_COLUMN = 0; 67 private static final int DISPLAY_NAME_COLUMN = 1; 68 private static final int EMAIL_ADDRESS_COLUMN = 2; 69 private static final int UNREAD_COUNT_COLUMN = 3; 70 71 /** Sort order. Show the default account first. */ 72 private static final String ORDER_BY = 73 EmailContent.Account.IS_DEFAULT + " desc, " + EmailContent.Account.RECORD_ID; 74 75 private final LayoutInflater mInflater; 76 private final Context mContext; 77 78 public static Loader<Cursor> createLoader(Context context) { 79 return new AccountsLoader(context); 80 } 81 82 public AccountSelectorAdapter(Context context, Cursor c) { 83 super(context, c, 0 /* no auto-requery */); 84 mContext = context; 85 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 86 } 87 88 @Override 89 public View getDropDownView(int position, View convertView, ViewGroup parent) { 90 final View view = mInflater.inflate(R.layout.account_selector_dropdown, parent, false); 91 92 final TextView displayNameView = (TextView) view.findViewById(R.id.display_name); 93 final TextView emailAddressView = (TextView) view.findViewById(R.id.email_address); 94 final TextView unreadCountView = (TextView) view.findViewById(R.id.unread_count); 95 96 final String displayName = getAccountDisplayName(position); 97 final String emailAddress = getAccountEmailAddress(position); 98 99 displayNameView.setText(displayName); 100 101 // Show the email address only when it's different from the display name. 102 if (emailAddress.equals(displayName)) { 103 emailAddressView.setVisibility(View.GONE); 104 } else { 105 emailAddressView.setVisibility(View.VISIBLE); 106 emailAddressView.setText(emailAddress); 107 } 108 109 unreadCountView.setText(UiUtilities.getMessageCountForUi(mContext, 110 getAccountUnreadCount(position), false)); 111 return view; 112 } 113 114 @Override 115 public void bindView(View view, Context context, Cursor cursor) { 116 TextView textView = (TextView) view.findViewById(R.id.display_name); 117 textView.setText(getAccountDisplayName(cursor)); 118 } 119 120 @Override 121 public View newView(Context context, Cursor cursor, ViewGroup parent) { 122 return mInflater.inflate(R.layout.account_selector, parent, false); 123 } 124 125 /** @return Account id extracted from a Cursor. */ 126 public static long getAccountId(Cursor c) { 127 return c.getLong(ID_COLUMN); 128 } 129 130 private String getAccountDisplayName(int position) { 131 final Cursor c = getCursor(); 132 return c.moveToPosition(position) ? getAccountDisplayName(c) : null; 133 } 134 135 private String getAccountEmailAddress(int position) { 136 final Cursor c = getCursor(); 137 return c.moveToPosition(position) ? getAccountEmailAddress(c) : null; 138 } 139 140 private int getAccountUnreadCount(int position) { 141 final Cursor c = getCursor(); 142 return c.moveToPosition(position) ? getAccountUnreadCount(c) : 0; 143 } 144 145 /** @return Account name extracted from a Cursor. */ 146 public static String getAccountDisplayName(Cursor cursor) { 147 return cursor.getString(DISPLAY_NAME_COLUMN); 148 } 149 150 /** @return Email address extracted from a Cursor. */ 151 public static String getAccountEmailAddress(Cursor cursor) { 152 return cursor.getString(EMAIL_ADDRESS_COLUMN); 153 } 154 155 /** @return Unread count extracted from a Cursor. */ 156 public static int getAccountUnreadCount(Cursor cursor) { 157 return cursor.getInt(UNREAD_COUNT_COLUMN); 158 } 159 160 /** 161 * Load the account list. The resulting cursor contains 162 * - Account info 163 * - # of unread messages in inbox 164 * - The "Combined view" row if there's more than one account. 165 */ 166 /* package */ static class AccountsLoader extends ThrottlingCursorLoader { 167 private final Context mContext; 168 169 public AccountsLoader(Context context) { 170 // Super class loads a regular account cursor, but we replace it in loadInBackground(). 171 super(context, EmailContent.Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null, 172 ORDER_BY); 173 mContext = context; 174 } 175 176 @Override 177 public Cursor loadInBackground() { 178 // Fetch account list 179 final Cursor accountsCursor = super.loadInBackground(); 180 181 // Cursor that's actually returned. 182 // Use ClosingMatrixCursor so that accountsCursor gets closed too when it's closed. 183 final MatrixCursor resultCursor = new ClosingMatrixCursor(RESULT_PROJECTION, 184 accountsCursor); 185 accountsCursor.moveToPosition(-1); 186 187 // Build the cursor... 188 int totalUnread = 0; 189 while (accountsCursor.moveToNext()) { 190 // Add account, with its unread count. 191 final long accountId = accountsCursor.getLong(0); 192 final int unread = Mailbox.getUnreadCountByAccountAndMailboxType( 193 mContext, accountId, Mailbox.TYPE_INBOX); 194 195 RowBuilder rb = resultCursor.newRow(); 196 rb.add(accountId); 197 rb.add(getAccountDisplayName(accountsCursor)); 198 rb.add(getAccountEmailAddress(accountsCursor)); 199 rb.add(unread); 200 totalUnread += unread; 201 } 202 // Add "combined view" 203 final int countAccounts = resultCursor.getCount(); 204 if (countAccounts > 1) { 205 RowBuilder rb = resultCursor.newRow(); 206 207 // Add ID, display name, # of accounts, total unread count. 208 rb.add(Account.ACCOUNT_ID_COMBINED_VIEW); 209 rb.add(mContext.getResources().getString( 210 R.string.mailbox_list_account_selector_combined_view)); 211 rb.add(mContext.getResources().getQuantityString(R.plurals.number_of_accounts, 212 countAccounts, countAccounts)); 213 rb.add(totalUnread); 214 } 215 return Utility.CloseTraceCursorWrapper.get(resultCursor); 216 } 217 } 218} 219