1 /** 2 * Copyright (c) 2012, Google Inc. 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 package com.android.mail.compose; 17 18 import android.content.Context; 19 import android.text.TextUtils; 20 import android.util.AttributeSet; 21 import android.view.View; 22 import android.widget.AdapterView; 23 import android.widget.AdapterView.OnItemSelectedListener; 24 import android.widget.Spinner; 25 26 import com.android.mail.providers.Account; 27 import com.android.mail.providers.Message; 28 import com.android.mail.providers.ReplyFromAccount; 29 import com.android.mail.utils.AccountUtils; 30 import com.google.common.annotations.VisibleForTesting; 31 import com.google.common.collect.ImmutableList; 32 import com.google.common.collect.Lists; 33 34 import java.util.List; 35 36 public class FromAddressSpinner extends Spinner implements OnItemSelectedListener { 37 private List<Account> mAccounts; 38 private ReplyFromAccount mAccount; 39 private final List<ReplyFromAccount> mReplyFromAccounts = Lists.newArrayList(); 40 private OnAccountChangedListener mAccountChangedListener; 41 FromAddressSpinner(Context context)42 public FromAddressSpinner(Context context) { 43 this(context, null); 44 } 45 FromAddressSpinner(Context context, AttributeSet set)46 public FromAddressSpinner(Context context, AttributeSet set) { 47 super(context, set); 48 } 49 setCurrentAccount(ReplyFromAccount account)50 public void setCurrentAccount(ReplyFromAccount account) { 51 mAccount = account; 52 selectCurrentAccount(); 53 } 54 selectCurrentAccount()55 private void selectCurrentAccount() { 56 if (mAccount == null) { 57 return; 58 } 59 int currentIndex = 0; 60 for (ReplyFromAccount acct : mReplyFromAccounts) { 61 if (TextUtils.equals(mAccount.name, acct.name) 62 && TextUtils.equals(mAccount.address, acct.address)) { 63 setSelection(currentIndex, true); 64 break; 65 } 66 currentIndex++; 67 } 68 } 69 getMatchingReplyFromAccount(String accountString)70 public ReplyFromAccount getMatchingReplyFromAccount(String accountString) { 71 if (!TextUtils.isEmpty(accountString)) { 72 for (ReplyFromAccount acct : mReplyFromAccounts) { 73 if (accountString.equals(acct.address)) { 74 return acct; 75 } 76 } 77 } 78 return null; 79 } 80 getCurrentAccount()81 public ReplyFromAccount getCurrentAccount() { 82 return mAccount; 83 } 84 85 /** 86 * @param action Action being performed; if this is COMPOSE, show all 87 * accounts. Otherwise, show just the account this was launched 88 * with. 89 * @param currentAccount Account used to launch activity. 90 * @param syncingAccounts 91 */ initialize(int action, Account currentAccount, Account[] syncingAccounts, Message refMessage)92 public void initialize(int action, Account currentAccount, Account[] syncingAccounts, 93 Message refMessage) { 94 final List<Account> accounts = AccountUtils.mergeAccountLists(mAccounts, 95 syncingAccounts, true /* prioritizeAccountList */); 96 if (action == ComposeActivity.COMPOSE) { 97 mAccounts = accounts; 98 } else { 99 // First assume that we are going to use the current account as the reply account 100 Account replyAccount = currentAccount; 101 102 if (refMessage != null && refMessage.accountUri != null) { 103 // This is a reply or forward of a message access through the "combined" account. 104 // We want to make sure that the real account is in the spinner 105 for (Account account : accounts) { 106 if (account.uri.equals(refMessage.accountUri)) { 107 replyAccount = account; 108 break; 109 } 110 } 111 } 112 mAccounts = ImmutableList.of(replyAccount); 113 } 114 initFromSpinner(); 115 } 116 117 @VisibleForTesting initFromSpinner()118 protected void initFromSpinner() { 119 // If there are not yet any accounts in the cached synced accounts 120 // because this is the first time mail was opened, and it was opened 121 // directly to the compose activity, don't bother populating the reply 122 // from spinner yet. 123 if (mAccounts == null || mAccounts.size() == 0) { 124 return; 125 } 126 FromAddressSpinnerAdapter adapter = 127 new FromAddressSpinnerAdapter(getContext()); 128 129 mReplyFromAccounts.clear(); 130 for (Account account : mAccounts) { 131 mReplyFromAccounts.addAll(account.getReplyFroms()); 132 } 133 adapter.addAccounts(mReplyFromAccounts); 134 135 setAdapter(adapter); 136 selectCurrentAccount(); 137 setOnItemSelectedListener(this); 138 } 139 getReplyFromAccounts()140 public List<ReplyFromAccount> getReplyFromAccounts() { 141 return mReplyFromAccounts; 142 } 143 setOnAccountChangedListener(OnAccountChangedListener listener)144 public void setOnAccountChangedListener(OnAccountChangedListener listener) { 145 mAccountChangedListener = listener; 146 } 147 148 @Override onItemSelected(AdapterView<?> parent, View view, int position, long id)149 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 150 ReplyFromAccount selection = (ReplyFromAccount) getItemAtPosition(position); 151 if (!selection.address.equals(mAccount.address)) { 152 mAccount = selection; 153 mAccountChangedListener.onAccountChanged(); 154 } 155 } 156 157 @Override onNothingSelected(AdapterView<?> parent)158 public void onNothingSelected(AdapterView<?> parent) { 159 // Do nothing. 160 } 161 162 /** 163 * Classes that want to know when a different account in the 164 * FromAddressSpinner has been selected should implement this interface. 165 * Note: if the user chooses the same account as the one that has already 166 * been selected, this method will not be called. 167 */ 168 public static interface OnAccountChangedListener { onAccountChanged()169 public void onAccountChanged(); 170 } 171 } 172