Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 Google Inc. |
| 3 | * Licensed to The Android Open Source Project. |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
Andy Huang | 30e2c24 | 2012-01-06 18:14:30 -0800 | [diff] [blame] | 18 | package com.android.mail; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 19 | |
| 20 | import android.content.Context; |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 21 | import android.net.Uri; |
Vikram Aggarwal | 59926d6 | 2012-07-19 14:49:11 -0700 | [diff] [blame] | 22 | import android.text.TextUtils; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 23 | import android.view.LayoutInflater; |
| 24 | import android.view.View; |
| 25 | import android.view.ViewGroup; |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 26 | import android.widget.BaseAdapter; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 27 | import android.widget.TextView; |
| 28 | |
Mindy Pereira | 28d5f72 | 2012-02-15 12:32:40 -0800 | [diff] [blame] | 29 | import com.android.mail.providers.Account; |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 30 | import com.android.mail.providers.AccountObserver; |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 31 | import com.android.mail.providers.Folder; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 32 | import com.android.mail.providers.FolderWatcher; |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 33 | import com.android.mail.ui.ControllableActivity; |
Vikram Aggarwal | 1a4bcc0 | 2012-03-01 10:09:44 -0800 | [diff] [blame] | 34 | import com.android.mail.ui.RecentFolderList; |
Paul Westbrook | b334c90 | 2012-06-25 11:42:46 -0700 | [diff] [blame] | 35 | import com.android.mail.utils.LogTag; |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 36 | import com.android.mail.utils.LogUtils; |
Mindy Pereira | c1469c7 | 2012-03-20 13:56:12 -0700 | [diff] [blame] | 37 | import com.android.mail.utils.Utils; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 38 | |
Marc Blank | 167faa8 | 2012-03-21 13:11:53 -0700 | [diff] [blame] | 39 | import java.util.ArrayList; |
| 40 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 41 | /** |
Mindy Pereira | ae18020 | 2012-02-29 13:09:58 -0800 | [diff] [blame] | 42 | * An adapter to return the list of accounts and folders for the Account Spinner. |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 43 | * This class keeps the account and folder information and returns appropriate views. |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 44 | */ |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 45 | public class AccountSpinnerAdapter extends BaseAdapter { |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 46 | private final LayoutInflater mInflater; |
| 47 | /** |
Mindy Pereira | 4067f2e | 2012-04-18 10:11:14 -0700 | [diff] [blame] | 48 | * The position of the current account being viewed. |
| 49 | */ |
| 50 | private Account mCurrentAccount = null; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 51 | /** |
| 52 | * Total number of accounts. |
| 53 | */ |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 54 | private int mNumAccounts = 0; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 55 | /** |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 56 | * Array of all the accounts on the device. |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 57 | */ |
Vikram Aggarwal | abd24d8 | 2012-04-26 13:23:14 -0700 | [diff] [blame] | 58 | private Account[] mAllAccounts = new Account[0]; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 59 | /** |
Vikram Aggarwal | 1a4bcc0 | 2012-03-01 10:09:44 -0800 | [diff] [blame] | 60 | * An object that provides a collection of recent folders, per account. |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 61 | */ |
Vikram Aggarwal | 9d6b6b0 | 2012-03-08 10:36:30 -0800 | [diff] [blame] | 62 | private final RecentFolderList mRecentFolders; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 63 | /** |
Vikram Aggarwal | 1a4bcc0 | 2012-03-01 10:09:44 -0800 | [diff] [blame] | 64 | * The actual collection of sorted recent folders obtained from {@link #mRecentFolders} |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 65 | */ |
Marc Blank | 167faa8 | 2012-03-21 13:11:53 -0700 | [diff] [blame] | 66 | private ArrayList<Folder> mRecentFolderList = new ArrayList<Folder>(); |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 67 | /** |
| 68 | * Boolean indicating whether the "Show All Folders" items should be shown |
| 69 | */ |
| 70 | private final boolean mShowAllFoldersItem; |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 71 | /** |
| 72 | * Set to true to enable recent folders, false to disable. |
| 73 | */ |
| 74 | private boolean mRecentFoldersVisible; |
Vikram Aggarwal | 1a4bcc0 | 2012-03-01 10:09:44 -0800 | [diff] [blame] | 75 | |
| 76 | /** The folder currently being viewed */ |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 77 | private Folder mCurrentFolder; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 78 | private final Context mContext; |
| 79 | /** Maintains the most fresh default inbox folder for each account. Used for unread counts. */ |
| 80 | private final FolderWatcher mFolderWatcher; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 81 | |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 82 | /** Type indicating the current account view shown in the actionbar (not the dropdown) */ |
| 83 | private static final int TYPE_NON_DROPDOWN = 0; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 84 | /** Type indicating a dead, non-clickable view that is not shown to the user. */ |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 85 | public static final int TYPE_DEAD_HEADER = 1; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 86 | /** Type indicating an account (user@example.com). */ |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 87 | public static final int TYPE_ACCOUNT = 2; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 88 | /** Type indicating a view that separates the account list from the recent folder list. */ |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 89 | public static final int TYPE_HEADER = 3; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 90 | /** Type indicating a view containing a recent folder (Sent, Outbox). */ |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 91 | public static final int TYPE_FOLDER = 4; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 92 | /** Type indicating the "Show All Folders" view. */ |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 93 | public static final int TYPE_ALL_FOLDERS = 5; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 94 | |
Paul Westbrook | b334c90 | 2012-06-25 11:42:46 -0700 | [diff] [blame] | 95 | private static final String LOG_TAG = LogTag.getLogTag(); |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 96 | |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 97 | final AccountObserver mAccountObserver = new AccountObserver() { |
| 98 | @Override |
| 99 | public void onChanged(Account newAccount){ |
| 100 | // If the account is missing or we have no accounts array, we cannot |
| 101 | // proceed. |
| 102 | if (newAccount == null) { |
| 103 | return; |
| 104 | } |
| 105 | if (newAccount.uri.equals(getCurrentAccountUri())) { |
| 106 | // The current account matches what is being given, get out. |
| 107 | return; |
| 108 | } |
| 109 | mCurrentAccount = newAccount; |
| 110 | final int pos = Account.findPosition(mAllAccounts, newAccount.uri); |
| 111 | LogUtils.d(LOG_TAG, "setCurrentAccount: mCurrentAccountPos = %d", pos); |
| 112 | if (pos >= 0) { |
| 113 | requestRecentFoldersAndRedraw(); |
| 114 | } |
| 115 | notifyDataSetChanged(); |
| 116 | } |
| 117 | }; |
| 118 | |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 119 | /** |
| 120 | * There can be three types of views: Accounts (test@android.com, fifi@example.com), folders |
| 121 | * (Inbox, Outbox) or header and footer. This method returns the type of account at given |
| 122 | * position in the drop down list. |
| 123 | * @param position |
| 124 | * @return the type of account: one of {@link #TYPE_ACCOUNT}, {@link #TYPE_HEADER}, or |
| 125 | * {@link #TYPE_FOLDER}. |
| 126 | */ |
Mindy Pereira | 0e7f463 | 2012-07-11 16:34:30 -0700 | [diff] [blame] | 127 | public int getType(int position) { |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 128 | if (position == 0) { |
| 129 | return TYPE_DEAD_HEADER; |
| 130 | } |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 131 | // First the accounts |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 132 | if (position <= mNumAccounts) { |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 133 | return TYPE_ACCOUNT; |
| 134 | } |
| 135 | // Then the header |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 136 | if (position == mNumAccounts + 1) { |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 137 | return TYPE_HEADER; |
| 138 | } |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 139 | if (mShowAllFoldersItem && getRecentOffset(position) >= mRecentFolderList.size()) { |
| 140 | return TYPE_ALL_FOLDERS; |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 141 | } |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 142 | // Finally, the recent folders. |
| 143 | return TYPE_FOLDER; |
| 144 | } |
| 145 | |
Vikram Aggarwal | ec5cbf7 | 2012-03-08 15:10:35 -0800 | [diff] [blame] | 146 | /** |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 147 | * Given a dropdown view, enable only the type, and disable everything else. |
| 148 | * @param view |
| 149 | * @param type |
| 150 | */ |
| 151 | private static final void selectRelevant(View view, int type) { |
| 152 | if (view == null) { |
| 153 | return; |
| 154 | } |
| 155 | final View anchor = view.findViewById(R.id.anchor); |
| 156 | final View account = view.findViewById(R.id.account); |
| 157 | final View header = view.findViewById(R.id.header); |
| 158 | final View folder = view.findViewById(R.id.folder); |
| 159 | final View footer = view.findViewById(R.id.footer); |
| 160 | // Disable everything initially. |
| 161 | anchor.setVisibility(View.GONE); |
| 162 | account.setVisibility(View.GONE); |
| 163 | header.setVisibility(View.GONE); |
| 164 | folder.setVisibility(View.GONE); |
| 165 | footer.setVisibility(View.GONE); |
| 166 | switch (type) { |
| 167 | case TYPE_NON_DROPDOWN: |
| 168 | anchor.setVisibility(View.VISIBLE); |
| 169 | break; |
| 170 | case TYPE_DEAD_HEADER: |
| 171 | // Select nothing. |
| 172 | break; |
| 173 | case TYPE_ACCOUNT: |
| 174 | account.setVisibility(View.VISIBLE); |
| 175 | break; |
| 176 | case TYPE_HEADER: |
| 177 | header.setVisibility(View.VISIBLE); |
| 178 | break; |
| 179 | case TYPE_FOLDER: |
| 180 | folder.setVisibility(View.VISIBLE); |
| 181 | break; |
| 182 | case TYPE_ALL_FOLDERS: |
| 183 | footer.setVisibility(View.VISIBLE); |
| 184 | break; |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | /** |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 189 | * Given a position in the list, what offset does it correspond to in the Recent Folders |
| 190 | * list? |
| 191 | * @param position |
| 192 | * @return |
| 193 | */ |
| 194 | private final int getRecentOffset(int position) { |
| 195 | return position - mNumAccounts - 2; |
| 196 | } |
| 197 | |
| 198 | /** |
Vikram Aggarwal | e6340bc | 2012-03-26 15:57:09 -0700 | [diff] [blame] | 199 | * Returns the position of the dead, unselectable element in the spinner. |
| 200 | * @return |
| 201 | */ |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 202 | public final int getSpacerPosition() { |
| 203 | // Return the position of the dead header, which is always at the top. |
| 204 | return 0; |
Vikram Aggarwal | e6340bc | 2012-03-26 15:57:09 -0700 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | /** |
Vikram Aggarwal | ec5cbf7 | 2012-03-08 15:10:35 -0800 | [diff] [blame] | 208 | * Create a spinner adapter with the context and the list of recent folders. |
| 209 | * @param context |
| 210 | * @param recentFolders |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 211 | * @param showAllFolders |
Vikram Aggarwal | ec5cbf7 | 2012-03-08 15:10:35 -0800 | [diff] [blame] | 212 | */ |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 213 | public AccountSpinnerAdapter(ControllableActivity activity, Context context, |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 214 | RecentFolderList recentFolders, boolean showAllFolders) { |
Mindy Pereira | c1469c7 | 2012-03-20 13:56:12 -0700 | [diff] [blame] | 215 | mContext = context; |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 216 | mInflater = LayoutInflater.from(context); |
Vikram Aggarwal | ec5cbf7 | 2012-03-08 15:10:35 -0800 | [diff] [blame] | 217 | mRecentFolders = recentFolders; |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 218 | mShowAllFoldersItem = showAllFolders; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 219 | // Owned by the AccountSpinnerAdapter since nobody else needed it. Move to controller if |
Vikram Aggarwal | 1dd77c9 | 2012-08-21 09:27:40 -0700 | [diff] [blame] | 220 | // required. The folder watcher tells us directly when new data is available. We are only |
| 221 | // interested in unread counts at this point. |
| 222 | mFolderWatcher = new FolderWatcher(activity, this); |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 223 | mCurrentAccount = mAccountObserver.initialize(activity.getAccountController()); |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 224 | } |
| 225 | |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 226 | /** |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 227 | * Set the accounts for this spinner. |
| 228 | * @param accounts |
| 229 | */ |
Vikram Aggarwal | abd24d8 | 2012-04-26 13:23:14 -0700 | [diff] [blame] | 230 | public void setAccountArray(Account[] accounts) { |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 231 | final Uri currentAccount = getCurrentAccountUri(); |
Vikram Aggarwal | abd24d8 | 2012-04-26 13:23:14 -0700 | [diff] [blame] | 232 | mAllAccounts = accounts; |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 233 | mNumAccounts = accounts.length; |
Mindy Pereira | 4067f2e | 2012-04-18 10:11:14 -0700 | [diff] [blame] | 234 | if (!isCurrentAccountInvalid()) { |
Vikram Aggarwal | 73bffaf | 2012-06-25 11:29:56 -0700 | [diff] [blame] | 235 | final int pos = Account.findPosition(accounts, currentAccount); |
| 236 | LogUtils.d(LOG_TAG, "setAccountArray: mCurrentAccountPos = %d", pos); |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 237 | } |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 238 | // Go through all the accounts and add the default inbox to our watcher. |
| 239 | for (int i=0; i < mNumAccounts; i++) { |
| 240 | final Uri uri = mAllAccounts[i].settings.defaultInbox; |
| 241 | mFolderWatcher.startWatching(uri); |
| 242 | } |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 243 | notifyDataSetChanged(); |
| 244 | } |
| 245 | |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 246 | /** |
Mindy Pereira | bc57bf1 | 2012-02-29 14:39:09 -0800 | [diff] [blame] | 247 | * Set the current folder. |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 248 | * @param folder |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 249 | * @return if changed. |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 250 | */ |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 251 | public boolean setCurrentFolder(Folder folder) { |
| 252 | if (folder != null && folder != mCurrentFolder) { |
| 253 | mCurrentFolder = folder; |
Vikram Aggarwal | 3726397 | 2012-04-17 15:51:14 -0700 | [diff] [blame] | 254 | requestRecentFoldersAndRedraw(); |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 255 | return true; |
| 256 | } |
| 257 | return false; |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 258 | } |
| 259 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 260 | @Override |
| 261 | public int getCount() { |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 262 | // If the recent folders are visible, then one header, recent folders, plus one if the |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 263 | // "show all folders" item should be shown |
Vikram Aggarwal | e93a01e | 2012-07-23 12:53:00 -0700 | [diff] [blame] | 264 | final int numRecents = mRecentFolderList.size(); |
| 265 | final int numFolders = (mRecentFoldersVisible && numRecents > 0) ? |
| 266 | (1 + numRecents + (mShowAllFoldersItem ? 1 : 0)) : 0; |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 267 | return 1 + mNumAccounts + numFolders; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 268 | } |
| 269 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 270 | @Override |
| 271 | public Object getItem(int position) { |
Mindy Pereira | 0e7f463 | 2012-07-11 16:34:30 -0700 | [diff] [blame] | 272 | switch (getType(position)){ |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 273 | case TYPE_DEAD_HEADER: |
| 274 | return "dead header"; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 275 | case TYPE_ACCOUNT: |
| 276 | return getAccount(position); |
| 277 | case TYPE_HEADER: |
| 278 | return "account spinner header"; |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 279 | case TYPE_ALL_FOLDERS: |
| 280 | return "show all folders"; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 281 | default: |
Marc Blank | 41e764d | 2012-03-20 20:46:28 -0700 | [diff] [blame] | 282 | // Return the folder at this location. |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 283 | return mRecentFolderList.get(getRecentOffset(position)); |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 284 | } |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 285 | } |
| 286 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 287 | @Override |
| 288 | public long getItemId(int position) { |
Vikram Aggarwal | 071fa7e | 2012-07-18 12:40:33 -0700 | [diff] [blame] | 289 | final int type = getType(position); |
| 290 | switch (type) { |
| 291 | case TYPE_DEAD_HEADER: |
| 292 | // Fall-through |
| 293 | case TYPE_HEADER: |
| 294 | // Fall-through |
| 295 | case TYPE_ALL_FOLDERS: |
| 296 | return type; |
| 297 | case TYPE_ACCOUNT: |
| 298 | return getAccount(position).uri.hashCode(); |
| 299 | default: |
| 300 | return mRecentFolderList.get(getRecentOffset(position)).uri.hashCode(); |
| 301 | } |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 302 | } |
| 303 | |
Mindy Pereira | f9323cd | 2012-02-29 13:47:09 -0800 | [diff] [blame] | 304 | private String getFolderLabel() { |
| 305 | return mCurrentFolder != null ? mCurrentFolder.name : ""; |
| 306 | } |
| 307 | |
Mindy Pereira | e973f22 | 2012-03-06 14:29:03 -0800 | [diff] [blame] | 308 | private int getFolderUnreadCount() { |
| 309 | return mCurrentFolder != null ? mCurrentFolder.unreadCount : 0; |
| 310 | } |
| 311 | |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 312 | /** |
| 313 | * Returns whether the current account is an invalid offset into the array. |
| 314 | * @return true if the current account is invalid, and false otherwise. |
| 315 | */ |
| 316 | private boolean isCurrentAccountInvalid() { |
Mindy Pereira | 4067f2e | 2012-04-18 10:11:14 -0700 | [diff] [blame] | 317 | return mCurrentAccount == null; |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 318 | } |
| 319 | |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 320 | private String getCurrentAccountName() { |
Vikram Aggarwal | 73bffaf | 2012-06-25 11:29:56 -0700 | [diff] [blame] | 321 | if (isCurrentAccountInvalid()) { |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 322 | return ""; |
| 323 | } |
Mindy Pereira | 5c9c9b8 | 2012-04-18 10:49:07 -0700 | [diff] [blame] | 324 | return mCurrentAccount.name; |
Vikram Aggarwal | 8183d45 | 2012-04-17 09:13:29 -0700 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | private Uri getCurrentAccountUri() { |
| 328 | if (isCurrentAccountInvalid()) { |
| 329 | return Uri.EMPTY; |
| 330 | } |
Mindy Pereira | 4067f2e | 2012-04-18 10:11:14 -0700 | [diff] [blame] | 331 | return mCurrentAccount.uri; |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 332 | } |
| 333 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 334 | @Override |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 335 | public View getView(int position, View view, ViewGroup parent) { |
| 336 | if (view == null) { |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 337 | view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null); |
Mindy Pereira | 0e7f463 | 2012-07-11 16:34:30 -0700 | [diff] [blame] | 338 | } |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 339 | selectRelevant(view, TYPE_NON_DROPDOWN); |
| 340 | ((TextView) view.findViewById(R.id.account_first)).setText(getFolderLabel()); |
| 341 | ((TextView) view.findViewById(R.id.account_second)) |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 342 | .setText(getCurrentAccountName()); |
Vikram Aggarwal | 1dd77c9 | 2012-08-21 09:27:40 -0700 | [diff] [blame] | 343 | final int currentViewUnreadCount = getFolderUnreadCount(); |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 344 | populateUnreadCountView((TextView) view.findViewById(R.id.account_unread), |
| 345 | currentViewUnreadCount); |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 346 | return view; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 347 | } |
| 348 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 349 | @Override |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 350 | public boolean hasStableIds() { |
Vikram Aggarwal | 071fa7e | 2012-07-18 12:40:33 -0700 | [diff] [blame] | 351 | // The ID is the hash of the URI of the object. |
| 352 | return true; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 353 | } |
| 354 | |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 355 | @Override |
| 356 | public boolean isEmpty() { |
| 357 | // No item will be empty. |
| 358 | return false; |
| 359 | } |
| 360 | |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 361 | @Override |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 362 | public View getDropDownView(int position, View view, ViewGroup parent) { |
Vikram Aggarwal | 5f09b6f | 2012-06-15 17:03:40 -0700 | [diff] [blame] | 363 | // Shown in the first text view with big font. |
| 364 | String bigText = ""; |
| 365 | // Shown in the second text view with smaller font. |
| 366 | String smallText = ""; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 367 | int unreadCount = 0; |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 368 | // Do not use stop view recycling in getDropDownView!!! |
| 369 | // For unknown reasons, using view recycling avoids bugs where the unread count used to |
| 370 | // disappear. |
| 371 | final int type = getType(position); |
| 372 | if (view == null) { |
| 373 | view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null); |
| 374 | } |
| 375 | selectRelevant(view, type); |
| 376 | switch (type) { |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 377 | case TYPE_DEAD_HEADER: |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 378 | return view; |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 379 | case TYPE_ACCOUNT: |
Vikram Aggarwal | 5e63e8a | 2012-07-19 10:05:24 -0700 | [diff] [blame] | 380 | final Account account = getAccount(position); |
Vikram Aggarwal | c5a575e | 2012-08-02 10:05:30 -0700 | [diff] [blame] | 381 | View colorView = view.findViewById(R.id.account_spinner_color); |
Vikram Aggarwal | 5e63e8a | 2012-07-19 10:05:24 -0700 | [diff] [blame] | 382 | if (account == null) { |
| 383 | bigText = ""; |
| 384 | smallText = ""; |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 385 | unreadCount = 0; |
Vikram Aggarwal | c5a575e | 2012-08-02 10:05:30 -0700 | [diff] [blame] | 386 | colorView.setVisibility(View.INVISIBLE); |
Vikram Aggarwal | 5e63e8a | 2012-07-19 10:05:24 -0700 | [diff] [blame] | 387 | } else { |
| 388 | bigText = account.settings.defaultInboxName; |
| 389 | smallText = account.name; |
Vikram Aggarwal | c5a575e | 2012-08-02 10:05:30 -0700 | [diff] [blame] | 390 | final int color = account.color; |
| 391 | if (color != 0) { |
| 392 | colorView.setVisibility(View.VISIBLE); |
| 393 | colorView.setBackgroundColor(color); |
| 394 | } else { |
| 395 | colorView.setVisibility(View.INVISIBLE); |
| 396 | } |
Vikram Aggarwal | 7a5d95a | 2012-07-27 16:24:54 -0700 | [diff] [blame] | 397 | final Folder inbox = mFolderWatcher.get(account.settings.defaultInbox); |
| 398 | unreadCount = (inbox != null) ? inbox.unreadCount : 0; |
Vikram Aggarwal | 5e63e8a | 2012-07-19 10:05:24 -0700 | [diff] [blame] | 399 | } |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 400 | displayOrHide(view, R.id.abd_account_first, bigText); |
| 401 | displayOrHide(view, R.id.abd_account_second, smallText); |
| 402 | populateUnreadCountView( |
| 403 | (TextView) view.findViewById(R.id.abd_account_unread), unreadCount); |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 404 | break; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 405 | case TYPE_HEADER: |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 406 | ((TextView) view.findViewById(R.id.account_spinner_header_account)) |
| 407 | .setText(getCurrentAccountName()); |
| 408 | return view; |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 409 | case TYPE_FOLDER: |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 410 | final Folder folder = mRecentFolderList.get(getRecentOffset(position)); |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 411 | colorView = view.findViewById(R.id.abd_folder_color); |
Vikram Aggarwal | 5f09b6f | 2012-06-15 17:03:40 -0700 | [diff] [blame] | 412 | bigText = folder.name; |
Vikram Aggarwal | 1a4bcc0 | 2012-03-01 10:09:44 -0800 | [diff] [blame] | 413 | unreadCount = folder.unreadCount; |
Vikram Aggarwal | c5a575e | 2012-08-02 10:05:30 -0700 | [diff] [blame] | 414 | Folder.setFolderBlockColor(folder, colorView); |
| 415 | colorView.setVisibility(View.VISIBLE); |
Vikram Aggarwal | 3da3c89 | 2012-08-21 15:00:22 -0700 | [diff] [blame^] | 416 | displayOrHide(view, R.id.abd_folder_first, bigText); |
| 417 | displayOrHide(view, R.id.abd_folder_second, smallText); |
| 418 | populateUnreadCountView( |
| 419 | (TextView) view.findViewById(R.id.abd_folder_unread), unreadCount); |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 420 | break; |
Paul Westbrook | 904b5f2 | 2012-04-12 00:29:58 -0700 | [diff] [blame] | 421 | case TYPE_ALL_FOLDERS: |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 422 | return view; |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 423 | } |
Vikram Aggarwal | c1057c6 | 2012-08-01 13:55:16 -0700 | [diff] [blame] | 424 | return view; |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 425 | } |
| 426 | |
Vikram Aggarwal | 5f09b6f | 2012-06-15 17:03:40 -0700 | [diff] [blame] | 427 | /** |
| 428 | * Sets the text of the TextView to the given text, if it is non-empty. If the given |
| 429 | * text is empty, then the TextView is hidden (set to View.GONE). |
| 430 | * @param v |
| 431 | * @param resourceId |
| 432 | * @param toDisplay the given text |
| 433 | */ |
| 434 | static private void displayOrHide(View v, int resourceId, String toDisplay) { |
| 435 | final TextView target = (TextView) v.findViewById(resourceId); |
Vikram Aggarwal | 59926d6 | 2012-07-19 14:49:11 -0700 | [diff] [blame] | 436 | if (TextUtils.isEmpty(toDisplay)) { |
Vikram Aggarwal | 5f09b6f | 2012-06-15 17:03:40 -0700 | [diff] [blame] | 437 | target.setVisibility(View.GONE); |
| 438 | return; |
| 439 | } |
| 440 | target.setText(toDisplay); |
| 441 | } |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 442 | |
Vikram Aggarwal | 1dd77c9 | 2012-08-21 09:27:40 -0700 | [diff] [blame] | 443 | /** |
| 444 | * Sets the unread count, which is a nonzero number or an empty string if there are no unread |
| 445 | * messages. |
| 446 | * @param unreadCountView |
| 447 | * @param unreadCount |
| 448 | */ |
| 449 | private final void populateUnreadCountView(TextView unreadCountView, int unreadCount) { |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 450 | unreadCountView.setText(Utils.getUnreadCountString(mContext, unreadCount)); |
Mindy Pereira | a6be848 | 2012-03-21 10:31:57 -0700 | [diff] [blame] | 451 | } |
| 452 | |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 453 | /** |
Mindy Pereira | 28d5f72 | 2012-02-15 12:32:40 -0800 | [diff] [blame] | 454 | * Returns the account given position in the spinner. |
| 455 | * @param position |
Vikram Aggarwal | a9b93f3 | 2012-02-23 14:51:58 -0800 | [diff] [blame] | 456 | * @return the account at the given position. |
Mindy Pereira | 28d5f72 | 2012-02-15 12:32:40 -0800 | [diff] [blame] | 457 | */ |
| 458 | private Account getAccount(int position) { |
Vikram Aggarwal | 5e63e8a | 2012-07-19 10:05:24 -0700 | [diff] [blame] | 459 | if (position >= mNumAccounts + 1) { |
| 460 | return null; |
| 461 | } |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 462 | return mAllAccounts[position - 1]; |
Mindy Pereira | 28d5f72 | 2012-02-15 12:32:40 -0800 | [diff] [blame] | 463 | } |
| 464 | |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 465 | |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 466 | @Override |
| 467 | public boolean isEnabled(int position) { |
| 468 | // Don't want the user selecting the header. |
Mindy Pereira | 0e7f463 | 2012-07-11 16:34:30 -0700 | [diff] [blame] | 469 | final int type = getType(position); |
Vikram Aggarwal | 071fa7e | 2012-07-18 12:40:33 -0700 | [diff] [blame] | 470 | return type != TYPE_HEADER; |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 471 | } |
| 472 | |
| 473 | @Override |
| 474 | public boolean areAllItemsEnabled() { |
Vikram Aggarwal | 8b15263 | 2012-02-03 14:58:45 -0800 | [diff] [blame] | 475 | // The header is not enabled, so return false here. |
Vikram Aggarwal | 6f6afe5 | 2012-01-04 14:43:44 -0800 | [diff] [blame] | 476 | return false; |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 477 | } |
Mindy Pereira | a46a57f | 2012-04-03 17:19:31 -0700 | [diff] [blame] | 478 | |
| 479 | /** |
| 480 | * Notify that the folder has changed. |
| 481 | */ |
| 482 | public void onFolderUpdated(Folder folder) { |
| 483 | mCurrentFolder = folder; |
| 484 | notifyDataSetChanged(); |
| 485 | } |
Vikram Aggarwal | 3726397 | 2012-04-17 15:51:14 -0700 | [diff] [blame] | 486 | |
| 487 | /** |
| 488 | * Cause a refresh of the recent folders for the current folder and redraw the spinner with |
| 489 | * the new information. |
| 490 | */ |
| 491 | public void requestRecentFoldersAndRedraw() { |
| 492 | mRecentFolderList = mRecentFolders.getRecentFolderList(mCurrentFolder); |
| 493 | notifyDataSetChanged(); |
| 494 | } |
Vikram Aggarwal | 67f36fc | 2012-06-18 14:36:44 -0700 | [diff] [blame] | 495 | |
| 496 | /** |
| 497 | * Disable recent folders. Can be enabled again with {@link #enableRecentFolders()} |
| 498 | */ |
| 499 | public void disableRecentFolders() { |
| 500 | if (mRecentFoldersVisible) { |
| 501 | notifyDataSetChanged(); |
| 502 | mRecentFoldersVisible = false; |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | /** |
| 507 | * Enable recent folders. Can be disabled again with {@link #disableRecentFolders()} |
| 508 | */ |
| 509 | public void enableRecentFolders() { |
| 510 | if (!mRecentFoldersVisible) { |
| 511 | notifyDataSetChanged(); |
| 512 | mRecentFoldersVisible = true; |
| 513 | } |
| 514 | } |
Vikram Aggarwal | 7c401b7 | 2012-08-13 16:43:47 -0700 | [diff] [blame] | 515 | |
| 516 | /** |
| 517 | * Destroys the spinner adapter |
| 518 | */ |
| 519 | public void destroy() { |
| 520 | mAccountObserver.unregisterAndDestroy(); |
| 521 | } |
Vikram Aggarwal | 5e5ac74 | 2011-12-19 08:14:16 -0800 | [diff] [blame] | 522 | } |