blob: d395b6c1fd0dc9fc5dae13f217ad777cb9632747 [file] [log] [blame]
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -08001/*
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 Huang30e2c242012-01-06 18:14:30 -080018package com.android.mail;
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080019
20import android.content.Context;
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080021import android.view.LayoutInflater;
22import android.view.View;
23import android.view.ViewGroup;
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080024import android.widget.BaseAdapter;
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080025import android.widget.TextView;
26
Mindy Pereira28d5f722012-02-15 12:32:40 -080027import com.android.mail.providers.Account;
Mindy Pereiraf9323cd2012-02-29 13:47:09 -080028import com.android.mail.providers.Folder;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080029import com.android.mail.providers.UIProvider;
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -080030import com.android.mail.ui.RecentFolderList;
Mindy Pereirac1469c72012-03-20 13:56:12 -070031import com.android.mail.utils.Utils;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080032
Marc Blank167faa82012-03-21 13:11:53 -070033import java.util.ArrayList;
34
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080035/**
Mindy Pereiraae180202012-02-29 13:09:58 -080036 * An adapter to return the list of accounts and folders for the Account Spinner.
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080037 * This class keeps the account and folder information and returns appropriate views.
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080038 */
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080039public class AccountSpinnerAdapter extends BaseAdapter {
Vikram Aggarwal8b152632012-02-03 14:58:45 -080040 private final LayoutInflater mInflater;
41 /**
42 * The current account being viewed
43 */
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080044 private Account mCurrentAccount = null;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080045 /**
46 * Total number of accounts.
47 */
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080048 private int mNumAccounts = 0;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080049 /**
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080050 * Array of all the accounts on the device.
Vikram Aggarwal8b152632012-02-03 14:58:45 -080051 */
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080052 private Account[] mAccounts = new Account[0];
Vikram Aggarwal8b152632012-02-03 14:58:45 -080053
54 /**
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080055 * The name of the account is the 2nd column in {@link UIProvider#ACCOUNTS_PROJECTION}
Vikram Aggarwal8b152632012-02-03 14:58:45 -080056 */
57 static final int NAME_COLUMN = 2;
58 /**
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -080059 * An object that provides a collection of recent folders, per account.
Vikram Aggarwal8b152632012-02-03 14:58:45 -080060 */
Vikram Aggarwal9d6b6b02012-03-08 10:36:30 -080061 private final RecentFolderList mRecentFolders;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080062 /**
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -080063 * The actual collection of sorted recent folders obtained from {@link #mRecentFolders}
Vikram Aggarwal8b152632012-02-03 14:58:45 -080064 */
Marc Blank167faa82012-03-21 13:11:53 -070065 private ArrayList<Folder> mRecentFolderList = new ArrayList<Folder>();
Paul Westbrook904b5f22012-04-12 00:29:58 -070066 /**
67 * Boolean indicating whether the "Show All Folders" items should be shown
68 */
69 private final boolean mShowAllFoldersItem;
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -080070
71 /** The folder currently being viewed */
Mindy Pereiraf9323cd2012-02-29 13:47:09 -080072 private Folder mCurrentFolder;
Mindy Pereirac1469c72012-03-20 13:56:12 -070073 private Context mContext;
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -080074
Mindy Pereira28d5f722012-02-15 12:32:40 -080075 public static final int TYPE_ACCOUNT = 0;
76 public static final int TYPE_HEADER = 1;
77 public static final int TYPE_FOLDER = 2;
Paul Westbrook904b5f22012-04-12 00:29:58 -070078 public static final int TYPE_ALL_FOLDERS = 3;
Vikram Aggarwal8b152632012-02-03 14:58:45 -080079
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080080 /**
81 * There can be three types of views: Accounts (test@android.com, fifi@example.com), folders
82 * (Inbox, Outbox) or header and footer. This method returns the type of account at given
83 * position in the drop down list.
84 * @param position
85 * @return the type of account: one of {@link #TYPE_ACCOUNT}, {@link #TYPE_HEADER}, or
86 * {@link #TYPE_FOLDER}.
87 */
Marc Blank41e764d2012-03-20 20:46:28 -070088 public int getType(int position) {
Vikram Aggarwal8b152632012-02-03 14:58:45 -080089 // First the accounts
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080090 if (position < mNumAccounts) {
Vikram Aggarwal8b152632012-02-03 14:58:45 -080091 return TYPE_ACCOUNT;
92 }
93 // Then the header
Vikram Aggarwala9b93f32012-02-23 14:51:58 -080094 if (position == mNumAccounts) {
Vikram Aggarwal8b152632012-02-03 14:58:45 -080095 return TYPE_HEADER;
96 }
Paul Westbrook904b5f22012-04-12 00:29:58 -070097 if (mShowAllFoldersItem) {
98 // The first few positions have accounts, and then the header.
99 final int offset = position - mNumAccounts - 1;
100 if (offset >= mRecentFolderList.size()) {
101 return TYPE_ALL_FOLDERS;
102 }
103 }
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800104 // Finally, the recent folders.
105 return TYPE_FOLDER;
106 }
107
Vikram Aggarwalec5cbf72012-03-08 15:10:35 -0800108 /**
Vikram Aggarwale6340bc2012-03-26 15:57:09 -0700109 * Returns the position of the dead, unselectable element in the spinner.
110 * @return
111 */
112 public int getSpacerPosition() {
113 return mNumAccounts;
114 }
115
116 /**
Vikram Aggarwalec5cbf72012-03-08 15:10:35 -0800117 * Create a spinner adapter with the context and the list of recent folders.
118 * @param context
119 * @param recentFolders
Paul Westbrook904b5f22012-04-12 00:29:58 -0700120 * @param showAllFolders
Vikram Aggarwalec5cbf72012-03-08 15:10:35 -0800121 */
Paul Westbrook904b5f22012-04-12 00:29:58 -0700122 public AccountSpinnerAdapter(Context context, RecentFolderList recentFolders,
123 boolean showAllFolders) {
Mindy Pereirac1469c72012-03-20 13:56:12 -0700124 mContext = context;
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800125 mInflater = LayoutInflater.from(context);
Vikram Aggarwalec5cbf72012-03-08 15:10:35 -0800126 mRecentFolders = recentFolders;
Paul Westbrook904b5f22012-04-12 00:29:58 -0700127 mShowAllFoldersItem = showAllFolders;
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800128 }
129
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800130 /**
131 * Set the accounts for this spinner.
132 * @param accounts
133 */
134 public void setAccounts(Account[] accounts) {
135 mAccounts = accounts;
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800136 mNumAccounts = accounts.length;
137 notifyDataSetChanged();
138 }
139
Mindy Pereiraf9323cd2012-02-29 13:47:09 -0800140 /**
Mindy Pereirabc57bf12012-02-29 14:39:09 -0800141 * Set the current folder.
Mindy Pereiraf9323cd2012-02-29 13:47:09 -0800142 * @param folder
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700143 * @return if changed.
Mindy Pereiraf9323cd2012-02-29 13:47:09 -0800144 */
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700145 public boolean setCurrentFolder(Folder folder) {
146 if (folder != null && folder != mCurrentFolder) {
147 mCurrentFolder = folder;
Marc Blank167faa82012-03-21 13:11:53 -0700148 mRecentFolderList = mRecentFolders.getRecentFolderList(folder);
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700149 notifyDataSetChanged();
150 return true;
151 }
152 return false;
Mindy Pereiraf9323cd2012-02-29 13:47:09 -0800153 }
154
Mindy Pereirabc57bf12012-02-29 14:39:09 -0800155 /**
156 * Set the current account.
157 * @param account
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700158 * @return if changed.
Mindy Pereirabc57bf12012-02-29 14:39:09 -0800159 */
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700160 public boolean setCurrentAccount(Account account) {
161 if (account != null && !account.equals(mCurrentAccount)) {
162 mCurrentAccount = account;
Marc Blank167faa82012-03-21 13:11:53 -0700163 mRecentFolderList = mRecentFolders.getRecentFolderList(mCurrentFolder);
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700164 notifyDataSetChanged();
165 return true;
166 }
167 return false;
Mindy Pereirabc57bf12012-02-29 14:39:09 -0800168 }
169
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800170 @Override
171 public int getCount() {
Paul Westbrook904b5f22012-04-12 00:29:58 -0700172 // All the accounts, plus one header, plus recent folders, plus one if the
173 // "show all folders" item should be shown
174 return mNumAccounts + 1 + mRecentFolderList.size() + (mShowAllFoldersItem ? 1 : 0);
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800175 }
176
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800177 @Override
178 public Object getItem(int position) {
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800179 switch (getType(position)){
180 case TYPE_ACCOUNT:
181 return getAccount(position);
182 case TYPE_HEADER:
183 return "account spinner header";
Paul Westbrook904b5f22012-04-12 00:29:58 -0700184 case TYPE_ALL_FOLDERS:
185 return "show all folders";
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800186 default:
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -0800187 // The first few positions have accounts, and then the header.
188 final int offset = position - mNumAccounts - 1;
Marc Blank41e764d2012-03-20 20:46:28 -0700189 // Return the folder at this location.
Marc Blank167faa82012-03-21 13:11:53 -0700190 return mRecentFolderList.get(offset);
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800191 }
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800192 }
193
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800194 @Override
195 public long getItemId(int position) {
196 // We use the position as the ID
197 return position;
198 }
199
Mindy Pereiraf9323cd2012-02-29 13:47:09 -0800200 private String getFolderLabel() {
201 return mCurrentFolder != null ? mCurrentFolder.name : "";
202 }
203
Mindy Pereirae973f222012-03-06 14:29:03 -0800204 private int getFolderUnreadCount() {
205 return mCurrentFolder != null ? mCurrentFolder.unreadCount : 0;
206 }
207
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700208 private String getCurrentAccountName() {
209 return mCurrentAccount != null ? mCurrentAccount.name : "";
210 }
211
212 // This call renders the view that will be shown in the header.
213 // Since we are tracking the current folder/ account, just
214 // always return what we believe that view is.
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800215 @Override
216 public View getView(int position, View convertView, ViewGroup parent) {
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700217 convertView = mInflater.inflate(R.layout.account_switch_spinner_item, null);
218 ((TextView) convertView.findViewById(R.id.account_spinner_account_name))
219 .setText(getCurrentAccountName());
220 ((TextView) convertView.findViewById(R.id.account_spinner_folder))
221 .setText(getFolderLabel());
222 populateUnreadCountView((TextView) convertView.findViewById(R.id.unread),
223 getFolderUnreadCount());
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800224 return convertView;
225 }
226
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800227 @Override
228 public int getViewTypeCount() {
Paul Westbrook904b5f22012-04-12 00:29:58 -0700229 // Two views, and one header, and potentially one "show all folders" item
230 return 3 + (mShowAllFoldersItem ? 1 : 0);
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800231 }
232
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800233 @Override
234 public boolean hasStableIds() {
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800235 // The account manager could add new accounts, so don't claim that the IDs are stable.
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800236 return false;
237 }
238
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800239 @Override
240 public boolean isEmpty() {
241 // No item will be empty.
242 return false;
243 }
244
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800245 @Override
246 public View getDropDownView(int position, View convertView, ViewGroup parent) {
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800247 String textLabel = "";
248 int unreadCount = 0;
249 switch (getType(position)) {
250 case TYPE_HEADER:
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700251 convertView = mInflater.inflate(R.layout.account_switch_spinner_dropdown_header,
252 null);
253 final String label = getCurrentAccountName();
254 TextView accountLabel = ((TextView) convertView.findViewById(
255 R.id.account_spinner_header_account));
256 if (accountLabel != null) {
257 accountLabel.setText(label);
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800258 }
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800259 return convertView;
260 case TYPE_ACCOUNT:
Mindy Pereira30fd47b2012-03-09 09:24:00 -0800261 textLabel = getAccountFolder(position);
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800262 break;
263 case TYPE_FOLDER:
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800264 final int offset = position - mNumAccounts - 1;
Marc Blank167faa82012-03-21 13:11:53 -0700265 final Folder folder = mRecentFolderList.get(offset);
Vikram Aggarwal1a4bcc02012-03-01 10:09:44 -0800266 textLabel = folder.name;
267 unreadCount = folder.unreadCount;
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800268 break;
Paul Westbrook904b5f22012-04-12 00:29:58 -0700269 case TYPE_ALL_FOLDERS:
270 textLabel = mContext.getResources().getString(R.string.show_all_folders);
271 break;
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800272 }
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700273 convertView = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null);
274 ((TextView) convertView.findViewById(R.id.account_spinner_accountname)).setText(textLabel);
275 populateUnreadCountView(
276 (TextView) convertView.findViewById(R.id.account_spinner_unread_count),
277 unreadCount);
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800278 return convertView;
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800279
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800280 }
281
Mindy Pereiraa6be8482012-03-21 10:31:57 -0700282
283 private void populateUnreadCountView(TextView unreadCountView, int unreadCount) {
284 unreadCountView.setText(Utils.getUnreadCountString(mContext, unreadCount));
285 unreadCountView.setVisibility(unreadCount == 0 ? View.GONE : View.VISIBLE);
286 }
287
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800288 /**
Mindy Pereiraae180202012-02-29 13:09:58 -0800289 * Returns the name of the folder at the given position in the spinner.
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800290 * @param position
Mindy Pereira30fd47b2012-03-09 09:24:00 -0800291 * @return the folder of the account at the given position.
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800292 */
Mindy Pereira30fd47b2012-03-09 09:24:00 -0800293 private String getAccountFolder(int position) {
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800294 if (position >= mNumAccounts) {
Paul Westbrook9732bdc2012-02-21 11:02:37 -0800295 return "";
296 }
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800297 return mAccounts[position].name;
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800298 }
299
Mindy Pereira28d5f722012-02-15 12:32:40 -0800300 /**
301 * Returns the account given position in the spinner.
302 * @param position
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800303 * @return the account at the given position.
Mindy Pereira28d5f722012-02-15 12:32:40 -0800304 */
305 private Account getAccount(int position) {
Vikram Aggarwala9b93f32012-02-23 14:51:58 -0800306 return mAccounts[position];
Mindy Pereira28d5f722012-02-15 12:32:40 -0800307 }
308
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800309
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800310 @Override
311 public boolean isEnabled(int position) {
312 // Don't want the user selecting the header.
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800313 return (getType(position) != TYPE_HEADER);
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800314 }
315
316 @Override
317 public boolean areAllItemsEnabled() {
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800318 // The header is not enabled, so return false here.
Vikram Aggarwal6f6afe52012-01-04 14:43:44 -0800319 return false;
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800320 }
Mindy Pereiraa46a57f2012-04-03 17:19:31 -0700321
322 /**
323 * Notify that the folder has changed.
324 */
325 public void onFolderUpdated(Folder folder) {
326 mCurrentFolder = folder;
327 notifyDataSetChanged();
328 }
Vikram Aggarwal5e5ac742011-12-19 08:14:16 -0800329}