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 18 package com.android.email.provider; 19 20 import android.app.AlertDialog; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.DialogInterface.OnCancelListener; 24 import android.content.DialogInterface.OnClickListener; 25 import android.content.DialogInterface.OnMultiChoiceClickListener; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.view.View; 29 import android.widget.AdapterView; 30 import android.widget.Button; 31 32 import com.android.mail.R; 33 import com.android.mail.providers.Folder; 34 import com.android.mail.providers.UIProvider; 35 import com.android.mail.ui.FolderSelectorAdapter; 36 import com.android.mail.ui.FolderSelectorAdapter.FolderRow; 37 import com.android.mail.ui.SeparatedFolderListAdapter; 38 39 import java.util.HashMap; 40 import java.util.HashSet; 41 import java.util.Map.Entry; 42 43 public class FolderPickerDialog implements OnClickListener, OnMultiChoiceClickListener, 44 OnCancelListener { 45 private final AlertDialog mDialog; 46 private final HashMap<Folder, Boolean> mCheckedState; 47 private final SeparatedFolderListAdapter mAdapter; 48 private final FolderPickerCallback mCallback; 49 FolderPickerDialog(final Context context, Uri uri, FolderPickerCallback callback, String header, boolean cancelable)50 public FolderPickerDialog(final Context context, Uri uri, 51 FolderPickerCallback callback, String header, boolean cancelable) { 52 mCallback = callback; 53 // Mapping of a folder's uri to its checked state 54 mCheckedState = new HashMap<Folder, Boolean>(); 55 AlertDialog.Builder builder = new AlertDialog.Builder(context); 56 builder.setTitle(header); 57 builder.setPositiveButton(R.string.ok, this); 58 builder.setCancelable(cancelable); 59 builder.setOnCancelListener(this); 60 // TODO: Do this on a background thread 61 final Cursor foldersCursor = context.getContentResolver().query( 62 uri, UIProvider.FOLDERS_PROJECTION, null, null, null); 63 try { 64 mAdapter = new SeparatedFolderListAdapter(); 65 mAdapter.addSection(new FolderPickerSelectorAdapter(context, foldersCursor, 66 new HashSet<String>(), R.layout.multi_folders_view)); 67 builder.setAdapter(mAdapter, this); 68 } finally { 69 foldersCursor.close(); 70 } 71 mDialog = builder.create(); 72 } 73 show()74 public void show() { 75 mDialog.show(); 76 mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { 77 @Override 78 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 79 final Object item = mAdapter.getItem(position); 80 if (item instanceof FolderRow) { 81 update((FolderRow) item); 82 } 83 } 84 }); 85 86 final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); 87 if (mCheckedState.size() == 0) { 88 // No items are selected, so disable the OK button. 89 button.setEnabled(false); 90 } 91 } 92 93 /** 94 * Call this to update the state of folders as a result of them being 95 * selected / de-selected. 96 * 97 * @param row The item being updated. 98 */ update(FolderSelectorAdapter.FolderRow row)99 public void update(FolderSelectorAdapter.FolderRow row) { 100 // Update the UI 101 final boolean add = !row.isSelected(); 102 if (!add) { 103 // This would remove the check on a single radio button, so just 104 // return. 105 return; 106 } 107 // Clear any other checked items. 108 mAdapter.getCount(); 109 for (int i = 0; i < mAdapter.getCount(); i++) { 110 Object item = mAdapter.getItem(i); 111 if (item instanceof FolderRow) { 112 ((FolderRow)item).setIsSelected(false); 113 } 114 } 115 mCheckedState.clear(); 116 row.setIsSelected(add); 117 mAdapter.notifyDataSetChanged(); 118 mCheckedState.put(row.getFolder(), add); 119 120 // Since we know that an item is selected in the list, enable the OK button 121 final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); 122 button.setEnabled(true); 123 } 124 125 @Override onClick(DialogInterface dialog, int which)126 public void onClick(DialogInterface dialog, int which) { 127 switch (which) { 128 case DialogInterface.BUTTON_POSITIVE: 129 Folder folder = null; 130 for (Entry<Folder, Boolean> entry : mCheckedState.entrySet()) { 131 if (entry.getValue()) { 132 folder = entry.getKey(); 133 break; 134 } 135 } 136 mCallback.select(folder); 137 break; 138 default: 139 onClick(dialog, which, true); 140 break; 141 } 142 } 143 144 @Override onClick(DialogInterface dialog, int which, boolean isChecked)145 public void onClick(DialogInterface dialog, int which, boolean isChecked) { 146 final FolderRow row = (FolderRow) mAdapter.getItem(which); 147 // Clear any other checked items. 148 mCheckedState.clear(); 149 isChecked = true; 150 mCheckedState.put(row.getFolder(), isChecked); 151 mDialog.getListView().setItemChecked(which, false); 152 } 153 154 @Override onCancel(DialogInterface dialog)155 public void onCancel(DialogInterface dialog) { 156 mCallback.cancel(); 157 } 158 } 159