AccountSelectorAdapter.java revision 8112732376d4cc033ee515a6531852ef42266929
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.data.ClosingMatrixCursor; 21import com.android.email.data.ThrottlingCursorLoader; 22import com.android.emailcommon.provider.EmailContent; 23import com.android.emailcommon.provider.EmailContent.Account; 24import com.android.emailcommon.provider.EmailContent.Mailbox; 25import com.android.emailcommon.utility.Utility; 26 27import android.content.Context; 28import android.content.Loader; 29import android.database.Cursor; 30import android.database.MatrixCursor; 31import android.database.MatrixCursor.RowBuilder; 32import android.view.LayoutInflater; 33import android.view.View; 34import android.view.ViewGroup; 35import android.widget.CursorAdapter; 36import android.widget.TextView; 37 38/** 39 * Adapter for the account selector on {@link UIControllerTwoPane}. 40 * 41 * TODO Test it! 42 */ 43public class AccountSelectorAdapter extends CursorAdapter { 44 /** Projection used to query from Account */ 45 private static final String[] ACCOUNT_PROJECTION = new String[] { 46 EmailContent.RECORD_ID, 47 EmailContent.Account.DISPLAY_NAME, 48 EmailContent.Account.EMAIL_ADDRESS, 49 }; 50 51 /** 52 * Projection for the resulting MatrixCursor -- must be {@link #ACCOUNT_PROJECTION} 53 * with "UNREAD_COUNT". 54 */ 55 private static final String[] RESULT_PROJECTION = new String[] { 56 EmailContent.RECORD_ID, 57 EmailContent.Account.DISPLAY_NAME, 58 EmailContent.Account.EMAIL_ADDRESS, 59 "UNREAD_COUNT" 60 }; 61 62 private static final int ID_COLUMN = 0; 63 private static final int DISPLAY_NAME_COLUMN = 1; 64 private static final int EMAIL_ADDRESS_COLUMN = 2; 65 private static final int UNREAD_COUNT_COLUMN = 3; 66 67 /** Sort order. Show the default account first. */ 68 private static final String ORDER_BY = 69 EmailContent.Account.IS_DEFAULT + " desc, " + EmailContent.Account.RECORD_ID; 70 71 private final LayoutInflater mInflater; 72 private final Context mContext; 73 74 public static Loader<Cursor> createLoader(Context context) { 75 return new AccountsLoader(context); 76 } 77 78 public AccountSelectorAdapter(Context context) { 79 super(context, null, 0 /* no auto-requery */); 80 mContext = context; 81 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 82 } 83 84 @Override 85 public View getDropDownView(int position, View convertView, ViewGroup parent) { 86 final View view = mInflater.inflate(R.layout.account_selector_dropdown, parent, false); 87 88 final TextView displayNameView = (TextView) view.findViewById(R.id.display_name); 89 final TextView emailAddressView = (TextView) view.findViewById(R.id.email_address); 90 final TextView unreadCountView = (TextView) view.findViewById(R.id.unread_count); 91 92 final String displayName = getAccountDisplayName(position); 93 final String emailAddress = getAccountEmailAddress(position); 94 95 displayNameView.setText(displayName); 96 97 // Show the email address only when it's different from the display name. 98 if (emailAddress.equals(displayName)) { 99 emailAddressView.setVisibility(View.GONE); 100 } else { 101 emailAddressView.setVisibility(View.VISIBLE); 102 emailAddressView.setText(emailAddress); 103 } 104 105 unreadCountView.setText(UiUtilities.getMessageCountForUi(mContext, 106 getAccountUnreadCount(position), false)); 107 return view; 108 } 109 110 @Override 111 public void bindView(View view, Context context, Cursor cursor) { 112 TextView textView = (TextView) view.findViewById(R.id.display_name); 113 textView.setText(getAccountDisplayName(cursor)); 114 } 115 116 @Override 117 public View newView(Context context, Cursor cursor, ViewGroup parent) { 118 return mInflater.inflate(R.layout.account_selector, parent, false); 119 } 120 121 /** @return Account id extracted from a Cursor. */ 122 public static long getAccountId(Cursor c) { 123 return c.getLong(ID_COLUMN); 124 } 125 126 private String getAccountDisplayName(int position) { 127 final Cursor c = getCursor(); 128 return c.moveToPosition(position) ? getAccountDisplayName(c) : null; 129 } 130 131 private String getAccountEmailAddress(int position) { 132 final Cursor c = getCursor(); 133 return c.moveToPosition(position) ? getAccountEmailAddress(c) : null; 134 } 135 136 private int getAccountUnreadCount(int position) { 137 final Cursor c = getCursor(); 138 return c.moveToPosition(position) ? getAccountUnreadCount(c) : 0; 139 } 140 141 /** @return Account name extracted from a Cursor. */ 142 public static String getAccountDisplayName(Cursor cursor) { 143 return cursor.getString(DISPLAY_NAME_COLUMN); 144 } 145 146 /** @return Email address extracted from a Cursor. */ 147 public static String getAccountEmailAddress(Cursor cursor) { 148 return cursor.getString(EMAIL_ADDRESS_COLUMN); 149 } 150 151 /** @return Unread count extracted from a Cursor. */ 152 public static int getAccountUnreadCount(Cursor cursor) { 153 return cursor.getInt(UNREAD_COUNT_COLUMN); 154 } 155 156 /** 157 * Load the account list. The resulting cursor contains 158 * - Account info 159 * - # of unread messages in inbox 160 * - The "Combined view" row if there's more than one account. 161 */ 162 /* package */ static class AccountsLoader extends ThrottlingCursorLoader { 163 private final Context mContext; 164 165 public AccountsLoader(Context context) { 166 // Super class loads a regular account cursor, but we replace it in loadInBackground(). 167 super(context, EmailContent.Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null, 168 ORDER_BY); 169 mContext = context; 170 } 171 172 @Override 173 public Cursor loadInBackground() { 174 // Fetch account list 175 final Cursor accountsCursor = super.loadInBackground(); 176 177 // Cursor that's actually returned. 178 // Use ClosingMatrixCursor so that accountsCursor gets closed too when it's closed. 179 final MatrixCursor resultCursor = new ClosingMatrixCursor(RESULT_PROJECTION, 180 accountsCursor); 181 accountsCursor.moveToPosition(-1); 182 183 // Build the cursor... 184 int totalUnread = 0; 185 while (accountsCursor.moveToNext()) { 186 // Add account, with its unread count. 187 final long accountId = accountsCursor.getLong(0); 188 final int unread = Mailbox.getUnreadCountByAccountAndMailboxType( 189 mContext, accountId, Mailbox.TYPE_INBOX); 190 191 RowBuilder rb = resultCursor.newRow(); 192 rb.add(accountId); 193 rb.add(getAccountDisplayName(accountsCursor)); 194 rb.add(getAccountEmailAddress(accountsCursor)); 195 rb.add(unread); 196 totalUnread += unread; 197 } 198 // Add "combined view" 199 final int countAccounts = resultCursor.getCount(); 200 if (countAccounts > 1) { 201 RowBuilder rb = resultCursor.newRow(); 202 203 // Add ID, display name, # of accounts, total unread count. 204 rb.add(Account.ACCOUNT_ID_COMBINED_VIEW); 205 rb.add(mContext.getResources().getString( 206 R.string.mailbox_list_account_selector_combined_view)); 207 rb.add(mContext.getResources().getQuantityString(R.plurals.number_of_accounts, 208 countAccounts, countAccounts)); 209 rb.add(totalUnread); 210 } 211 return Utility.CloseTraceCursorWrapper.get(resultCursor); 212 } 213 } 214} 215