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