1c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank/* 2c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Copyright (C) 2012 Google Inc. 3c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Licensed to The Android Open Source Project. 4c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * 5c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 6c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * you may not use this file except in compliance with the License. 7c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * You may obtain a copy of the License at 8c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * 9c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * http://www.apache.org/licenses/LICENSE-2.0 10c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * 11c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Unless required by applicable law or agreed to in writing, software 12c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * distributed under the License is distributed on an "AS IS" BASIS, 13c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * See the License for the specific language governing permissions and 15c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * limitations under the License. 16c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank */ 17c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 18c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankpackage com.android.email.provider; 19c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 20c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.app.AlertDialog; 21c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.Context; 22c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface; 2326164054710375519ba7468987971a7a3340ba7eMarc Blankimport android.content.DialogInterface.OnCancelListener; 24c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface.OnClickListener; 25c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface.OnMultiChoiceClickListener; 26c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.database.Cursor; 2726164054710375519ba7468987971a7a3340ba7eMarc Blankimport android.net.Uri; 28c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.view.View; 29c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.widget.AdapterView; 309439595e582803ede8c4bb8634cf93457681edd7Paul Westbrookimport android.widget.Button; 31c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 32c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.R; 33c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.providers.Folder; 34c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.providers.UIProvider; 35c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.FolderSelectorAdapter; 36c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.FolderSelectorAdapter.FolderRow; 37c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.SeparatedFolderListAdapter; 38c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 39c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.HashMap; 40c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.HashSet; 41c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.Map.Entry; 42c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 43266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blankpublic class FolderPickerDialog implements OnClickListener, OnMultiChoiceClickListener, 44266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank OnCancelListener { 459439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook private final AlertDialog mDialog; 469439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook private final HashMap<Folder, Boolean> mCheckedState; 479439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook private final SeparatedFolderListAdapter mAdapter; 489439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook private final FolderPickerCallback mCallback; 49c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 50266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank public FolderPickerDialog(final Context context, Uri uri, 51266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank FolderPickerCallback callback, String header, boolean cancelable) { 52c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCallback = callback; 53c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // Mapping of a folder's uri to its checked state 54c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCheckedState = new HashMap<Folder, Boolean>(); 55c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank AlertDialog.Builder builder = new AlertDialog.Builder(context); 5626164054710375519ba7468987971a7a3340ba7eMarc Blank builder.setTitle(header); 57c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank builder.setPositiveButton(R.string.ok, this); 58266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank builder.setCancelable(cancelable); 59266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank builder.setOnCancelListener(this); 6026164054710375519ba7468987971a7a3340ba7eMarc Blank // TODO: Do this on a background thread 61c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank final Cursor foldersCursor = context.getContentResolver().query( 6226164054710375519ba7468987971a7a3340ba7eMarc Blank uri, UIProvider.FOLDERS_PROJECTION, null, null, null); 63c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank try { 644f32213ebebb59d5316e0dd4ca9d78dc1c170879Tony Mantler mAdapter = new SeparatedFolderListAdapter(); 658ff282a260eef699c3e22e8809075191706a171amindyp mAdapter.addSection(new FolderPickerSelectorAdapter(context, foldersCursor, 66c07a44240311eb0ce44654284b010e6df8b08e86Andrew Sapperstein new HashSet<String>(), R.layout.multi_folders_view)); 67c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank builder.setAdapter(mAdapter, this); 68c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } finally { 69c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank foldersCursor.close(); 70c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 71c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mDialog = builder.create(); 72c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 73c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 74c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank public void show() { 75c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mDialog.show(); 76c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { 77c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank @Override 78c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 799439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook final Object item = mAdapter.getItem(position); 80c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank if (item instanceof FolderRow) { 81c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank update((FolderRow) item); 82c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 83c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 84c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank }); 859439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook 869439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); 879439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook if (mCheckedState.size() == 0) { 889439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook // No items are selected, so disable the OK button. 899439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook button.setEnabled(false); 909439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook } 91c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 92c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 93c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank /** 94c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Call this to update the state of folders as a result of them being 95c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * selected / de-selected. 96c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * 97c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * @param row The item being updated. 98c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank */ 99c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank public void update(FolderSelectorAdapter.FolderRow row) { 100c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // Update the UI 101cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao final boolean add = !row.isSelected(); 102c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank if (!add) { 103c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // This would remove the check on a single radio button, so just 104c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // return. 105c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank return; 106c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 107c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // Clear any other checked items. 108c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mAdapter.getCount(); 109c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank for (int i = 0; i < mAdapter.getCount(); i++) { 110c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank Object item = mAdapter.getItem(i); 111c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank if (item instanceof FolderRow) { 112cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao ((FolderRow)item).setIsSelected(false); 113c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 114c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 115c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCheckedState.clear(); 116cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao row.setIsSelected(add); 117c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mAdapter.notifyDataSetChanged(); 118c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCheckedState.put(row.getFolder(), add); 1199439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook 1209439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook // Since we know that an item is selected in the list, enable the OK button 1219439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); 1229439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook button.setEnabled(true); 123c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 124c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 125c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank @Override 126c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank public void onClick(DialogInterface dialog, int which) { 127c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank switch (which) { 128c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank case DialogInterface.BUTTON_POSITIVE: 129c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank Folder folder = null; 130c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank for (Entry<Folder, Boolean> entry : mCheckedState.entrySet()) { 131c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank if (entry.getValue()) { 132c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank folder = entry.getKey(); 133c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank break; 134c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 135c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 136c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCallback.select(folder); 137c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank break; 138c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank default: 139c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank onClick(dialog, which, true); 140c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank break; 141c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 142c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 143c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank 144c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank @Override 145c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank public void onClick(DialogInterface dialog, int which, boolean isChecked) { 146c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank final FolderRow row = (FolderRow) mAdapter.getItem(which); 147c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank // Clear any other checked items. 148c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCheckedState.clear(); 149c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank isChecked = true; 150c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mCheckedState.put(row.getFolder(), isChecked); 151c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank mDialog.getListView().setItemChecked(which, false); 152c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank } 153266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank 154266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank @Override 155266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank public void onCancel(DialogInterface dialog) { 156266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank mCallback.cancel(); 157266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank } 158c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank} 159